Skip to content

Commit 4a3d241

Browse files
authored
gh-113212: Improve error message & document zero-arg super inside nested functions and generator expressions (GH-113307)
1 parent 237e2cf commit 4a3d241

File tree

4 files changed

+51
-3
lines changed

4 files changed

+51
-3
lines changed

Doc/library/functions.rst

+7
Original file line numberDiff line numberDiff line change
@@ -1800,6 +1800,13 @@ are always available. They are listed here in alphabetical order.
18001800
the second argument is a type, ``issubclass(type2, type)`` must be true (this
18011801
is useful for classmethods).
18021802

1803+
When called directly within an ordinary method of a class, both arguments may
1804+
be omitted ("zero-argument :func:`!super`"). In this case, *type* will be the
1805+
enclosing class, and *obj* will be the first argument of the immediately
1806+
enclosing function (typically ``self``). (This means that zero-argument
1807+
:func:`!super` will not work as expected within nested functions, including
1808+
generator expressions, which implicitly create nested functions.)
1809+
18031810
There are two typical use cases for *super*. In a class hierarchy with
18041811
single inheritance, *super* can be used to refer to parent classes without
18051812
naming them explicitly, thus making the code more maintainable. This use

Lib/test/test_super.py

+27
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,33 @@ def method(self):
396396
with self.assertRaisesRegex(TypeError, "argument 1 must be a type"):
397397
C().method()
398398

399+
def test_supercheck_fail(self):
400+
class C:
401+
def method(self, type_, obj):
402+
return super(type_, obj).method()
403+
404+
c = C()
405+
err_msg = (
406+
r"super\(type, obj\): obj \({} {}\) is not "
407+
r"an instance or subtype of type \({}\)."
408+
)
409+
410+
cases = (
411+
(int, c, int.__name__, C.__name__, "instance of"),
412+
# obj is instance of type
413+
(C, list(), C.__name__, list.__name__, "instance of"),
414+
# obj is type itself
415+
(C, list, C.__name__, list.__name__, "type"),
416+
)
417+
418+
for case in cases:
419+
with self.subTest(case=case):
420+
type_, obj, type_str, obj_str, instance_or_type = case
421+
regex = err_msg.format(instance_or_type, obj_str, type_str)
422+
423+
with self.assertRaisesRegex(TypeError, regex):
424+
c.method(type_, obj)
425+
399426
def test_super___class__(self):
400427
class C:
401428
def method(self):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Improve :py:class:`super` error messages.

Objects/typeobject.c

+16-3
Original file line numberDiff line numberDiff line change
@@ -10404,9 +10404,22 @@ supercheck(PyTypeObject *type, PyObject *obj)
1040410404
Py_XDECREF(class_attr);
1040510405
}
1040610406

10407-
PyErr_SetString(PyExc_TypeError,
10408-
"super(type, obj): "
10409-
"obj must be an instance or subtype of type");
10407+
const char *type_or_instance, *obj_str;
10408+
10409+
if (PyType_Check(obj)) {
10410+
type_or_instance = "type";
10411+
obj_str = ((PyTypeObject*)obj)->tp_name;
10412+
}
10413+
else {
10414+
type_or_instance = "instance of";
10415+
obj_str = Py_TYPE(obj)->tp_name;
10416+
}
10417+
10418+
PyErr_Format(PyExc_TypeError,
10419+
"super(type, obj): obj (%s %.200s) is not "
10420+
"an instance or subtype of type (%.200s).",
10421+
type_or_instance, obj_str, type->tp_name);
10422+
1041010423
return NULL;
1041110424
}
1041210425

0 commit comments

Comments
 (0)