bpo-43977: Properly update the tp_flags of existing subclasses when their parents are registered (GH-26864)

(cherry picked from commit ca2009d72a)

Co-authored-by: Brandt Bucher <brandt@python.org>
This commit is contained in:
Miss Islington (bot) 2021-06-25 08:46:23 -07:00 committed by GitHub
parent 8bec9fb92f
commit 88970125e7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 129 additions and 34 deletions

View file

@ -24,7 +24,43 @@ class TestCompiler(unittest.TestCase):
class TestInheritance(unittest.TestCase):
def test_multiple_inheritance(self):
@staticmethod
def check_sequence_then_mapping(x):
match x:
case [*_]:
return "seq"
case {}:
return "map"
@staticmethod
def check_mapping_then_sequence(x):
match x:
case {}:
return "map"
case [*_]:
return "seq"
def test_multiple_inheritance_mapping(self):
class C:
pass
class M1(collections.UserDict, collections.abc.Sequence):
pass
class M2(C, collections.UserDict, collections.abc.Sequence):
pass
class M3(collections.UserDict, C, list):
pass
class M4(dict, collections.abc.Sequence, C):
pass
self.assertEqual(self.check_sequence_then_mapping(M1()), "map")
self.assertEqual(self.check_sequence_then_mapping(M2()), "map")
self.assertEqual(self.check_sequence_then_mapping(M3()), "map")
self.assertEqual(self.check_sequence_then_mapping(M4()), "map")
self.assertEqual(self.check_mapping_then_sequence(M1()), "map")
self.assertEqual(self.check_mapping_then_sequence(M2()), "map")
self.assertEqual(self.check_mapping_then_sequence(M3()), "map")
self.assertEqual(self.check_mapping_then_sequence(M4()), "map")
def test_multiple_inheritance_sequence(self):
class C:
pass
class S1(collections.UserList, collections.abc.Mapping):
@ -35,32 +71,60 @@ class TestInheritance(unittest.TestCase):
pass
class S4(collections.UserList, dict, C):
pass
class M1(collections.UserDict, collections.abc.Sequence):
self.assertEqual(self.check_sequence_then_mapping(S1()), "seq")
self.assertEqual(self.check_sequence_then_mapping(S2()), "seq")
self.assertEqual(self.check_sequence_then_mapping(S3()), "seq")
self.assertEqual(self.check_sequence_then_mapping(S4()), "seq")
self.assertEqual(self.check_mapping_then_sequence(S1()), "seq")
self.assertEqual(self.check_mapping_then_sequence(S2()), "seq")
self.assertEqual(self.check_mapping_then_sequence(S3()), "seq")
self.assertEqual(self.check_mapping_then_sequence(S4()), "seq")
def test_late_registration_mapping(self):
class Parent:
pass
class M2(C, collections.UserDict, collections.abc.Sequence):
class ChildPre(Parent):
pass
class M3(collections.UserDict, C, list):
class GrandchildPre(ChildPre):
pass
class M4(dict, collections.abc.Sequence, C):
collections.abc.Mapping.register(Parent)
class ChildPost(Parent):
pass
def f(x):
match x:
case []:
return "seq"
case {}:
return "map"
def g(x):
match x:
case {}:
return "map"
case []:
return "seq"
for Seq in (S1, S2, S3, S4):
self.assertEqual(f(Seq()), "seq")
self.assertEqual(g(Seq()), "seq")
for Map in (M1, M2, M3, M4):
self.assertEqual(f(Map()), "map")
self.assertEqual(g(Map()), "map")
class GrandchildPost(ChildPost):
pass
self.assertEqual(self.check_sequence_then_mapping(Parent()), "map")
self.assertEqual(self.check_sequence_then_mapping(ChildPre()), "map")
self.assertEqual(self.check_sequence_then_mapping(GrandchildPre()), "map")
self.assertEqual(self.check_sequence_then_mapping(ChildPost()), "map")
self.assertEqual(self.check_sequence_then_mapping(GrandchildPost()), "map")
self.assertEqual(self.check_mapping_then_sequence(Parent()), "map")
self.assertEqual(self.check_mapping_then_sequence(ChildPre()), "map")
self.assertEqual(self.check_mapping_then_sequence(GrandchildPre()), "map")
self.assertEqual(self.check_mapping_then_sequence(ChildPost()), "map")
self.assertEqual(self.check_mapping_then_sequence(GrandchildPost()), "map")
def test_late_registration_sequence(self):
class Parent:
pass
class ChildPre(Parent):
pass
class GrandchildPre(ChildPre):
pass
collections.abc.Sequence.register(Parent)
class ChildPost(Parent):
pass
class GrandchildPost(ChildPost):
pass
self.assertEqual(self.check_sequence_then_mapping(Parent()), "seq")
self.assertEqual(self.check_sequence_then_mapping(ChildPre()), "seq")
self.assertEqual(self.check_sequence_then_mapping(GrandchildPre()), "seq")
self.assertEqual(self.check_sequence_then_mapping(ChildPost()), "seq")
self.assertEqual(self.check_sequence_then_mapping(GrandchildPost()), "seq")
self.assertEqual(self.check_mapping_then_sequence(Parent()), "seq")
self.assertEqual(self.check_mapping_then_sequence(ChildPre()), "seq")
self.assertEqual(self.check_mapping_then_sequence(GrandchildPre()), "seq")
self.assertEqual(self.check_mapping_then_sequence(ChildPost()), "seq")
self.assertEqual(self.check_mapping_then_sequence(GrandchildPost()), "seq")
class TestPatma(unittest.TestCase):