|
1 # Copyright 2007 Google, Inc. All Rights Reserved. |
|
2 # Licensed to PSF under a Contributor Agreement. |
|
3 |
|
4 """Unit tests for abc.py.""" |
|
5 |
|
6 import unittest |
|
7 from test import test_support |
|
8 |
|
9 import abc |
|
10 from inspect import isabstract |
|
11 |
|
12 |
|
13 class TestABC(unittest.TestCase): |
|
14 |
|
15 def test_abstractmethod_basics(self): |
|
16 @abc.abstractmethod |
|
17 def foo(self): pass |
|
18 self.assertEqual(foo.__isabstractmethod__, True) |
|
19 def bar(self): pass |
|
20 self.assertEqual(hasattr(bar, "__isabstractmethod__"), False) |
|
21 |
|
22 def test_abstractproperty_basics(self): |
|
23 @abc.abstractproperty |
|
24 def foo(self): pass |
|
25 self.assertEqual(foo.__isabstractmethod__, True) |
|
26 def bar(self): pass |
|
27 self.assertEqual(hasattr(bar, "__isabstractmethod__"), False) |
|
28 |
|
29 class C: |
|
30 __metaclass__ = abc.ABCMeta |
|
31 @abc.abstractproperty |
|
32 def foo(self): return 3 |
|
33 class D(C): |
|
34 @property |
|
35 def foo(self): return super(D, self).foo |
|
36 self.assertEqual(D().foo, 3) |
|
37 |
|
38 def test_abstractmethod_integration(self): |
|
39 for abstractthing in [abc.abstractmethod, abc.abstractproperty]: |
|
40 class C: |
|
41 __metaclass__ = abc.ABCMeta |
|
42 @abstractthing |
|
43 def foo(self): pass # abstract |
|
44 def bar(self): pass # concrete |
|
45 self.assertEqual(C.__abstractmethods__, set(["foo"])) |
|
46 self.assertRaises(TypeError, C) # because foo is abstract |
|
47 self.assert_(isabstract(C)) |
|
48 class D(C): |
|
49 def bar(self): pass # concrete override of concrete |
|
50 self.assertEqual(D.__abstractmethods__, set(["foo"])) |
|
51 self.assertRaises(TypeError, D) # because foo is still abstract |
|
52 self.assert_(isabstract(D)) |
|
53 class E(D): |
|
54 def foo(self): pass |
|
55 self.assertEqual(E.__abstractmethods__, set()) |
|
56 E() # now foo is concrete, too |
|
57 self.failIf(isabstract(E)) |
|
58 class F(E): |
|
59 @abstractthing |
|
60 def bar(self): pass # abstract override of concrete |
|
61 self.assertEqual(F.__abstractmethods__, set(["bar"])) |
|
62 self.assertRaises(TypeError, F) # because bar is abstract now |
|
63 self.assert_(isabstract(F)) |
|
64 |
|
65 def test_subclass_oldstyle_class(self): |
|
66 class A: |
|
67 __metaclass__ = abc.ABCMeta |
|
68 class OldstyleClass: |
|
69 pass |
|
70 self.assertFalse(issubclass(OldstyleClass, A)) |
|
71 self.assertFalse(issubclass(A, OldstyleClass)) |
|
72 |
|
73 def test_isinstance_class(self): |
|
74 class A: |
|
75 __metaclass__ = abc.ABCMeta |
|
76 class OldstyleClass: |
|
77 pass |
|
78 self.assertFalse(isinstance(OldstyleClass, A)) |
|
79 self.assertTrue(isinstance(OldstyleClass, type(OldstyleClass))) |
|
80 self.assertFalse(isinstance(A, OldstyleClass)) |
|
81 # This raises a recursion depth error, but is low-priority: |
|
82 # self.assertTrue(isinstance(A, abc.ABCMeta)) |
|
83 |
|
84 def test_registration_basics(self): |
|
85 class A: |
|
86 __metaclass__ = abc.ABCMeta |
|
87 class B(object): |
|
88 pass |
|
89 b = B() |
|
90 self.assertEqual(issubclass(B, A), False) |
|
91 self.assertEqual(issubclass(B, (A,)), False) |
|
92 self.assertEqual(isinstance(b, A), False) |
|
93 self.assertEqual(isinstance(b, (A,)), False) |
|
94 A.register(B) |
|
95 self.assertEqual(issubclass(B, A), True) |
|
96 self.assertEqual(issubclass(B, (A,)), True) |
|
97 self.assertEqual(isinstance(b, A), True) |
|
98 self.assertEqual(isinstance(b, (A,)), True) |
|
99 class C(B): |
|
100 pass |
|
101 c = C() |
|
102 self.assertEqual(issubclass(C, A), True) |
|
103 self.assertEqual(issubclass(C, (A,)), True) |
|
104 self.assertEqual(isinstance(c, A), True) |
|
105 self.assertEqual(isinstance(c, (A,)), True) |
|
106 |
|
107 def test_isinstance_invalidation(self): |
|
108 class A: |
|
109 __metaclass__ = abc.ABCMeta |
|
110 class B(object): |
|
111 pass |
|
112 b = B() |
|
113 self.assertEqual(isinstance(b, A), False) |
|
114 self.assertEqual(isinstance(b, (A,)), False) |
|
115 A.register(B) |
|
116 self.assertEqual(isinstance(b, A), True) |
|
117 self.assertEqual(isinstance(b, (A,)), True) |
|
118 |
|
119 def test_registration_builtins(self): |
|
120 class A: |
|
121 __metaclass__ = abc.ABCMeta |
|
122 A.register(int) |
|
123 self.assertEqual(isinstance(42, A), True) |
|
124 self.assertEqual(isinstance(42, (A,)), True) |
|
125 self.assertEqual(issubclass(int, A), True) |
|
126 self.assertEqual(issubclass(int, (A,)), True) |
|
127 class B(A): |
|
128 pass |
|
129 B.register(basestring) |
|
130 self.assertEqual(isinstance("", A), True) |
|
131 self.assertEqual(isinstance("", (A,)), True) |
|
132 self.assertEqual(issubclass(str, A), True) |
|
133 self.assertEqual(issubclass(str, (A,)), True) |
|
134 |
|
135 def test_registration_edge_cases(self): |
|
136 class A: |
|
137 __metaclass__ = abc.ABCMeta |
|
138 A.register(A) # should pass silently |
|
139 class A1(A): |
|
140 pass |
|
141 self.assertRaises(RuntimeError, A1.register, A) # cycles not allowed |
|
142 class B(object): |
|
143 pass |
|
144 A1.register(B) # ok |
|
145 A1.register(B) # should pass silently |
|
146 class C(A): |
|
147 pass |
|
148 A.register(C) # should pass silently |
|
149 self.assertRaises(RuntimeError, C.register, A) # cycles not allowed |
|
150 C.register(B) # ok |
|
151 |
|
152 def test_registration_transitiveness(self): |
|
153 class A: |
|
154 __metaclass__ = abc.ABCMeta |
|
155 self.failUnless(issubclass(A, A)) |
|
156 self.failUnless(issubclass(A, (A,))) |
|
157 class B: |
|
158 __metaclass__ = abc.ABCMeta |
|
159 self.failIf(issubclass(A, B)) |
|
160 self.failIf(issubclass(A, (B,))) |
|
161 self.failIf(issubclass(B, A)) |
|
162 self.failIf(issubclass(B, (A,))) |
|
163 class C: |
|
164 __metaclass__ = abc.ABCMeta |
|
165 A.register(B) |
|
166 class B1(B): |
|
167 pass |
|
168 self.failUnless(issubclass(B1, A)) |
|
169 self.failUnless(issubclass(B1, (A,))) |
|
170 class C1(C): |
|
171 pass |
|
172 B1.register(C1) |
|
173 self.failIf(issubclass(C, B)) |
|
174 self.failIf(issubclass(C, (B,))) |
|
175 self.failIf(issubclass(C, B1)) |
|
176 self.failIf(issubclass(C, (B1,))) |
|
177 self.failUnless(issubclass(C1, A)) |
|
178 self.failUnless(issubclass(C1, (A,))) |
|
179 self.failUnless(issubclass(C1, B)) |
|
180 self.failUnless(issubclass(C1, (B,))) |
|
181 self.failUnless(issubclass(C1, B1)) |
|
182 self.failUnless(issubclass(C1, (B1,))) |
|
183 C1.register(int) |
|
184 class MyInt(int): |
|
185 pass |
|
186 self.failUnless(issubclass(MyInt, A)) |
|
187 self.failUnless(issubclass(MyInt, (A,))) |
|
188 self.failUnless(isinstance(42, A)) |
|
189 self.failUnless(isinstance(42, (A,))) |
|
190 |
|
191 def test_all_new_methods_are_called(self): |
|
192 class A: |
|
193 __metaclass__ = abc.ABCMeta |
|
194 class B(object): |
|
195 counter = 0 |
|
196 def __new__(cls): |
|
197 B.counter += 1 |
|
198 return super(B, cls).__new__(cls) |
|
199 class C(A, B): |
|
200 pass |
|
201 self.assertEqual(B.counter, 0) |
|
202 C() |
|
203 self.assertEqual(B.counter, 1) |
|
204 |
|
205 |
|
206 def test_main(): |
|
207 test_support.run_unittest(TestABC) |
|
208 |
|
209 |
|
210 if __name__ == "__main__": |
|
211 unittest.main() |