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