Skip to content

Commit 5d03b24

Browse files
authored
[3.13] gh-148450: abc.register needs to update type_version when tp_flags is changed (GH-148623) (#150307)
1 parent 95c9323 commit 5d03b24

3 files changed

Lines changed: 30 additions & 0 deletions

File tree

Lib/test/test_type_cache.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
""" Tests for the internal type cache in CPython. """
2+
import collections.abc
23
import unittest
34
import dis
45
from test import support
@@ -108,6 +109,25 @@ class HolderSub(Holder):
108109
Holder.set_value()
109110
HolderSub.value
110111

112+
def test_abc_register_invalidates_subclass_versions(self):
113+
class Parent:
114+
pass
115+
116+
class Child(Parent):
117+
pass
118+
119+
type_assign_version(Parent)
120+
type_assign_version(Child)
121+
parent_version = type_get_version(Parent)
122+
child_version = type_get_version(Child)
123+
if parent_version == 0 or child_version == 0:
124+
self.skipTest("Could not assign valid type versions")
125+
126+
collections.abc.Mapping.register(Parent)
127+
128+
self.assertEqual(type_get_version(Parent), 0)
129+
self.assertEqual(type_get_version(Child), 0)
130+
111131
@support.cpython_only
112132
@requires_specialization
113133
class TypeCacheWithSpecializationTests(unittest.TestCase):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix ``abc.register()`` so it invalidates type version tags for registered classes.

Objects/typeobject.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5398,6 +5398,15 @@ void
53985398
_PyType_SetFlagsRecursive(PyTypeObject *self, unsigned long mask, unsigned long flags)
53995399
{
54005400
BEGIN_TYPE_LOCK();
5401+
/* Ideally, changing flags and invalidating the old version tag would
5402+
happen in one step. For this backport, keep it simple and invalidate
5403+
first while holding TYPE_LOCK. Immutable types are skipped because
5404+
set_flags_recursive() does not modify them. */
5405+
if (!PyType_HasFeature(self, Py_TPFLAGS_IMMUTABLETYPE) &&
5406+
(self->tp_flags & mask) != flags)
5407+
{
5408+
type_modified_unlocked(self);
5409+
}
54015410
set_flags_recursive(self, mask, flags);
54025411
END_TYPE_LOCK();
54035412
}

0 commit comments

Comments
 (0)