blob: d4d7556518669b520df6c98bacd03b1010c2ce86 [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
Benjamin Petersonee8712c2008-05-20 21:35:26 +00007from test import support
Guido van Rossumcd16bf62007-06-13 18:07:49 +00008
9import abc
Christian Heimesbe5b30b2008-03-03 19:18:51 +000010from inspect import isabstract
Guido van Rossumcd16bf62007-06-13 18:07:49 +000011
12
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -050013class TestLegacyAPI(unittest.TestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000014
Guido van Rossum70d2b892007-08-01 17:52:23 +000015 def test_abstractproperty_basics(self):
16 @abc.abstractproperty
17 def foo(self): pass
Benjamin Peterson83cd3b92010-08-17 01:07:53 +000018 self.assertTrue(foo.__isabstractmethod__)
Guido van Rossum70d2b892007-08-01 17:52:23 +000019 def bar(self): pass
Benjamin Peterson83cd3b92010-08-17 01:07:53 +000020 self.assertFalse(hasattr(bar, "__isabstractmethod__"))
Guido van Rossum70d2b892007-08-01 17:52:23 +000021
Guido van Rossumcd16bf62007-06-13 18:07:49 +000022 class C(metaclass=abc.ABCMeta):
Guido van Rossum70d2b892007-08-01 17:52:23 +000023 @abc.abstractproperty
24 def foo(self): return 3
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -050025 self.assertRaises(TypeError, C)
Guido van Rossumcd16bf62007-06-13 18:07:49 +000026 class D(C):
Guido van Rossum70d2b892007-08-01 17:52:23 +000027 @property
28 def foo(self): return super().foo
29 self.assertEqual(D().foo, 3)
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -050030 self.assertFalse(getattr(D.foo, "__isabstractmethod__", False))
Guido van Rossum70d2b892007-08-01 17:52:23 +000031
Benjamin Peterson45c257f2010-08-17 00:52:52 +000032 def test_abstractclassmethod_basics(self):
33 @abc.abstractclassmethod
34 def foo(cls): pass
Benjamin Peterson83cd3b92010-08-17 01:07:53 +000035 self.assertTrue(foo.__isabstractmethod__)
Benjamin Peterson45c257f2010-08-17 00:52:52 +000036 @classmethod
37 def bar(cls): pass
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -050038 self.assertFalse(getattr(bar, "__isabstractmethod__", False))
Benjamin Peterson45c257f2010-08-17 00:52:52 +000039
40 class C(metaclass=abc.ABCMeta):
41 @abc.abstractclassmethod
42 def foo(cls): return cls.__name__
43 self.assertRaises(TypeError, C)
44 class D(C):
45 @classmethod
46 def foo(cls): return super().foo()
47 self.assertEqual(D.foo(), 'D')
48 self.assertEqual(D().foo(), 'D')
49
50 def test_abstractstaticmethod_basics(self):
51 @abc.abstractstaticmethod
52 def foo(): pass
Benjamin Peterson83cd3b92010-08-17 01:07:53 +000053 self.assertTrue(foo.__isabstractmethod__)
Benjamin Peterson45c257f2010-08-17 00:52:52 +000054 @staticmethod
55 def bar(): pass
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -050056 self.assertFalse(getattr(bar, "__isabstractmethod__", False))
Benjamin Peterson45c257f2010-08-17 00:52:52 +000057
58 class C(metaclass=abc.ABCMeta):
59 @abc.abstractstaticmethod
60 def foo(): return 3
61 self.assertRaises(TypeError, C)
62 class D(C):
63 @staticmethod
64 def foo(): return 4
65 self.assertEqual(D.foo(), 4)
66 self.assertEqual(D().foo(), 4)
67
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -050068
69class TestABC(unittest.TestCase):
70
71 def test_abstractmethod_basics(self):
72 @abc.abstractmethod
73 def foo(self): pass
74 self.assertTrue(foo.__isabstractmethod__)
75 def bar(self): pass
76 self.assertFalse(hasattr(bar, "__isabstractmethod__"))
77
78 def test_abstractproperty_basics(self):
79 @property
80 @abc.abstractmethod
81 def foo(self): pass
82 self.assertTrue(foo.__isabstractmethod__)
83 def bar(self): pass
84 self.assertFalse(getattr(bar, "__isabstractmethod__", False))
85
86 class C(metaclass=abc.ABCMeta):
87 @property
88 @abc.abstractmethod
89 def foo(self): return 3
90 self.assertRaises(TypeError, C)
91 class D(C):
92 @C.foo.getter
93 def foo(self): return super().foo
94 self.assertEqual(D().foo, 3)
95
96 def test_abstractclassmethod_basics(self):
97 @classmethod
98 @abc.abstractmethod
99 def foo(cls): pass
100 self.assertTrue(foo.__isabstractmethod__)
101 @classmethod
102 def bar(cls): pass
103 self.assertFalse(getattr(bar, "__isabstractmethod__", False))
104
105 class C(metaclass=abc.ABCMeta):
106 @classmethod
107 @abc.abstractmethod
108 def foo(cls): return cls.__name__
109 self.assertRaises(TypeError, C)
110 class D(C):
111 @classmethod
112 def foo(cls): return super().foo()
113 self.assertEqual(D.foo(), 'D')
114 self.assertEqual(D().foo(), 'D')
115
116 def test_abstractstaticmethod_basics(self):
117 @staticmethod
118 @abc.abstractmethod
119 def foo(): pass
120 self.assertTrue(foo.__isabstractmethod__)
121 @staticmethod
122 def bar(): pass
123 self.assertFalse(getattr(bar, "__isabstractmethod__", False))
124
125 class C(metaclass=abc.ABCMeta):
126 @staticmethod
127 @abc.abstractmethod
128 def foo(): return 3
129 self.assertRaises(TypeError, C)
130 class D(C):
131 @staticmethod
132 def foo(): return 4
133 self.assertEqual(D.foo(), 4)
134 self.assertEqual(D().foo(), 4)
135
136 def test_abstractmethod_integration(self):
137 for abstractthing in [abc.abstractmethod, abc.abstractproperty,
138 abc.abstractclassmethod,
139 abc.abstractstaticmethod]:
140 class C(metaclass=abc.ABCMeta):
141 @abstractthing
142 def foo(self): pass # abstract
143 def bar(self): pass # concrete
144 self.assertEqual(C.__abstractmethods__, {"foo"})
145 self.assertRaises(TypeError, C) # because foo is abstract
146 self.assertTrue(isabstract(C))
147 class D(C):
148 def bar(self): pass # concrete override of concrete
149 self.assertEqual(D.__abstractmethods__, {"foo"})
150 self.assertRaises(TypeError, D) # because foo is still abstract
151 self.assertTrue(isabstract(D))
152 class E(D):
153 def foo(self): pass
154 self.assertEqual(E.__abstractmethods__, set())
155 E() # now foo is concrete, too
156 self.assertFalse(isabstract(E))
157 class F(E):
158 @abstractthing
159 def bar(self): pass # abstract override of concrete
160 self.assertEqual(F.__abstractmethods__, {"bar"})
161 self.assertRaises(TypeError, F) # because bar is abstract now
162 self.assertTrue(isabstract(F))
163
164 def test_descriptors_with_abstractmethod(self):
165 class C(metaclass=abc.ABCMeta):
166 @property
167 @abc.abstractmethod
168 def foo(self): return 3
169 @foo.setter
170 @abc.abstractmethod
171 def foo(self, val): pass
172 self.assertRaises(TypeError, C)
173 class D(C):
174 @C.foo.getter
175 def foo(self): return super().foo
176 self.assertRaises(TypeError, D)
177 class E(D):
178 @D.foo.setter
179 def foo(self, val): pass
180 self.assertEqual(E().foo, 3)
181 # check that the property's __isabstractmethod__ descriptor does the
182 # right thing when presented with a value that fails truth testing:
183 class NotBool(object):
184 def __nonzero__(self):
185 raise ValueError()
186 __len__ = __nonzero__
187 with self.assertRaises(ValueError):
188 class F(C):
189 def bar(self):
190 pass
191 bar.__isabstractmethod__ = NotBool()
192 foo = property(bar)
193
194
195 def test_customdescriptors_with_abstractmethod(self):
196 class Descriptor:
197 def __init__(self, fget, fset=None):
198 self._fget = fget
199 self._fset = fset
200 def getter(self, callable):
201 return Descriptor(callable, self._fget)
202 def setter(self, callable):
203 return Descriptor(self._fget, callable)
204 @property
205 def __isabstractmethod__(self):
206 return (getattr(self._fget, '__isabstractmethod__', False)
207 or getattr(self._fset, '__isabstractmethod__', False))
208 class C(metaclass=abc.ABCMeta):
209 @Descriptor
210 @abc.abstractmethod
211 def foo(self): return 3
212 @foo.setter
213 @abc.abstractmethod
214 def foo(self, val): pass
215 self.assertRaises(TypeError, C)
216 class D(C):
217 @C.foo.getter
218 def foo(self): return super().foo
219 self.assertRaises(TypeError, D)
220 class E(D):
221 @D.foo.setter
222 def foo(self, val): pass
223 self.assertFalse(E.foo.__isabstractmethod__)
224
Benjamin Peterson970d1882010-10-02 17:55:47 +0000225 def test_metaclass_abc(self):
226 # Metaclasses can be ABCs, too.
227 class A(metaclass=abc.ABCMeta):
228 @abc.abstractmethod
229 def x(self):
230 pass
231 self.assertEqual(A.__abstractmethods__, {"x"})
232 class meta(type, A):
233 def x(self):
234 return 1
235 class C(metaclass=meta):
236 pass
237
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000238 def test_registration_basics(self):
239 class A(metaclass=abc.ABCMeta):
240 pass
Christian Heimes043d6f62008-01-07 17:19:16 +0000241 class B(object):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000242 pass
243 b = B()
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000244 self.assertFalse(issubclass(B, A))
245 self.assertFalse(issubclass(B, (A,)))
Ezio Melottie9615932010-01-24 19:26:24 +0000246 self.assertNotIsInstance(b, A)
247 self.assertNotIsInstance(b, (A,))
Éric Araujo6c3787c2011-02-24 18:03:10 +0000248 B1 = A.register(B)
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000249 self.assertTrue(issubclass(B, A))
250 self.assertTrue(issubclass(B, (A,)))
Ezio Melottie9615932010-01-24 19:26:24 +0000251 self.assertIsInstance(b, A)
252 self.assertIsInstance(b, (A,))
Éric Araujo6c3787c2011-02-24 18:03:10 +0000253 self.assertIs(B1, B)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000254 class C(B):
255 pass
256 c = C()
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000257 self.assertTrue(issubclass(C, A))
258 self.assertTrue(issubclass(C, (A,)))
Ezio Melottie9615932010-01-24 19:26:24 +0000259 self.assertIsInstance(c, A)
260 self.assertIsInstance(c, (A,))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000261
Éric Araujo6c3787c2011-02-24 18:03:10 +0000262 def test_register_as_class_deco(self):
263 class A(metaclass=abc.ABCMeta):
264 pass
265 @A.register
266 class B(object):
267 pass
268 b = B()
269 self.assertTrue(issubclass(B, A))
270 self.assertTrue(issubclass(B, (A,)))
271 self.assertIsInstance(b, A)
272 self.assertIsInstance(b, (A,))
273 @A.register
274 class C(B):
275 pass
276 c = C()
277 self.assertTrue(issubclass(C, A))
278 self.assertTrue(issubclass(C, (A,)))
279 self.assertIsInstance(c, A)
280 self.assertIsInstance(c, (A,))
281 self.assertIs(C, A.register(C))
282
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000283 def test_isinstance_invalidation(self):
284 class A(metaclass=abc.ABCMeta):
285 pass
286 class B:
287 pass
288 b = B()
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000289 self.assertFalse(isinstance(b, A))
290 self.assertFalse(isinstance(b, (A,)))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000291 A.register(B)
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000292 self.assertTrue(isinstance(b, A))
293 self.assertTrue(isinstance(b, (A,)))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000294
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000295 def test_registration_builtins(self):
296 class A(metaclass=abc.ABCMeta):
297 pass
298 A.register(int)
Ezio Melottie9615932010-01-24 19:26:24 +0000299 self.assertIsInstance(42, A)
300 self.assertIsInstance(42, (A,))
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000301 self.assertTrue(issubclass(int, A))
302 self.assertTrue(issubclass(int, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000303 class B(A):
304 pass
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000305 B.register(str)
306 class C(str): pass
Ezio Melottie9615932010-01-24 19:26:24 +0000307 self.assertIsInstance("", A)
308 self.assertIsInstance("", (A,))
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000309 self.assertTrue(issubclass(str, A))
310 self.assertTrue(issubclass(str, (A,)))
311 self.assertTrue(issubclass(C, A))
312 self.assertTrue(issubclass(C, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000313
314 def test_registration_edge_cases(self):
315 class A(metaclass=abc.ABCMeta):
316 pass
317 A.register(A) # should pass silently
318 class A1(A):
319 pass
320 self.assertRaises(RuntimeError, A1.register, A) # cycles not allowed
Christian Heimes043d6f62008-01-07 17:19:16 +0000321 class B(object):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000322 pass
323 A1.register(B) # ok
324 A1.register(B) # should pass silently
325 class C(A):
326 pass
327 A.register(C) # should pass silently
328 self.assertRaises(RuntimeError, C.register, A) # cycles not allowed
329 C.register(B) # ok
330
Benjamin Petersond6326642010-01-27 02:25:58 +0000331 def test_register_non_class(self):
332 class A(metaclass=abc.ABCMeta):
333 pass
Ezio Melottied3a7d22010-12-01 02:32:32 +0000334 self.assertRaisesRegex(TypeError, "Can only register classes",
335 A.register, 4)
Benjamin Petersond6326642010-01-27 02:25:58 +0000336
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000337 def test_registration_transitiveness(self):
338 class A(metaclass=abc.ABCMeta):
339 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000340 self.assertTrue(issubclass(A, A))
341 self.assertTrue(issubclass(A, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000342 class B(metaclass=abc.ABCMeta):
343 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000344 self.assertFalse(issubclass(A, B))
345 self.assertFalse(issubclass(A, (B,)))
346 self.assertFalse(issubclass(B, A))
347 self.assertFalse(issubclass(B, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000348 class C(metaclass=abc.ABCMeta):
349 pass
350 A.register(B)
351 class B1(B):
352 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000353 self.assertTrue(issubclass(B1, A))
354 self.assertTrue(issubclass(B1, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000355 class C1(C):
356 pass
357 B1.register(C1)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000358 self.assertFalse(issubclass(C, B))
359 self.assertFalse(issubclass(C, (B,)))
360 self.assertFalse(issubclass(C, B1))
361 self.assertFalse(issubclass(C, (B1,)))
362 self.assertTrue(issubclass(C1, A))
363 self.assertTrue(issubclass(C1, (A,)))
364 self.assertTrue(issubclass(C1, B))
365 self.assertTrue(issubclass(C1, (B,)))
366 self.assertTrue(issubclass(C1, B1))
367 self.assertTrue(issubclass(C1, (B1,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000368 C1.register(int)
369 class MyInt(int):
370 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000371 self.assertTrue(issubclass(MyInt, A))
372 self.assertTrue(issubclass(MyInt, (A,)))
Ezio Melottie9615932010-01-24 19:26:24 +0000373 self.assertIsInstance(42, A)
374 self.assertIsInstance(42, (A,))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000375
Guido van Rossum894d35e2007-09-11 20:42:30 +0000376 def test_all_new_methods_are_called(self):
377 class A(metaclass=abc.ABCMeta):
378 pass
Christian Heimes043d6f62008-01-07 17:19:16 +0000379 class B(object):
Guido van Rossum894d35e2007-09-11 20:42:30 +0000380 counter = 0
381 def __new__(cls):
382 B.counter += 1
383 return super().__new__(cls)
384 class C(A, B):
385 pass
386 self.assertEqual(B.counter, 0)
387 C()
388 self.assertEqual(B.counter, 1)
389
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000390
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000391if __name__ == "__main__":
392 unittest.main()