summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_descr.py52
-rw-r--r--Objects/typeobject.c53
2 files changed, 87 insertions, 18 deletions
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
index 8166d7c..f3b81ac 100644
--- a/Lib/test/test_descr.py
+++ b/Lib/test/test_descr.py
@@ -1572,7 +1572,57 @@ def supers():
def meth(self, a):
return "D(%r)" % a + super(D, self).meth(a)
- verify (D().meth(4) == "D(4)C(4)B(4)A(4)")
+ vereq(D().meth(4), "D(4)C(4)B(4)A(4)")
+
+ # Test for subclassing super
+
+ class mysuper(super):
+ def __init__(self, *args):
+ return super(mysuper, self).__init__(*args)
+
+ class E(D):
+ def meth(self, a):
+ return "E(%r)" % a + mysuper(E, self).meth(a)
+
+ vereq(E().meth(5), "E(5)D(5)C(5)B(5)A(5)")
+
+ class F(E):
+ def meth(self, a):
+ s = self.__super
+ return "F(%r)[%s]" % (a, s.__class__.__name__) + s.meth(a)
+ F._F__super = mysuper(F)
+
+ vereq(F().meth(6), "F(6)[mysuper]E(6)D(6)C(6)B(6)A(6)")
+
+ # Make sure certain errors are raised
+
+ try:
+ super(D, 42)
+ except TypeError:
+ pass
+ else:
+ raise TestFailed, "shouldn't allow super(D, 42)"
+
+ try:
+ super(D, C())
+ except TypeError:
+ pass
+ else:
+ raise TestFailed, "shouldn't allow super(D, C())"
+
+ try:
+ super(D).__get__(12)
+ except TypeError:
+ pass
+ else:
+ raise TestFailed, "shouldn't allow super(D).__get__(12)"
+
+ try:
+ super(D).__get__(C())
+ except TypeError:
+ pass
+ else:
+ raise TestFailed, "shouldn't allow super(D).__get__(C())"
def inherits():
if verbose: print "Testing inheritance from basic types..."
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index c79636d..6fc5d02 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -3929,7 +3929,7 @@ super_getattro(PyObject *self, PyObject *name)
else
continue;
res = PyDict_GetItem(dict, name);
- if (res != NULL) {
+ if (res != NULL && !PyDescr_IsData(res)) {
Py_INCREF(res);
f = res->ob_type->tp_descr_get;
if (f != NULL) {
@@ -3944,6 +3944,21 @@ super_getattro(PyObject *self, PyObject *name)
return PyObject_GenericGetAttr(self, name);
}
+static int
+supercheck(PyTypeObject *type, PyObject *obj)
+{
+ if (!PyType_IsSubtype(obj->ob_type, type) &&
+ !(PyType_Check(obj) &&
+ PyType_IsSubtype((PyTypeObject *)obj, type))) {
+ PyErr_SetString(PyExc_TypeError,
+ "super(type, obj): "
+ "obj must be an instance or subtype of type");
+ return -1;
+ }
+ else
+ return 0;
+}
+
static PyObject *
super_descr_get(PyObject *self, PyObject *obj, PyObject *type)
{
@@ -3955,14 +3970,25 @@ super_descr_get(PyObject *self, PyObject *obj, PyObject *type)
Py_INCREF(self);
return self;
}
- new = (superobject *)PySuper_Type.tp_new(&PySuper_Type, NULL, NULL);
- if (new == NULL)
- return NULL;
- Py_INCREF(su->type);
- Py_INCREF(obj);
- new->type = su->type;
- new->obj = obj;
- return (PyObject *)new;
+ if (su->ob_type != &PySuper_Type)
+ /* If su is an instance of a subclass of super,
+ call its type */
+ return PyObject_CallFunction((PyObject *)su->ob_type,
+ "OO", su->type, obj);
+ else {
+ /* Inline the common case */
+ if (supercheck(su->type, obj) < 0)
+ return NULL;
+ new = (superobject *)PySuper_Type.tp_new(&PySuper_Type,
+ NULL, NULL);
+ if (new == NULL)
+ return NULL;
+ Py_INCREF(su->type);
+ Py_INCREF(obj);
+ new->type = su->type;
+ new->obj = obj;
+ return (PyObject *)new;
+ }
}
static int
@@ -3976,15 +4002,8 @@ super_init(PyObject *self, PyObject *args, PyObject *kwds)
return -1;
if (obj == Py_None)
obj = NULL;
- if (obj != NULL &&
- !PyType_IsSubtype(obj->ob_type, type) &&
- !(PyType_Check(obj) &&
- PyType_IsSubtype((PyTypeObject *)obj, type))) {
- PyErr_SetString(PyExc_TypeError,
- "super(type, obj): "
- "obj must be an instance or subtype of type");
+ if (obj != NULL && supercheck(type, obj) < 0)
return -1;
- }
Py_INCREF(type);
Py_XINCREF(obj);
su->type = type;