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