]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-119775: Remove ability to create immutable types with mutable bases (#119776)
authorNikita Sobolev <mail@sobolevn.me>
Sun, 2 Jun 2024 07:27:20 +0000 (10:27 +0300)
committerGitHub <noreply@github.com>
Sun, 2 Jun 2024 07:27:20 +0000 (07:27 +0000)
Doc/whatsnew/3.14.rst
Lib/test/test_capi/test_misc.py
Misc/NEWS.d/next/C API/2024-05-30-12-51-21.gh-issue-119775.CBq9IG.rst [new file with mode: 0644]
Objects/typeobject.c

index d443cf9bc56b9850aa0ae75ecc0e1fbf62b821b8..45ffb281fcc03205bb85ce398ad72f666deafdb4 100644 (file)
@@ -258,3 +258,5 @@ Deprecated
 Removed
 -------
 
+* Creating :c:data:`immutable types <Py_TPFLAGS_IMMUTABLETYPE>` with mutable
+  bases was deprecated since 3.12 and now raises a :exc:`TypeError`.
index f3d16e4a2fc92a3c4661974ee2904b07b42a621b..0dc0b530aec971fa36939148496ab7c038eabe10 100644 (file)
@@ -777,33 +777,11 @@ class CAPITest(unittest.TestCase):
                 with self.assertRaises(SystemError):
                     _testcapi.create_type_from_repeated_slots(variant)
 
-    @warnings_helper.ignore_warnings(category=DeprecationWarning)
     def test_immutable_type_with_mutable_base(self):
-        # Add deprecation warning here so it's removed in 3.14
-        warnings._deprecated(
-            'creating immutable classes with mutable bases', remove=(3, 14))
-
-        class MutableBase:
-            def meth(self):
-                return 'original'
-
-        with self.assertWarns(DeprecationWarning):
-            ImmutableSubclass = _testcapi.make_immutable_type_with_base(
-                MutableBase)
-        instance = ImmutableSubclass()
+        class MutableBase: ...
 
-        self.assertEqual(instance.meth(), 'original')
-
-        # Cannot override the static type's method
-        with self.assertRaisesRegex(
-                TypeError,
-                "cannot set 'meth' attribute of immutable type"):
-            ImmutableSubclass.meth = lambda self: 'overridden'
-        self.assertEqual(instance.meth(), 'original')
-
-        # Can change the method on the mutable base
-        MutableBase.meth = lambda self: 'changed'
-        self.assertEqual(instance.meth(), 'changed')
+        with self.assertRaisesRegex(TypeError, 'Creating immutable type'):
+            _testcapi.make_immutable_type_with_base(MutableBase)
 
     def test_pynumber_tobase(self):
         from _testcapi import pynumber_tobase
diff --git a/Misc/NEWS.d/next/C API/2024-05-30-12-51-21.gh-issue-119775.CBq9IG.rst b/Misc/NEWS.d/next/C API/2024-05-30-12-51-21.gh-issue-119775.CBq9IG.rst
new file mode 100644 (file)
index 0000000..c342a38
--- /dev/null
@@ -0,0 +1,2 @@
+Creating :c:data:`immutable types <Py_TPFLAGS_IMMUTABLETYPE>` with mutable
+bases was deprecated since 3.12 and now raises a :exc:`TypeError`.
index 290306cdb677e52319de2a83839ec94d402ee3bb..0095a79a2cafec4ad755b6130f27d632ef4b3715 100644 (file)
@@ -4613,16 +4613,12 @@ _PyType_FromMetaclass_impl(
                 goto finally;
             }
             if (!_PyType_HasFeature(b, Py_TPFLAGS_IMMUTABLETYPE)) {
-                if (PyErr_WarnFormat(
-                    PyExc_DeprecationWarning,
-                    0,
-                    "Creating immutable type %s from mutable base %s is "
-                    "deprecated, and slated to be disallowed in Python 3.14.",
-                    spec->name,
-                    b->tp_name))
-                {
-                    goto finally;
-                }
+                PyErr_Format(
+                    PyExc_TypeError,
+                    "Creating immutable type %s from mutable base %N",
+                    spec->name, b
+                );
+                goto finally;
             }
         }
     }