]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-44232: Fix type_new() error reporting (GH-26359) (GH-26365)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Wed, 26 May 2021 09:30:55 +0000 (02:30 -0700)
committerGitHub <noreply@github.com>
Wed, 26 May 2021 09:30:55 +0000 (11:30 +0200)
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.
(cherry picked from commit bd199e72fb60a8ff001a023f23925092a290be91)

Co-authored-by: Victor Stinner <vstinner@python.org>
Lib/test/test_types.py
Misc/NEWS.d/next/Core and Builtins/2021-05-25-18-20-10.bpo-44232.DMcCCf.rst [new file with mode: 0644]
Objects/typeobject.c

index 25ebec5fa5509357bc44085f41164462011b5d22..767c3d06a4f5839fc4a200f097b0640882214cc7 100644 (file)
@@ -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 (file)
index 0000000..fcd124d
--- /dev/null
@@ -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.
index 8f6764879c2aed6b69449c1957226b1b1bed83b2..a551402b5ce53f4e6a519984736f5515f717c48e 100644 (file)
@@ -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) {