Skip to content

Commit bc06c6b

Browse files
Ivan Levkivskyiilevkivskyi
authored andcommitted
Add tests for __subclass_base__
1 parent c2d8ac2 commit bc06c6b

1 file changed

Lines changed: 124 additions & 7 deletions

File tree

Lib/test/test_genericclass.py

Lines changed: 124 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,140 @@
22

33

44
class TestSubclassBase(unittest.TestCase):
5+
def test_subclass_base_signature(self):
6+
tested = []
7+
class B: ...
8+
class C:
9+
def __subclass_base__(self, *args, **kwargs):
10+
tested.extend([args, kwargs])
11+
return C
12+
c = C()
13+
self.assertEqual(tested, [])
14+
class D(B, c): ...
15+
self.assertEqual(tested[0], ((B, c),))
16+
self.assertEqual(tested[1], {})
17+
518
def test_subclass_base(self):
6-
pass
19+
tested = []
20+
class A: ...
21+
class B: ...
22+
class C:
23+
def __subclass_base__(self, bases):
24+
tested.append(bases)
25+
return self.__class__
26+
c = C()
27+
self.assertEqual(tested, [])
28+
class D(A, c, B): ...
29+
self.assertEqual(tested[-1], (A, c, B))
30+
self.assertEqual(D.__bases__, (A, C, B))
31+
self.assertEqual(D.__orig_bases__, (A, c, B))
32+
self.assertEqual(D.__mro__, (D, A, C, B, object))
33+
d = D()
34+
class E(d): ...
35+
self.assertEqual(tested[-1], (d,))
36+
self.assertEqual(E.__bases__, (D,))
37+
38+
def test_subclass_base_none(self):
39+
tested = []
40+
class A: ...
41+
class B: ...
42+
class C:
43+
def __subclass_base__(self, bases):
44+
tested.append(bases)
45+
return None
46+
c = C()
47+
self.assertEqual(tested, [])
48+
class D(A, c, B): ...
49+
self.assertEqual(tested[-1], (A, c, B))
50+
self.assertEqual(D.__bases__, (A, B))
51+
self.assertEqual(D.__orig_bases__, (A, c, B))
52+
self.assertEqual(D.__mro__, (D, A, B, object))
53+
class E(c): ...
54+
self.assertEqual(tested[-1], (c,))
55+
self.assertEqual(E.__bases__, (object,))
56+
self.assertEqual(E.__orig_bases__, (c,))
57+
self.assertEqual(E.__mro__, (E, object))
758

859
def test_subclass_base_with_builtins(self):
9-
pass
60+
tested = []
61+
class A: ...
62+
class C:
63+
def __subclass_base__(self, bases):
64+
tested.append(bases)
65+
return dict
66+
c = C()
67+
self.assertEqual(tested, [])
68+
class D(A, c): ...
69+
self.assertEqual(tested[-1], (A, c))
70+
self.assertEqual(D.__bases__, (A, dict))
71+
self.assertEqual(D.__orig_bases__, (A, c))
72+
self.assertEqual(D.__mro__, (D, A, dict, object))
73+
74+
def test_subclass_base_with_builtins_2(self):
75+
tested = []
76+
class C:
77+
def __subclass_base__(self, bases):
78+
tested.append(bases)
79+
return C
80+
c = C()
81+
self.assertEqual(tested, [])
82+
class D(c, dict): ...
83+
self.assertEqual(tested[-1], (c, dict))
84+
self.assertEqual(D.__bases__, (C, dict))
85+
self.assertEqual(D.__orig_bases__, (c, dict))
86+
self.assertEqual(D.__mro__, (D, C, dict, object))
1087

1188
def test_subclass_base_errors(self):
12-
pass
89+
class C_too_many:
90+
def __subclass_base__(self, bases, something, other):
91+
return None
92+
c = C_too_many()
93+
with self.assertRaises(TypeError):
94+
class D(c): ...
95+
class C_too_few:
96+
def __subclass_base__(self, bases, something, other):
97+
return None
98+
d = C_too_few()
99+
with self.assertRaises(TypeError):
100+
class D(d): ...
13101

14-
def test_subclass_base_wrong(self):
15-
pass
102+
def test_subclass_base_errors_2(self):
103+
class C_not_callable:
104+
__subclass_base__ = "Surprise!"
105+
c = C_not_callable()
106+
with self.assertRaises(TypeError):
107+
class D(c): ...
16108

17109
def test_subclass_base_metaclass(self):
18-
pass
110+
meta_args = []
111+
class Meta(type):
112+
def __new__(mcls, name, bases, ns):
113+
meta_args.extend([mcls, name, bases, ns])
114+
return super().__new__(mcls, name, bases, ns)
115+
class A: ...
116+
class C:
117+
def __subclass_base__(self, bases):
118+
return A
119+
c = C()
120+
class D(c, metaclass=Meta):
121+
x = 1
122+
self.assertEqual(meta_args[0], Meta)
123+
self.assertEqual(meta_args[1], 'D')
124+
self.assertEqual(meta_args[2], (A,))
125+
self.assertEqual(meta_args[3]['x'], 1)
126+
self.assertEqual(D.__bases__, (A,))
127+
self.assertEqual(D.__orig_bases__, (c,))
128+
self.assertEqual(D.__mro__, (D, A, object))
129+
self.assertEqual(D.__class__, Meta)
19130

20131
def test_subclass_base_type_call(self):
21-
pass
132+
# Substitution should _not_ happen in direct type call
133+
class C:
134+
def __subclass_base__(self, bases):
135+
return None
136+
c = C()
137+
with self.assertRaises(TypeError):
138+
type('Bad', (c,), {})
22139

23140

24141
class TestClassGetitem(unittest.TestCase):

0 commit comments

Comments
 (0)