diff options
author | Guido van Rossum <guido@python.org> | 2001-08-29 15:47:06 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2001-08-29 15:47:06 (GMT) |
commit | e705ef1bced126819d7568b1d4e0ac6944b987e0 (patch) | |
tree | b8677392a5ceee32d5a9f6ee2adfd1ff51910abd | |
parent | c16fcdf533583039d687f8ca2e88a1c21f3feeb3 (diff) | |
download | cpython-e705ef1bced126819d7568b1d4e0ac6944b987e0.zip cpython-e705ef1bced126819d7568b1d4e0ac6944b987e0.tar.gz cpython-e705ef1bced126819d7568b1d4e0ac6944b987e0.tar.bz2 |
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).
-rw-r--r-- | Objects/typeobject.c | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 8bae366..9d1a315 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" |