diff options
author | Victor Stinner <vstinner@python.org> | 2021-05-25 20:28:10 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-25 20:28:10 (GMT) |
commit | bd199e72fb60a8ff001a023f23925092a290be91 (patch) | |
tree | e9b5c2af362534862219d453a36046301212d8b5 | |
parent | bd404ccac0d3e8358995ac0cbeec9373bb6c4d96 (diff) | |
download | cpython-bd199e72fb60a8ff001a023f23925092a290be91.zip cpython-bd199e72fb60a8ff001a023f23925092a290be91.tar.gz cpython-bd199e72fb60a8ff001a023f23925092a290be91.tar.bz2 |
bpo-44232: Fix type_new() error reporting (GH-26359)
Fix a regression in type() when a metaclass raises an exception. The
C function type_new() must properly report the exception when a
metaclass constructor raises an exception and the winner class is not
the metaclass.
-rw-r--r-- | Lib/test/test_types.py | 18 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2021-05-25-18-20-10.bpo-44232.DMcCCf.rst | 4 | ||||
-rw-r--r-- | Objects/typeobject.c | 4 |
3 files changed, 26 insertions, 0 deletions
diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index 25ebec5..767c3d0 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -1334,6 +1334,24 @@ class ClassCreationTests(unittest.TestCase): N(5) self.assertEqual(str(cm.exception), expected_message) + def test_metaclass_new_error(self): + # bpo-44232: The C function type_new() must properly report the + # exception when a metaclass constructor raises an exception and the + # winner class is not the metaclass. + class ModelBase(type): + def __new__(cls, name, bases, attrs): + super_new = super().__new__ + new_class = super_new(cls, name, bases, {}) + if name != "Model": + raise RuntimeWarning(f"{name=}") + return new_class + + class Model(metaclass=ModelBase): + pass + + with self.assertRaises(RuntimeWarning): + type("SouthPonies", (Model,), {}) + class SimpleNamespaceTests(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-05-25-18-20-10.bpo-44232.DMcCCf.rst b/Misc/NEWS.d/next/Core and Builtins/2021-05-25-18-20-10.bpo-44232.DMcCCf.rst new file mode 100644 index 0000000..fcd124d --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-05-25-18-20-10.bpo-44232.DMcCCf.rst @@ -0,0 +1,4 @@ +Fix a regression in :func:`type` when a metaclass raises an exception. The C +function :c:func:`type_new` must properly report the exception when a metaclass +constructor raises an exception and the winner class is not the metaclass. +Patch by Victor Stinner. diff --git a/Objects/typeobject.c b/Objects/typeobject.c index af99ab7..1460085 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3256,6 +3256,9 @@ type_new_get_bases(type_new_ctx *ctx, PyObject **type) if (winner->tp_new != type_new) { /* Pass it to the winner */ *type = winner->tp_new(winner, ctx->args, ctx->kwds); + if (*type == NULL) { + return -1; + } return 1; } @@ -3307,6 +3310,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) PyObject *type = NULL; int res = type_new_get_bases(&ctx, &type); if (res < 0) { + assert(PyErr_Occurred()); return NULL; } if (res == 1) { |