1 import unittest
2 from test import support
3
4
5 class ESC[4;38;5;81mTestMROEntry(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
6 def test_mro_entry_signature(self):
7 tested = []
8 class ESC[4;38;5;81mB: ...
9 class ESC[4;38;5;81mC:
10 def __mro_entries__(self, *args, **kwargs):
11 tested.extend([args, kwargs])
12 return (C,)
13 c = C()
14 self.assertEqual(tested, [])
15 class ESC[4;38;5;81mD(ESC[4;38;5;149mB, ESC[4;38;5;149mc): ...
16 self.assertEqual(tested[0], ((B, c),))
17 self.assertEqual(tested[1], {})
18
19 def test_mro_entry(self):
20 tested = []
21 class ESC[4;38;5;81mA: ...
22 class ESC[4;38;5;81mB: ...
23 class ESC[4;38;5;81mC:
24 def __mro_entries__(self, bases):
25 tested.append(bases)
26 return (self.__class__,)
27 c = C()
28 self.assertEqual(tested, [])
29 class ESC[4;38;5;81mD(ESC[4;38;5;149mA, ESC[4;38;5;149mc, ESC[4;38;5;149mB): ...
30 self.assertEqual(tested[-1], (A, c, B))
31 self.assertEqual(D.__bases__, (A, C, B))
32 self.assertEqual(D.__orig_bases__, (A, c, B))
33 self.assertEqual(D.__mro__, (D, A, C, B, object))
34 d = D()
35 class ESC[4;38;5;81mE(ESC[4;38;5;149md): ...
36 self.assertEqual(tested[-1], (d,))
37 self.assertEqual(E.__bases__, (D,))
38
39 def test_mro_entry_none(self):
40 tested = []
41 class ESC[4;38;5;81mA: ...
42 class ESC[4;38;5;81mB: ...
43 class ESC[4;38;5;81mC:
44 def __mro_entries__(self, bases):
45 tested.append(bases)
46 return ()
47 c = C()
48 self.assertEqual(tested, [])
49 class ESC[4;38;5;81mD(ESC[4;38;5;149mA, ESC[4;38;5;149mc, ESC[4;38;5;149mB): ...
50 self.assertEqual(tested[-1], (A, c, B))
51 self.assertEqual(D.__bases__, (A, B))
52 self.assertEqual(D.__orig_bases__, (A, c, B))
53 self.assertEqual(D.__mro__, (D, A, B, object))
54 class ESC[4;38;5;81mE(ESC[4;38;5;149mc): ...
55 self.assertEqual(tested[-1], (c,))
56 self.assertEqual(E.__bases__, (object,))
57 self.assertEqual(E.__orig_bases__, (c,))
58 self.assertEqual(E.__mro__, (E, object))
59
60 def test_mro_entry_with_builtins(self):
61 tested = []
62 class ESC[4;38;5;81mA: ...
63 class ESC[4;38;5;81mC:
64 def __mro_entries__(self, bases):
65 tested.append(bases)
66 return (dict,)
67 c = C()
68 self.assertEqual(tested, [])
69 class ESC[4;38;5;81mD(ESC[4;38;5;149mA, ESC[4;38;5;149mc): ...
70 self.assertEqual(tested[-1], (A, c))
71 self.assertEqual(D.__bases__, (A, dict))
72 self.assertEqual(D.__orig_bases__, (A, c))
73 self.assertEqual(D.__mro__, (D, A, dict, object))
74
75 def test_mro_entry_with_builtins_2(self):
76 tested = []
77 class ESC[4;38;5;81mC:
78 def __mro_entries__(self, bases):
79 tested.append(bases)
80 return (C,)
81 c = C()
82 self.assertEqual(tested, [])
83 class ESC[4;38;5;81mD(ESC[4;38;5;149mc, ESC[4;38;5;149mdict): ...
84 self.assertEqual(tested[-1], (c, dict))
85 self.assertEqual(D.__bases__, (C, dict))
86 self.assertEqual(D.__orig_bases__, (c, dict))
87 self.assertEqual(D.__mro__, (D, C, dict, object))
88
89 def test_mro_entry_errors(self):
90 class ESC[4;38;5;81mC_too_many:
91 def __mro_entries__(self, bases, something, other):
92 return ()
93 c = C_too_many()
94 with self.assertRaises(TypeError):
95 class ESC[4;38;5;81mD(ESC[4;38;5;149mc): ...
96 class ESC[4;38;5;81mC_too_few:
97 def __mro_entries__(self):
98 return ()
99 d = C_too_few()
100 with self.assertRaises(TypeError):
101 class ESC[4;38;5;81mE(ESC[4;38;5;149md): ...
102
103 def test_mro_entry_errors_2(self):
104 class ESC[4;38;5;81mC_not_callable:
105 __mro_entries__ = "Surprise!"
106 c = C_not_callable()
107 with self.assertRaises(TypeError):
108 class ESC[4;38;5;81mD(ESC[4;38;5;149mc): ...
109 class ESC[4;38;5;81mC_not_tuple:
110 def __mro_entries__(self):
111 return object
112 c = C_not_tuple()
113 with self.assertRaises(TypeError):
114 class ESC[4;38;5;81mE(ESC[4;38;5;149mc): ...
115
116 def test_mro_entry_metaclass(self):
117 meta_args = []
118 class ESC[4;38;5;81mMeta(ESC[4;38;5;149mtype):
119 def __new__(mcls, name, bases, ns):
120 meta_args.extend([mcls, name, bases, ns])
121 return super().__new__(mcls, name, bases, ns)
122 class ESC[4;38;5;81mA: ...
123 class ESC[4;38;5;81mC:
124 def __mro_entries__(self, bases):
125 return (A,)
126 c = C()
127 class ESC[4;38;5;81mD(ESC[4;38;5;149mc, metaclass=ESC[4;38;5;149mMeta):
128 x = 1
129 self.assertEqual(meta_args[0], Meta)
130 self.assertEqual(meta_args[1], 'D')
131 self.assertEqual(meta_args[2], (A,))
132 self.assertEqual(meta_args[3]['x'], 1)
133 self.assertEqual(D.__bases__, (A,))
134 self.assertEqual(D.__orig_bases__, (c,))
135 self.assertEqual(D.__mro__, (D, A, object))
136 self.assertEqual(D.__class__, Meta)
137
138 def test_mro_entry_type_call(self):
139 # Substitution should _not_ happen in direct type call
140 class ESC[4;38;5;81mC:
141 def __mro_entries__(self, bases):
142 return ()
143 c = C()
144 with self.assertRaisesRegex(TypeError,
145 "MRO entry resolution; "
146 "use types.new_class()"):
147 type('Bad', (c,), {})
148
149
150 class ESC[4;38;5;81mTestClassGetitem(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
151 def test_class_getitem(self):
152 getitem_args = []
153 class ESC[4;38;5;81mC:
154 def __class_getitem__(*args, **kwargs):
155 getitem_args.extend([args, kwargs])
156 return None
157 C[int, str]
158 self.assertEqual(getitem_args[0], (C, (int, str)))
159 self.assertEqual(getitem_args[1], {})
160
161 def test_class_getitem_format(self):
162 class ESC[4;38;5;81mC:
163 def __class_getitem__(cls, item):
164 return f'C[{item.__name__}]'
165 self.assertEqual(C[int], 'C[int]')
166 self.assertEqual(C[C], 'C[C]')
167
168 def test_class_getitem_inheritance(self):
169 class ESC[4;38;5;81mC:
170 def __class_getitem__(cls, item):
171 return f'{cls.__name__}[{item.__name__}]'
172 class ESC[4;38;5;81mD(ESC[4;38;5;149mC): ...
173 self.assertEqual(D[int], 'D[int]')
174 self.assertEqual(D[D], 'D[D]')
175
176 def test_class_getitem_inheritance_2(self):
177 class ESC[4;38;5;81mC:
178 def __class_getitem__(cls, item):
179 return 'Should not see this'
180 class ESC[4;38;5;81mD(ESC[4;38;5;149mC):
181 def __class_getitem__(cls, item):
182 return f'{cls.__name__}[{item.__name__}]'
183 self.assertEqual(D[int], 'D[int]')
184 self.assertEqual(D[D], 'D[D]')
185
186 def test_class_getitem_classmethod(self):
187 class ESC[4;38;5;81mC:
188 @classmethod
189 def __class_getitem__(cls, item):
190 return f'{cls.__name__}[{item.__name__}]'
191 class ESC[4;38;5;81mD(ESC[4;38;5;149mC): ...
192 self.assertEqual(D[int], 'D[int]')
193 self.assertEqual(D[D], 'D[D]')
194
195 def test_class_getitem_patched(self):
196 class ESC[4;38;5;81mC:
197 def __init_subclass__(cls):
198 def __class_getitem__(cls, item):
199 return f'{cls.__name__}[{item.__name__}]'
200 cls.__class_getitem__ = classmethod(__class_getitem__)
201 class ESC[4;38;5;81mD(ESC[4;38;5;149mC): ...
202 self.assertEqual(D[int], 'D[int]')
203 self.assertEqual(D[D], 'D[D]')
204
205 def test_class_getitem_with_builtins(self):
206 class ESC[4;38;5;81mA(ESC[4;38;5;149mdict):
207 called_with = None
208
209 def __class_getitem__(cls, item):
210 cls.called_with = item
211 class ESC[4;38;5;81mB(ESC[4;38;5;149mA):
212 pass
213 self.assertIs(B.called_with, None)
214 B[int]
215 self.assertIs(B.called_with, int)
216
217 def test_class_getitem_errors(self):
218 class ESC[4;38;5;81mC_too_few:
219 def __class_getitem__(cls):
220 return None
221 with self.assertRaises(TypeError):
222 C_too_few[int]
223
224 class ESC[4;38;5;81mC_too_many:
225 def __class_getitem__(cls, one, two):
226 return None
227 with self.assertRaises(TypeError):
228 C_too_many[int]
229
230 def test_class_getitem_errors_2(self):
231 class ESC[4;38;5;81mC:
232 def __class_getitem__(cls, item):
233 return None
234 with self.assertRaises(TypeError):
235 C()[int]
236
237 class ESC[4;38;5;81mE: ...
238 e = E()
239 e.__class_getitem__ = lambda cls, item: 'This will not work'
240 with self.assertRaises(TypeError):
241 e[int]
242
243 class ESC[4;38;5;81mC_not_callable:
244 __class_getitem__ = "Surprise!"
245 with self.assertRaises(TypeError):
246 C_not_callable[int]
247
248 class ESC[4;38;5;81mC_is_none(ESC[4;38;5;149mtuple):
249 __class_getitem__ = None
250 with self.assertRaisesRegex(TypeError, "C_is_none"):
251 C_is_none[int]
252
253 def test_class_getitem_metaclass(self):
254 class ESC[4;38;5;81mMeta(ESC[4;38;5;149mtype):
255 def __class_getitem__(cls, item):
256 return f'{cls.__name__}[{item.__name__}]'
257 self.assertEqual(Meta[int], 'Meta[int]')
258
259 def test_class_getitem_with_metaclass(self):
260 class ESC[4;38;5;81mMeta(ESC[4;38;5;149mtype): pass
261 class ESC[4;38;5;81mC(metaclass=ESC[4;38;5;149mMeta):
262 def __class_getitem__(cls, item):
263 return f'{cls.__name__}[{item.__name__}]'
264 self.assertEqual(C[int], 'C[int]')
265
266 def test_class_getitem_metaclass_first(self):
267 class ESC[4;38;5;81mMeta(ESC[4;38;5;149mtype):
268 def __getitem__(cls, item):
269 return 'from metaclass'
270 class ESC[4;38;5;81mC(metaclass=ESC[4;38;5;149mMeta):
271 def __class_getitem__(cls, item):
272 return 'from __class_getitem__'
273 self.assertEqual(C[int], 'from metaclass')
274
275
276 @support.cpython_only
277 class ESC[4;38;5;81mCAPITest(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
278
279 def test_c_class(self):
280 from _testcapi import Generic, GenericAlias
281 self.assertIsInstance(Generic.__class_getitem__(int), GenericAlias)
282
283 IntGeneric = Generic[int]
284 self.assertIs(type(IntGeneric), GenericAlias)
285 self.assertEqual(IntGeneric.__mro_entries__(()), (int,))
286 class ESC[4;38;5;81mC(ESC[4;38;5;149mIntGeneric):
287 pass
288 self.assertEqual(C.__bases__, (int,))
289 self.assertEqual(C.__orig_bases__, (IntGeneric,))
290 self.assertEqual(C.__mro__, (C, int, object))
291
292
293 if __name__ == "__main__":
294 unittest.main()