Branch data Line data Source code
1 : : /* Descriptors -- a new, flexible way to describe attributes */
2 : :
3 : : #include "Python.h"
4 : : #include "pycore_ceval.h" // _Py_EnterRecursiveCallTstate()
5 : : #include "pycore_object.h" // _PyObject_GC_UNTRACK()
6 : : #include "pycore_pystate.h" // _PyThreadState_GET()
7 : : #include "pycore_tuple.h" // _PyTuple_ITEMS()
8 : : #include "structmember.h" // PyMemberDef
9 : : #include "pycore_descrobject.h"
10 : :
11 : : /*[clinic input]
12 : : class mappingproxy "mappingproxyobject *" "&PyDictProxy_Type"
13 : : class property "propertyobject *" "&PyProperty_Type"
14 : : [clinic start generated code]*/
15 : : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=556352653fd4c02e]*/
16 : :
17 : : // see pycore_object.h
18 : : #if defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE)
19 : : #include <emscripten.h>
20 : : EM_JS(PyObject*, descr_set_trampoline_call, (setter set, PyObject *obj, PyObject *value, void *closure), {
21 : : return wasmTable.get(set)(obj, value, closure);
22 : : });
23 : :
24 : : EM_JS(PyObject*, descr_get_trampoline_call, (getter get, PyObject *obj, void *closure), {
25 : : return wasmTable.get(get)(obj, closure);
26 : : });
27 : : #else
28 : : #define descr_set_trampoline_call(set, obj, value, closure) \
29 : : (set)((obj), (value), (closure))
30 : :
31 : : #define descr_get_trampoline_call(get, obj, closure) \
32 : : (get)((obj), (closure))
33 : :
34 : : #endif // __EMSCRIPTEN__ && PY_CALL_TRAMPOLINE
35 : :
36 : : static void
37 : 7436598 : descr_dealloc(PyDescrObject *descr)
38 : : {
39 : 7436598 : _PyObject_GC_UNTRACK(descr);
40 : 7436598 : Py_XDECREF(descr->d_type);
41 : 7436598 : Py_XDECREF(descr->d_name);
42 : 7436598 : Py_XDECREF(descr->d_qualname);
43 : 7436598 : PyObject_GC_Del(descr);
44 : 7436598 : }
45 : :
46 : : static PyObject *
47 : 212 : descr_name(PyDescrObject *descr)
48 : : {
49 [ + - + - ]: 212 : if (descr->d_name != NULL && PyUnicode_Check(descr->d_name))
50 : 212 : return descr->d_name;
51 : 0 : return NULL;
52 : : }
53 : :
54 : : static PyObject *
55 : 93 : descr_repr(PyDescrObject *descr, const char *format)
56 : : {
57 : 93 : PyObject *name = NULL;
58 [ + - + - ]: 93 : if (descr->d_name != NULL && PyUnicode_Check(descr->d_name))
59 : 93 : name = descr->d_name;
60 : :
61 : 93 : return PyUnicode_FromFormat(format, name, "?", descr->d_type->tp_name);
62 : : }
63 : :
64 : : static PyObject *
65 : 88 : method_repr(PyMethodDescrObject *descr)
66 : : {
67 : 88 : return descr_repr((PyDescrObject *)descr,
68 : : "<method '%V' of '%s' objects>");
69 : : }
70 : :
71 : : static PyObject *
72 : 1 : member_repr(PyMemberDescrObject *descr)
73 : : {
74 : 1 : return descr_repr((PyDescrObject *)descr,
75 : : "<member '%V' of '%s' objects>");
76 : : }
77 : :
78 : : static PyObject *
79 : 4 : getset_repr(PyGetSetDescrObject *descr)
80 : : {
81 : 4 : return descr_repr((PyDescrObject *)descr,
82 : : "<attribute '%V' of '%s' objects>");
83 : : }
84 : :
85 : : static PyObject *
86 : 0 : wrapperdescr_repr(PyWrapperDescrObject *descr)
87 : : {
88 : 0 : return descr_repr((PyDescrObject *)descr,
89 : : "<slot wrapper '%V' of '%s' objects>");
90 : : }
91 : :
92 : : static int
93 : 133155245 : descr_check(PyDescrObject *descr, PyObject *obj)
94 : : {
95 [ + + ]: 133155245 : if (!PyObject_TypeCheck(obj, descr->d_type)) {
96 : 168 : PyErr_Format(PyExc_TypeError,
97 : : "descriptor '%V' for '%.100s' objects "
98 : : "doesn't apply to a '%.100s' object",
99 : : descr_name((PyDescrObject *)descr), "?",
100 : 168 : descr->d_type->tp_name,
101 : 168 : Py_TYPE(obj)->tp_name);
102 : 168 : return -1;
103 : : }
104 : 133155077 : return 0;
105 : : }
106 : :
107 : : static PyObject *
108 : 3245043 : classmethod_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type)
109 : : {
110 : : /* Ensure a valid type. Class methods ignore obj. */
111 [ + + ]: 3245043 : if (type == NULL) {
112 [ + - ]: 2 : if (obj != NULL)
113 : 2 : type = (PyObject *)Py_TYPE(obj);
114 : : else {
115 : : /* Wot - no type?! */
116 : 0 : PyErr_Format(PyExc_TypeError,
117 : : "descriptor '%V' for type '%.100s' "
118 : : "needs either an object or a type",
119 : : descr_name((PyDescrObject *)descr), "?",
120 : 0 : PyDescr_TYPE(descr)->tp_name);
121 : 0 : return NULL;
122 : : }
123 : : }
124 [ + + ]: 3245043 : if (!PyType_Check(type)) {
125 : 2 : PyErr_Format(PyExc_TypeError,
126 : : "descriptor '%V' for type '%.100s' "
127 : : "needs a type, not a '%.100s' as arg 2",
128 : : descr_name((PyDescrObject *)descr), "?",
129 : 2 : PyDescr_TYPE(descr)->tp_name,
130 : 2 : Py_TYPE(type)->tp_name);
131 : 2 : return NULL;
132 : : }
133 [ + + ]: 3245041 : if (!PyType_IsSubtype((PyTypeObject *)type, PyDescr_TYPE(descr))) {
134 : 4 : PyErr_Format(PyExc_TypeError,
135 : : "descriptor '%V' requires a subtype of '%.100s' "
136 : : "but received '%.100s'",
137 : : descr_name((PyDescrObject *)descr), "?",
138 : 4 : PyDescr_TYPE(descr)->tp_name,
139 : : ((PyTypeObject *)type)->tp_name);
140 : 4 : return NULL;
141 : : }
142 : 3245037 : PyTypeObject *cls = NULL;
143 [ - + ]: 3245037 : if (descr->d_method->ml_flags & METH_METHOD) {
144 : 0 : cls = descr->d_common.d_type;
145 : : }
146 : 3245037 : return PyCMethod_New(descr->d_method, type, NULL, cls);
147 : : }
148 : :
149 : : static PyObject *
150 : 25735512 : method_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type)
151 : : {
152 [ + + ]: 25735512 : if (obj == NULL) {
153 : 605407 : return Py_NewRef(descr);
154 : : }
155 [ + + ]: 25130105 : if (descr_check((PyDescrObject *)descr, obj) < 0) {
156 : 3 : return NULL;
157 : : }
158 [ + + ]: 25130102 : if (descr->d_method->ml_flags & METH_METHOD) {
159 [ + - ]: 2725970 : if (PyType_Check(type)) {
160 : 2725970 : return PyCMethod_New(descr->d_method, obj, NULL, descr->d_common.d_type);
161 : : } else {
162 : 0 : PyErr_Format(PyExc_TypeError,
163 : : "descriptor '%V' needs a type, not '%s', as arg 2",
164 : : descr_name((PyDescrObject *)descr),
165 : 0 : Py_TYPE(type)->tp_name);
166 : 0 : return NULL;
167 : : }
168 : : } else {
169 : 22404132 : return PyCFunction_NewEx(descr->d_method, obj, NULL);
170 : : }
171 : : }
172 : :
173 : : static PyObject *
174 : 10249958 : member_get(PyMemberDescrObject *descr, PyObject *obj, PyObject *type)
175 : : {
176 [ + + ]: 10249958 : if (obj == NULL) {
177 : 5405 : return Py_NewRef(descr);
178 : : }
179 [ + + ]: 10244553 : if (descr_check((PyDescrObject *)descr, obj) < 0) {
180 : 55 : return NULL;
181 : : }
182 : :
183 [ + + ]: 10244498 : if (descr->d_member->flags & PY_AUDIT_READ) {
184 [ - + ]: 282063 : if (PySys_Audit("object.__getattr__", "Os",
185 [ + - ]: 282063 : obj ? obj : Py_None, descr->d_member->name) < 0) {
186 : 0 : return NULL;
187 : : }
188 : : }
189 : :
190 : 10244498 : return PyMember_GetOne((char *)obj, descr->d_member);
191 : : }
192 : :
193 : : static PyObject *
194 : 42182029 : getset_get(PyGetSetDescrObject *descr, PyObject *obj, PyObject *type)
195 : : {
196 [ + + ]: 42182029 : if (obj == NULL) {
197 : 12848 : return Py_NewRef(descr);
198 : : }
199 [ - + ]: 42169181 : if (descr_check((PyDescrObject *)descr, obj) < 0) {
200 : 0 : return NULL;
201 : : }
202 [ + - ]: 42169181 : if (descr->d_getset->get != NULL)
203 : 42169181 : return descr_get_trampoline_call(
204 : : descr->d_getset->get, obj, descr->d_getset->closure);
205 : 0 : PyErr_Format(PyExc_AttributeError,
206 : : "attribute '%V' of '%.100s' objects is not readable",
207 : : descr_name((PyDescrObject *)descr), "?",
208 : 0 : PyDescr_TYPE(descr)->tp_name);
209 : 0 : return NULL;
210 : : }
211 : :
212 : : static PyObject *
213 : 8742851 : wrapperdescr_get(PyWrapperDescrObject *descr, PyObject *obj, PyObject *type)
214 : : {
215 [ + + ]: 8742851 : if (obj == NULL) {
216 : 834530 : return Py_NewRef(descr);
217 : : }
218 [ - + ]: 7908321 : if (descr_check((PyDescrObject *)descr, obj) < 0) {
219 : 0 : return NULL;
220 : : }
221 : 7908321 : return PyWrapper_New((PyObject *)descr, obj);
222 : : }
223 : :
224 : : static int
225 : 4427645 : descr_setcheck(PyDescrObject *descr, PyObject *obj, PyObject *value)
226 : : {
227 : : assert(obj != NULL);
228 [ + + ]: 4427645 : if (!PyObject_TypeCheck(obj, descr->d_type)) {
229 : 2 : PyErr_Format(PyExc_TypeError,
230 : : "descriptor '%V' for '%.100s' objects "
231 : : "doesn't apply to a '%.100s' object",
232 : : descr_name(descr), "?",
233 : 2 : descr->d_type->tp_name,
234 : 2 : Py_TYPE(obj)->tp_name);
235 : 2 : return -1;
236 : : }
237 : 4427643 : return 0;
238 : : }
239 : :
240 : : static int
241 : 3646565 : member_set(PyMemberDescrObject *descr, PyObject *obj, PyObject *value)
242 : : {
243 [ + + ]: 3646565 : if (descr_setcheck((PyDescrObject *)descr, obj, value) < 0) {
244 : 1 : return -1;
245 : : }
246 : 3646564 : return PyMember_SetOne((char *)obj, descr->d_member, value);
247 : : }
248 : :
249 : : static int
250 : 781080 : getset_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value)
251 : : {
252 [ + + ]: 781080 : if (descr_setcheck((PyDescrObject *)descr, obj, value) < 0) {
253 : 1 : return -1;
254 : : }
255 [ + + ]: 781079 : if (descr->d_getset->set != NULL) {
256 : 781050 : return descr_set_trampoline_call(
257 : : descr->d_getset->set, obj, value,
258 : : descr->d_getset->closure);
259 : : }
260 : 29 : PyErr_Format(PyExc_AttributeError,
261 : : "attribute '%V' of '%.100s' objects is not writable",
262 : : descr_name((PyDescrObject *)descr), "?",
263 : 29 : PyDescr_TYPE(descr)->tp_name);
264 : 29 : return -1;
265 : : }
266 : :
267 : :
268 : : /* Vectorcall functions for each of the PyMethodDescr calling conventions.
269 : : *
270 : : * First, common helpers
271 : : */
272 : : static inline int
273 : 47703096 : method_check_args(PyObject *func, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
274 : : {
275 : : assert(!PyErr_Occurred());
276 [ + + ]: 47703096 : if (nargs < 1) {
277 : 11 : PyObject *funcstr = _PyObject_FunctionStr(func);
278 [ + - ]: 11 : if (funcstr != NULL) {
279 : 11 : PyErr_Format(PyExc_TypeError,
280 : : "unbound method %U needs an argument", funcstr);
281 : 11 : Py_DECREF(funcstr);
282 : : }
283 : 11 : return -1;
284 : : }
285 : 47703085 : PyObject *self = args[0];
286 [ + + ]: 47703085 : if (descr_check((PyDescrObject *)func, self) < 0) {
287 : 110 : return -1;
288 : : }
289 [ + + + + ]: 47702975 : if (kwnames && PyTuple_GET_SIZE(kwnames)) {
290 : 6 : PyObject *funcstr = _PyObject_FunctionStr(func);
291 [ + - ]: 6 : if (funcstr != NULL) {
292 : 6 : PyErr_Format(PyExc_TypeError,
293 : : "%U takes no keyword arguments", funcstr);
294 : 6 : Py_DECREF(funcstr);
295 : : }
296 : 6 : return -1;
297 : : }
298 : 47702969 : return 0;
299 : : }
300 : :
301 : : typedef void (*funcptr)(void);
302 : :
303 : : static inline funcptr
304 : 47702964 : method_enter_call(PyThreadState *tstate, PyObject *func)
305 : : {
306 [ + + ]: 47702964 : if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object")) {
307 : 9 : return NULL;
308 : : }
309 : 47702955 : return (funcptr)((PyMethodDescrObject *)func)->d_method->ml_meth;
310 : : }
311 : :
312 : : /* Now the actual vectorcall functions */
313 : : static PyObject *
314 : 15819807 : method_vectorcall_VARARGS(
315 : : PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
316 : : {
317 : 15819807 : PyThreadState *tstate = _PyThreadState_GET();
318 : 15819807 : Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
319 [ + + ]: 15819807 : if (method_check_args(func, args, nargs, kwnames)) {
320 : 1 : return NULL;
321 : : }
322 : 15819806 : PyObject *argstuple = _PyTuple_FromArray(args+1, nargs-1);
323 [ - + ]: 15819806 : if (argstuple == NULL) {
324 : 0 : return NULL;
325 : : }
326 : 15819806 : PyCFunction meth = (PyCFunction)method_enter_call(tstate, func);
327 [ + + ]: 15819806 : if (meth == NULL) {
328 : 1 : Py_DECREF(argstuple);
329 : 1 : return NULL;
330 : : }
331 : 15819805 : PyObject *result = _PyCFunction_TrampolineCall(
332 : : meth, args[0], argstuple);
333 : 15819805 : Py_DECREF(argstuple);
334 : 15819805 : _Py_LeaveRecursiveCallTstate(tstate);
335 : 15819805 : return result;
336 : : }
337 : :
338 : : static PyObject *
339 : 6458805 : method_vectorcall_VARARGS_KEYWORDS(
340 : : PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
341 : : {
342 : 6458805 : PyThreadState *tstate = _PyThreadState_GET();
343 : 6458805 : Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
344 [ + + ]: 6458805 : if (method_check_args(func, args, nargs, NULL)) {
345 : 6 : return NULL;
346 : : }
347 : 6458799 : PyObject *argstuple = _PyTuple_FromArray(args+1, nargs-1);
348 [ - + ]: 6458799 : if (argstuple == NULL) {
349 : 0 : return NULL;
350 : : }
351 : 6458799 : PyObject *result = NULL;
352 : : /* Create a temporary dict for keyword arguments */
353 : 6458799 : PyObject *kwdict = NULL;
354 [ + + + - ]: 6458799 : if (kwnames != NULL && PyTuple_GET_SIZE(kwnames) > 0) {
355 : 36521 : kwdict = _PyStack_AsDict(args + nargs, kwnames);
356 [ - + ]: 36521 : if (kwdict == NULL) {
357 : 0 : goto exit;
358 : : }
359 : : }
360 : : PyCFunctionWithKeywords meth = (PyCFunctionWithKeywords)
361 : 6458799 : method_enter_call(tstate, func);
362 [ + + ]: 6458799 : if (meth == NULL) {
363 : 1 : goto exit;
364 : : }
365 : 6458798 : result = _PyCFunctionWithKeywords_TrampolineCall(
366 : : meth, args[0], argstuple, kwdict);
367 : 6458795 : _Py_LeaveRecursiveCallTstate(tstate);
368 : 6458796 : exit:
369 : 6458796 : Py_DECREF(argstuple);
370 : 6458796 : Py_XDECREF(kwdict);
371 : 6458796 : return result;
372 : : }
373 : :
374 : : static PyObject *
375 : 10899293 : method_vectorcall_FASTCALL_KEYWORDS_METHOD(
376 : : PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
377 : : {
378 : 10899293 : PyThreadState *tstate = _PyThreadState_GET();
379 : 10899293 : Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
380 [ - + ]: 10899293 : if (method_check_args(func, args, nargs, NULL)) {
381 : 0 : return NULL;
382 : : }
383 : 10899293 : PyCMethod meth = (PyCMethod) method_enter_call(tstate, func);
384 [ - + ]: 10899293 : if (meth == NULL) {
385 : 0 : return NULL;
386 : : }
387 : 10899293 : PyObject *result = meth(args[0],
388 : : ((PyMethodDescrObject *)func)->d_common.d_type,
389 : 10899293 : args+1, nargs-1, kwnames);
390 : 10899293 : _Py_LeaveRecursiveCall();
391 : 10899293 : return result;
392 : : }
393 : :
394 : : static PyObject *
395 : 2197868 : method_vectorcall_FASTCALL(
396 : : PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
397 : : {
398 : 2197868 : PyThreadState *tstate = _PyThreadState_GET();
399 : 2197868 : Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
400 [ + + ]: 2197868 : if (method_check_args(func, args, nargs, kwnames)) {
401 : 24 : return NULL;
402 : : }
403 : : _PyCFunctionFast meth = (_PyCFunctionFast)
404 : 2197844 : method_enter_call(tstate, func);
405 [ + + ]: 2197844 : if (meth == NULL) {
406 : 1 : return NULL;
407 : : }
408 : 2197843 : PyObject *result = meth(args[0], args+1, nargs-1);
409 : 2197835 : _Py_LeaveRecursiveCallTstate(tstate);
410 : 2197835 : return result;
411 : : }
412 : :
413 : : static PyObject *
414 : 852812 : method_vectorcall_FASTCALL_KEYWORDS(
415 : : PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
416 : : {
417 : 852812 : PyThreadState *tstate = _PyThreadState_GET();
418 : 852812 : Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
419 [ + + ]: 852812 : if (method_check_args(func, args, nargs, NULL)) {
420 : 51 : return NULL;
421 : : }
422 : : _PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords)
423 : 852761 : method_enter_call(tstate, func);
424 [ - + ]: 852761 : if (meth == NULL) {
425 : 0 : return NULL;
426 : : }
427 : 852761 : PyObject *result = meth(args[0], args+1, nargs-1, kwnames);
428 : 852761 : _Py_LeaveRecursiveCallTstate(tstate);
429 : 852761 : return result;
430 : : }
431 : :
432 : : static PyObject *
433 : 8500105 : method_vectorcall_NOARGS(
434 : : PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
435 : : {
436 : 8500105 : PyThreadState *tstate = _PyThreadState_GET();
437 : 8500105 : Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
438 [ + + ]: 8500105 : if (method_check_args(func, args, nargs, kwnames)) {
439 : 21 : return NULL;
440 : : }
441 [ + + ]: 8500084 : if (nargs != 1) {
442 : 3 : PyObject *funcstr = _PyObject_FunctionStr(func);
443 [ + - ]: 3 : if (funcstr != NULL) {
444 : 3 : PyErr_Format(PyExc_TypeError,
445 : : "%U takes no arguments (%zd given)", funcstr, nargs-1);
446 : 3 : Py_DECREF(funcstr);
447 : : }
448 : 3 : return NULL;
449 : : }
450 : 8500081 : PyCFunction meth = (PyCFunction)method_enter_call(tstate, func);
451 [ + + ]: 8500081 : if (meth == NULL) {
452 : 2 : return NULL;
453 : : }
454 : 8500079 : PyObject *result = _PyCFunction_TrampolineCall(meth, args[0], NULL);
455 : 8500023 : _Py_LeaveRecursiveCallTstate(tstate);
456 : 8500023 : return result;
457 : : }
458 : :
459 : : static PyObject *
460 : 2974406 : method_vectorcall_O(
461 : : PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
462 : : {
463 : 2974406 : PyThreadState *tstate = _PyThreadState_GET();
464 : 2974406 : Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
465 [ + + ]: 2974406 : if (method_check_args(func, args, nargs, kwnames)) {
466 : 24 : return NULL;
467 : : }
468 [ + + ]: 2974382 : if (nargs != 2) {
469 : 2 : PyObject *funcstr = _PyObject_FunctionStr(func);
470 [ + - ]: 2 : if (funcstr != NULL) {
471 : 2 : PyErr_Format(PyExc_TypeError,
472 : : "%U takes exactly one argument (%zd given)",
473 : : funcstr, nargs-1);
474 : 2 : Py_DECREF(funcstr);
475 : : }
476 : 2 : return NULL;
477 : : }
478 : 2974380 : PyCFunction meth = (PyCFunction)method_enter_call(tstate, func);
479 [ + + ]: 2974380 : if (meth == NULL) {
480 : 4 : return NULL;
481 : : }
482 : 2974376 : PyObject *result = _PyCFunction_TrampolineCall(meth, args[0], args[1]);
483 : 2974366 : _Py_LeaveRecursiveCallTstate(tstate);
484 : 2974366 : return result;
485 : : }
486 : :
487 : :
488 : : /* Instances of classmethod_descriptor are unlikely to be called directly.
489 : : For one, the analogous class "classmethod" (for Python classes) is not
490 : : callable. Second, users are not likely to access a classmethod_descriptor
491 : : directly, since it means pulling it from the class __dict__.
492 : :
493 : : This is just an excuse to say that this doesn't need to be optimized:
494 : : we implement this simply by calling __get__ and then calling the result.
495 : : */
496 : : static PyObject *
497 : 5 : classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
498 : : PyObject *kwds)
499 : : {
500 : 5 : Py_ssize_t argc = PyTuple_GET_SIZE(args);
501 [ + + ]: 5 : if (argc < 1) {
502 : 1 : PyErr_Format(PyExc_TypeError,
503 : : "descriptor '%V' of '%.100s' "
504 : : "object needs an argument",
505 : : descr_name((PyDescrObject *)descr), "?",
506 : 1 : PyDescr_TYPE(descr)->tp_name);
507 : 1 : return NULL;
508 : : }
509 : 4 : PyObject *self = PyTuple_GET_ITEM(args, 0);
510 : 4 : PyObject *bound = classmethod_get(descr, NULL, self);
511 [ + + ]: 4 : if (bound == NULL) {
512 : 2 : return NULL;
513 : : }
514 : 2 : PyObject *res = PyObject_VectorcallDict(bound, _PyTuple_ITEMS(args)+1,
515 : 2 : argc-1, kwds);
516 : 2 : Py_DECREF(bound);
517 : 2 : return res;
518 : : }
519 : :
520 : : Py_LOCAL_INLINE(PyObject *)
521 : 14062051 : wrapperdescr_raw_call(PyWrapperDescrObject *descr, PyObject *self,
522 : : PyObject *args, PyObject *kwds)
523 : : {
524 : 14062051 : wrapperfunc wrapper = descr->d_base->wrapper;
525 : :
526 [ + + ]: 14062051 : if (descr->d_base->flags & PyWrapperFlag_KEYWORDS) {
527 : 5030262 : wrapperfunc_kwds wk = (wrapperfunc_kwds)(void(*)(void))wrapper;
528 : 5030262 : return (*wk)(self, args, descr->d_wrapped, kwds);
529 : : }
530 : :
531 [ + + + - : 9031789 : if (kwds != NULL && (!PyDict_Check(kwds) || PyDict_GET_SIZE(kwds) != 0)) {
- + ]
532 : 0 : PyErr_Format(PyExc_TypeError,
533 : : "wrapper %s() takes no keyword arguments",
534 : 0 : descr->d_base->name);
535 : 0 : return NULL;
536 : : }
537 : 9031789 : return (*wrapper)(self, args, descr->d_wrapped);
538 : : }
539 : :
540 : : static PyObject *
541 : 5156915 : wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)
542 : : {
543 : : Py_ssize_t argc;
544 : : PyObject *self, *result;
545 : :
546 : : /* Make sure that the first argument is acceptable as 'self' */
547 : : assert(PyTuple_Check(args));
548 : 5156915 : argc = PyTuple_GET_SIZE(args);
549 [ + + ]: 5156915 : if (argc < 1) {
550 : 3 : PyErr_Format(PyExc_TypeError,
551 : : "descriptor '%V' of '%.100s' "
552 : : "object needs an argument",
553 : : descr_name((PyDescrObject *)descr), "?",
554 : 3 : PyDescr_TYPE(descr)->tp_name);
555 : 3 : return NULL;
556 : : }
557 : 5156912 : self = PyTuple_GET_ITEM(args, 0);
558 [ + + ]: 5156912 : if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
559 : 5156912 : (PyObject *)PyDescr_TYPE(descr))) {
560 : 3 : PyErr_Format(PyExc_TypeError,
561 : : "descriptor '%V' "
562 : : "requires a '%.100s' object "
563 : : "but received a '%.100s'",
564 : : descr_name((PyDescrObject *)descr), "?",
565 : 3 : PyDescr_TYPE(descr)->tp_name,
566 : 3 : Py_TYPE(self)->tp_name);
567 : 3 : return NULL;
568 : : }
569 : :
570 : 5156909 : args = PyTuple_GetSlice(args, 1, argc);
571 [ - + ]: 5156909 : if (args == NULL) {
572 : 0 : return NULL;
573 : : }
574 : 5156909 : result = wrapperdescr_raw_call(descr, self, args, kwds);
575 : 5156909 : Py_DECREF(args);
576 : 5156909 : return result;
577 : : }
578 : :
579 : :
580 : : static PyObject *
581 : 2467 : method_get_doc(PyMethodDescrObject *descr, void *closure)
582 : : {
583 : 2467 : return _PyType_GetDocFromInternalDoc(descr->d_method->ml_name, descr->d_method->ml_doc);
584 : : }
585 : :
586 : : static PyObject *
587 : 314 : method_get_text_signature(PyMethodDescrObject *descr, void *closure)
588 : : {
589 : 314 : return _PyType_GetTextSignatureFromInternalDoc(descr->d_method->ml_name, descr->d_method->ml_doc);
590 : : }
591 : :
592 : : static PyObject *
593 : 205 : calculate_qualname(PyDescrObject *descr)
594 : : {
595 : : PyObject *type_qualname, *res;
596 : :
597 [ + - - + ]: 205 : if (descr->d_name == NULL || !PyUnicode_Check(descr->d_name)) {
598 : 0 : PyErr_SetString(PyExc_TypeError,
599 : : "<descriptor>.__name__ is not a unicode object");
600 : 0 : return NULL;
601 : : }
602 : :
603 : 205 : type_qualname = PyObject_GetAttr(
604 : 205 : (PyObject *)descr->d_type, &_Py_ID(__qualname__));
605 [ - + ]: 205 : if (type_qualname == NULL)
606 : 0 : return NULL;
607 : :
608 [ - + ]: 205 : if (!PyUnicode_Check(type_qualname)) {
609 : 0 : PyErr_SetString(PyExc_TypeError, "<descriptor>.__objclass__."
610 : : "__qualname__ is not a unicode object");
611 : 0 : Py_XDECREF(type_qualname);
612 : 0 : return NULL;
613 : : }
614 : :
615 : 205 : res = PyUnicode_FromFormat("%S.%S", type_qualname, descr->d_name);
616 : 205 : Py_DECREF(type_qualname);
617 : 205 : return res;
618 : : }
619 : :
620 : : static PyObject *
621 : 1067 : descr_get_qualname(PyDescrObject *descr, void *Py_UNUSED(ignored))
622 : : {
623 [ + + ]: 1067 : if (descr->d_qualname == NULL)
624 : 205 : descr->d_qualname = calculate_qualname(descr);
625 : 1067 : Py_XINCREF(descr->d_qualname);
626 : 1067 : return descr->d_qualname;
627 : : }
628 : :
629 : : static PyObject *
630 : 180 : descr_reduce(PyDescrObject *descr, PyObject *Py_UNUSED(ignored))
631 : : {
632 : 180 : return Py_BuildValue("N(OO)", _PyEval_GetBuiltin(&_Py_ID(getattr)),
633 : : PyDescr_TYPE(descr), PyDescr_NAME(descr));
634 : : }
635 : :
636 : : static PyMethodDef descr_methods[] = {
637 : : {"__reduce__", (PyCFunction)descr_reduce, METH_NOARGS, NULL},
638 : : {NULL, NULL}
639 : : };
640 : :
641 : : static PyMemberDef descr_members[] = {
642 : : {"__objclass__", T_OBJECT, offsetof(PyDescrObject, d_type), READONLY},
643 : : {"__name__", T_OBJECT, offsetof(PyDescrObject, d_name), READONLY},
644 : : {0}
645 : : };
646 : :
647 : : static PyGetSetDef method_getset[] = {
648 : : {"__doc__", (getter)method_get_doc},
649 : : {"__qualname__", (getter)descr_get_qualname},
650 : : {"__text_signature__", (getter)method_get_text_signature},
651 : : {0}
652 : : };
653 : :
654 : : static PyObject *
655 : 25 : member_get_doc(PyMemberDescrObject *descr, void *closure)
656 : : {
657 [ + + ]: 25 : if (descr->d_member->doc == NULL) {
658 : 18 : Py_RETURN_NONE;
659 : : }
660 : 7 : return PyUnicode_FromString(descr->d_member->doc);
661 : : }
662 : :
663 : : static PyGetSetDef member_getset[] = {
664 : : {"__doc__", (getter)member_get_doc},
665 : : {"__qualname__", (getter)descr_get_qualname},
666 : : {0}
667 : : };
668 : :
669 : : static PyObject *
670 : 121 : getset_get_doc(PyGetSetDescrObject *descr, void *closure)
671 : : {
672 [ + + ]: 121 : if (descr->d_getset->doc == NULL) {
673 : 21 : Py_RETURN_NONE;
674 : : }
675 : 100 : return PyUnicode_FromString(descr->d_getset->doc);
676 : : }
677 : :
678 : : static PyGetSetDef getset_getset[] = {
679 : : {"__doc__", (getter)getset_get_doc},
680 : : {"__qualname__", (getter)descr_get_qualname},
681 : : {0}
682 : : };
683 : :
684 : : static PyObject *
685 : 3072 : wrapperdescr_get_doc(PyWrapperDescrObject *descr, void *closure)
686 : : {
687 : 3072 : return _PyType_GetDocFromInternalDoc(descr->d_base->name, descr->d_base->doc);
688 : : }
689 : :
690 : : static PyObject *
691 : 836 : wrapperdescr_get_text_signature(PyWrapperDescrObject *descr, void *closure)
692 : : {
693 : 836 : return _PyType_GetTextSignatureFromInternalDoc(descr->d_base->name, descr->d_base->doc);
694 : : }
695 : :
696 : : static PyGetSetDef wrapperdescr_getset[] = {
697 : : {"__doc__", (getter)wrapperdescr_get_doc},
698 : : {"__qualname__", (getter)descr_get_qualname},
699 : : {"__text_signature__", (getter)wrapperdescr_get_text_signature},
700 : : {0}
701 : : };
702 : :
703 : : static int
704 : 183396823 : descr_traverse(PyObject *self, visitproc visit, void *arg)
705 : : {
706 : 183396823 : PyDescrObject *descr = (PyDescrObject *)self;
707 [ + - - + ]: 183396823 : Py_VISIT(descr->d_type);
708 : 183396823 : return 0;
709 : : }
710 : :
711 : : PyTypeObject PyMethodDescr_Type = {
712 : : PyVarObject_HEAD_INIT(&PyType_Type, 0)
713 : : "method_descriptor",
714 : : sizeof(PyMethodDescrObject),
715 : : 0,
716 : : (destructor)descr_dealloc, /* tp_dealloc */
717 : : offsetof(PyMethodDescrObject, vectorcall), /* tp_vectorcall_offset */
718 : : 0, /* tp_getattr */
719 : : 0, /* tp_setattr */
720 : : 0, /* tp_as_async */
721 : : (reprfunc)method_repr, /* tp_repr */
722 : : 0, /* tp_as_number */
723 : : 0, /* tp_as_sequence */
724 : : 0, /* tp_as_mapping */
725 : : 0, /* tp_hash */
726 : : PyVectorcall_Call, /* tp_call */
727 : : 0, /* tp_str */
728 : : PyObject_GenericGetAttr, /* tp_getattro */
729 : : 0, /* tp_setattro */
730 : : 0, /* tp_as_buffer */
731 : : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
732 : : Py_TPFLAGS_HAVE_VECTORCALL |
733 : : Py_TPFLAGS_METHOD_DESCRIPTOR, /* tp_flags */
734 : : 0, /* tp_doc */
735 : : descr_traverse, /* tp_traverse */
736 : : 0, /* tp_clear */
737 : : 0, /* tp_richcompare */
738 : : 0, /* tp_weaklistoffset */
739 : : 0, /* tp_iter */
740 : : 0, /* tp_iternext */
741 : : descr_methods, /* tp_methods */
742 : : descr_members, /* tp_members */
743 : : method_getset, /* tp_getset */
744 : : 0, /* tp_base */
745 : : 0, /* tp_dict */
746 : : (descrgetfunc)method_get, /* tp_descr_get */
747 : : 0, /* tp_descr_set */
748 : : };
749 : :
750 : : /* This is for METH_CLASS in C, not for "f = classmethod(f)" in Python! */
751 : : PyTypeObject PyClassMethodDescr_Type = {
752 : : PyVarObject_HEAD_INIT(&PyType_Type, 0)
753 : : "classmethod_descriptor",
754 : : sizeof(PyMethodDescrObject),
755 : : 0,
756 : : (destructor)descr_dealloc, /* tp_dealloc */
757 : : 0, /* tp_vectorcall_offset */
758 : : 0, /* tp_getattr */
759 : : 0, /* tp_setattr */
760 : : 0, /* tp_as_async */
761 : : (reprfunc)method_repr, /* tp_repr */
762 : : 0, /* tp_as_number */
763 : : 0, /* tp_as_sequence */
764 : : 0, /* tp_as_mapping */
765 : : 0, /* tp_hash */
766 : : (ternaryfunc)classmethoddescr_call, /* tp_call */
767 : : 0, /* tp_str */
768 : : PyObject_GenericGetAttr, /* tp_getattro */
769 : : 0, /* tp_setattro */
770 : : 0, /* tp_as_buffer */
771 : : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
772 : : 0, /* tp_doc */
773 : : descr_traverse, /* tp_traverse */
774 : : 0, /* tp_clear */
775 : : 0, /* tp_richcompare */
776 : : 0, /* tp_weaklistoffset */
777 : : 0, /* tp_iter */
778 : : 0, /* tp_iternext */
779 : : descr_methods, /* tp_methods */
780 : : descr_members, /* tp_members */
781 : : method_getset, /* tp_getset */
782 : : 0, /* tp_base */
783 : : 0, /* tp_dict */
784 : : (descrgetfunc)classmethod_get, /* tp_descr_get */
785 : : 0, /* tp_descr_set */
786 : : };
787 : :
788 : : PyTypeObject PyMemberDescr_Type = {
789 : : PyVarObject_HEAD_INIT(&PyType_Type, 0)
790 : : "member_descriptor",
791 : : sizeof(PyMemberDescrObject),
792 : : 0,
793 : : (destructor)descr_dealloc, /* tp_dealloc */
794 : : 0, /* tp_vectorcall_offset */
795 : : 0, /* tp_getattr */
796 : : 0, /* tp_setattr */
797 : : 0, /* tp_as_async */
798 : : (reprfunc)member_repr, /* tp_repr */
799 : : 0, /* tp_as_number */
800 : : 0, /* tp_as_sequence */
801 : : 0, /* tp_as_mapping */
802 : : 0, /* tp_hash */
803 : : 0, /* tp_call */
804 : : 0, /* tp_str */
805 : : PyObject_GenericGetAttr, /* tp_getattro */
806 : : 0, /* tp_setattro */
807 : : 0, /* tp_as_buffer */
808 : : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
809 : : 0, /* tp_doc */
810 : : descr_traverse, /* tp_traverse */
811 : : 0, /* tp_clear */
812 : : 0, /* tp_richcompare */
813 : : 0, /* tp_weaklistoffset */
814 : : 0, /* tp_iter */
815 : : 0, /* tp_iternext */
816 : : descr_methods, /* tp_methods */
817 : : descr_members, /* tp_members */
818 : : member_getset, /* tp_getset */
819 : : 0, /* tp_base */
820 : : 0, /* tp_dict */
821 : : (descrgetfunc)member_get, /* tp_descr_get */
822 : : (descrsetfunc)member_set, /* tp_descr_set */
823 : : };
824 : :
825 : : PyTypeObject PyGetSetDescr_Type = {
826 : : PyVarObject_HEAD_INIT(&PyType_Type, 0)
827 : : "getset_descriptor",
828 : : sizeof(PyGetSetDescrObject),
829 : : 0,
830 : : (destructor)descr_dealloc, /* tp_dealloc */
831 : : 0, /* tp_vectorcall_offset */
832 : : 0, /* tp_getattr */
833 : : 0, /* tp_setattr */
834 : : 0, /* tp_as_async */
835 : : (reprfunc)getset_repr, /* tp_repr */
836 : : 0, /* tp_as_number */
837 : : 0, /* tp_as_sequence */
838 : : 0, /* tp_as_mapping */
839 : : 0, /* tp_hash */
840 : : 0, /* tp_call */
841 : : 0, /* tp_str */
842 : : PyObject_GenericGetAttr, /* tp_getattro */
843 : : 0, /* tp_setattro */
844 : : 0, /* tp_as_buffer */
845 : : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
846 : : 0, /* tp_doc */
847 : : descr_traverse, /* tp_traverse */
848 : : 0, /* tp_clear */
849 : : 0, /* tp_richcompare */
850 : : 0, /* tp_weaklistoffset */
851 : : 0, /* tp_iter */
852 : : 0, /* tp_iternext */
853 : : 0, /* tp_methods */
854 : : descr_members, /* tp_members */
855 : : getset_getset, /* tp_getset */
856 : : 0, /* tp_base */
857 : : 0, /* tp_dict */
858 : : (descrgetfunc)getset_get, /* tp_descr_get */
859 : : (descrsetfunc)getset_set, /* tp_descr_set */
860 : : };
861 : :
862 : : PyTypeObject PyWrapperDescr_Type = {
863 : : PyVarObject_HEAD_INIT(&PyType_Type, 0)
864 : : "wrapper_descriptor",
865 : : sizeof(PyWrapperDescrObject),
866 : : 0,
867 : : (destructor)descr_dealloc, /* tp_dealloc */
868 : : 0, /* tp_vectorcall_offset */
869 : : 0, /* tp_getattr */
870 : : 0, /* tp_setattr */
871 : : 0, /* tp_as_async */
872 : : (reprfunc)wrapperdescr_repr, /* tp_repr */
873 : : 0, /* tp_as_number */
874 : : 0, /* tp_as_sequence */
875 : : 0, /* tp_as_mapping */
876 : : 0, /* tp_hash */
877 : : (ternaryfunc)wrapperdescr_call, /* tp_call */
878 : : 0, /* tp_str */
879 : : PyObject_GenericGetAttr, /* tp_getattro */
880 : : 0, /* tp_setattro */
881 : : 0, /* tp_as_buffer */
882 : : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
883 : : Py_TPFLAGS_METHOD_DESCRIPTOR, /* tp_flags */
884 : : 0, /* tp_doc */
885 : : descr_traverse, /* tp_traverse */
886 : : 0, /* tp_clear */
887 : : 0, /* tp_richcompare */
888 : : 0, /* tp_weaklistoffset */
889 : : 0, /* tp_iter */
890 : : 0, /* tp_iternext */
891 : : descr_methods, /* tp_methods */
892 : : descr_members, /* tp_members */
893 : : wrapperdescr_getset, /* tp_getset */
894 : : 0, /* tp_base */
895 : : 0, /* tp_dict */
896 : : (descrgetfunc)wrapperdescr_get, /* tp_descr_get */
897 : : 0, /* tp_descr_set */
898 : : };
899 : :
900 : : static PyDescrObject *
901 : 8228998 : descr_new(PyTypeObject *descrtype, PyTypeObject *type, const char *name)
902 : : {
903 : : PyDescrObject *descr;
904 : :
905 : 8228998 : descr = (PyDescrObject *)PyType_GenericAlloc(descrtype, 0);
906 [ + - ]: 8228998 : if (descr != NULL) {
907 : 8228998 : Py_XINCREF(type);
908 : 8228998 : descr->d_type = type;
909 : 8228998 : descr->d_name = PyUnicode_InternFromString(name);
910 [ - + ]: 8228998 : if (descr->d_name == NULL) {
911 : 0 : Py_DECREF(descr);
912 : 0 : descr = NULL;
913 : : }
914 : : else {
915 : 8228998 : descr->d_qualname = NULL;
916 : : }
917 : : }
918 : 8228998 : return descr;
919 : : }
920 : :
921 : : PyObject *
922 : 2267095 : PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method)
923 : : {
924 : : /* Figure out correct vectorcall function to use */
925 : : vectorcallfunc vectorcall;
926 [ + + + + : 2267095 : switch (method->ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS |
+ + + - ]
927 : : METH_O | METH_KEYWORDS | METH_METHOD))
928 : : {
929 : 215991 : case METH_VARARGS:
930 : 215991 : vectorcall = method_vectorcall_VARARGS;
931 : 215991 : break;
932 : 31154 : case METH_VARARGS | METH_KEYWORDS:
933 : 31154 : vectorcall = method_vectorcall_VARARGS_KEYWORDS;
934 : 31154 : break;
935 : 248937 : case METH_FASTCALL:
936 : 248937 : vectorcall = method_vectorcall_FASTCALL;
937 : 248937 : break;
938 : 127048 : case METH_FASTCALL | METH_KEYWORDS:
939 : 127048 : vectorcall = method_vectorcall_FASTCALL_KEYWORDS;
940 : 127048 : break;
941 : 1174876 : case METH_NOARGS:
942 : 1174876 : vectorcall = method_vectorcall_NOARGS;
943 : 1174876 : break;
944 : 416898 : case METH_O:
945 : 416898 : vectorcall = method_vectorcall_O;
946 : 416898 : break;
947 : 52191 : case METH_METHOD | METH_FASTCALL | METH_KEYWORDS:
948 : 52191 : vectorcall = method_vectorcall_FASTCALL_KEYWORDS_METHOD;
949 : 52191 : break;
950 : 0 : default:
951 : 0 : PyErr_Format(PyExc_SystemError,
952 : : "%s() method: bad call flags", method->ml_name);
953 : 0 : return NULL;
954 : : }
955 : :
956 : : PyMethodDescrObject *descr;
957 : :
958 : 2267095 : descr = (PyMethodDescrObject *)descr_new(&PyMethodDescr_Type,
959 : : type, method->ml_name);
960 [ + - ]: 2267095 : if (descr != NULL) {
961 : 2267095 : descr->d_method = method;
962 : 2267095 : descr->vectorcall = vectorcall;
963 : : }
964 : 2267095 : return (PyObject *)descr;
965 : : }
966 : :
967 : : PyObject *
968 : 96968 : PyDescr_NewClassMethod(PyTypeObject *type, PyMethodDef *method)
969 : : {
970 : : PyMethodDescrObject *descr;
971 : :
972 : 96968 : descr = (PyMethodDescrObject *)descr_new(&PyClassMethodDescr_Type,
973 : : type, method->ml_name);
974 [ + - ]: 96968 : if (descr != NULL)
975 : 96968 : descr->d_method = method;
976 : 96968 : return (PyObject *)descr;
977 : : }
978 : :
979 : : PyObject *
980 : 1030308 : PyDescr_NewMember(PyTypeObject *type, PyMemberDef *member)
981 : : {
982 : : PyMemberDescrObject *descr;
983 : :
984 : 1030308 : descr = (PyMemberDescrObject *)descr_new(&PyMemberDescr_Type,
985 : : type, member->name);
986 [ + - ]: 1030308 : if (descr != NULL)
987 : 1030308 : descr->d_member = member;
988 : 1030308 : return (PyObject *)descr;
989 : : }
990 : :
991 : : PyObject *
992 : 1404280 : PyDescr_NewGetSet(PyTypeObject *type, PyGetSetDef *getset)
993 : : {
994 : : PyGetSetDescrObject *descr;
995 : :
996 : 1404280 : descr = (PyGetSetDescrObject *)descr_new(&PyGetSetDescr_Type,
997 : : type, getset->name);
998 [ + - ]: 1404280 : if (descr != NULL)
999 : 1404280 : descr->d_getset = getset;
1000 : 1404280 : return (PyObject *)descr;
1001 : : }
1002 : :
1003 : : PyObject *
1004 : 3430347 : PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *base, void *wrapped)
1005 : : {
1006 : : PyWrapperDescrObject *descr;
1007 : :
1008 : 3430347 : descr = (PyWrapperDescrObject *)descr_new(&PyWrapperDescr_Type,
1009 : : type, base->name);
1010 [ + - ]: 3430347 : if (descr != NULL) {
1011 : 3430347 : descr->d_base = base;
1012 : 3430347 : descr->d_wrapped = wrapped;
1013 : : }
1014 : 3430347 : return (PyObject *)descr;
1015 : : }
1016 : :
1017 : : int
1018 : 89011205 : PyDescr_IsData(PyObject *ob)
1019 : : {
1020 : 89011205 : return Py_TYPE(ob)->tp_descr_set != NULL;
1021 : : }
1022 : :
1023 : : /* --- mappingproxy: read-only proxy for mappings --- */
1024 : :
1025 : : /* This has no reason to be in this file except that adding new files is a
1026 : : bit of a pain */
1027 : :
1028 : : typedef struct {
1029 : : PyObject_HEAD
1030 : : PyObject *mapping;
1031 : : } mappingproxyobject;
1032 : :
1033 : : static Py_ssize_t
1034 : 6788 : mappingproxy_len(mappingproxyobject *pp)
1035 : : {
1036 : 6788 : return PyObject_Size(pp->mapping);
1037 : : }
1038 : :
1039 : : static PyObject *
1040 : 2093945 : mappingproxy_getitem(mappingproxyobject *pp, PyObject *key)
1041 : : {
1042 : 2093945 : return PyObject_GetItem(pp->mapping, key);
1043 : : }
1044 : :
1045 : : static PyMappingMethods mappingproxy_as_mapping = {
1046 : : (lenfunc)mappingproxy_len, /* mp_length */
1047 : : (binaryfunc)mappingproxy_getitem, /* mp_subscript */
1048 : : 0, /* mp_ass_subscript */
1049 : : };
1050 : :
1051 : : static PyObject *
1052 : 4 : mappingproxy_or(PyObject *left, PyObject *right)
1053 : : {
1054 [ + + ]: 4 : if (PyObject_TypeCheck(left, &PyDictProxy_Type)) {
1055 : 2 : left = ((mappingproxyobject*)left)->mapping;
1056 : : }
1057 [ + + ]: 4 : if (PyObject_TypeCheck(right, &PyDictProxy_Type)) {
1058 : 2 : right = ((mappingproxyobject*)right)->mapping;
1059 : : }
1060 : 4 : return PyNumber_Or(left, right);
1061 : : }
1062 : :
1063 : : static PyObject *
1064 : 1 : mappingproxy_ior(PyObject *self, PyObject *Py_UNUSED(other))
1065 : : {
1066 : 1 : return PyErr_Format(PyExc_TypeError,
1067 : 1 : "'|=' is not supported by %s; use '|' instead", Py_TYPE(self)->tp_name);
1068 : : }
1069 : :
1070 : : static PyNumberMethods mappingproxy_as_number = {
1071 : : .nb_or = mappingproxy_or,
1072 : : .nb_inplace_or = mappingproxy_ior,
1073 : : };
1074 : :
1075 : : static int
1076 : 341530 : mappingproxy_contains(mappingproxyobject *pp, PyObject *key)
1077 : : {
1078 [ + + ]: 341530 : if (PyDict_CheckExact(pp->mapping))
1079 : 341521 : return PyDict_Contains(pp->mapping, key);
1080 : : else
1081 : 9 : return PySequence_Contains(pp->mapping, key);
1082 : : }
1083 : :
1084 : : static PySequenceMethods mappingproxy_as_sequence = {
1085 : : 0, /* sq_length */
1086 : : 0, /* sq_concat */
1087 : : 0, /* sq_repeat */
1088 : : 0, /* sq_item */
1089 : : 0, /* sq_slice */
1090 : : 0, /* sq_ass_item */
1091 : : 0, /* sq_ass_slice */
1092 : : (objobjproc)mappingproxy_contains, /* sq_contains */
1093 : : 0, /* sq_inplace_concat */
1094 : : 0, /* sq_inplace_repeat */
1095 : : };
1096 : :
1097 : : static PyObject *
1098 : 563738 : mappingproxy_get(mappingproxyobject *pp, PyObject *const *args, Py_ssize_t nargs)
1099 : : {
1100 : : /* newargs: mapping, key, default=None */
1101 : : PyObject *newargs[3];
1102 : 563738 : newargs[0] = pp->mapping;
1103 : 563738 : newargs[2] = Py_None;
1104 : :
1105 [ - + ]: 563738 : if (!_PyArg_UnpackStack(args, nargs, "get", 1, 2,
1106 : : &newargs[1], &newargs[2]))
1107 : : {
1108 : 0 : return NULL;
1109 : : }
1110 : 563738 : return _PyObject_VectorcallMethod(&_Py_ID(get), newargs,
1111 : : 3 | PY_VECTORCALL_ARGUMENTS_OFFSET,
1112 : : NULL);
1113 : : }
1114 : :
1115 : : static PyObject *
1116 : 95922 : mappingproxy_keys(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
1117 : : {
1118 : 95922 : return PyObject_CallMethodNoArgs(pp->mapping, &_Py_ID(keys));
1119 : : }
1120 : :
1121 : : static PyObject *
1122 : 15037 : mappingproxy_values(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
1123 : : {
1124 : 15037 : return PyObject_CallMethodNoArgs(pp->mapping, &_Py_ID(values));
1125 : : }
1126 : :
1127 : : static PyObject *
1128 : 199131 : mappingproxy_items(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
1129 : : {
1130 : 199131 : return PyObject_CallMethodNoArgs(pp->mapping, &_Py_ID(items));
1131 : : }
1132 : :
1133 : : static PyObject *
1134 : 18 : mappingproxy_copy(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
1135 : : {
1136 : 18 : return PyObject_CallMethodNoArgs(pp->mapping, &_Py_ID(copy));
1137 : : }
1138 : :
1139 : : static PyObject *
1140 : 1 : mappingproxy_reversed(mappingproxyobject *pp, PyObject *Py_UNUSED(ignored))
1141 : : {
1142 : 1 : return PyObject_CallMethodNoArgs(pp->mapping, &_Py_ID(__reversed__));
1143 : : }
1144 : :
1145 : : /* WARNING: mappingproxy methods must not give access
1146 : : to the underlying mapping */
1147 : :
1148 : : static PyMethodDef mappingproxy_methods[] = {
1149 : : {"get", _PyCFunction_CAST(mappingproxy_get), METH_FASTCALL,
1150 : : PyDoc_STR("D.get(k[,d]) -> D[k] if k in D, else d."
1151 : : " d defaults to None.")},
1152 : : {"keys", (PyCFunction)mappingproxy_keys, METH_NOARGS,
1153 : : PyDoc_STR("D.keys() -> a set-like object providing a view on D's keys")},
1154 : : {"values", (PyCFunction)mappingproxy_values, METH_NOARGS,
1155 : : PyDoc_STR("D.values() -> an object providing a view on D's values")},
1156 : : {"items", (PyCFunction)mappingproxy_items, METH_NOARGS,
1157 : : PyDoc_STR("D.items() -> a set-like object providing a view on D's items")},
1158 : : {"copy", (PyCFunction)mappingproxy_copy, METH_NOARGS,
1159 : : PyDoc_STR("D.copy() -> a shallow copy of D")},
1160 : : {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS,
1161 : : PyDoc_STR("See PEP 585")},
1162 : : {"__reversed__", (PyCFunction)mappingproxy_reversed, METH_NOARGS,
1163 : : PyDoc_STR("D.__reversed__() -> reverse iterator")},
1164 : : {0}
1165 : : };
1166 : :
1167 : : static void
1168 : 1365456 : mappingproxy_dealloc(mappingproxyobject *pp)
1169 : : {
1170 : 1365456 : _PyObject_GC_UNTRACK(pp);
1171 : 1365456 : Py_DECREF(pp->mapping);
1172 : 1365456 : PyObject_GC_Del(pp);
1173 : 1365456 : }
1174 : :
1175 : : static PyObject *
1176 : 9071 : mappingproxy_getiter(mappingproxyobject *pp)
1177 : : {
1178 : 9071 : return PyObject_GetIter(pp->mapping);
1179 : : }
1180 : :
1181 : : static Py_hash_t
1182 : 2 : mappingproxy_hash(mappingproxyobject *pp)
1183 : : {
1184 : 2 : return PyObject_Hash(pp->mapping);
1185 : : }
1186 : :
1187 : : static PyObject *
1188 : 0 : mappingproxy_str(mappingproxyobject *pp)
1189 : : {
1190 : 0 : return PyObject_Str(pp->mapping);
1191 : : }
1192 : :
1193 : : static PyObject *
1194 : 9 : mappingproxy_repr(mappingproxyobject *pp)
1195 : : {
1196 : 9 : return PyUnicode_FromFormat("mappingproxy(%R)", pp->mapping);
1197 : : }
1198 : :
1199 : : static int
1200 : 76615 : mappingproxy_traverse(PyObject *self, visitproc visit, void *arg)
1201 : : {
1202 : 76615 : mappingproxyobject *pp = (mappingproxyobject *)self;
1203 [ + - - + ]: 76615 : Py_VISIT(pp->mapping);
1204 : 76615 : return 0;
1205 : : }
1206 : :
1207 : : static PyObject *
1208 : 133 : mappingproxy_richcompare(mappingproxyobject *v, PyObject *w, int op)
1209 : : {
1210 : 133 : return PyObject_RichCompare(v->mapping, w, op);
1211 : : }
1212 : :
1213 : : static int
1214 : 1365463 : mappingproxy_check_mapping(PyObject *mapping)
1215 : : {
1216 [ + + ]: 1365463 : if (!PyMapping_Check(mapping)
1217 [ + + ]: 1365461 : || PyList_Check(mapping)
1218 [ + + ]: 1365460 : || PyTuple_Check(mapping)) {
1219 : 4 : PyErr_Format(PyExc_TypeError,
1220 : : "mappingproxy() argument must be a mapping, not %s",
1221 : 4 : Py_TYPE(mapping)->tp_name);
1222 : 4 : return -1;
1223 : : }
1224 : 1365459 : return 0;
1225 : : }
1226 : :
1227 : : /*[clinic input]
1228 : : @classmethod
1229 : : mappingproxy.__new__ as mappingproxy_new
1230 : :
1231 : : mapping: object
1232 : :
1233 : : [clinic start generated code]*/
1234 : :
1235 : : static PyObject *
1236 : 27644 : mappingproxy_new_impl(PyTypeObject *type, PyObject *mapping)
1237 : : /*[clinic end generated code: output=65f27f02d5b68fa7 input=d2d620d4f598d4f8]*/
1238 : : {
1239 : : mappingproxyobject *mappingproxy;
1240 : :
1241 [ + + ]: 27644 : if (mappingproxy_check_mapping(mapping) == -1)
1242 : 4 : return NULL;
1243 : :
1244 : 27640 : mappingproxy = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type);
1245 [ - + ]: 27640 : if (mappingproxy == NULL)
1246 : 0 : return NULL;
1247 : 27640 : Py_INCREF(mapping);
1248 : 27640 : mappingproxy->mapping = mapping;
1249 : 27640 : _PyObject_GC_TRACK(mappingproxy);
1250 : 27640 : return (PyObject *)mappingproxy;
1251 : : }
1252 : :
1253 : : PyObject *
1254 : 1337819 : PyDictProxy_New(PyObject *mapping)
1255 : : {
1256 : : mappingproxyobject *pp;
1257 : :
1258 [ - + ]: 1337819 : if (mappingproxy_check_mapping(mapping) == -1)
1259 : 0 : return NULL;
1260 : :
1261 : 1337819 : pp = PyObject_GC_New(mappingproxyobject, &PyDictProxy_Type);
1262 [ + - ]: 1337819 : if (pp != NULL) {
1263 : 1337819 : Py_INCREF(mapping);
1264 : 1337819 : pp->mapping = mapping;
1265 : 1337819 : _PyObject_GC_TRACK(pp);
1266 : : }
1267 : 1337819 : return (PyObject *)pp;
1268 : : }
1269 : :
1270 : :
1271 : : /* --- Wrapper object for "slot" methods --- */
1272 : :
1273 : : /* This has no reason to be in this file except that adding new files is a
1274 : : bit of a pain */
1275 : :
1276 : : typedef struct {
1277 : : PyObject_HEAD
1278 : : PyWrapperDescrObject *descr;
1279 : : PyObject *self;
1280 : : } wrapperobject;
1281 : :
1282 : : #define Wrapper_Check(v) Py_IS_TYPE(v, &_PyMethodWrapper_Type)
1283 : :
1284 : : static void
1285 : 7928725 : wrapper_dealloc(wrapperobject *wp)
1286 : : {
1287 : 7928725 : PyObject_GC_UnTrack(wp);
1288 [ + - + + ]: 7928725 : Py_TRASHCAN_BEGIN(wp, wrapper_dealloc)
1289 : 7908317 : Py_XDECREF(wp->descr);
1290 : 7908317 : Py_XDECREF(wp->self);
1291 : 7908317 : PyObject_GC_Del(wp);
1292 [ + - ]: 7908317 : Py_TRASHCAN_END
1293 : 7928725 : }
1294 : :
1295 : : static PyObject *
1296 : 14 : wrapper_richcompare(PyObject *a, PyObject *b, int op)
1297 : : {
1298 : : wrapperobject *wa, *wb;
1299 : : int eq;
1300 : :
1301 : : assert(a != NULL && b != NULL);
1302 : :
1303 : : /* both arguments should be wrapperobjects */
1304 [ + + + + ]: 14 : if ((op != Py_EQ && op != Py_NE)
1305 [ + - - + ]: 6 : || !Wrapper_Check(a) || !Wrapper_Check(b))
1306 : : {
1307 : 8 : Py_RETURN_NOTIMPLEMENTED;
1308 : : }
1309 : :
1310 : 6 : wa = (wrapperobject *)a;
1311 : 6 : wb = (wrapperobject *)b;
1312 [ + + + + ]: 6 : eq = (wa->descr == wb->descr && wa->self == wb->self);
1313 [ + + ]: 6 : if (eq == (op == Py_EQ)) {
1314 : 3 : Py_RETURN_TRUE;
1315 : : }
1316 : : else {
1317 : 3 : Py_RETURN_FALSE;
1318 : : }
1319 : : }
1320 : :
1321 : : static Py_hash_t
1322 : 1 : wrapper_hash(wrapperobject *wp)
1323 : : {
1324 : : Py_hash_t x, y;
1325 : 1 : x = _Py_HashPointer(wp->self);
1326 : 1 : y = _Py_HashPointer(wp->descr);
1327 : 1 : x = x ^ y;
1328 [ - + ]: 1 : if (x == -1)
1329 : 0 : x = -2;
1330 : 1 : return x;
1331 : : }
1332 : :
1333 : : static PyObject *
1334 : 34 : wrapper_repr(wrapperobject *wp)
1335 : : {
1336 : 102 : return PyUnicode_FromFormat("<method-wrapper '%s' of %s object at %p>",
1337 : 34 : wp->descr->d_base->name,
1338 : 34 : Py_TYPE(wp->self)->tp_name,
1339 : : wp->self);
1340 : : }
1341 : :
1342 : : static PyObject *
1343 : 36 : wrapper_reduce(wrapperobject *wp, PyObject *Py_UNUSED(ignored))
1344 : : {
1345 : 36 : return Py_BuildValue("N(OO)", _PyEval_GetBuiltin(&_Py_ID(getattr)),
1346 : 36 : wp->self, PyDescr_NAME(wp->descr));
1347 : : }
1348 : :
1349 : : static PyMethodDef wrapper_methods[] = {
1350 : : {"__reduce__", (PyCFunction)wrapper_reduce, METH_NOARGS, NULL},
1351 : : {NULL, NULL}
1352 : : };
1353 : :
1354 : : static PyMemberDef wrapper_members[] = {
1355 : : {"__self__", T_OBJECT, offsetof(wrapperobject, self), READONLY},
1356 : : {0}
1357 : : };
1358 : :
1359 : : static PyObject *
1360 : 1 : wrapper_objclass(wrapperobject *wp, void *Py_UNUSED(ignored))
1361 : : {
1362 : 1 : PyObject *c = (PyObject *)PyDescr_TYPE(wp->descr);
1363 : :
1364 : 1 : Py_INCREF(c);
1365 : 1 : return c;
1366 : : }
1367 : :
1368 : : static PyObject *
1369 : 138148 : wrapper_name(wrapperobject *wp, void *Py_UNUSED(ignored))
1370 : : {
1371 : 138148 : const char *s = wp->descr->d_base->name;
1372 : :
1373 : 138148 : return PyUnicode_FromString(s);
1374 : : }
1375 : :
1376 : : static PyObject *
1377 : 164 : wrapper_doc(wrapperobject *wp, void *Py_UNUSED(ignored))
1378 : : {
1379 : 164 : return _PyType_GetDocFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc);
1380 : : }
1381 : :
1382 : : static PyObject *
1383 : 531 : wrapper_text_signature(wrapperobject *wp, void *Py_UNUSED(ignored))
1384 : : {
1385 : 531 : return _PyType_GetTextSignatureFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc);
1386 : : }
1387 : :
1388 : : static PyObject *
1389 : 0 : wrapper_qualname(wrapperobject *wp, void *Py_UNUSED(ignored))
1390 : : {
1391 : 0 : return descr_get_qualname((PyDescrObject *)wp->descr, NULL);
1392 : : }
1393 : :
1394 : : static PyGetSetDef wrapper_getsets[] = {
1395 : : {"__objclass__", (getter)wrapper_objclass},
1396 : : {"__name__", (getter)wrapper_name},
1397 : : {"__qualname__", (getter)wrapper_qualname},
1398 : : {"__doc__", (getter)wrapper_doc},
1399 : : {"__text_signature__", (getter)wrapper_text_signature},
1400 : : {0}
1401 : : };
1402 : :
1403 : : static PyObject *
1404 : 8905142 : wrapper_call(wrapperobject *wp, PyObject *args, PyObject *kwds)
1405 : : {
1406 : 8905142 : return wrapperdescr_raw_call(wp->descr, wp->self, args, kwds);
1407 : : }
1408 : :
1409 : : static int
1410 : 11342500 : wrapper_traverse(PyObject *self, visitproc visit, void *arg)
1411 : : {
1412 : 11342500 : wrapperobject *wp = (wrapperobject *)self;
1413 [ + - - + ]: 11342500 : Py_VISIT(wp->descr);
1414 [ + - - + ]: 11342500 : Py_VISIT(wp->self);
1415 : 11342500 : return 0;
1416 : : }
1417 : :
1418 : : PyTypeObject _PyMethodWrapper_Type = {
1419 : : PyVarObject_HEAD_INIT(&PyType_Type, 0)
1420 : : "method-wrapper", /* tp_name */
1421 : : sizeof(wrapperobject), /* tp_basicsize */
1422 : : 0, /* tp_itemsize */
1423 : : /* methods */
1424 : : (destructor)wrapper_dealloc, /* tp_dealloc */
1425 : : 0, /* tp_vectorcall_offset */
1426 : : 0, /* tp_getattr */
1427 : : 0, /* tp_setattr */
1428 : : 0, /* tp_as_async */
1429 : : (reprfunc)wrapper_repr, /* tp_repr */
1430 : : 0, /* tp_as_number */
1431 : : 0, /* tp_as_sequence */
1432 : : 0, /* tp_as_mapping */
1433 : : (hashfunc)wrapper_hash, /* tp_hash */
1434 : : (ternaryfunc)wrapper_call, /* tp_call */
1435 : : 0, /* tp_str */
1436 : : PyObject_GenericGetAttr, /* tp_getattro */
1437 : : 0, /* tp_setattro */
1438 : : 0, /* tp_as_buffer */
1439 : : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
1440 : : 0, /* tp_doc */
1441 : : wrapper_traverse, /* tp_traverse */
1442 : : 0, /* tp_clear */
1443 : : wrapper_richcompare, /* tp_richcompare */
1444 : : 0, /* tp_weaklistoffset */
1445 : : 0, /* tp_iter */
1446 : : 0, /* tp_iternext */
1447 : : wrapper_methods, /* tp_methods */
1448 : : wrapper_members, /* tp_members */
1449 : : wrapper_getsets, /* tp_getset */
1450 : : 0, /* tp_base */
1451 : : 0, /* tp_dict */
1452 : : 0, /* tp_descr_get */
1453 : : 0, /* tp_descr_set */
1454 : : };
1455 : :
1456 : : PyObject *
1457 : 7908321 : PyWrapper_New(PyObject *d, PyObject *self)
1458 : : {
1459 : : wrapperobject *wp;
1460 : : PyWrapperDescrObject *descr;
1461 : :
1462 : : assert(PyObject_TypeCheck(d, &PyWrapperDescr_Type));
1463 : 7908321 : descr = (PyWrapperDescrObject *)d;
1464 : : assert(_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
1465 : : (PyObject *)PyDescr_TYPE(descr)));
1466 : :
1467 : 7908321 : wp = PyObject_GC_New(wrapperobject, &_PyMethodWrapper_Type);
1468 [ + - ]: 7908321 : if (wp != NULL) {
1469 : 7908321 : Py_INCREF(descr);
1470 : 7908321 : wp->descr = descr;
1471 : 7908321 : Py_INCREF(self);
1472 : 7908321 : wp->self = self;
1473 : 7908321 : _PyObject_GC_TRACK(wp);
1474 : : }
1475 : 7908321 : return (PyObject *)wp;
1476 : : }
1477 : :
1478 : :
1479 : : /* A built-in 'property' type */
1480 : :
1481 : : /*
1482 : : class property(object):
1483 : :
1484 : : def __init__(self, fget=None, fset=None, fdel=None, doc=None):
1485 : : if doc is None and fget is not None and hasattr(fget, "__doc__"):
1486 : : doc = fget.__doc__
1487 : : self.__get = fget
1488 : : self.__set = fset
1489 : : self.__del = fdel
1490 : : self.__doc__ = doc
1491 : :
1492 : : def __get__(self, inst, type=None):
1493 : : if inst is None:
1494 : : return self
1495 : : if self.__get is None:
1496 : : raise AttributeError, "property has no getter"
1497 : : return self.__get(inst)
1498 : :
1499 : : def __set__(self, inst, value):
1500 : : if self.__set is None:
1501 : : raise AttributeError, "property has no setter"
1502 : : return self.__set(inst, value)
1503 : :
1504 : : def __delete__(self, inst):
1505 : : if self.__del is None:
1506 : : raise AttributeError, "property has no deleter"
1507 : : return self.__del(inst)
1508 : :
1509 : : */
1510 : :
1511 : : static PyObject * property_copy(PyObject *, PyObject *, PyObject *,
1512 : : PyObject *);
1513 : :
1514 : : static PyMemberDef property_members[] = {
1515 : : {"fget", T_OBJECT, offsetof(propertyobject, prop_get), READONLY},
1516 : : {"fset", T_OBJECT, offsetof(propertyobject, prop_set), READONLY},
1517 : : {"fdel", T_OBJECT, offsetof(propertyobject, prop_del), READONLY},
1518 : : {"__doc__", T_OBJECT, offsetof(propertyobject, prop_doc), 0},
1519 : : {0}
1520 : : };
1521 : :
1522 : :
1523 : : PyDoc_STRVAR(getter_doc,
1524 : : "Descriptor to obtain a copy of the property with a different getter.");
1525 : :
1526 : : static PyObject *
1527 : 16 : property_getter(PyObject *self, PyObject *getter)
1528 : : {
1529 : 16 : return property_copy(self, getter, NULL, NULL);
1530 : : }
1531 : :
1532 : :
1533 : : PyDoc_STRVAR(setter_doc,
1534 : : "Descriptor to obtain a copy of the property with a different setter.");
1535 : :
1536 : : static PyObject *
1537 : 24982 : property_setter(PyObject *self, PyObject *setter)
1538 : : {
1539 : 24982 : return property_copy(self, NULL, setter, NULL);
1540 : : }
1541 : :
1542 : :
1543 : : PyDoc_STRVAR(deleter_doc,
1544 : : "Descriptor to obtain a copy of the property with a different deleter.");
1545 : :
1546 : : static PyObject *
1547 : 79 : property_deleter(PyObject *self, PyObject *deleter)
1548 : : {
1549 : 79 : return property_copy(self, NULL, NULL, deleter);
1550 : : }
1551 : :
1552 : :
1553 : : PyDoc_STRVAR(set_name_doc,
1554 : : "Method to set name of a property.");
1555 : :
1556 : : static PyObject *
1557 : 161873 : property_set_name(PyObject *self, PyObject *args) {
1558 [ + + ]: 161873 : if (PyTuple_GET_SIZE(args) != 2) {
1559 : 3 : PyErr_Format(
1560 : : PyExc_TypeError,
1561 : : "__set_name__() takes 2 positional arguments but %d were given",
1562 : : PyTuple_GET_SIZE(args));
1563 : 3 : return NULL;
1564 : : }
1565 : :
1566 : 161870 : propertyobject *prop = (propertyobject *)self;
1567 : 161870 : PyObject *name = PyTuple_GET_ITEM(args, 1);
1568 : :
1569 : 161870 : Py_XINCREF(name);
1570 : 161870 : Py_XSETREF(prop->prop_name, name);
1571 : :
1572 : 161870 : Py_RETURN_NONE;
1573 : : }
1574 : :
1575 : : static PyMethodDef property_methods[] = {
1576 : : {"getter", property_getter, METH_O, getter_doc},
1577 : : {"setter", property_setter, METH_O, setter_doc},
1578 : : {"deleter", property_deleter, METH_O, deleter_doc},
1579 : : {"__set_name__", property_set_name, METH_VARARGS, set_name_doc},
1580 : : {0}
1581 : : };
1582 : :
1583 : :
1584 : : static void
1585 : 178472 : property_dealloc(PyObject *self)
1586 : : {
1587 : 178472 : propertyobject *gs = (propertyobject *)self;
1588 : :
1589 : 178472 : _PyObject_GC_UNTRACK(self);
1590 : 178472 : Py_XDECREF(gs->prop_get);
1591 : 178472 : Py_XDECREF(gs->prop_set);
1592 : 178472 : Py_XDECREF(gs->prop_del);
1593 : 178472 : Py_XDECREF(gs->prop_doc);
1594 : 178472 : Py_XDECREF(gs->prop_name);
1595 : 178472 : Py_TYPE(self)->tp_free(self);
1596 : 178472 : }
1597 : :
1598 : : static PyObject *
1599 : 634749 : property_descr_get(PyObject *self, PyObject *obj, PyObject *type)
1600 : : {
1601 [ + + - + ]: 634749 : if (obj == NULL || obj == Py_None) {
1602 : 2251 : Py_INCREF(self);
1603 : 2251 : return self;
1604 : : }
1605 : :
1606 : 632498 : propertyobject *gs = (propertyobject *)self;
1607 [ + + ]: 632498 : if (gs->prop_get == NULL) {
1608 : 2 : PyObject *qualname = PyType_GetQualName(Py_TYPE(obj));
1609 [ + + + - ]: 2 : if (gs->prop_name != NULL && qualname != NULL) {
1610 : 1 : PyErr_Format(PyExc_AttributeError,
1611 : : "property %R of %R object has no getter",
1612 : : gs->prop_name,
1613 : : qualname);
1614 : : }
1615 [ + - ]: 1 : else if (qualname != NULL) {
1616 : 1 : PyErr_Format(PyExc_AttributeError,
1617 : : "property of %R object has no getter",
1618 : : qualname);
1619 : : } else {
1620 : 0 : PyErr_SetString(PyExc_AttributeError,
1621 : : "property has no getter");
1622 : : }
1623 : 2 : Py_XDECREF(qualname);
1624 : 2 : return NULL;
1625 : : }
1626 : :
1627 : 632496 : return PyObject_CallOneArg(gs->prop_get, obj);
1628 : : }
1629 : :
1630 : : static int
1631 : 78555 : property_descr_set(PyObject *self, PyObject *obj, PyObject *value)
1632 : : {
1633 : 78555 : propertyobject *gs = (propertyobject *)self;
1634 : : PyObject *func, *res;
1635 : :
1636 [ + + ]: 78555 : if (value == NULL) {
1637 : 17 : func = gs->prop_del;
1638 : : }
1639 : : else {
1640 : 78538 : func = gs->prop_set;
1641 : : }
1642 : :
1643 [ + + ]: 78555 : if (func == NULL) {
1644 : 104 : PyObject *qualname = NULL;
1645 [ + - ]: 104 : if (obj != NULL) {
1646 : 104 : qualname = PyType_GetQualName(Py_TYPE(obj));
1647 : : }
1648 [ + + + - ]: 104 : if (gs->prop_name != NULL && qualname != NULL) {
1649 [ + + ]: 102 : PyErr_Format(PyExc_AttributeError,
1650 : : value == NULL ?
1651 : : "property %R of %R object has no deleter" :
1652 : : "property %R of %R object has no setter",
1653 : : gs->prop_name,
1654 : : qualname);
1655 : : }
1656 [ + - ]: 2 : else if (qualname != NULL) {
1657 [ + + ]: 2 : PyErr_Format(PyExc_AttributeError,
1658 : : value == NULL ?
1659 : : "property of %R object has no deleter" :
1660 : : "property of %R object has no setter",
1661 : : qualname);
1662 : : }
1663 : : else {
1664 [ # # ]: 0 : PyErr_SetString(PyExc_AttributeError,
1665 : : value == NULL ?
1666 : : "property has no deleter" :
1667 : : "property has no setter");
1668 : : }
1669 : 104 : Py_XDECREF(qualname);
1670 : 104 : return -1;
1671 : : }
1672 : :
1673 [ + + ]: 78451 : if (value == NULL) {
1674 : 15 : res = PyObject_CallOneArg(func, obj);
1675 : : }
1676 : : else {
1677 : : EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_API, func);
1678 : 78436 : PyObject *args[] = { obj, value };
1679 : 78436 : res = PyObject_Vectorcall(func, args, 2, NULL);
1680 : : }
1681 : :
1682 [ + + ]: 78451 : if (res == NULL) {
1683 : 29 : return -1;
1684 : : }
1685 : :
1686 : 78422 : Py_DECREF(res);
1687 : 78422 : return 0;
1688 : : }
1689 : :
1690 : : static PyObject *
1691 : 25077 : property_copy(PyObject *old, PyObject *get, PyObject *set, PyObject *del)
1692 : : {
1693 : 25077 : propertyobject *pold = (propertyobject *)old;
1694 : : PyObject *new, *type, *doc;
1695 : :
1696 : 25077 : type = PyObject_Type(old);
1697 [ - + ]: 25077 : if (type == NULL)
1698 : 0 : return NULL;
1699 : :
1700 [ + + - + ]: 25077 : if (get == NULL || get == Py_None) {
1701 : 25061 : Py_XDECREF(get);
1702 [ + - ]: 25061 : get = pold->prop_get ? pold->prop_get : Py_None;
1703 : : }
1704 [ + + - + ]: 25077 : if (set == NULL || set == Py_None) {
1705 : 95 : Py_XDECREF(set);
1706 [ + + ]: 95 : set = pold->prop_set ? pold->prop_set : Py_None;
1707 : : }
1708 [ + + - + ]: 25077 : if (del == NULL || del == Py_None) {
1709 : 24998 : Py_XDECREF(del);
1710 [ + + ]: 24998 : del = pold->prop_del ? pold->prop_del : Py_None;
1711 : : }
1712 [ + + + - ]: 25077 : if (pold->getter_doc && get != Py_None) {
1713 : : /* make _init use __doc__ from getter */
1714 : 9327 : doc = Py_None;
1715 : : }
1716 : : else {
1717 [ + + ]: 15750 : doc = pold->prop_doc ? pold->prop_doc : Py_None;
1718 : : }
1719 : :
1720 : 25077 : new = PyObject_CallFunctionObjArgs(type, get, set, del, doc, NULL);
1721 : 25077 : Py_DECREF(type);
1722 [ - + ]: 25077 : if (new == NULL)
1723 : 0 : return NULL;
1724 : :
1725 : 25077 : Py_XINCREF(pold->prop_name);
1726 : 25077 : Py_XSETREF(((propertyobject *) new)->prop_name, pold->prop_name);
1727 : 25077 : return new;
1728 : : }
1729 : :
1730 : : /*[clinic input]
1731 : : property.__init__ as property_init
1732 : :
1733 : : fget: object(c_default="NULL") = None
1734 : : function to be used for getting an attribute value
1735 : : fset: object(c_default="NULL") = None
1736 : : function to be used for setting an attribute value
1737 : : fdel: object(c_default="NULL") = None
1738 : : function to be used for del'ing an attribute
1739 : : doc: object(c_default="NULL") = None
1740 : : docstring
1741 : :
1742 : : Property attribute.
1743 : :
1744 : : Typical use is to define a managed attribute x:
1745 : :
1746 : : class C(object):
1747 : : def getx(self): return self._x
1748 : : def setx(self, value): self._x = value
1749 : : def delx(self): del self._x
1750 : : x = property(getx, setx, delx, "I'm the 'x' property.")
1751 : :
1752 : : Decorators make defining new properties or modifying existing ones easy:
1753 : :
1754 : : class C(object):
1755 : : @property
1756 : : def x(self):
1757 : : "I am the 'x' property."
1758 : : return self._x
1759 : : @x.setter
1760 : : def x(self, value):
1761 : : self._x = value
1762 : : @x.deleter
1763 : : def x(self):
1764 : : del self._x
1765 : : [clinic start generated code]*/
1766 : :
1767 : : static int
1768 : 181465 : property_init_impl(propertyobject *self, PyObject *fget, PyObject *fset,
1769 : : PyObject *fdel, PyObject *doc)
1770 : : /*[clinic end generated code: output=01a960742b692b57 input=dfb5dbbffc6932d5]*/
1771 : : {
1772 [ + + ]: 181465 : if (fget == Py_None)
1773 : 1 : fget = NULL;
1774 [ + + ]: 181465 : if (fset == Py_None)
1775 : 36 : fset = NULL;
1776 [ + + ]: 181465 : if (fdel == Py_None)
1777 : 25012 : fdel = NULL;
1778 : :
1779 : 181465 : Py_XINCREF(fget);
1780 : 181465 : Py_XINCREF(fset);
1781 : 181465 : Py_XINCREF(fdel);
1782 : :
1783 : 181465 : Py_XSETREF(self->prop_get, fget);
1784 : 181465 : Py_XSETREF(self->prop_set, fset);
1785 : 181465 : Py_XSETREF(self->prop_del, fdel);
1786 : 181465 : Py_XSETREF(self->prop_doc, NULL);
1787 : 181465 : Py_XSETREF(self->prop_name, NULL);
1788 : :
1789 : 181465 : self->getter_doc = 0;
1790 : 181465 : PyObject *prop_doc = NULL;
1791 : :
1792 [ + + + + ]: 181465 : if (doc != NULL && doc != Py_None) {
1793 : 1275 : prop_doc = doc;
1794 : 1275 : Py_XINCREF(prop_doc);
1795 : : }
1796 : : /* if no docstring given and the getter has one, use that one */
1797 [ + + ]: 180190 : else if (fget != NULL) {
1798 : 180184 : int rc = _PyObject_LookupAttr(fget, &_Py_ID(__doc__), &prop_doc);
1799 [ - + ]: 180184 : if (rc <= 0) {
1800 : 0 : return rc;
1801 : : }
1802 [ + + ]: 180184 : if (prop_doc == Py_None) {
1803 : 115456 : prop_doc = NULL;
1804 : 115456 : Py_DECREF(Py_None);
1805 : : }
1806 [ + + ]: 180184 : if (prop_doc != NULL){
1807 : 64728 : self->getter_doc = 1;
1808 : : }
1809 : : }
1810 : :
1811 : : /* At this point `prop_doc` is either NULL or
1812 : : a non-None object with incremented ref counter */
1813 : :
1814 [ + + ]: 181465 : if (Py_IS_TYPE(self, &PyProperty_Type)) {
1815 : 181378 : Py_XSETREF(self->prop_doc, prop_doc);
1816 : : } else {
1817 : : /* If this is a property subclass, put __doc__
1818 : : in dict of the subclass instance instead,
1819 : : otherwise it gets shadowed by __doc__ in the
1820 : : class's dict. */
1821 : :
1822 [ + + ]: 87 : if (prop_doc == NULL) {
1823 : 11 : prop_doc = Py_None;
1824 : 11 : Py_INCREF(prop_doc);
1825 : : }
1826 : 87 : int err = PyObject_SetAttr(
1827 : : (PyObject *)self, &_Py_ID(__doc__), prop_doc);
1828 : 87 : Py_XDECREF(prop_doc);
1829 [ + + ]: 87 : if (err < 0)
1830 : 1 : return -1;
1831 : : }
1832 : :
1833 : 181464 : return 0;
1834 : : }
1835 : :
1836 : : static PyObject *
1837 : 15779 : property_get___isabstractmethod__(propertyobject *prop, void *closure)
1838 : : {
1839 : 15779 : int res = _PyObject_IsAbstract(prop->prop_get);
1840 [ + + ]: 15779 : if (res == -1) {
1841 : 1 : return NULL;
1842 : : }
1843 [ + + ]: 15778 : else if (res) {
1844 : 301 : Py_RETURN_TRUE;
1845 : : }
1846 : :
1847 : 15477 : res = _PyObject_IsAbstract(prop->prop_set);
1848 [ - + ]: 15477 : if (res == -1) {
1849 : 0 : return NULL;
1850 : : }
1851 [ + + ]: 15477 : else if (res) {
1852 : 4 : Py_RETURN_TRUE;
1853 : : }
1854 : :
1855 : 15473 : res = _PyObject_IsAbstract(prop->prop_del);
1856 [ - + ]: 15473 : if (res == -1) {
1857 : 0 : return NULL;
1858 : : }
1859 [ - + ]: 15473 : else if (res) {
1860 : 0 : Py_RETURN_TRUE;
1861 : : }
1862 : 15473 : Py_RETURN_FALSE;
1863 : : }
1864 : :
1865 : : static PyGetSetDef property_getsetlist[] = {
1866 : : {"__isabstractmethod__",
1867 : : (getter)property_get___isabstractmethod__, NULL,
1868 : : NULL,
1869 : : NULL},
1870 : : {NULL} /* Sentinel */
1871 : : };
1872 : :
1873 : : static int
1874 : 4282248 : property_traverse(PyObject *self, visitproc visit, void *arg)
1875 : : {
1876 : 4282248 : propertyobject *pp = (propertyobject *)self;
1877 [ + + + + ]: 4282248 : Py_VISIT(pp->prop_get);
1878 [ + + - + ]: 4282245 : Py_VISIT(pp->prop_set);
1879 [ + + - + ]: 4282245 : Py_VISIT(pp->prop_del);
1880 [ + + - + ]: 4282245 : Py_VISIT(pp->prop_doc);
1881 [ + + - + ]: 4282245 : Py_VISIT(pp->prop_name);
1882 : 4282245 : return 0;
1883 : : }
1884 : :
1885 : : static int
1886 : 2444 : property_clear(PyObject *self)
1887 : : {
1888 : 2444 : propertyobject *pp = (propertyobject *)self;
1889 [ + + ]: 2444 : Py_CLEAR(pp->prop_doc);
1890 : 2444 : return 0;
1891 : : }
1892 : :
1893 : : #include "clinic/descrobject.c.h"
1894 : :
1895 : : PyTypeObject PyDictProxy_Type = {
1896 : : PyVarObject_HEAD_INIT(&PyType_Type, 0)
1897 : : "mappingproxy", /* tp_name */
1898 : : sizeof(mappingproxyobject), /* tp_basicsize */
1899 : : 0, /* tp_itemsize */
1900 : : /* methods */
1901 : : (destructor)mappingproxy_dealloc, /* tp_dealloc */
1902 : : 0, /* tp_vectorcall_offset */
1903 : : 0, /* tp_getattr */
1904 : : 0, /* tp_setattr */
1905 : : 0, /* tp_as_async */
1906 : : (reprfunc)mappingproxy_repr, /* tp_repr */
1907 : : &mappingproxy_as_number, /* tp_as_number */
1908 : : &mappingproxy_as_sequence, /* tp_as_sequence */
1909 : : &mappingproxy_as_mapping, /* tp_as_mapping */
1910 : : (hashfunc)mappingproxy_hash, /* tp_hash */
1911 : : 0, /* tp_call */
1912 : : (reprfunc)mappingproxy_str, /* tp_str */
1913 : : PyObject_GenericGetAttr, /* tp_getattro */
1914 : : 0, /* tp_setattro */
1915 : : 0, /* tp_as_buffer */
1916 : : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1917 : : Py_TPFLAGS_MAPPING, /* tp_flags */
1918 : : 0, /* tp_doc */
1919 : : mappingproxy_traverse, /* tp_traverse */
1920 : : 0, /* tp_clear */
1921 : : (richcmpfunc)mappingproxy_richcompare, /* tp_richcompare */
1922 : : 0, /* tp_weaklistoffset */
1923 : : (getiterfunc)mappingproxy_getiter, /* tp_iter */
1924 : : 0, /* tp_iternext */
1925 : : mappingproxy_methods, /* tp_methods */
1926 : : 0, /* tp_members */
1927 : : 0, /* tp_getset */
1928 : : 0, /* tp_base */
1929 : : 0, /* tp_dict */
1930 : : 0, /* tp_descr_get */
1931 : : 0, /* tp_descr_set */
1932 : : 0, /* tp_dictoffset */
1933 : : 0, /* tp_init */
1934 : : 0, /* tp_alloc */
1935 : : mappingproxy_new, /* tp_new */
1936 : : };
1937 : :
1938 : : PyTypeObject PyProperty_Type = {
1939 : : PyVarObject_HEAD_INIT(&PyType_Type, 0)
1940 : : "property", /* tp_name */
1941 : : sizeof(propertyobject), /* tp_basicsize */
1942 : : 0, /* tp_itemsize */
1943 : : /* methods */
1944 : : property_dealloc, /* tp_dealloc */
1945 : : 0, /* tp_vectorcall_offset */
1946 : : 0, /* tp_getattr */
1947 : : 0, /* tp_setattr */
1948 : : 0, /* tp_as_async */
1949 : : 0, /* tp_repr */
1950 : : 0, /* tp_as_number */
1951 : : 0, /* tp_as_sequence */
1952 : : 0, /* tp_as_mapping */
1953 : : 0, /* tp_hash */
1954 : : 0, /* tp_call */
1955 : : 0, /* tp_str */
1956 : : PyObject_GenericGetAttr, /* tp_getattro */
1957 : : 0, /* tp_setattro */
1958 : : 0, /* tp_as_buffer */
1959 : : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1960 : : Py_TPFLAGS_BASETYPE, /* tp_flags */
1961 : : property_init__doc__, /* tp_doc */
1962 : : property_traverse, /* tp_traverse */
1963 : : (inquiry)property_clear, /* tp_clear */
1964 : : 0, /* tp_richcompare */
1965 : : 0, /* tp_weaklistoffset */
1966 : : 0, /* tp_iter */
1967 : : 0, /* tp_iternext */
1968 : : property_methods, /* tp_methods */
1969 : : property_members, /* tp_members */
1970 : : property_getsetlist, /* tp_getset */
1971 : : 0, /* tp_base */
1972 : : 0, /* tp_dict */
1973 : : property_descr_get, /* tp_descr_get */
1974 : : property_descr_set, /* tp_descr_set */
1975 : : 0, /* tp_dictoffset */
1976 : : property_init, /* tp_init */
1977 : : PyType_GenericAlloc, /* tp_alloc */
1978 : : PyType_GenericNew, /* tp_new */
1979 : : PyObject_GC_Del, /* tp_free */
1980 : : };
|