Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e705ef1

Browse files
committed
Fix super() so that it is usable for static methods (like __new__) as well.
In particular, the second argument can now be a subclass of the first as well (normally it must be an instance though).
1 parent c16fcdf commit e705ef1

1 file changed

Lines changed: 27 additions & 8 deletions

File tree

Objects/typeobject.c

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3112,7 +3112,7 @@ override_slots(PyTypeObject *type, PyObject *dict)
31123112

31133113
typedef struct {
31143114
PyObject_HEAD
3115-
PyObject *type;
3115+
PyTypeObject *type;
31163116
PyObject *obj;
31173117
} superobject;
31183118

@@ -3136,14 +3136,28 @@ super_getattro(PyObject *self, PyObject *name)
31363136
descrgetfunc f;
31373137
int i, n;
31383138

3139-
mro = ((PyTypeObject *)(su->obj->ob_type))->tp_mro;
3139+
mro = su->obj->ob_type->tp_mro;
31403140
assert(mro != NULL && PyTuple_Check(mro));
31413141
n = PyTuple_GET_SIZE(mro);
31423142
for (i = 0; i < n; i++) {
3143-
if (su->type == PyTuple_GET_ITEM(mro, i))
3143+
if ((PyObject *)(su->type) == PyTuple_GET_ITEM(mro, i))
31443144
break;
31453145
}
3146-
assert(i < n);
3146+
if (i >= n && PyType_Check(su->obj)) {
3147+
mro = ((PyTypeObject *)(su->obj))->tp_mro;
3148+
assert(mro != NULL && PyTuple_Check(mro));
3149+
n = PyTuple_GET_SIZE(mro);
3150+
for (i = 0; i < n; i++) {
3151+
if ((PyObject *)(su->type) ==
3152+
PyTuple_GET_ITEM(mro, i))
3153+
break;
3154+
}
3155+
if (i >= n) {
3156+
PyErr_SetString(PyExc_TypeError,
3157+
"bogus super object");
3158+
return NULL;
3159+
}
3160+
}
31473161
i++;
31483162
res = NULL;
31493163
for (; i < n; i++) {
@@ -3191,16 +3205,20 @@ static int
31913205
super_init(PyObject *self, PyObject *args, PyObject *kwds)
31923206
{
31933207
superobject *su = (superobject *)self;
3194-
PyObject *type, *obj = NULL;
3208+
PyTypeObject *type;
3209+
PyObject *obj = NULL;
31953210

31963211
if (!PyArg_ParseTuple(args, "O!|O:super", &PyType_Type, &type, &obj))
31973212
return -1;
31983213
if (obj == Py_None)
31993214
obj = NULL;
3200-
if (obj != NULL && !PyType_IsSubtype(obj->ob_type,
3201-
(PyTypeObject *)type)) {
3215+
if (obj != NULL &&
3216+
!PyType_IsSubtype(obj->ob_type, type) &&
3217+
!(PyType_Check(obj) &&
3218+
PyType_IsSubtype((PyTypeObject *)obj, type))) {
32023219
PyErr_SetString(PyExc_TypeError,
3203-
"super(type, obj) requires isinstance(obj, type)");
3220+
"super(type, obj): "
3221+
"obj must be an instance or subtype of type");
32043222
return -1;
32053223
}
32063224
Py_INCREF(type);
@@ -3213,6 +3231,7 @@ super_init(PyObject *self, PyObject *args, PyObject *kwds)
32133231
static char super_doc[] =
32143232
"super(type) -> unbound super object\n"
32153233
"super(type, obj) -> bound super object; requires isinstance(obj, type)\n"
3234+
"super(type, type2) -> bound super object; requires issubclass(type2, type)\n"
32163235
"Typical use to call a cooperative superclass method:\n"
32173236
"class C(B):\n"
32183237
" def meth(self, arg):\n"

0 commit comments

Comments
 (0)