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