Skip to content

Commit cae0a73

Browse files
committed
gh-119775: Remove ability to create immutable types with mutable bases
1 parent db00934 commit cae0a73

File tree

4 files changed

+13
-28
lines changed

4 files changed

+13
-28
lines changed

Doc/whatsnew/3.14.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,3 +254,5 @@ Deprecated
254254
Removed
255255
-------
256256

257+
* Creating :c:data:`immutable types <Py_TPFLAGS_IMMUTABLETYPE>` with mutable
258+
bases was deprecated since 3.12 and now raises a :exc:`TypeError`.

Lib/test/test_capi/test_misc.py

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -777,33 +777,17 @@ def test_pytype_fromspec_with_repeated_slots(self):
777777
with self.assertRaises(SystemError):
778778
_testcapi.create_type_from_repeated_slots(variant)
779779

780-
@warnings_helper.ignore_warnings(category=DeprecationWarning)
781780
def test_immutable_type_with_mutable_base(self):
782-
# Add deprecation warning here so it's removed in 3.14
783-
warnings._deprecated(
784-
'creating immutable classes with mutable bases', remove=(3, 14))
785-
786781
class MutableBase:
787782
def meth(self):
788783
return 'original'
789784

790-
with self.assertWarns(DeprecationWarning):
791-
ImmutableSubclass = _testcapi.make_immutable_type_with_base(
792-
MutableBase)
793-
instance = ImmutableSubclass()
794-
795-
self.assertEqual(instance.meth(), 'original')
796-
797-
# Cannot override the static type's method
798-
with self.assertRaisesRegex(
799-
TypeError,
800-
"cannot set 'meth' attribute of immutable type"):
801-
ImmutableSubclass.meth = lambda self: 'overridden'
802-
self.assertEqual(instance.meth(), 'original')
785+
# with self.assertRaisesRegex(TypeError, 'Creating immutable type'):
786+
# _testcapi.make_immutable_type_with_base(MutableBase)
803787

804788
# Can change the method on the mutable base
805789
MutableBase.meth = lambda self: 'changed'
806-
self.assertEqual(instance.meth(), 'changed')
790+
self.assertEqual(MutableBase().meth(), 'changed')
807791

808792
def test_pynumber_tobase(self):
809793
from _testcapi import pynumber_tobase
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Creating :c:data:`immutable types <Py_TPFLAGS_IMMUTABLETYPE>` with mutable
2+
bases was deprecated since 3.12 and now raises a :exc:`TypeError`.

Objects/typeobject.c

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4613,16 +4613,13 @@ _PyType_FromMetaclass_impl(
46134613
goto finally;
46144614
}
46154615
if (!_PyType_HasFeature(b, Py_TPFLAGS_IMMUTABLETYPE)) {
4616-
if (PyErr_WarnFormat(
4617-
PyExc_DeprecationWarning,
4618-
0,
4619-
"Creating immutable type %s from mutable base %s is "
4620-
"deprecated, and slated to be disallowed in Python 3.14.",
4616+
PyErr_Format(
4617+
PyExc_TypeError,
4618+
"Creating immutable type %s from mutable base %s",
46214619
spec->name,
4622-
b->tp_name))
4623-
{
4624-
goto finally;
4625-
}
4620+
b->tp_name
4621+
);
4622+
goto finally;
46264623
}
46274624
}
46284625
}

0 commit comments

Comments
 (0)