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