diff options
Diffstat (limited to 'Objects/typeobject.c')
-rw-r--r-- | Objects/typeobject.c | 93 |
1 files changed, 65 insertions, 28 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c index d2b77a0..e1497d6 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -9346,26 +9346,20 @@ super_repr(PyObject *self) su->type ? su->type->tp_name : "NULL"); } +// if `method` is non-NULL, we are looking for a method descriptor, +// and setting `*method` to 1 means we found one. static PyObject * -super_getattro(PyObject *self, PyObject *name) +do_super_lookup(superobject *su, PyTypeObject *su_type, PyObject *su_obj, + PyTypeObject *su_obj_type, PyObject *name, int *method) { - superobject *su = (superobject *)self; - PyTypeObject *starttype; - PyObject *mro; + PyObject *mro, *res; Py_ssize_t i, n; + int temp_su = 0; - starttype = su->obj_type; - if (starttype == NULL) - goto skip; - - /* We want __class__ to return the class of the super object - (i.e. super, or a subclass), not the class of su->obj. */ - if (PyUnicode_Check(name) && - PyUnicode_GET_LENGTH(name) == 9 && - _PyUnicode_Equal(name, &_Py_ID(__class__))) + if (su_obj_type == NULL) goto skip; - mro = starttype->tp_mro; + mro = su_obj_type->tp_mro; if (mro == NULL) goto skip; @@ -9374,14 +9368,14 @@ super_getattro(PyObject *self, PyObject *name) /* No need to check the last one: it's gonna be skipped anyway. */ for (i = 0; i+1 < n; i++) { - if ((PyObject *)(su->type) == PyTuple_GET_ITEM(mro, i)) + if ((PyObject *)(su_type) == PyTuple_GET_ITEM(mro, i)) break; } i++; /* skip su->type (if any) */ if (i >= n) goto skip; - /* keep a strong reference to mro because starttype->tp_mro can be + /* keep a strong reference to mro because su_obj_type->tp_mro can be replaced during PyDict_GetItemWithError(dict, name) */ Py_INCREF(mro); do { @@ -9389,19 +9383,23 @@ super_getattro(PyObject *self, PyObject *name) PyObject *dict = _PyType_CAST(obj)->tp_dict; assert(dict != NULL && PyDict_Check(dict)); - PyObject *res = PyDict_GetItemWithError(dict, name); + res = PyDict_GetItemWithError(dict, name); if (res != NULL) { Py_INCREF(res); - - descrgetfunc f = Py_TYPE(res)->tp_descr_get; - if (f != NULL) { - PyObject *res2; - res2 = f(res, - /* Only pass 'obj' param if this is instance-mode super - (See SF ID #743627) */ - (su->obj == (PyObject *)starttype) ? NULL : su->obj, - (PyObject *)starttype); - Py_SETREF(res, res2); + if (method && _PyType_HasFeature(Py_TYPE(res), Py_TPFLAGS_METHOD_DESCRIPTOR)) { + *method = 1; + } + else { + descrgetfunc f = Py_TYPE(res)->tp_descr_get; + if (f != NULL) { + PyObject *res2; + res2 = f(res, + /* Only pass 'obj' param if this is instance-mode super + (See SF ID #743627) */ + (su_obj == (PyObject *)su_obj_type) ? NULL : su_obj, + (PyObject *)su_obj_type); + Py_SETREF(res, res2); + } } Py_DECREF(mro); @@ -9417,7 +9415,34 @@ super_getattro(PyObject *self, PyObject *name) Py_DECREF(mro); skip: - return PyObject_GenericGetAttr(self, name); + if (su == NULL) { + PyObject *args[] = {(PyObject *)su_type, su_obj}; + su = (superobject *)PyObject_Vectorcall((PyObject *)&PySuper_Type, args, 2, NULL); + if (su == NULL) { + return NULL; + } + temp_su = 1; + } + res = PyObject_GenericGetAttr((PyObject *)su, name); + if (temp_su) { + Py_DECREF(su); + } + return res; +} + +static PyObject * +super_getattro(PyObject *self, PyObject *name) +{ + superobject *su = (superobject *)self; + + /* We want __class__ to return the class of the super object + (i.e. super, or a subclass), not the class of su->obj. */ + if (PyUnicode_Check(name) && + PyUnicode_GET_LENGTH(name) == 9 && + _PyUnicode_Equal(name, &_Py_ID(__class__))) + return PyObject_GenericGetAttr(self, name); + + return do_super_lookup(su, su->type, su->obj, su->obj_type, name, NULL); } static PyTypeObject * @@ -9473,6 +9498,18 @@ supercheck(PyTypeObject *type, PyObject *obj) return NULL; } +PyObject * +_PySuper_Lookup(PyTypeObject *su_type, PyObject *su_obj, PyObject *name, int *method) +{ + PyTypeObject *su_obj_type = supercheck(su_type, su_obj); + if (su_obj_type == NULL) { + return NULL; + } + PyObject *res = do_super_lookup(NULL, su_type, su_obj, su_obj_type, name, method); + Py_DECREF(su_obj_type); + return res; +} + static PyObject * super_descr_get(PyObject *self, PyObject *obj, PyObject *type) { |