blob: 7a932fcf30987f6517fdc460def97c70c7285df0 [file] [log] [blame]
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001# Copyright 2007 Google, Inc. All Rights Reserved.
2# Licensed to PSF under a Contributor Agreement.
3
4"""Unit tests for abc.py."""
5
Guido van Rossumcd16bf62007-06-13 18:07:49 +00006import unittest
7from test import test_support
8
9import abc
10
11
12class TestABC(unittest.TestCase):
13
14 def test_abstractmethod_basics(self):
15 @abc.abstractmethod
16 def foo(self): pass
17 self.assertEqual(foo.__isabstractmethod__, True)
18 def bar(self): pass
19 self.assertEqual(hasattr(bar, "__isabstractmethod__"), False)
20
Guido van Rossum70d2b892007-08-01 17:52:23 +000021 def test_abstractproperty_basics(self):
22 @abc.abstractproperty
23 def foo(self): pass
24 self.assertEqual(foo.__isabstractmethod__, True)
25 def bar(self): pass
26 self.assertEqual(hasattr(bar, "__isabstractmethod__"), False)
27
Guido van Rossumcd16bf62007-06-13 18:07:49 +000028 class C(metaclass=abc.ABCMeta):
Guido van Rossum70d2b892007-08-01 17:52:23 +000029 @abc.abstractproperty
30 def foo(self): return 3
Guido van Rossumcd16bf62007-06-13 18:07:49 +000031 class D(C):
Guido van Rossum70d2b892007-08-01 17:52:23 +000032 @property
33 def foo(self): return super().foo
34 self.assertEqual(D().foo, 3)
35
36 def test_abstractmethod_integration(self):
37 for abstractthing in [abc.abstractmethod, abc.abstractproperty]:
38 class C(metaclass=abc.ABCMeta):
39 @abstractthing
40 def foo(self): pass # abstract
41 def bar(self): pass # concrete
42 self.assertEqual(C.__abstractmethods__, {"foo"})
43 self.assertRaises(TypeError, C) # because foo is abstract
44 class D(C):
45 def bar(self): pass # concrete override of concrete
46 self.assertEqual(D.__abstractmethods__, {"foo"})
47 self.assertRaises(TypeError, D) # because foo is still abstract
48 class E(D):
49 def foo(self): pass
50 self.assertEqual(E.__abstractmethods__, set())
51 E() # now foo is concrete, too
52 class F(E):
53 @abstractthing
54 def bar(self): pass # abstract override of concrete
55 self.assertEqual(F.__abstractmethods__, {"bar"})
56 self.assertRaises(TypeError, F) # because bar is abstract now
Guido van Rossumcd16bf62007-06-13 18:07:49 +000057
Christian Heimes043d6f62008-01-07 17:19:16 +000058 def test_subclass_oldstyle_class(self):
59 class A:
60 __metaclass__ = abc.ABCMeta
61 class OldstyleClass:
62 pass
63 self.assertFalse(issubclass(OldstyleClass, A))
64 self.assertFalse(issubclass(A, OldstyleClass))
65
Guido van Rossumcd16bf62007-06-13 18:07:49 +000066 def test_registration_basics(self):
67 class A(metaclass=abc.ABCMeta):
68 pass
Christian Heimes043d6f62008-01-07 17:19:16 +000069 class B(object):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000070 pass
71 b = B()
72 self.assertEqual(issubclass(B, A), False)
73 self.assertEqual(isinstance(b, A), False)
74 A.register(B)
75 self.assertEqual(issubclass(B, A), True)
76 self.assertEqual(isinstance(b, A), True)
77 class C(B):
78 pass
79 c = C()
80 self.assertEqual(issubclass(C, A), True)
81 self.assertEqual(isinstance(c, A), True)
82
Christian Heimes68f5fbe2008-02-14 08:27:37 +000083 def test_isinstance_invalidation(self):
84 class A(metaclass=abc.ABCMeta):
85 pass
86 class B:
87 pass
88 b = B()
89 self.assertEqual(isinstance(b, A), False)
90 A.register(B)
91 self.assertEqual(isinstance(b, A), True)
92
Guido van Rossumcd16bf62007-06-13 18:07:49 +000093 def test_registration_builtins(self):
94 class A(metaclass=abc.ABCMeta):
95 pass
96 A.register(int)
97 self.assertEqual(isinstance(42, A), True)
98 self.assertEqual(issubclass(int, A), True)
99 class B(A):
100 pass
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000101 B.register(str)
102 class C(str): pass
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000103 self.assertEqual(isinstance("", A), True)
104 self.assertEqual(issubclass(str, A), True)
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000105 self.assertEqual(issubclass(C, A), True)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000106
107 def test_registration_edge_cases(self):
108 class A(metaclass=abc.ABCMeta):
109 pass
110 A.register(A) # should pass silently
111 class A1(A):
112 pass
113 self.assertRaises(RuntimeError, A1.register, A) # cycles not allowed
Christian Heimes043d6f62008-01-07 17:19:16 +0000114 class B(object):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000115 pass
116 A1.register(B) # ok
117 A1.register(B) # should pass silently
118 class C(A):
119 pass
120 A.register(C) # should pass silently
121 self.assertRaises(RuntimeError, C.register, A) # cycles not allowed
122 C.register(B) # ok
123
124 def test_registration_transitiveness(self):
125 class A(metaclass=abc.ABCMeta):
126 pass
127 self.failUnless(issubclass(A, A))
128 class B(metaclass=abc.ABCMeta):
129 pass
130 self.failIf(issubclass(A, B))
131 self.failIf(issubclass(B, A))
132 class C(metaclass=abc.ABCMeta):
133 pass
134 A.register(B)
135 class B1(B):
136 pass
137 self.failUnless(issubclass(B1, A))
138 class C1(C):
139 pass
140 B1.register(C1)
141 self.failIf(issubclass(C, B))
142 self.failIf(issubclass(C, B1))
143 self.failUnless(issubclass(C1, A))
144 self.failUnless(issubclass(C1, B))
145 self.failUnless(issubclass(C1, B1))
146 C1.register(int)
147 class MyInt(int):
148 pass
149 self.failUnless(issubclass(MyInt, A))
150 self.failUnless(isinstance(42, A))
151
Guido van Rossum894d35e2007-09-11 20:42:30 +0000152 def test_all_new_methods_are_called(self):
153 class A(metaclass=abc.ABCMeta):
154 pass
Christian Heimes043d6f62008-01-07 17:19:16 +0000155 class B(object):
Guido van Rossum894d35e2007-09-11 20:42:30 +0000156 counter = 0
157 def __new__(cls):
158 B.counter += 1
159 return super().__new__(cls)
160 class C(A, B):
161 pass
162 self.assertEqual(B.counter, 0)
163 C()
164 self.assertEqual(B.counter, 1)
165
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000166
167def test_main():
168 test_support.run_unittest(TestABC)
169
170
171if __name__ == "__main__":
172 unittest.main()