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):
--- /dev/null
+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.
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;
}
PyObject *type = NULL;
int res = type_new_get_bases(&ctx, &type);
if (res < 0) {
+ assert(PyErr_Occurred());
return NULL;
}
if (res == 1) {