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