From e705ef1bced126819d7568b1d4e0ac6944b987e0 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Wed, 29 Aug 2001 15:47:06 +0000 Subject: [PATCH] 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). --- Objects/typeobject.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 8bae366719..9d1a315846 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3112,7 +3112,7 @@ override_slots(PyTypeObject *type, PyObject *dict) typedef struct { PyObject_HEAD - PyObject *type; + PyTypeObject *type; PyObject *obj; } superobject; @@ -3136,14 +3136,28 @@ super_getattro(PyObject *self, PyObject *name) descrgetfunc f; int i, n; - mro = ((PyTypeObject *)(su->obj->ob_type))->tp_mro; + mro = su->obj->ob_type->tp_mro; assert(mro != NULL && PyTuple_Check(mro)); n = PyTuple_GET_SIZE(mro); for (i = 0; i < n; i++) { - if (su->type == PyTuple_GET_ITEM(mro, i)) + if ((PyObject *)(su->type) == PyTuple_GET_ITEM(mro, i)) break; } - assert(i < n); + if (i >= n && PyType_Check(su->obj)) { + mro = ((PyTypeObject *)(su->obj))->tp_mro; + assert(mro != NULL && PyTuple_Check(mro)); + n = PyTuple_GET_SIZE(mro); + for (i = 0; i < n; i++) { + if ((PyObject *)(su->type) == + PyTuple_GET_ITEM(mro, i)) + break; + } + if (i >= n) { + PyErr_SetString(PyExc_TypeError, + "bogus super object"); + return NULL; + } + } i++; res = NULL; for (; i < n; i++) { @@ -3191,16 +3205,20 @@ static int super_init(PyObject *self, PyObject *args, PyObject *kwds) { superobject *su = (superobject *)self; - PyObject *type, *obj = NULL; + PyTypeObject *type; + PyObject *obj = NULL; if (!PyArg_ParseTuple(args, "O!|O:super", &PyType_Type, &type, &obj)) return -1; if (obj == Py_None) obj = NULL; - if (obj != NULL && !PyType_IsSubtype(obj->ob_type, - (PyTypeObject *)type)) { + if (obj != NULL && + !PyType_IsSubtype(obj->ob_type, type) && + !(PyType_Check(obj) && + PyType_IsSubtype((PyTypeObject *)obj, type))) { PyErr_SetString(PyExc_TypeError, - "super(type, obj) requires isinstance(obj, type)"); + "super(type, obj): " + "obj must be an instance or subtype of type"); return -1; } Py_INCREF(type); @@ -3213,6 +3231,7 @@ super_init(PyObject *self, PyObject *args, PyObject *kwds) static char super_doc[] = "super(type) -> unbound super object\n" "super(type, obj) -> bound super object; requires isinstance(obj, type)\n" +"super(type, type2) -> bound super object; requires issubclass(type2, type)\n" "Typical use to call a cooperative superclass method:\n" "class C(B):\n" " def meth(self, arg):\n" -- 2.50.1