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