17db96d56Sopenharmony_ci# Copyright 2007 Google, Inc. All Rights Reserved. 27db96d56Sopenharmony_ci# Licensed to PSF under a Contributor Agreement. 37db96d56Sopenharmony_ci 47db96d56Sopenharmony_ci# Note: each test is run with Python and C versions of ABCMeta. Except for 57db96d56Sopenharmony_ci# test_ABC_helper(), which assures that abc.ABC is an instance of abc.ABCMeta. 67db96d56Sopenharmony_ci 77db96d56Sopenharmony_ci"""Unit tests for abc.py.""" 87db96d56Sopenharmony_ci 97db96d56Sopenharmony_ciimport unittest 107db96d56Sopenharmony_ci 117db96d56Sopenharmony_ciimport abc 127db96d56Sopenharmony_ciimport _py_abc 137db96d56Sopenharmony_cifrom inspect import isabstract 147db96d56Sopenharmony_ci 157db96d56Sopenharmony_cidef test_factory(abc_ABCMeta, abc_get_cache_token): 167db96d56Sopenharmony_ci class TestLegacyAPI(unittest.TestCase): 177db96d56Sopenharmony_ci 187db96d56Sopenharmony_ci def test_abstractproperty_basics(self): 197db96d56Sopenharmony_ci @abc.abstractproperty 207db96d56Sopenharmony_ci def foo(self): pass 217db96d56Sopenharmony_ci self.assertTrue(foo.__isabstractmethod__) 227db96d56Sopenharmony_ci def bar(self): pass 237db96d56Sopenharmony_ci self.assertFalse(hasattr(bar, "__isabstractmethod__")) 247db96d56Sopenharmony_ci 257db96d56Sopenharmony_ci class C(metaclass=abc_ABCMeta): 267db96d56Sopenharmony_ci @abc.abstractproperty 277db96d56Sopenharmony_ci def foo(self): return 3 287db96d56Sopenharmony_ci self.assertRaises(TypeError, C) 297db96d56Sopenharmony_ci class D(C): 307db96d56Sopenharmony_ci @property 317db96d56Sopenharmony_ci def foo(self): return super().foo 327db96d56Sopenharmony_ci self.assertEqual(D().foo, 3) 337db96d56Sopenharmony_ci self.assertFalse(getattr(D.foo, "__isabstractmethod__", False)) 347db96d56Sopenharmony_ci 357db96d56Sopenharmony_ci def test_abstractclassmethod_basics(self): 367db96d56Sopenharmony_ci @abc.abstractclassmethod 377db96d56Sopenharmony_ci def foo(cls): pass 387db96d56Sopenharmony_ci self.assertTrue(foo.__isabstractmethod__) 397db96d56Sopenharmony_ci @classmethod 407db96d56Sopenharmony_ci def bar(cls): pass 417db96d56Sopenharmony_ci self.assertFalse(getattr(bar, "__isabstractmethod__", False)) 427db96d56Sopenharmony_ci 437db96d56Sopenharmony_ci class C(metaclass=abc_ABCMeta): 447db96d56Sopenharmony_ci @abc.abstractclassmethod 457db96d56Sopenharmony_ci def foo(cls): return cls.__name__ 467db96d56Sopenharmony_ci self.assertRaises(TypeError, C) 477db96d56Sopenharmony_ci class D(C): 487db96d56Sopenharmony_ci @classmethod 497db96d56Sopenharmony_ci def foo(cls): return super().foo() 507db96d56Sopenharmony_ci self.assertEqual(D.foo(), 'D') 517db96d56Sopenharmony_ci self.assertEqual(D().foo(), 'D') 527db96d56Sopenharmony_ci 537db96d56Sopenharmony_ci def test_abstractstaticmethod_basics(self): 547db96d56Sopenharmony_ci @abc.abstractstaticmethod 557db96d56Sopenharmony_ci def foo(): pass 567db96d56Sopenharmony_ci self.assertTrue(foo.__isabstractmethod__) 577db96d56Sopenharmony_ci @staticmethod 587db96d56Sopenharmony_ci def bar(): pass 597db96d56Sopenharmony_ci self.assertFalse(getattr(bar, "__isabstractmethod__", False)) 607db96d56Sopenharmony_ci 617db96d56Sopenharmony_ci class C(metaclass=abc_ABCMeta): 627db96d56Sopenharmony_ci @abc.abstractstaticmethod 637db96d56Sopenharmony_ci def foo(): return 3 647db96d56Sopenharmony_ci self.assertRaises(TypeError, C) 657db96d56Sopenharmony_ci class D(C): 667db96d56Sopenharmony_ci @staticmethod 677db96d56Sopenharmony_ci def foo(): return 4 687db96d56Sopenharmony_ci self.assertEqual(D.foo(), 4) 697db96d56Sopenharmony_ci self.assertEqual(D().foo(), 4) 707db96d56Sopenharmony_ci 717db96d56Sopenharmony_ci 727db96d56Sopenharmony_ci class TestABC(unittest.TestCase): 737db96d56Sopenharmony_ci 747db96d56Sopenharmony_ci def test_ABC_helper(self): 757db96d56Sopenharmony_ci # create an ABC using the helper class and perform basic checks 767db96d56Sopenharmony_ci class C(abc.ABC): 777db96d56Sopenharmony_ci @classmethod 787db96d56Sopenharmony_ci @abc.abstractmethod 797db96d56Sopenharmony_ci def foo(cls): return cls.__name__ 807db96d56Sopenharmony_ci self.assertEqual(type(C), abc.ABCMeta) 817db96d56Sopenharmony_ci self.assertRaises(TypeError, C) 827db96d56Sopenharmony_ci class D(C): 837db96d56Sopenharmony_ci @classmethod 847db96d56Sopenharmony_ci def foo(cls): return super().foo() 857db96d56Sopenharmony_ci self.assertEqual(D.foo(), 'D') 867db96d56Sopenharmony_ci 877db96d56Sopenharmony_ci def test_abstractmethod_basics(self): 887db96d56Sopenharmony_ci @abc.abstractmethod 897db96d56Sopenharmony_ci def foo(self): pass 907db96d56Sopenharmony_ci self.assertTrue(foo.__isabstractmethod__) 917db96d56Sopenharmony_ci def bar(self): pass 927db96d56Sopenharmony_ci self.assertFalse(hasattr(bar, "__isabstractmethod__")) 937db96d56Sopenharmony_ci 947db96d56Sopenharmony_ci def test_abstractproperty_basics(self): 957db96d56Sopenharmony_ci @property 967db96d56Sopenharmony_ci @abc.abstractmethod 977db96d56Sopenharmony_ci def foo(self): pass 987db96d56Sopenharmony_ci self.assertTrue(foo.__isabstractmethod__) 997db96d56Sopenharmony_ci def bar(self): pass 1007db96d56Sopenharmony_ci self.assertFalse(getattr(bar, "__isabstractmethod__", False)) 1017db96d56Sopenharmony_ci 1027db96d56Sopenharmony_ci class C(metaclass=abc_ABCMeta): 1037db96d56Sopenharmony_ci @property 1047db96d56Sopenharmony_ci @abc.abstractmethod 1057db96d56Sopenharmony_ci def foo(self): return 3 1067db96d56Sopenharmony_ci self.assertRaises(TypeError, C) 1077db96d56Sopenharmony_ci class D(C): 1087db96d56Sopenharmony_ci @C.foo.getter 1097db96d56Sopenharmony_ci def foo(self): return super().foo 1107db96d56Sopenharmony_ci self.assertEqual(D().foo, 3) 1117db96d56Sopenharmony_ci 1127db96d56Sopenharmony_ci def test_abstractclassmethod_basics(self): 1137db96d56Sopenharmony_ci @classmethod 1147db96d56Sopenharmony_ci @abc.abstractmethod 1157db96d56Sopenharmony_ci def foo(cls): pass 1167db96d56Sopenharmony_ci self.assertTrue(foo.__isabstractmethod__) 1177db96d56Sopenharmony_ci @classmethod 1187db96d56Sopenharmony_ci def bar(cls): pass 1197db96d56Sopenharmony_ci self.assertFalse(getattr(bar, "__isabstractmethod__", False)) 1207db96d56Sopenharmony_ci 1217db96d56Sopenharmony_ci class C(metaclass=abc_ABCMeta): 1227db96d56Sopenharmony_ci @classmethod 1237db96d56Sopenharmony_ci @abc.abstractmethod 1247db96d56Sopenharmony_ci def foo(cls): return cls.__name__ 1257db96d56Sopenharmony_ci self.assertRaises(TypeError, C) 1267db96d56Sopenharmony_ci class D(C): 1277db96d56Sopenharmony_ci @classmethod 1287db96d56Sopenharmony_ci def foo(cls): return super().foo() 1297db96d56Sopenharmony_ci self.assertEqual(D.foo(), 'D') 1307db96d56Sopenharmony_ci self.assertEqual(D().foo(), 'D') 1317db96d56Sopenharmony_ci 1327db96d56Sopenharmony_ci def test_abstractstaticmethod_basics(self): 1337db96d56Sopenharmony_ci @staticmethod 1347db96d56Sopenharmony_ci @abc.abstractmethod 1357db96d56Sopenharmony_ci def foo(): pass 1367db96d56Sopenharmony_ci self.assertTrue(foo.__isabstractmethod__) 1377db96d56Sopenharmony_ci @staticmethod 1387db96d56Sopenharmony_ci def bar(): pass 1397db96d56Sopenharmony_ci self.assertFalse(getattr(bar, "__isabstractmethod__", False)) 1407db96d56Sopenharmony_ci 1417db96d56Sopenharmony_ci class C(metaclass=abc_ABCMeta): 1427db96d56Sopenharmony_ci @staticmethod 1437db96d56Sopenharmony_ci @abc.abstractmethod 1447db96d56Sopenharmony_ci def foo(): return 3 1457db96d56Sopenharmony_ci self.assertRaises(TypeError, C) 1467db96d56Sopenharmony_ci class D(C): 1477db96d56Sopenharmony_ci @staticmethod 1487db96d56Sopenharmony_ci def foo(): return 4 1497db96d56Sopenharmony_ci self.assertEqual(D.foo(), 4) 1507db96d56Sopenharmony_ci self.assertEqual(D().foo(), 4) 1517db96d56Sopenharmony_ci 1527db96d56Sopenharmony_ci def test_object_new_with_one_abstractmethod(self): 1537db96d56Sopenharmony_ci class C(metaclass=abc_ABCMeta): 1547db96d56Sopenharmony_ci @abc.abstractmethod 1557db96d56Sopenharmony_ci def method_one(self): 1567db96d56Sopenharmony_ci pass 1577db96d56Sopenharmony_ci msg = r"class C with abstract method method_one" 1587db96d56Sopenharmony_ci self.assertRaisesRegex(TypeError, msg, C) 1597db96d56Sopenharmony_ci 1607db96d56Sopenharmony_ci def test_object_new_with_many_abstractmethods(self): 1617db96d56Sopenharmony_ci class C(metaclass=abc_ABCMeta): 1627db96d56Sopenharmony_ci @abc.abstractmethod 1637db96d56Sopenharmony_ci def method_one(self): 1647db96d56Sopenharmony_ci pass 1657db96d56Sopenharmony_ci @abc.abstractmethod 1667db96d56Sopenharmony_ci def method_two(self): 1677db96d56Sopenharmony_ci pass 1687db96d56Sopenharmony_ci msg = r"class C with abstract methods method_one, method_two" 1697db96d56Sopenharmony_ci self.assertRaisesRegex(TypeError, msg, C) 1707db96d56Sopenharmony_ci 1717db96d56Sopenharmony_ci def test_abstractmethod_integration(self): 1727db96d56Sopenharmony_ci for abstractthing in [abc.abstractmethod, abc.abstractproperty, 1737db96d56Sopenharmony_ci abc.abstractclassmethod, 1747db96d56Sopenharmony_ci abc.abstractstaticmethod]: 1757db96d56Sopenharmony_ci class C(metaclass=abc_ABCMeta): 1767db96d56Sopenharmony_ci @abstractthing 1777db96d56Sopenharmony_ci def foo(self): pass # abstract 1787db96d56Sopenharmony_ci def bar(self): pass # concrete 1797db96d56Sopenharmony_ci self.assertEqual(C.__abstractmethods__, {"foo"}) 1807db96d56Sopenharmony_ci self.assertRaises(TypeError, C) # because foo is abstract 1817db96d56Sopenharmony_ci self.assertTrue(isabstract(C)) 1827db96d56Sopenharmony_ci class D(C): 1837db96d56Sopenharmony_ci def bar(self): pass # concrete override of concrete 1847db96d56Sopenharmony_ci self.assertEqual(D.__abstractmethods__, {"foo"}) 1857db96d56Sopenharmony_ci self.assertRaises(TypeError, D) # because foo is still abstract 1867db96d56Sopenharmony_ci self.assertTrue(isabstract(D)) 1877db96d56Sopenharmony_ci class E(D): 1887db96d56Sopenharmony_ci def foo(self): pass 1897db96d56Sopenharmony_ci self.assertEqual(E.__abstractmethods__, set()) 1907db96d56Sopenharmony_ci E() # now foo is concrete, too 1917db96d56Sopenharmony_ci self.assertFalse(isabstract(E)) 1927db96d56Sopenharmony_ci class F(E): 1937db96d56Sopenharmony_ci @abstractthing 1947db96d56Sopenharmony_ci def bar(self): pass # abstract override of concrete 1957db96d56Sopenharmony_ci self.assertEqual(F.__abstractmethods__, {"bar"}) 1967db96d56Sopenharmony_ci self.assertRaises(TypeError, F) # because bar is abstract now 1977db96d56Sopenharmony_ci self.assertTrue(isabstract(F)) 1987db96d56Sopenharmony_ci 1997db96d56Sopenharmony_ci def test_descriptors_with_abstractmethod(self): 2007db96d56Sopenharmony_ci class C(metaclass=abc_ABCMeta): 2017db96d56Sopenharmony_ci @property 2027db96d56Sopenharmony_ci @abc.abstractmethod 2037db96d56Sopenharmony_ci def foo(self): return 3 2047db96d56Sopenharmony_ci @foo.setter 2057db96d56Sopenharmony_ci @abc.abstractmethod 2067db96d56Sopenharmony_ci def foo(self, val): pass 2077db96d56Sopenharmony_ci self.assertRaises(TypeError, C) 2087db96d56Sopenharmony_ci class D(C): 2097db96d56Sopenharmony_ci @C.foo.getter 2107db96d56Sopenharmony_ci def foo(self): return super().foo 2117db96d56Sopenharmony_ci self.assertRaises(TypeError, D) 2127db96d56Sopenharmony_ci class E(D): 2137db96d56Sopenharmony_ci @D.foo.setter 2147db96d56Sopenharmony_ci def foo(self, val): pass 2157db96d56Sopenharmony_ci self.assertEqual(E().foo, 3) 2167db96d56Sopenharmony_ci # check that the property's __isabstractmethod__ descriptor does the 2177db96d56Sopenharmony_ci # right thing when presented with a value that fails truth testing: 2187db96d56Sopenharmony_ci class NotBool(object): 2197db96d56Sopenharmony_ci def __bool__(self): 2207db96d56Sopenharmony_ci raise ValueError() 2217db96d56Sopenharmony_ci __len__ = __bool__ 2227db96d56Sopenharmony_ci with self.assertRaises(ValueError): 2237db96d56Sopenharmony_ci class F(C): 2247db96d56Sopenharmony_ci def bar(self): 2257db96d56Sopenharmony_ci pass 2267db96d56Sopenharmony_ci bar.__isabstractmethod__ = NotBool() 2277db96d56Sopenharmony_ci foo = property(bar) 2287db96d56Sopenharmony_ci 2297db96d56Sopenharmony_ci 2307db96d56Sopenharmony_ci def test_customdescriptors_with_abstractmethod(self): 2317db96d56Sopenharmony_ci class Descriptor: 2327db96d56Sopenharmony_ci def __init__(self, fget, fset=None): 2337db96d56Sopenharmony_ci self._fget = fget 2347db96d56Sopenharmony_ci self._fset = fset 2357db96d56Sopenharmony_ci def getter(self, callable): 2367db96d56Sopenharmony_ci return Descriptor(callable, self._fget) 2377db96d56Sopenharmony_ci def setter(self, callable): 2387db96d56Sopenharmony_ci return Descriptor(self._fget, callable) 2397db96d56Sopenharmony_ci @property 2407db96d56Sopenharmony_ci def __isabstractmethod__(self): 2417db96d56Sopenharmony_ci return (getattr(self._fget, '__isabstractmethod__', False) 2427db96d56Sopenharmony_ci or getattr(self._fset, '__isabstractmethod__', False)) 2437db96d56Sopenharmony_ci class C(metaclass=abc_ABCMeta): 2447db96d56Sopenharmony_ci @Descriptor 2457db96d56Sopenharmony_ci @abc.abstractmethod 2467db96d56Sopenharmony_ci def foo(self): return 3 2477db96d56Sopenharmony_ci @foo.setter 2487db96d56Sopenharmony_ci @abc.abstractmethod 2497db96d56Sopenharmony_ci def foo(self, val): pass 2507db96d56Sopenharmony_ci self.assertRaises(TypeError, C) 2517db96d56Sopenharmony_ci class D(C): 2527db96d56Sopenharmony_ci @C.foo.getter 2537db96d56Sopenharmony_ci def foo(self): return super().foo 2547db96d56Sopenharmony_ci self.assertRaises(TypeError, D) 2557db96d56Sopenharmony_ci class E(D): 2567db96d56Sopenharmony_ci @D.foo.setter 2577db96d56Sopenharmony_ci def foo(self, val): pass 2587db96d56Sopenharmony_ci self.assertFalse(E.foo.__isabstractmethod__) 2597db96d56Sopenharmony_ci 2607db96d56Sopenharmony_ci def test_metaclass_abc(self): 2617db96d56Sopenharmony_ci # Metaclasses can be ABCs, too. 2627db96d56Sopenharmony_ci class A(metaclass=abc_ABCMeta): 2637db96d56Sopenharmony_ci @abc.abstractmethod 2647db96d56Sopenharmony_ci def x(self): 2657db96d56Sopenharmony_ci pass 2667db96d56Sopenharmony_ci self.assertEqual(A.__abstractmethods__, {"x"}) 2677db96d56Sopenharmony_ci class meta(type, A): 2687db96d56Sopenharmony_ci def x(self): 2697db96d56Sopenharmony_ci return 1 2707db96d56Sopenharmony_ci class C(metaclass=meta): 2717db96d56Sopenharmony_ci pass 2727db96d56Sopenharmony_ci 2737db96d56Sopenharmony_ci def test_registration_basics(self): 2747db96d56Sopenharmony_ci class A(metaclass=abc_ABCMeta): 2757db96d56Sopenharmony_ci pass 2767db96d56Sopenharmony_ci class B(object): 2777db96d56Sopenharmony_ci pass 2787db96d56Sopenharmony_ci b = B() 2797db96d56Sopenharmony_ci self.assertFalse(issubclass(B, A)) 2807db96d56Sopenharmony_ci self.assertFalse(issubclass(B, (A,))) 2817db96d56Sopenharmony_ci self.assertNotIsInstance(b, A) 2827db96d56Sopenharmony_ci self.assertNotIsInstance(b, (A,)) 2837db96d56Sopenharmony_ci B1 = A.register(B) 2847db96d56Sopenharmony_ci self.assertTrue(issubclass(B, A)) 2857db96d56Sopenharmony_ci self.assertTrue(issubclass(B, (A,))) 2867db96d56Sopenharmony_ci self.assertIsInstance(b, A) 2877db96d56Sopenharmony_ci self.assertIsInstance(b, (A,)) 2887db96d56Sopenharmony_ci self.assertIs(B1, B) 2897db96d56Sopenharmony_ci class C(B): 2907db96d56Sopenharmony_ci pass 2917db96d56Sopenharmony_ci c = C() 2927db96d56Sopenharmony_ci self.assertTrue(issubclass(C, A)) 2937db96d56Sopenharmony_ci self.assertTrue(issubclass(C, (A,))) 2947db96d56Sopenharmony_ci self.assertIsInstance(c, A) 2957db96d56Sopenharmony_ci self.assertIsInstance(c, (A,)) 2967db96d56Sopenharmony_ci 2977db96d56Sopenharmony_ci def test_register_as_class_deco(self): 2987db96d56Sopenharmony_ci class A(metaclass=abc_ABCMeta): 2997db96d56Sopenharmony_ci pass 3007db96d56Sopenharmony_ci @A.register 3017db96d56Sopenharmony_ci class B(object): 3027db96d56Sopenharmony_ci pass 3037db96d56Sopenharmony_ci b = B() 3047db96d56Sopenharmony_ci self.assertTrue(issubclass(B, A)) 3057db96d56Sopenharmony_ci self.assertTrue(issubclass(B, (A,))) 3067db96d56Sopenharmony_ci self.assertIsInstance(b, A) 3077db96d56Sopenharmony_ci self.assertIsInstance(b, (A,)) 3087db96d56Sopenharmony_ci @A.register 3097db96d56Sopenharmony_ci class C(B): 3107db96d56Sopenharmony_ci pass 3117db96d56Sopenharmony_ci c = C() 3127db96d56Sopenharmony_ci self.assertTrue(issubclass(C, A)) 3137db96d56Sopenharmony_ci self.assertTrue(issubclass(C, (A,))) 3147db96d56Sopenharmony_ci self.assertIsInstance(c, A) 3157db96d56Sopenharmony_ci self.assertIsInstance(c, (A,)) 3167db96d56Sopenharmony_ci self.assertIs(C, A.register(C)) 3177db96d56Sopenharmony_ci 3187db96d56Sopenharmony_ci def test_isinstance_invalidation(self): 3197db96d56Sopenharmony_ci class A(metaclass=abc_ABCMeta): 3207db96d56Sopenharmony_ci pass 3217db96d56Sopenharmony_ci class B: 3227db96d56Sopenharmony_ci pass 3237db96d56Sopenharmony_ci b = B() 3247db96d56Sopenharmony_ci self.assertFalse(isinstance(b, A)) 3257db96d56Sopenharmony_ci self.assertFalse(isinstance(b, (A,))) 3267db96d56Sopenharmony_ci token_old = abc_get_cache_token() 3277db96d56Sopenharmony_ci A.register(B) 3287db96d56Sopenharmony_ci token_new = abc_get_cache_token() 3297db96d56Sopenharmony_ci self.assertGreater(token_new, token_old) 3307db96d56Sopenharmony_ci self.assertTrue(isinstance(b, A)) 3317db96d56Sopenharmony_ci self.assertTrue(isinstance(b, (A,))) 3327db96d56Sopenharmony_ci 3337db96d56Sopenharmony_ci def test_registration_builtins(self): 3347db96d56Sopenharmony_ci class A(metaclass=abc_ABCMeta): 3357db96d56Sopenharmony_ci pass 3367db96d56Sopenharmony_ci A.register(int) 3377db96d56Sopenharmony_ci self.assertIsInstance(42, A) 3387db96d56Sopenharmony_ci self.assertIsInstance(42, (A,)) 3397db96d56Sopenharmony_ci self.assertTrue(issubclass(int, A)) 3407db96d56Sopenharmony_ci self.assertTrue(issubclass(int, (A,))) 3417db96d56Sopenharmony_ci class B(A): 3427db96d56Sopenharmony_ci pass 3437db96d56Sopenharmony_ci B.register(str) 3447db96d56Sopenharmony_ci class C(str): pass 3457db96d56Sopenharmony_ci self.assertIsInstance("", A) 3467db96d56Sopenharmony_ci self.assertIsInstance("", (A,)) 3477db96d56Sopenharmony_ci self.assertTrue(issubclass(str, A)) 3487db96d56Sopenharmony_ci self.assertTrue(issubclass(str, (A,))) 3497db96d56Sopenharmony_ci self.assertTrue(issubclass(C, A)) 3507db96d56Sopenharmony_ci self.assertTrue(issubclass(C, (A,))) 3517db96d56Sopenharmony_ci 3527db96d56Sopenharmony_ci def test_registration_edge_cases(self): 3537db96d56Sopenharmony_ci class A(metaclass=abc_ABCMeta): 3547db96d56Sopenharmony_ci pass 3557db96d56Sopenharmony_ci A.register(A) # should pass silently 3567db96d56Sopenharmony_ci class A1(A): 3577db96d56Sopenharmony_ci pass 3587db96d56Sopenharmony_ci self.assertRaises(RuntimeError, A1.register, A) # cycles not allowed 3597db96d56Sopenharmony_ci class B(object): 3607db96d56Sopenharmony_ci pass 3617db96d56Sopenharmony_ci A1.register(B) # ok 3627db96d56Sopenharmony_ci A1.register(B) # should pass silently 3637db96d56Sopenharmony_ci class C(A): 3647db96d56Sopenharmony_ci pass 3657db96d56Sopenharmony_ci A.register(C) # should pass silently 3667db96d56Sopenharmony_ci self.assertRaises(RuntimeError, C.register, A) # cycles not allowed 3677db96d56Sopenharmony_ci C.register(B) # ok 3687db96d56Sopenharmony_ci 3697db96d56Sopenharmony_ci def test_register_non_class(self): 3707db96d56Sopenharmony_ci class A(metaclass=abc_ABCMeta): 3717db96d56Sopenharmony_ci pass 3727db96d56Sopenharmony_ci self.assertRaisesRegex(TypeError, "Can only register classes", 3737db96d56Sopenharmony_ci A.register, 4) 3747db96d56Sopenharmony_ci 3757db96d56Sopenharmony_ci def test_registration_transitiveness(self): 3767db96d56Sopenharmony_ci class A(metaclass=abc_ABCMeta): 3777db96d56Sopenharmony_ci pass 3787db96d56Sopenharmony_ci self.assertTrue(issubclass(A, A)) 3797db96d56Sopenharmony_ci self.assertTrue(issubclass(A, (A,))) 3807db96d56Sopenharmony_ci class B(metaclass=abc_ABCMeta): 3817db96d56Sopenharmony_ci pass 3827db96d56Sopenharmony_ci self.assertFalse(issubclass(A, B)) 3837db96d56Sopenharmony_ci self.assertFalse(issubclass(A, (B,))) 3847db96d56Sopenharmony_ci self.assertFalse(issubclass(B, A)) 3857db96d56Sopenharmony_ci self.assertFalse(issubclass(B, (A,))) 3867db96d56Sopenharmony_ci class C(metaclass=abc_ABCMeta): 3877db96d56Sopenharmony_ci pass 3887db96d56Sopenharmony_ci A.register(B) 3897db96d56Sopenharmony_ci class B1(B): 3907db96d56Sopenharmony_ci pass 3917db96d56Sopenharmony_ci self.assertTrue(issubclass(B1, A)) 3927db96d56Sopenharmony_ci self.assertTrue(issubclass(B1, (A,))) 3937db96d56Sopenharmony_ci class C1(C): 3947db96d56Sopenharmony_ci pass 3957db96d56Sopenharmony_ci B1.register(C1) 3967db96d56Sopenharmony_ci self.assertFalse(issubclass(C, B)) 3977db96d56Sopenharmony_ci self.assertFalse(issubclass(C, (B,))) 3987db96d56Sopenharmony_ci self.assertFalse(issubclass(C, B1)) 3997db96d56Sopenharmony_ci self.assertFalse(issubclass(C, (B1,))) 4007db96d56Sopenharmony_ci self.assertTrue(issubclass(C1, A)) 4017db96d56Sopenharmony_ci self.assertTrue(issubclass(C1, (A,))) 4027db96d56Sopenharmony_ci self.assertTrue(issubclass(C1, B)) 4037db96d56Sopenharmony_ci self.assertTrue(issubclass(C1, (B,))) 4047db96d56Sopenharmony_ci self.assertTrue(issubclass(C1, B1)) 4057db96d56Sopenharmony_ci self.assertTrue(issubclass(C1, (B1,))) 4067db96d56Sopenharmony_ci C1.register(int) 4077db96d56Sopenharmony_ci class MyInt(int): 4087db96d56Sopenharmony_ci pass 4097db96d56Sopenharmony_ci self.assertTrue(issubclass(MyInt, A)) 4107db96d56Sopenharmony_ci self.assertTrue(issubclass(MyInt, (A,))) 4117db96d56Sopenharmony_ci self.assertIsInstance(42, A) 4127db96d56Sopenharmony_ci self.assertIsInstance(42, (A,)) 4137db96d56Sopenharmony_ci 4147db96d56Sopenharmony_ci def test_issubclass_bad_arguments(self): 4157db96d56Sopenharmony_ci class A(metaclass=abc_ABCMeta): 4167db96d56Sopenharmony_ci pass 4177db96d56Sopenharmony_ci 4187db96d56Sopenharmony_ci with self.assertRaises(TypeError): 4197db96d56Sopenharmony_ci issubclass({}, A) # unhashable 4207db96d56Sopenharmony_ci 4217db96d56Sopenharmony_ci with self.assertRaises(TypeError): 4227db96d56Sopenharmony_ci issubclass(42, A) # No __mro__ 4237db96d56Sopenharmony_ci 4247db96d56Sopenharmony_ci # Python version supports any iterable as __mro__. 4257db96d56Sopenharmony_ci # But it's implementation detail and don't emulate it in C version. 4267db96d56Sopenharmony_ci class C: 4277db96d56Sopenharmony_ci __mro__ = 42 # __mro__ is not tuple 4287db96d56Sopenharmony_ci 4297db96d56Sopenharmony_ci with self.assertRaises(TypeError): 4307db96d56Sopenharmony_ci issubclass(C(), A) 4317db96d56Sopenharmony_ci 4327db96d56Sopenharmony_ci # bpo-34441: Check that issubclass() doesn't crash on bogus 4337db96d56Sopenharmony_ci # classes. 4347db96d56Sopenharmony_ci bogus_subclasses = [ 4357db96d56Sopenharmony_ci None, 4367db96d56Sopenharmony_ci lambda x: [], 4377db96d56Sopenharmony_ci lambda: 42, 4387db96d56Sopenharmony_ci lambda: [42], 4397db96d56Sopenharmony_ci ] 4407db96d56Sopenharmony_ci 4417db96d56Sopenharmony_ci for i, func in enumerate(bogus_subclasses): 4427db96d56Sopenharmony_ci class S(metaclass=abc_ABCMeta): 4437db96d56Sopenharmony_ci __subclasses__ = func 4447db96d56Sopenharmony_ci 4457db96d56Sopenharmony_ci with self.subTest(i=i): 4467db96d56Sopenharmony_ci with self.assertRaises(TypeError): 4477db96d56Sopenharmony_ci issubclass(int, S) 4487db96d56Sopenharmony_ci 4497db96d56Sopenharmony_ci # Also check that issubclass() propagates exceptions raised by 4507db96d56Sopenharmony_ci # __subclasses__. 4517db96d56Sopenharmony_ci exc_msg = "exception from __subclasses__" 4527db96d56Sopenharmony_ci 4537db96d56Sopenharmony_ci def raise_exc(): 4547db96d56Sopenharmony_ci raise Exception(exc_msg) 4557db96d56Sopenharmony_ci 4567db96d56Sopenharmony_ci class S(metaclass=abc_ABCMeta): 4577db96d56Sopenharmony_ci __subclasses__ = raise_exc 4587db96d56Sopenharmony_ci 4597db96d56Sopenharmony_ci with self.assertRaisesRegex(Exception, exc_msg): 4607db96d56Sopenharmony_ci issubclass(int, S) 4617db96d56Sopenharmony_ci 4627db96d56Sopenharmony_ci def test_subclasshook(self): 4637db96d56Sopenharmony_ci class A(metaclass=abc.ABCMeta): 4647db96d56Sopenharmony_ci @classmethod 4657db96d56Sopenharmony_ci def __subclasshook__(cls, C): 4667db96d56Sopenharmony_ci if cls is A: 4677db96d56Sopenharmony_ci return 'foo' in C.__dict__ 4687db96d56Sopenharmony_ci return NotImplemented 4697db96d56Sopenharmony_ci self.assertFalse(issubclass(A, A)) 4707db96d56Sopenharmony_ci self.assertFalse(issubclass(A, (A,))) 4717db96d56Sopenharmony_ci class B: 4727db96d56Sopenharmony_ci foo = 42 4737db96d56Sopenharmony_ci self.assertTrue(issubclass(B, A)) 4747db96d56Sopenharmony_ci self.assertTrue(issubclass(B, (A,))) 4757db96d56Sopenharmony_ci class C: 4767db96d56Sopenharmony_ci spam = 42 4777db96d56Sopenharmony_ci self.assertFalse(issubclass(C, A)) 4787db96d56Sopenharmony_ci self.assertFalse(issubclass(C, (A,))) 4797db96d56Sopenharmony_ci 4807db96d56Sopenharmony_ci def test_all_new_methods_are_called(self): 4817db96d56Sopenharmony_ci class A(metaclass=abc_ABCMeta): 4827db96d56Sopenharmony_ci pass 4837db96d56Sopenharmony_ci class B(object): 4847db96d56Sopenharmony_ci counter = 0 4857db96d56Sopenharmony_ci def __new__(cls): 4867db96d56Sopenharmony_ci B.counter += 1 4877db96d56Sopenharmony_ci return super().__new__(cls) 4887db96d56Sopenharmony_ci class C(A, B): 4897db96d56Sopenharmony_ci pass 4907db96d56Sopenharmony_ci self.assertEqual(B.counter, 0) 4917db96d56Sopenharmony_ci C() 4927db96d56Sopenharmony_ci self.assertEqual(B.counter, 1) 4937db96d56Sopenharmony_ci 4947db96d56Sopenharmony_ci def test_ABC_has___slots__(self): 4957db96d56Sopenharmony_ci self.assertTrue(hasattr(abc.ABC, '__slots__')) 4967db96d56Sopenharmony_ci 4977db96d56Sopenharmony_ci def test_tricky_new_works(self): 4987db96d56Sopenharmony_ci def with_metaclass(meta, *bases): 4997db96d56Sopenharmony_ci class metaclass(type): 5007db96d56Sopenharmony_ci def __new__(cls, name, this_bases, d): 5017db96d56Sopenharmony_ci return meta(name, bases, d) 5027db96d56Sopenharmony_ci return type.__new__(metaclass, 'temporary_class', (), {}) 5037db96d56Sopenharmony_ci class A: ... 5047db96d56Sopenharmony_ci class B: ... 5057db96d56Sopenharmony_ci class C(with_metaclass(abc_ABCMeta, A, B)): 5067db96d56Sopenharmony_ci pass 5077db96d56Sopenharmony_ci self.assertEqual(C.__class__, abc_ABCMeta) 5087db96d56Sopenharmony_ci 5097db96d56Sopenharmony_ci def test_update_del(self): 5107db96d56Sopenharmony_ci class A(metaclass=abc_ABCMeta): 5117db96d56Sopenharmony_ci @abc.abstractmethod 5127db96d56Sopenharmony_ci def foo(self): 5137db96d56Sopenharmony_ci pass 5147db96d56Sopenharmony_ci 5157db96d56Sopenharmony_ci del A.foo 5167db96d56Sopenharmony_ci self.assertEqual(A.__abstractmethods__, {'foo'}) 5177db96d56Sopenharmony_ci self.assertFalse(hasattr(A, 'foo')) 5187db96d56Sopenharmony_ci 5197db96d56Sopenharmony_ci abc.update_abstractmethods(A) 5207db96d56Sopenharmony_ci 5217db96d56Sopenharmony_ci self.assertEqual(A.__abstractmethods__, set()) 5227db96d56Sopenharmony_ci A() 5237db96d56Sopenharmony_ci 5247db96d56Sopenharmony_ci 5257db96d56Sopenharmony_ci def test_update_new_abstractmethods(self): 5267db96d56Sopenharmony_ci class A(metaclass=abc_ABCMeta): 5277db96d56Sopenharmony_ci @abc.abstractmethod 5287db96d56Sopenharmony_ci def bar(self): 5297db96d56Sopenharmony_ci pass 5307db96d56Sopenharmony_ci 5317db96d56Sopenharmony_ci @abc.abstractmethod 5327db96d56Sopenharmony_ci def updated_foo(self): 5337db96d56Sopenharmony_ci pass 5347db96d56Sopenharmony_ci 5357db96d56Sopenharmony_ci A.foo = updated_foo 5367db96d56Sopenharmony_ci abc.update_abstractmethods(A) 5377db96d56Sopenharmony_ci self.assertEqual(A.__abstractmethods__, {'foo', 'bar'}) 5387db96d56Sopenharmony_ci msg = "class A with abstract methods bar, foo" 5397db96d56Sopenharmony_ci self.assertRaisesRegex(TypeError, msg, A) 5407db96d56Sopenharmony_ci 5417db96d56Sopenharmony_ci def test_update_implementation(self): 5427db96d56Sopenharmony_ci class A(metaclass=abc_ABCMeta): 5437db96d56Sopenharmony_ci @abc.abstractmethod 5447db96d56Sopenharmony_ci def foo(self): 5457db96d56Sopenharmony_ci pass 5467db96d56Sopenharmony_ci 5477db96d56Sopenharmony_ci class B(A): 5487db96d56Sopenharmony_ci pass 5497db96d56Sopenharmony_ci 5507db96d56Sopenharmony_ci msg = "class B with abstract method foo" 5517db96d56Sopenharmony_ci self.assertRaisesRegex(TypeError, msg, B) 5527db96d56Sopenharmony_ci self.assertEqual(B.__abstractmethods__, {'foo'}) 5537db96d56Sopenharmony_ci 5547db96d56Sopenharmony_ci B.foo = lambda self: None 5557db96d56Sopenharmony_ci 5567db96d56Sopenharmony_ci abc.update_abstractmethods(B) 5577db96d56Sopenharmony_ci 5587db96d56Sopenharmony_ci B() 5597db96d56Sopenharmony_ci self.assertEqual(B.__abstractmethods__, set()) 5607db96d56Sopenharmony_ci 5617db96d56Sopenharmony_ci def test_update_as_decorator(self): 5627db96d56Sopenharmony_ci class A(metaclass=abc_ABCMeta): 5637db96d56Sopenharmony_ci @abc.abstractmethod 5647db96d56Sopenharmony_ci def foo(self): 5657db96d56Sopenharmony_ci pass 5667db96d56Sopenharmony_ci 5677db96d56Sopenharmony_ci def class_decorator(cls): 5687db96d56Sopenharmony_ci cls.foo = lambda self: None 5697db96d56Sopenharmony_ci return cls 5707db96d56Sopenharmony_ci 5717db96d56Sopenharmony_ci @abc.update_abstractmethods 5727db96d56Sopenharmony_ci @class_decorator 5737db96d56Sopenharmony_ci class B(A): 5747db96d56Sopenharmony_ci pass 5757db96d56Sopenharmony_ci 5767db96d56Sopenharmony_ci B() 5777db96d56Sopenharmony_ci self.assertEqual(B.__abstractmethods__, set()) 5787db96d56Sopenharmony_ci 5797db96d56Sopenharmony_ci def test_update_non_abc(self): 5807db96d56Sopenharmony_ci class A: 5817db96d56Sopenharmony_ci pass 5827db96d56Sopenharmony_ci 5837db96d56Sopenharmony_ci @abc.abstractmethod 5847db96d56Sopenharmony_ci def updated_foo(self): 5857db96d56Sopenharmony_ci pass 5867db96d56Sopenharmony_ci 5877db96d56Sopenharmony_ci A.foo = updated_foo 5887db96d56Sopenharmony_ci abc.update_abstractmethods(A) 5897db96d56Sopenharmony_ci A() 5907db96d56Sopenharmony_ci self.assertFalse(hasattr(A, '__abstractmethods__')) 5917db96d56Sopenharmony_ci 5927db96d56Sopenharmony_ci def test_update_del_implementation(self): 5937db96d56Sopenharmony_ci class A(metaclass=abc_ABCMeta): 5947db96d56Sopenharmony_ci @abc.abstractmethod 5957db96d56Sopenharmony_ci def foo(self): 5967db96d56Sopenharmony_ci pass 5977db96d56Sopenharmony_ci 5987db96d56Sopenharmony_ci class B(A): 5997db96d56Sopenharmony_ci def foo(self): 6007db96d56Sopenharmony_ci pass 6017db96d56Sopenharmony_ci 6027db96d56Sopenharmony_ci B() 6037db96d56Sopenharmony_ci 6047db96d56Sopenharmony_ci del B.foo 6057db96d56Sopenharmony_ci 6067db96d56Sopenharmony_ci abc.update_abstractmethods(B) 6077db96d56Sopenharmony_ci 6087db96d56Sopenharmony_ci msg = "class B with abstract method foo" 6097db96d56Sopenharmony_ci self.assertRaisesRegex(TypeError, msg, B) 6107db96d56Sopenharmony_ci 6117db96d56Sopenharmony_ci def test_update_layered_implementation(self): 6127db96d56Sopenharmony_ci class A(metaclass=abc_ABCMeta): 6137db96d56Sopenharmony_ci @abc.abstractmethod 6147db96d56Sopenharmony_ci def foo(self): 6157db96d56Sopenharmony_ci pass 6167db96d56Sopenharmony_ci 6177db96d56Sopenharmony_ci class B(A): 6187db96d56Sopenharmony_ci pass 6197db96d56Sopenharmony_ci 6207db96d56Sopenharmony_ci class C(B): 6217db96d56Sopenharmony_ci def foo(self): 6227db96d56Sopenharmony_ci pass 6237db96d56Sopenharmony_ci 6247db96d56Sopenharmony_ci C() 6257db96d56Sopenharmony_ci 6267db96d56Sopenharmony_ci del C.foo 6277db96d56Sopenharmony_ci 6287db96d56Sopenharmony_ci abc.update_abstractmethods(C) 6297db96d56Sopenharmony_ci 6307db96d56Sopenharmony_ci msg = "class C with abstract method foo" 6317db96d56Sopenharmony_ci self.assertRaisesRegex(TypeError, msg, C) 6327db96d56Sopenharmony_ci 6337db96d56Sopenharmony_ci def test_update_multi_inheritance(self): 6347db96d56Sopenharmony_ci class A(metaclass=abc_ABCMeta): 6357db96d56Sopenharmony_ci @abc.abstractmethod 6367db96d56Sopenharmony_ci def foo(self): 6377db96d56Sopenharmony_ci pass 6387db96d56Sopenharmony_ci 6397db96d56Sopenharmony_ci class B(metaclass=abc_ABCMeta): 6407db96d56Sopenharmony_ci def foo(self): 6417db96d56Sopenharmony_ci pass 6427db96d56Sopenharmony_ci 6437db96d56Sopenharmony_ci class C(B, A): 6447db96d56Sopenharmony_ci @abc.abstractmethod 6457db96d56Sopenharmony_ci def foo(self): 6467db96d56Sopenharmony_ci pass 6477db96d56Sopenharmony_ci 6487db96d56Sopenharmony_ci self.assertEqual(C.__abstractmethods__, {'foo'}) 6497db96d56Sopenharmony_ci 6507db96d56Sopenharmony_ci del C.foo 6517db96d56Sopenharmony_ci 6527db96d56Sopenharmony_ci abc.update_abstractmethods(C) 6537db96d56Sopenharmony_ci 6547db96d56Sopenharmony_ci self.assertEqual(C.__abstractmethods__, set()) 6557db96d56Sopenharmony_ci 6567db96d56Sopenharmony_ci C() 6577db96d56Sopenharmony_ci 6587db96d56Sopenharmony_ci 6597db96d56Sopenharmony_ci class TestABCWithInitSubclass(unittest.TestCase): 6607db96d56Sopenharmony_ci def test_works_with_init_subclass(self): 6617db96d56Sopenharmony_ci class abc_ABC(metaclass=abc_ABCMeta): 6627db96d56Sopenharmony_ci __slots__ = () 6637db96d56Sopenharmony_ci saved_kwargs = {} 6647db96d56Sopenharmony_ci class ReceivesClassKwargs: 6657db96d56Sopenharmony_ci def __init_subclass__(cls, **kwargs): 6667db96d56Sopenharmony_ci super().__init_subclass__() 6677db96d56Sopenharmony_ci saved_kwargs.update(kwargs) 6687db96d56Sopenharmony_ci class Receiver(ReceivesClassKwargs, abc_ABC, x=1, y=2, z=3): 6697db96d56Sopenharmony_ci pass 6707db96d56Sopenharmony_ci self.assertEqual(saved_kwargs, dict(x=1, y=2, z=3)) 6717db96d56Sopenharmony_ci 6727db96d56Sopenharmony_ci def test_positional_only_and_kwonlyargs_with_init_subclass(self): 6737db96d56Sopenharmony_ci saved_kwargs = {} 6747db96d56Sopenharmony_ci 6757db96d56Sopenharmony_ci class A: 6767db96d56Sopenharmony_ci def __init_subclass__(cls, **kwargs): 6777db96d56Sopenharmony_ci super().__init_subclass__() 6787db96d56Sopenharmony_ci saved_kwargs.update(kwargs) 6797db96d56Sopenharmony_ci 6807db96d56Sopenharmony_ci class B(A, metaclass=abc_ABCMeta, name="test"): 6817db96d56Sopenharmony_ci pass 6827db96d56Sopenharmony_ci self.assertEqual(saved_kwargs, dict(name="test")) 6837db96d56Sopenharmony_ci 6847db96d56Sopenharmony_ci return TestLegacyAPI, TestABC, TestABCWithInitSubclass 6857db96d56Sopenharmony_ci 6867db96d56Sopenharmony_ciTestLegacyAPI_Py, TestABC_Py, TestABCWithInitSubclass_Py = test_factory(abc.ABCMeta, 6877db96d56Sopenharmony_ci abc.get_cache_token) 6887db96d56Sopenharmony_ciTestLegacyAPI_C, TestABC_C, TestABCWithInitSubclass_C = test_factory(_py_abc.ABCMeta, 6897db96d56Sopenharmony_ci _py_abc.get_cache_token) 6907db96d56Sopenharmony_ci 6917db96d56Sopenharmony_ciif __name__ == "__main__": 6927db96d56Sopenharmony_ci unittest.main() 693