LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/python3/Objects - descrobject.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 163 533 30.6 %
Date: 2012-12-17 Functions: 25 70 35.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10