mirror of https://github.com/python/cpython
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.
This commit is contained in:
parent
bd404ccac0
commit
bd199e72fb
|
@ -1334,6 +1334,24 @@ class ClassCreationTests(unittest.TestCase):
|
||||||
N(5)
|
N(5)
|
||||||
self.assertEqual(str(cm.exception), expected_message)
|
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):
|
class SimpleNamespaceTests(unittest.TestCase):
|
||||||
|
|
||||||
|
|
|
@ -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.
|
|
@ -3256,6 +3256,9 @@ type_new_get_bases(type_new_ctx *ctx, PyObject **type)
|
||||||
if (winner->tp_new != type_new) {
|
if (winner->tp_new != type_new) {
|
||||||
/* Pass it to the winner */
|
/* Pass it to the winner */
|
||||||
*type = winner->tp_new(winner, ctx->args, ctx->kwds);
|
*type = winner->tp_new(winner, ctx->args, ctx->kwds);
|
||||||
|
if (*type == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3307,6 +3310,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
|
||||||
PyObject *type = NULL;
|
PyObject *type = NULL;
|
||||||
int res = type_new_get_bases(&ctx, &type);
|
int res = type_new_get_bases(&ctx, &type);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
|
assert(PyErr_Occurred());
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (res == 1) {
|
if (res == 1) {
|
||||||
|
|
Loading…
Reference in New Issue