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