1 # Copyright 2007 Google, Inc. All Rights Reserved.
2 # Licensed to PSF under a Contributor Agreement.
3
4 # Note: each test is run with Python and C versions of ABCMeta. Except for
5 # test_ABC_helper(), which assures that abc.ABC is an instance of abc.ABCMeta.
6
7 """Unit tests for abc.py."""
8
9 import unittest
10
11 import abc
12 import _py_abc
13 from inspect import isabstract
14
15 def test_factory(abc_ABCMeta, abc_get_cache_token):
16 class ESC[4;38;5;81mTestLegacyAPI(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
17
18 def test_abstractproperty_basics(self):
19 @abc.abstractproperty
20 def foo(self): pass
21 self.assertTrue(foo.__isabstractmethod__)
22 def bar(self): pass
23 self.assertFalse(hasattr(bar, "__isabstractmethod__"))
24
25 class ESC[4;38;5;81mC(metaclass=ESC[4;38;5;149mabc_ABCMeta):
26 @abc.abstractproperty
27 def foo(self): return 3
28 self.assertRaises(TypeError, C)
29 class ESC[4;38;5;81mD(ESC[4;38;5;149mC):
30 @property
31 def foo(self): return super().foo
32 self.assertEqual(D().foo, 3)
33 self.assertFalse(getattr(D.foo, "__isabstractmethod__", False))
34
35 def test_abstractclassmethod_basics(self):
36 @abc.abstractclassmethod
37 def foo(cls): pass
38 self.assertTrue(foo.__isabstractmethod__)
39 @classmethod
40 def bar(cls): pass
41 self.assertFalse(getattr(bar, "__isabstractmethod__", False))
42
43 class ESC[4;38;5;81mC(metaclass=ESC[4;38;5;149mabc_ABCMeta):
44 @abc.abstractclassmethod
45 def foo(cls): return cls.__name__
46 self.assertRaises(TypeError, C)
47 class ESC[4;38;5;81mD(ESC[4;38;5;149mC):
48 @classmethod
49 def foo(cls): return super().foo()
50 self.assertEqual(D.foo(), 'D')
51 self.assertEqual(D().foo(), 'D')
52
53 def test_abstractstaticmethod_basics(self):
54 @abc.abstractstaticmethod
55 def foo(): pass
56 self.assertTrue(foo.__isabstractmethod__)
57 @staticmethod
58 def bar(): pass
59 self.assertFalse(getattr(bar, "__isabstractmethod__", False))
60
61 class ESC[4;38;5;81mC(metaclass=ESC[4;38;5;149mabc_ABCMeta):
62 @abc.abstractstaticmethod
63 def foo(): return 3
64 self.assertRaises(TypeError, C)
65 class ESC[4;38;5;81mD(ESC[4;38;5;149mC):
66 @staticmethod
67 def foo(): return 4
68 self.assertEqual(D.foo(), 4)
69 self.assertEqual(D().foo(), 4)
70
71
72 class ESC[4;38;5;81mTestABC(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
73
74 def test_ABC_helper(self):
75 # create an ABC using the helper class and perform basic checks
76 class ESC[4;38;5;81mC(ESC[4;38;5;149mabcESC[4;38;5;149m.ESC[4;38;5;149mABC):
77 @classmethod
78 @abc.abstractmethod
79 def foo(cls): return cls.__name__
80 self.assertEqual(type(C), abc.ABCMeta)
81 self.assertRaises(TypeError, C)
82 class ESC[4;38;5;81mD(ESC[4;38;5;149mC):
83 @classmethod
84 def foo(cls): return super().foo()
85 self.assertEqual(D.foo(), 'D')
86
87 def test_abstractmethod_basics(self):
88 @abc.abstractmethod
89 def foo(self): pass
90 self.assertTrue(foo.__isabstractmethod__)
91 def bar(self): pass
92 self.assertFalse(hasattr(bar, "__isabstractmethod__"))
93
94 def test_abstractproperty_basics(self):
95 @property
96 @abc.abstractmethod
97 def foo(self): pass
98 self.assertTrue(foo.__isabstractmethod__)
99 def bar(self): pass
100 self.assertFalse(getattr(bar, "__isabstractmethod__", False))
101
102 class ESC[4;38;5;81mC(metaclass=ESC[4;38;5;149mabc_ABCMeta):
103 @property
104 @abc.abstractmethod
105 def foo(self): return 3
106 self.assertRaises(TypeError, C)
107 class ESC[4;38;5;81mD(ESC[4;38;5;149mC):
108 @C.foo.getter
109 def foo(self): return super().foo
110 self.assertEqual(D().foo, 3)
111
112 def test_abstractclassmethod_basics(self):
113 @classmethod
114 @abc.abstractmethod
115 def foo(cls): pass
116 self.assertTrue(foo.__isabstractmethod__)
117 @classmethod
118 def bar(cls): pass
119 self.assertFalse(getattr(bar, "__isabstractmethod__", False))
120
121 class ESC[4;38;5;81mC(metaclass=ESC[4;38;5;149mabc_ABCMeta):
122 @classmethod
123 @abc.abstractmethod
124 def foo(cls): return cls.__name__
125 self.assertRaises(TypeError, C)
126 class ESC[4;38;5;81mD(ESC[4;38;5;149mC):
127 @classmethod
128 def foo(cls): return super().foo()
129 self.assertEqual(D.foo(), 'D')
130 self.assertEqual(D().foo(), 'D')
131
132 def test_abstractstaticmethod_basics(self):
133 @staticmethod
134 @abc.abstractmethod
135 def foo(): pass
136 self.assertTrue(foo.__isabstractmethod__)
137 @staticmethod
138 def bar(): pass
139 self.assertFalse(getattr(bar, "__isabstractmethod__", False))
140
141 class ESC[4;38;5;81mC(metaclass=ESC[4;38;5;149mabc_ABCMeta):
142 @staticmethod
143 @abc.abstractmethod
144 def foo(): return 3
145 self.assertRaises(TypeError, C)
146 class ESC[4;38;5;81mD(ESC[4;38;5;149mC):
147 @staticmethod
148 def foo(): return 4
149 self.assertEqual(D.foo(), 4)
150 self.assertEqual(D().foo(), 4)
151
152 def test_object_new_with_one_abstractmethod(self):
153 class ESC[4;38;5;81mC(metaclass=ESC[4;38;5;149mabc_ABCMeta):
154 @abc.abstractmethod
155 def method_one(self):
156 pass
157 msg = r"class C with abstract method method_one"
158 self.assertRaisesRegex(TypeError, msg, C)
159
160 def test_object_new_with_many_abstractmethods(self):
161 class ESC[4;38;5;81mC(metaclass=ESC[4;38;5;149mabc_ABCMeta):
162 @abc.abstractmethod
163 def method_one(self):
164 pass
165 @abc.abstractmethod
166 def method_two(self):
167 pass
168 msg = r"class C with abstract methods method_one, method_two"
169 self.assertRaisesRegex(TypeError, msg, C)
170
171 def test_abstractmethod_integration(self):
172 for abstractthing in [abc.abstractmethod, abc.abstractproperty,
173 abc.abstractclassmethod,
174 abc.abstractstaticmethod]:
175 class ESC[4;38;5;81mC(metaclass=ESC[4;38;5;149mabc_ABCMeta):
176 @abstractthing
177 def foo(self): pass # abstract
178 def bar(self): pass # concrete
179 self.assertEqual(C.__abstractmethods__, {"foo"})
180 self.assertRaises(TypeError, C) # because foo is abstract
181 self.assertTrue(isabstract(C))
182 class ESC[4;38;5;81mD(ESC[4;38;5;149mC):
183 def bar(self): pass # concrete override of concrete
184 self.assertEqual(D.__abstractmethods__, {"foo"})
185 self.assertRaises(TypeError, D) # because foo is still abstract
186 self.assertTrue(isabstract(D))
187 class ESC[4;38;5;81mE(ESC[4;38;5;149mD):
188 def foo(self): pass
189 self.assertEqual(E.__abstractmethods__, set())
190 E() # now foo is concrete, too
191 self.assertFalse(isabstract(E))
192 class ESC[4;38;5;81mF(ESC[4;38;5;149mE):
193 @abstractthing
194 def bar(self): pass # abstract override of concrete
195 self.assertEqual(F.__abstractmethods__, {"bar"})
196 self.assertRaises(TypeError, F) # because bar is abstract now
197 self.assertTrue(isabstract(F))
198
199 def test_descriptors_with_abstractmethod(self):
200 class ESC[4;38;5;81mC(metaclass=ESC[4;38;5;149mabc_ABCMeta):
201 @property
202 @abc.abstractmethod
203 def foo(self): return 3
204 @foo.setter
205 @abc.abstractmethod
206 def foo(self, val): pass
207 self.assertRaises(TypeError, C)
208 class ESC[4;38;5;81mD(ESC[4;38;5;149mC):
209 @C.foo.getter
210 def foo(self): return super().foo
211 self.assertRaises(TypeError, D)
212 class ESC[4;38;5;81mE(ESC[4;38;5;149mD):
213 @D.foo.setter
214 def foo(self, val): pass
215 self.assertEqual(E().foo, 3)
216 # check that the property's __isabstractmethod__ descriptor does the
217 # right thing when presented with a value that fails truth testing:
218 class ESC[4;38;5;81mNotBool(ESC[4;38;5;149mobject):
219 def __bool__(self):
220 raise ValueError()
221 __len__ = __bool__
222 with self.assertRaises(ValueError):
223 class ESC[4;38;5;81mF(ESC[4;38;5;149mC):
224 def bar(self):
225 pass
226 bar.__isabstractmethod__ = NotBool()
227 foo = property(bar)
228
229
230 def test_customdescriptors_with_abstractmethod(self):
231 class ESC[4;38;5;81mDescriptor:
232 def __init__(self, fget, fset=None):
233 self._fget = fget
234 self._fset = fset
235 def getter(self, callable):
236 return Descriptor(callable, self._fget)
237 def setter(self, callable):
238 return Descriptor(self._fget, callable)
239 @property
240 def __isabstractmethod__(self):
241 return (getattr(self._fget, '__isabstractmethod__', False)
242 or getattr(self._fset, '__isabstractmethod__', False))
243 class ESC[4;38;5;81mC(metaclass=ESC[4;38;5;149mabc_ABCMeta):
244 @Descriptor
245 @abc.abstractmethod
246 def foo(self): return 3
247 @foo.setter
248 @abc.abstractmethod
249 def foo(self, val): pass
250 self.assertRaises(TypeError, C)
251 class ESC[4;38;5;81mD(ESC[4;38;5;149mC):
252 @C.foo.getter
253 def foo(self): return super().foo
254 self.assertRaises(TypeError, D)
255 class ESC[4;38;5;81mE(ESC[4;38;5;149mD):
256 @D.foo.setter
257 def foo(self, val): pass
258 self.assertFalse(E.foo.__isabstractmethod__)
259
260 def test_metaclass_abc(self):
261 # Metaclasses can be ABCs, too.
262 class ESC[4;38;5;81mA(metaclass=ESC[4;38;5;149mabc_ABCMeta):
263 @abc.abstractmethod
264 def x(self):
265 pass
266 self.assertEqual(A.__abstractmethods__, {"x"})
267 class ESC[4;38;5;81mmeta(ESC[4;38;5;149mtype, ESC[4;38;5;149mA):
268 def x(self):
269 return 1
270 class ESC[4;38;5;81mC(metaclass=ESC[4;38;5;149mmeta):
271 pass
272
273 def test_registration_basics(self):
274 class ESC[4;38;5;81mA(metaclass=ESC[4;38;5;149mabc_ABCMeta):
275 pass
276 class ESC[4;38;5;81mB(ESC[4;38;5;149mobject):
277 pass
278 b = B()
279 self.assertFalse(issubclass(B, A))
280 self.assertFalse(issubclass(B, (A,)))
281 self.assertNotIsInstance(b, A)
282 self.assertNotIsInstance(b, (A,))
283 B1 = A.register(B)
284 self.assertTrue(issubclass(B, A))
285 self.assertTrue(issubclass(B, (A,)))
286 self.assertIsInstance(b, A)
287 self.assertIsInstance(b, (A,))
288 self.assertIs(B1, B)
289 class ESC[4;38;5;81mC(ESC[4;38;5;149mB):
290 pass
291 c = C()
292 self.assertTrue(issubclass(C, A))
293 self.assertTrue(issubclass(C, (A,)))
294 self.assertIsInstance(c, A)
295 self.assertIsInstance(c, (A,))
296
297 def test_register_as_class_deco(self):
298 class ESC[4;38;5;81mA(metaclass=ESC[4;38;5;149mabc_ABCMeta):
299 pass
300 @A.register
301 class ESC[4;38;5;81mB(ESC[4;38;5;149mobject):
302 pass
303 b = B()
304 self.assertTrue(issubclass(B, A))
305 self.assertTrue(issubclass(B, (A,)))
306 self.assertIsInstance(b, A)
307 self.assertIsInstance(b, (A,))
308 @A.register
309 class ESC[4;38;5;81mC(ESC[4;38;5;149mB):
310 pass
311 c = C()
312 self.assertTrue(issubclass(C, A))
313 self.assertTrue(issubclass(C, (A,)))
314 self.assertIsInstance(c, A)
315 self.assertIsInstance(c, (A,))
316 self.assertIs(C, A.register(C))
317
318 def test_isinstance_invalidation(self):
319 class ESC[4;38;5;81mA(metaclass=ESC[4;38;5;149mabc_ABCMeta):
320 pass
321 class ESC[4;38;5;81mB:
322 pass
323 b = B()
324 self.assertFalse(isinstance(b, A))
325 self.assertFalse(isinstance(b, (A,)))
326 token_old = abc_get_cache_token()
327 A.register(B)
328 token_new = abc_get_cache_token()
329 self.assertGreater(token_new, token_old)
330 self.assertTrue(isinstance(b, A))
331 self.assertTrue(isinstance(b, (A,)))
332
333 def test_registration_builtins(self):
334 class ESC[4;38;5;81mA(metaclass=ESC[4;38;5;149mabc_ABCMeta):
335 pass
336 A.register(int)
337 self.assertIsInstance(42, A)
338 self.assertIsInstance(42, (A,))
339 self.assertTrue(issubclass(int, A))
340 self.assertTrue(issubclass(int, (A,)))
341 class ESC[4;38;5;81mB(ESC[4;38;5;149mA):
342 pass
343 B.register(str)
344 class ESC[4;38;5;81mC(ESC[4;38;5;149mstr): pass
345 self.assertIsInstance("", A)
346 self.assertIsInstance("", (A,))
347 self.assertTrue(issubclass(str, A))
348 self.assertTrue(issubclass(str, (A,)))
349 self.assertTrue(issubclass(C, A))
350 self.assertTrue(issubclass(C, (A,)))
351
352 def test_registration_edge_cases(self):
353 class ESC[4;38;5;81mA(metaclass=ESC[4;38;5;149mabc_ABCMeta):
354 pass
355 A.register(A) # should pass silently
356 class ESC[4;38;5;81mA1(ESC[4;38;5;149mA):
357 pass
358 self.assertRaises(RuntimeError, A1.register, A) # cycles not allowed
359 class ESC[4;38;5;81mB(ESC[4;38;5;149mobject):
360 pass
361 A1.register(B) # ok
362 A1.register(B) # should pass silently
363 class ESC[4;38;5;81mC(ESC[4;38;5;149mA):
364 pass
365 A.register(C) # should pass silently
366 self.assertRaises(RuntimeError, C.register, A) # cycles not allowed
367 C.register(B) # ok
368
369 def test_register_non_class(self):
370 class ESC[4;38;5;81mA(metaclass=ESC[4;38;5;149mabc_ABCMeta):
371 pass
372 self.assertRaisesRegex(TypeError, "Can only register classes",
373 A.register, 4)
374
375 def test_registration_transitiveness(self):
376 class ESC[4;38;5;81mA(metaclass=ESC[4;38;5;149mabc_ABCMeta):
377 pass
378 self.assertTrue(issubclass(A, A))
379 self.assertTrue(issubclass(A, (A,)))
380 class ESC[4;38;5;81mB(metaclass=ESC[4;38;5;149mabc_ABCMeta):
381 pass
382 self.assertFalse(issubclass(A, B))
383 self.assertFalse(issubclass(A, (B,)))
384 self.assertFalse(issubclass(B, A))
385 self.assertFalse(issubclass(B, (A,)))
386 class ESC[4;38;5;81mC(metaclass=ESC[4;38;5;149mabc_ABCMeta):
387 pass
388 A.register(B)
389 class ESC[4;38;5;81mB1(ESC[4;38;5;149mB):
390 pass
391 self.assertTrue(issubclass(B1, A))
392 self.assertTrue(issubclass(B1, (A,)))
393 class ESC[4;38;5;81mC1(ESC[4;38;5;149mC):
394 pass
395 B1.register(C1)
396 self.assertFalse(issubclass(C, B))
397 self.assertFalse(issubclass(C, (B,)))
398 self.assertFalse(issubclass(C, B1))
399 self.assertFalse(issubclass(C, (B1,)))
400 self.assertTrue(issubclass(C1, A))
401 self.assertTrue(issubclass(C1, (A,)))
402 self.assertTrue(issubclass(C1, B))
403 self.assertTrue(issubclass(C1, (B,)))
404 self.assertTrue(issubclass(C1, B1))
405 self.assertTrue(issubclass(C1, (B1,)))
406 C1.register(int)
407 class ESC[4;38;5;81mMyInt(ESC[4;38;5;149mint):
408 pass
409 self.assertTrue(issubclass(MyInt, A))
410 self.assertTrue(issubclass(MyInt, (A,)))
411 self.assertIsInstance(42, A)
412 self.assertIsInstance(42, (A,))
413
414 def test_issubclass_bad_arguments(self):
415 class ESC[4;38;5;81mA(metaclass=ESC[4;38;5;149mabc_ABCMeta):
416 pass
417
418 with self.assertRaises(TypeError):
419 issubclass({}, A) # unhashable
420
421 with self.assertRaises(TypeError):
422 issubclass(42, A) # No __mro__
423
424 # Python version supports any iterable as __mro__.
425 # But it's implementation detail and don't emulate it in C version.
426 class ESC[4;38;5;81mC:
427 __mro__ = 42 # __mro__ is not tuple
428
429 with self.assertRaises(TypeError):
430 issubclass(C(), A)
431
432 # bpo-34441: Check that issubclass() doesn't crash on bogus
433 # classes.
434 bogus_subclasses = [
435 None,
436 lambda x: [],
437 lambda: 42,
438 lambda: [42],
439 ]
440
441 for i, func in enumerate(bogus_subclasses):
442 class ESC[4;38;5;81mS(metaclass=ESC[4;38;5;149mabc_ABCMeta):
443 __subclasses__ = func
444
445 with self.subTest(i=i):
446 with self.assertRaises(TypeError):
447 issubclass(int, S)
448
449 # Also check that issubclass() propagates exceptions raised by
450 # __subclasses__.
451 class ESC[4;38;5;81mCustomError(ESC[4;38;5;149mException): ...
452 exc_msg = "exception from __subclasses__"
453
454 def raise_exc():
455 raise CustomError(exc_msg)
456
457 class ESC[4;38;5;81mS(metaclass=ESC[4;38;5;149mabc_ABCMeta):
458 __subclasses__ = raise_exc
459
460 with self.assertRaisesRegex(CustomError, exc_msg):
461 issubclass(int, S)
462
463 def test_subclasshook(self):
464 class ESC[4;38;5;81mA(metaclass=ESC[4;38;5;149mabcESC[4;38;5;149m.ESC[4;38;5;149mABCMeta):
465 @classmethod
466 def __subclasshook__(cls, C):
467 if cls is A:
468 return 'foo' in C.__dict__
469 return NotImplemented
470 self.assertFalse(issubclass(A, A))
471 self.assertFalse(issubclass(A, (A,)))
472 class ESC[4;38;5;81mB:
473 foo = 42
474 self.assertTrue(issubclass(B, A))
475 self.assertTrue(issubclass(B, (A,)))
476 class ESC[4;38;5;81mC:
477 spam = 42
478 self.assertFalse(issubclass(C, A))
479 self.assertFalse(issubclass(C, (A,)))
480
481 def test_all_new_methods_are_called(self):
482 class ESC[4;38;5;81mA(metaclass=ESC[4;38;5;149mabc_ABCMeta):
483 pass
484 class ESC[4;38;5;81mB(ESC[4;38;5;149mobject):
485 counter = 0
486 def __new__(cls):
487 B.counter += 1
488 return super().__new__(cls)
489 class ESC[4;38;5;81mC(ESC[4;38;5;149mA, ESC[4;38;5;149mB):
490 pass
491 self.assertEqual(B.counter, 0)
492 C()
493 self.assertEqual(B.counter, 1)
494
495 def test_ABC_has___slots__(self):
496 self.assertTrue(hasattr(abc.ABC, '__slots__'))
497
498 def test_tricky_new_works(self):
499 def with_metaclass(meta, *bases):
500 class ESC[4;38;5;81mmetaclass(ESC[4;38;5;149mtype):
501 def __new__(cls, name, this_bases, d):
502 return meta(name, bases, d)
503 return type.__new__(metaclass, 'temporary_class', (), {})
504 class ESC[4;38;5;81mA: ...
505 class ESC[4;38;5;81mB: ...
506 class ESC[4;38;5;81mC(ESC[4;38;5;149mwith_metaclass(abc_ABCMeta, A, B)):
507 pass
508 self.assertEqual(C.__class__, abc_ABCMeta)
509
510 def test_update_del(self):
511 class ESC[4;38;5;81mA(metaclass=ESC[4;38;5;149mabc_ABCMeta):
512 @abc.abstractmethod
513 def foo(self):
514 pass
515
516 del A.foo
517 self.assertEqual(A.__abstractmethods__, {'foo'})
518 self.assertFalse(hasattr(A, 'foo'))
519
520 abc.update_abstractmethods(A)
521
522 self.assertEqual(A.__abstractmethods__, set())
523 A()
524
525
526 def test_update_new_abstractmethods(self):
527 class ESC[4;38;5;81mA(metaclass=ESC[4;38;5;149mabc_ABCMeta):
528 @abc.abstractmethod
529 def bar(self):
530 pass
531
532 @abc.abstractmethod
533 def updated_foo(self):
534 pass
535
536 A.foo = updated_foo
537 abc.update_abstractmethods(A)
538 self.assertEqual(A.__abstractmethods__, {'foo', 'bar'})
539 msg = "class A with abstract methods bar, foo"
540 self.assertRaisesRegex(TypeError, msg, A)
541
542 def test_update_implementation(self):
543 class ESC[4;38;5;81mA(metaclass=ESC[4;38;5;149mabc_ABCMeta):
544 @abc.abstractmethod
545 def foo(self):
546 pass
547
548 class ESC[4;38;5;81mB(ESC[4;38;5;149mA):
549 pass
550
551 msg = "class B with abstract method foo"
552 self.assertRaisesRegex(TypeError, msg, B)
553 self.assertEqual(B.__abstractmethods__, {'foo'})
554
555 B.foo = lambda self: None
556
557 abc.update_abstractmethods(B)
558
559 B()
560 self.assertEqual(B.__abstractmethods__, set())
561
562 def test_update_as_decorator(self):
563 class ESC[4;38;5;81mA(metaclass=ESC[4;38;5;149mabc_ABCMeta):
564 @abc.abstractmethod
565 def foo(self):
566 pass
567
568 def class_decorator(cls):
569 cls.foo = lambda self: None
570 return cls
571
572 @abc.update_abstractmethods
573 @class_decorator
574 class ESC[4;38;5;81mB(ESC[4;38;5;149mA):
575 pass
576
577 B()
578 self.assertEqual(B.__abstractmethods__, set())
579
580 def test_update_non_abc(self):
581 class ESC[4;38;5;81mA:
582 pass
583
584 @abc.abstractmethod
585 def updated_foo(self):
586 pass
587
588 A.foo = updated_foo
589 abc.update_abstractmethods(A)
590 A()
591 self.assertFalse(hasattr(A, '__abstractmethods__'))
592
593 def test_update_del_implementation(self):
594 class ESC[4;38;5;81mA(metaclass=ESC[4;38;5;149mabc_ABCMeta):
595 @abc.abstractmethod
596 def foo(self):
597 pass
598
599 class ESC[4;38;5;81mB(ESC[4;38;5;149mA):
600 def foo(self):
601 pass
602
603 B()
604
605 del B.foo
606
607 abc.update_abstractmethods(B)
608
609 msg = "class B with abstract method foo"
610 self.assertRaisesRegex(TypeError, msg, B)
611
612 def test_update_layered_implementation(self):
613 class ESC[4;38;5;81mA(metaclass=ESC[4;38;5;149mabc_ABCMeta):
614 @abc.abstractmethod
615 def foo(self):
616 pass
617
618 class ESC[4;38;5;81mB(ESC[4;38;5;149mA):
619 pass
620
621 class ESC[4;38;5;81mC(ESC[4;38;5;149mB):
622 def foo(self):
623 pass
624
625 C()
626
627 del C.foo
628
629 abc.update_abstractmethods(C)
630
631 msg = "class C with abstract method foo"
632 self.assertRaisesRegex(TypeError, msg, C)
633
634 def test_update_multi_inheritance(self):
635 class ESC[4;38;5;81mA(metaclass=ESC[4;38;5;149mabc_ABCMeta):
636 @abc.abstractmethod
637 def foo(self):
638 pass
639
640 class ESC[4;38;5;81mB(metaclass=ESC[4;38;5;149mabc_ABCMeta):
641 def foo(self):
642 pass
643
644 class ESC[4;38;5;81mC(ESC[4;38;5;149mB, ESC[4;38;5;149mA):
645 @abc.abstractmethod
646 def foo(self):
647 pass
648
649 self.assertEqual(C.__abstractmethods__, {'foo'})
650
651 del C.foo
652
653 abc.update_abstractmethods(C)
654
655 self.assertEqual(C.__abstractmethods__, set())
656
657 C()
658
659
660 class ESC[4;38;5;81mTestABCWithInitSubclass(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
661 def test_works_with_init_subclass(self):
662 class ESC[4;38;5;81mabc_ABC(metaclass=ESC[4;38;5;149mabc_ABCMeta):
663 __slots__ = ()
664 saved_kwargs = {}
665 class ESC[4;38;5;81mReceivesClassKwargs:
666 def __init_subclass__(cls, **kwargs):
667 super().__init_subclass__()
668 saved_kwargs.update(kwargs)
669 class ESC[4;38;5;81mReceiver(ESC[4;38;5;149mReceivesClassKwargs, ESC[4;38;5;149mabc_ABC, x=1, y=2, z=3):
670 pass
671 self.assertEqual(saved_kwargs, dict(x=1, y=2, z=3))
672
673 def test_positional_only_and_kwonlyargs_with_init_subclass(self):
674 saved_kwargs = {}
675
676 class ESC[4;38;5;81mA:
677 def __init_subclass__(cls, **kwargs):
678 super().__init_subclass__()
679 saved_kwargs.update(kwargs)
680
681 class ESC[4;38;5;81mB(ESC[4;38;5;149mA, metaclass=ESC[4;38;5;149mabc_ABCMeta, name="test"):
682 pass
683 self.assertEqual(saved_kwargs, dict(name="test"))
684
685 return TestLegacyAPI, TestABC, TestABCWithInitSubclass
686
687 TestLegacyAPI_Py, TestABC_Py, TestABCWithInitSubclass_Py = test_factory(abc.ABCMeta,
688 abc.get_cache_token)
689 TestLegacyAPI_C, TestABC_C, TestABCWithInitSubclass_C = test_factory(_py_abc.ABCMeta,
690 _py_abc.get_cache_token)
691
692 if __name__ == "__main__":
693 unittest.main()