the second argument is a type, ``issubclass(type2, type)`` must be true (this
is useful for classmethods).
+ When called directly within an ordinary method of a class, both arguments may
+ be omitted ("zero-argument :func:`!super`"). In this case, *type* will be the
+ enclosing class, and *obj* will be the first argument of the immediately
+ enclosing function (typically ``self``). (This means that zero-argument
+ :func:`!super` will not work as expected within nested functions, including
+ generator expressions, which implicitly create nested functions.)
+
There are two typical use cases for *super*. In a class hierarchy with
single inheritance, *super* can be used to refer to parent classes without
naming them explicitly, thus making the code more maintainable. This use
with self.assertRaisesRegex(TypeError, "argument 1 must be a type"):
C().method()
+ def test_supercheck_fail(self):
+ class C:
+ def method(self, type_, obj):
+ return super(type_, obj).method()
+
+ c = C()
+ err_msg = (
+ r"super\(type, obj\): obj \({} {}\) is not "
+ r"an instance or subtype of type \({}\)."
+ )
+
+ cases = (
+ (int, c, int.__name__, C.__name__, "instance of"),
+ # obj is instance of type
+ (C, list(), C.__name__, list.__name__, "instance of"),
+ # obj is type itself
+ (C, list, C.__name__, list.__name__, "type"),
+ )
+
+ for case in cases:
+ with self.subTest(case=case):
+ type_, obj, type_str, obj_str, instance_or_type = case
+ regex = err_msg.format(instance_or_type, obj_str, type_str)
+
+ with self.assertRaisesRegex(TypeError, regex):
+ c.method(type_, obj)
+
def test_super___class__(self):
class C:
def method(self):
--- /dev/null
+Improve :py:class:`super` error messages.
Py_XDECREF(class_attr);
}
- PyErr_SetString(PyExc_TypeError,
- "super(type, obj): "
- "obj must be an instance or subtype of type");
+ const char *type_or_instance, *obj_str;
+
+ if (PyType_Check(obj)) {
+ type_or_instance = "type";
+ obj_str = ((PyTypeObject*)obj)->tp_name;
+ }
+ else {
+ type_or_instance = "instance of";
+ obj_str = Py_TYPE(obj)->tp_name;
+ }
+
+ PyErr_Format(PyExc_TypeError,
+ "super(type, obj): obj (%s %.200s) is not "
+ "an instance or subtype of type (%.200s).",
+ type_or_instance, obj_str, type->tp_name);
+
return NULL;
}