8000 bpo-44232: Fix type_new() error reporting (GH-26359) · python/cpython@bd199e7 · GitHub
[go: up one dir, main page]

Skip to content

Commit bd199e7

Browse files
authored
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.
1 parent bd404cc commit bd199e7

File tree

3 files changed

+26
-0
lines changed

3 files changed

+26
-0
lines changed

Lib/test/test_types.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1334,6 +1334,24 @@ class N(type, metaclass=M):
13341334
N(5)
13351335
self.assertEqual(str(cm.exception), expected_message)
13361336

1337+
def test_metaclass_new_error(self):
1338+
# bpo-44232: The C function type_new() must properly report the
1339+
# exception when a metaclass constructor raises an exception and the
1340+
# winner class is not the metaclass.
1341+
class ModelBase(type):
1342+
def __new__(cls, name, bases, attrs):
1343+
super_new = super().__new__
1344+
new_class = super_new(cls, name, bases, {})
1345+
if name != "Model":
1346+
raise RuntimeWarning(f"{name=}")
1347+
return new_class
1348+
1349+
class Model(metaclass=ModelBase):
1350+
pass
1351+
1352+
with self.assertRaises(RuntimeWarning):
1353+
type("SouthPonies", (Model,), {})
1354+
13371355

13381356
class SimpleNamespaceTests(unittest.TestCase):
13391357

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Fix a regression in :func:`type` when a metaclass raises an exception. The C
2+
function :c:func:`type_new` must properly report the exception when a metaclass
3+
constructor raises an exception and the winner class is not the metaclass.
4+
Patch by Victor Stinner.

Objects/typeobject.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3256,6 +3256,9 @@ type_new_get_bases(type_new_ctx *ctx, PyObject **type)
32563256
if (winner->tp_new != type_new) {
32573257
/* Pass it to the winner */
32583258
*type = winner->tp_new(winner, ctx->args, ctx->kwds);
3259+
if (*type == NULL) {
3260+
return -1;
3261+
}
32593262
return 1;
32603263
}
32613264

@@ -3307,6 +3310,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
33073310
PyObject *type = NULL;
33083311
int res = type_new_get_bases(&ctx, &type);
33093312
if (res < 0) {
3313+
assert(PyErr_Occurred());
33103314
return NULL;
33113315
}
33123316
if (res == 1) {

0 commit comments

Comments
 (0)
0