mirror of https://github.com/python/cpython
gh-113212: Improve error message & document zero-arg super inside nested functions and generator expressions (GH-113307)
This commit is contained in:
parent
237e2cff00
commit
4a3d2419bb
|
@ -1800,6 +1800,13 @@ are always available. They are listed here in alphabetical order.
|
|||
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
|
||||
|
|
|
@ -396,6 +396,33 @@ class TestSuper(unittest.TestCase):
|
|||
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):
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Improve :py:class:`super` error messages.
|
|
@ -10404,9 +10404,22 @@ supercheck(PyTypeObject *type, PyObject *obj)
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue