gh-119775: Remove ability to create immutable types with mutable bases (#119776)

This commit is contained in:
Nikita Sobolev 2024-06-02 10:27:20 +03:00 committed by GitHub
parent fd6cd621e0
commit 4aed319a8e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 13 additions and 35 deletions

View 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`.

View 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: ...
class MutableBase:
def meth(self):
return 'original'
with self.assertWarns(DeprecationWarning):
ImmutableSubclass = _testcapi.make_immutable_type_with_base(
MutableBase)
instance = ImmutableSubclass()
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

View File

@ -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`.

View 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;
}
}
}