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