summaryrefslogtreecommitdiffstats
path: root/Objects/typeobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/typeobject.c')
-rw-r--r--Objects/typeobject.c93
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)
{