diff options
Diffstat (limited to 'Lib/test/test_abc.py')
| -rw-r--r-- | Lib/test/test_abc.py | 153 |
1 files changed, 85 insertions, 68 deletions
diff --git a/Lib/test/test_abc.py b/Lib/test/test_abc.py index 6a8c3a1..d86f97c 100644 --- a/Lib/test/test_abc.py +++ b/Lib/test/test_abc.py @@ -3,8 +3,8 @@ """Unit tests for abc.py.""" -import unittest, weakref -from test import test_support +import unittest +from test import support import abc from inspect import isabstract @@ -26,28 +26,64 @@ class TestABC(unittest.TestCase): def bar(self): pass self.assertFalse(hasattr(bar, "__isabstractmethod__")) - class C: - __metaclass__ = abc.ABCMeta + class C(metaclass=abc.ABCMeta): @abc.abstractproperty def foo(self): return 3 class D(C): @property - def foo(self): return super(D, self).foo + def foo(self): return super().foo self.assertEqual(D().foo, 3) + def test_abstractclassmethod_basics(self): + @abc.abstractclassmethod + def foo(cls): pass + self.assertTrue(foo.__isabstractmethod__) + @classmethod + def bar(cls): pass + self.assertFalse(hasattr(bar, "__isabstractmethod__")) + + class C(metaclass=abc.ABCMeta): + @abc.abstractclassmethod + def foo(cls): return cls.__name__ + self.assertRaises(TypeError, C) + class D(C): + @classmethod + def foo(cls): return super().foo() + self.assertEqual(D.foo(), 'D') + self.assertEqual(D().foo(), 'D') + + def test_abstractstaticmethod_basics(self): + @abc.abstractstaticmethod + def foo(): pass + self.assertTrue(foo.__isabstractmethod__) + @staticmethod + def bar(): pass + self.assertFalse(hasattr(bar, "__isabstractmethod__")) + + class C(metaclass=abc.ABCMeta): + @abc.abstractstaticmethod + def foo(): return 3 + self.assertRaises(TypeError, C) + class D(C): + @staticmethod + def foo(): return 4 + self.assertEqual(D.foo(), 4) + self.assertEqual(D().foo(), 4) + def test_abstractmethod_integration(self): - for abstractthing in [abc.abstractmethod, abc.abstractproperty]: - class C: - __metaclass__ = abc.ABCMeta + for abstractthing in [abc.abstractmethod, abc.abstractproperty, + abc.abstractclassmethod, + abc.abstractstaticmethod]: + class C(metaclass=abc.ABCMeta): @abstractthing def foo(self): pass # abstract def bar(self): pass # concrete - self.assertEqual(C.__abstractmethods__, set(["foo"])) + self.assertEqual(C.__abstractmethods__, {"foo"}) self.assertRaises(TypeError, C) # because foo is abstract self.assertTrue(isabstract(C)) class D(C): def bar(self): pass # concrete override of concrete - self.assertEqual(D.__abstractmethods__, set(["foo"])) + self.assertEqual(D.__abstractmethods__, {"foo"}) self.assertRaises(TypeError, D) # because foo is still abstract self.assertTrue(isabstract(D)) class E(D): @@ -58,32 +94,26 @@ class TestABC(unittest.TestCase): class F(E): @abstractthing def bar(self): pass # abstract override of concrete - self.assertEqual(F.__abstractmethods__, set(["bar"])) + self.assertEqual(F.__abstractmethods__, {"bar"}) self.assertRaises(TypeError, F) # because bar is abstract now self.assertTrue(isabstract(F)) - def test_subclass_oldstyle_class(self): - class A: - __metaclass__ = abc.ABCMeta - class OldstyleClass: - pass - self.assertFalse(issubclass(OldstyleClass, A)) - self.assertFalse(issubclass(A, OldstyleClass)) - - def test_isinstance_class(self): - class A: - __metaclass__ = abc.ABCMeta - class OldstyleClass: + def test_metaclass_abc(self): + # Metaclasses can be ABCs, too. + class A(metaclass=abc.ABCMeta): + @abc.abstractmethod + def x(self): + pass + self.assertEqual(A.__abstractmethods__, {"x"}) + class meta(type, A): + def x(self): + return 1 + class C(metaclass=meta): pass - self.assertFalse(isinstance(OldstyleClass, A)) - self.assertTrue(isinstance(OldstyleClass, type(OldstyleClass))) - self.assertFalse(isinstance(A, OldstyleClass)) - # This raises a recursion depth error, but is low-priority: - # self.assertTrue(isinstance(A, abc.ABCMeta)) def test_registration_basics(self): - class A: - __metaclass__ = abc.ABCMeta + class A(metaclass=abc.ABCMeta): + pass class B(object): pass b = B() @@ -105,9 +135,9 @@ class TestABC(unittest.TestCase): self.assertIsInstance(c, (A,)) def test_isinstance_invalidation(self): - class A: - __metaclass__ = abc.ABCMeta - class B(object): + class A(metaclass=abc.ABCMeta): + pass + class B: pass b = B() self.assertFalse(isinstance(b, A)) @@ -117,8 +147,8 @@ class TestABC(unittest.TestCase): self.assertTrue(isinstance(b, (A,))) def test_registration_builtins(self): - class A: - __metaclass__ = abc.ABCMeta + class A(metaclass=abc.ABCMeta): + pass A.register(int) self.assertIsInstance(42, A) self.assertIsInstance(42, (A,)) @@ -126,15 +156,18 @@ class TestABC(unittest.TestCase): self.assertTrue(issubclass(int, (A,))) class B(A): pass - B.register(basestring) + B.register(str) + class C(str): pass self.assertIsInstance("", A) self.assertIsInstance("", (A,)) self.assertTrue(issubclass(str, A)) self.assertTrue(issubclass(str, (A,))) + self.assertTrue(issubclass(C, A)) + self.assertTrue(issubclass(C, (A,))) def test_registration_edge_cases(self): - class A: - __metaclass__ = abc.ABCMeta + class A(metaclass=abc.ABCMeta): + pass A.register(A) # should pass silently class A1(A): pass @@ -150,24 +183,24 @@ class TestABC(unittest.TestCase): C.register(B) # ok def test_register_non_class(self): - class A(object): - __metaclass__ = abc.ABCMeta - self.assertRaisesRegexp(TypeError, "Can only register classes", - A.register, 4) + class A(metaclass=abc.ABCMeta): + pass + self.assertRaisesRegex(TypeError, "Can only register classes", + A.register, 4) def test_registration_transitiveness(self): - class A: - __metaclass__ = abc.ABCMeta + class A(metaclass=abc.ABCMeta): + pass self.assertTrue(issubclass(A, A)) self.assertTrue(issubclass(A, (A,))) - class B: - __metaclass__ = abc.ABCMeta + class B(metaclass=abc.ABCMeta): + pass self.assertFalse(issubclass(A, B)) self.assertFalse(issubclass(A, (B,))) self.assertFalse(issubclass(B, A)) self.assertFalse(issubclass(B, (A,))) - class C: - __metaclass__ = abc.ABCMeta + class C(metaclass=abc.ABCMeta): + pass A.register(B) class B1(B): pass @@ -195,38 +228,22 @@ class TestABC(unittest.TestCase): self.assertIsInstance(42, (A,)) def test_all_new_methods_are_called(self): - class A: - __metaclass__ = abc.ABCMeta + class A(metaclass=abc.ABCMeta): + pass class B(object): counter = 0 def __new__(cls): B.counter += 1 - return super(B, cls).__new__(cls) + return super().__new__(cls) class C(A, B): pass self.assertEqual(B.counter, 0) C() self.assertEqual(B.counter, 1) - def test_cache_leak(self): - # See issue #2521. - class A(object): - __metaclass__ = abc.ABCMeta - @abc.abstractmethod - def f(self): - pass - class C(A): - def f(self): - A.f(self) - r = weakref.ref(C) - # Trigger cache. - C().f() - del C - test_support.gc_collect() - self.assertEqual(r(), None) def test_main(): - test_support.run_unittest(TestABC) + support.run_unittest(TestABC) if __name__ == "__main__": |
