blob: 653c957b814ac247063942499aadc16beca34665 [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
Guido van Rossum70d2b892007-08-01 17:52:23 +000068 def test_abstractmethod_integration(self):
Benjamin Peterson45c257f2010-08-17 00:52:52 +000069 for abstractthing in [abc.abstractmethod, abc.abstractproperty,
70 abc.abstractclassmethod,
71 abc.abstractstaticmethod]:
Guido van Rossum70d2b892007-08-01 17:52:23 +000072 class C(metaclass=abc.ABCMeta):
73 @abstractthing
74 def foo(self): pass # abstract
75 def bar(self): pass # concrete
76 self.assertEqual(C.__abstractmethods__, {"foo"})
77 self.assertRaises(TypeError, C) # because foo is abstract
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000078 self.assertTrue(isabstract(C))
Guido van Rossum70d2b892007-08-01 17:52:23 +000079 class D(C):
80 def bar(self): pass # concrete override of concrete
81 self.assertEqual(D.__abstractmethods__, {"foo"})
82 self.assertRaises(TypeError, D) # because foo is still abstract
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000083 self.assertTrue(isabstract(D))
Guido van Rossum70d2b892007-08-01 17:52:23 +000084 class E(D):
85 def foo(self): pass
86 self.assertEqual(E.__abstractmethods__, set())
87 E() # now foo is concrete, too
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000088 self.assertFalse(isabstract(E))
Guido van Rossum70d2b892007-08-01 17:52:23 +000089 class F(E):
90 @abstractthing
91 def bar(self): pass # abstract override of concrete
92 self.assertEqual(F.__abstractmethods__, {"bar"})
93 self.assertRaises(TypeError, F) # because bar is abstract now
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000094 self.assertTrue(isabstract(F))
Guido van Rossumcd16bf62007-06-13 18:07:49 +000095
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -050096
97class TestABC(unittest.TestCase):
98
99 def test_abstractmethod_basics(self):
100 @abc.abstractmethod
101 def foo(self): pass
102 self.assertTrue(foo.__isabstractmethod__)
103 def bar(self): pass
104 self.assertFalse(hasattr(bar, "__isabstractmethod__"))
105
106 def test_abstractproperty_basics(self):
107 @property
108 @abc.abstractmethod
109 def foo(self): pass
110 self.assertTrue(foo.__isabstractmethod__)
111 def bar(self): pass
112 self.assertFalse(getattr(bar, "__isabstractmethod__", False))
113
114 class C(metaclass=abc.ABCMeta):
115 @property
116 @abc.abstractmethod
117 def foo(self): return 3
118 self.assertRaises(TypeError, C)
119 class D(C):
120 @C.foo.getter
121 def foo(self): return super().foo
122 self.assertEqual(D().foo, 3)
123
124 def test_abstractclassmethod_basics(self):
125 @classmethod
126 @abc.abstractmethod
127 def foo(cls): pass
128 self.assertTrue(foo.__isabstractmethod__)
129 @classmethod
130 def bar(cls): pass
131 self.assertFalse(getattr(bar, "__isabstractmethod__", False))
132
133 class C(metaclass=abc.ABCMeta):
134 @classmethod
135 @abc.abstractmethod
136 def foo(cls): return cls.__name__
137 self.assertRaises(TypeError, C)
138 class D(C):
139 @classmethod
140 def foo(cls): return super().foo()
141 self.assertEqual(D.foo(), 'D')
142 self.assertEqual(D().foo(), 'D')
143
144 def test_abstractstaticmethod_basics(self):
145 @staticmethod
146 @abc.abstractmethod
147 def foo(): pass
148 self.assertTrue(foo.__isabstractmethod__)
149 @staticmethod
150 def bar(): pass
151 self.assertFalse(getattr(bar, "__isabstractmethod__", False))
152
153 class C(metaclass=abc.ABCMeta):
154 @staticmethod
155 @abc.abstractmethod
156 def foo(): return 3
157 self.assertRaises(TypeError, C)
158 class D(C):
159 @staticmethod
160 def foo(): return 4
161 self.assertEqual(D.foo(), 4)
162 self.assertEqual(D().foo(), 4)
163
164 def test_abstractmethod_integration(self):
165 for abstractthing in [abc.abstractmethod, abc.abstractproperty,
166 abc.abstractclassmethod,
167 abc.abstractstaticmethod]:
168 class C(metaclass=abc.ABCMeta):
169 @abstractthing
170 def foo(self): pass # abstract
171 def bar(self): pass # concrete
172 self.assertEqual(C.__abstractmethods__, {"foo"})
173 self.assertRaises(TypeError, C) # because foo is abstract
174 self.assertTrue(isabstract(C))
175 class D(C):
176 def bar(self): pass # concrete override of concrete
177 self.assertEqual(D.__abstractmethods__, {"foo"})
178 self.assertRaises(TypeError, D) # because foo is still abstract
179 self.assertTrue(isabstract(D))
180 class E(D):
181 def foo(self): pass
182 self.assertEqual(E.__abstractmethods__, set())
183 E() # now foo is concrete, too
184 self.assertFalse(isabstract(E))
185 class F(E):
186 @abstractthing
187 def bar(self): pass # abstract override of concrete
188 self.assertEqual(F.__abstractmethods__, {"bar"})
189 self.assertRaises(TypeError, F) # because bar is abstract now
190 self.assertTrue(isabstract(F))
191
192 def test_descriptors_with_abstractmethod(self):
193 class C(metaclass=abc.ABCMeta):
194 @property
195 @abc.abstractmethod
196 def foo(self): return 3
197 @foo.setter
198 @abc.abstractmethod
199 def foo(self, val): pass
200 self.assertRaises(TypeError, C)
201 class D(C):
202 @C.foo.getter
203 def foo(self): return super().foo
204 self.assertRaises(TypeError, D)
205 class E(D):
206 @D.foo.setter
207 def foo(self, val): pass
208 self.assertEqual(E().foo, 3)
209 # check that the property's __isabstractmethod__ descriptor does the
210 # right thing when presented with a value that fails truth testing:
211 class NotBool(object):
212 def __nonzero__(self):
213 raise ValueError()
214 __len__ = __nonzero__
215 with self.assertRaises(ValueError):
216 class F(C):
217 def bar(self):
218 pass
219 bar.__isabstractmethod__ = NotBool()
220 foo = property(bar)
221
222
223 def test_customdescriptors_with_abstractmethod(self):
224 class Descriptor:
225 def __init__(self, fget, fset=None):
226 self._fget = fget
227 self._fset = fset
228 def getter(self, callable):
229 return Descriptor(callable, self._fget)
230 def setter(self, callable):
231 return Descriptor(self._fget, callable)
232 @property
233 def __isabstractmethod__(self):
234 return (getattr(self._fget, '__isabstractmethod__', False)
235 or getattr(self._fset, '__isabstractmethod__', False))
236 class C(metaclass=abc.ABCMeta):
237 @Descriptor
238 @abc.abstractmethod
239 def foo(self): return 3
240 @foo.setter
241 @abc.abstractmethod
242 def foo(self, val): pass
243 self.assertRaises(TypeError, C)
244 class D(C):
245 @C.foo.getter
246 def foo(self): return super().foo
247 self.assertRaises(TypeError, D)
248 class E(D):
249 @D.foo.setter
250 def foo(self, val): pass
251 self.assertFalse(E.foo.__isabstractmethod__)
252
Benjamin Peterson970d1882010-10-02 17:55:47 +0000253 def test_metaclass_abc(self):
254 # Metaclasses can be ABCs, too.
255 class A(metaclass=abc.ABCMeta):
256 @abc.abstractmethod
257 def x(self):
258 pass
259 self.assertEqual(A.__abstractmethods__, {"x"})
260 class meta(type, A):
261 def x(self):
262 return 1
263 class C(metaclass=meta):
264 pass
265
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000266 def test_registration_basics(self):
267 class A(metaclass=abc.ABCMeta):
268 pass
Christian Heimes043d6f62008-01-07 17:19:16 +0000269 class B(object):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000270 pass
271 b = B()
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000272 self.assertFalse(issubclass(B, A))
273 self.assertFalse(issubclass(B, (A,)))
Ezio Melottie9615932010-01-24 19:26:24 +0000274 self.assertNotIsInstance(b, A)
275 self.assertNotIsInstance(b, (A,))
Éric Araujo6c3787c2011-02-24 18:03:10 +0000276 B1 = A.register(B)
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000277 self.assertTrue(issubclass(B, A))
278 self.assertTrue(issubclass(B, (A,)))
Ezio Melottie9615932010-01-24 19:26:24 +0000279 self.assertIsInstance(b, A)
280 self.assertIsInstance(b, (A,))
Éric Araujo6c3787c2011-02-24 18:03:10 +0000281 self.assertIs(B1, B)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000282 class C(B):
283 pass
284 c = C()
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000285 self.assertTrue(issubclass(C, A))
286 self.assertTrue(issubclass(C, (A,)))
Ezio Melottie9615932010-01-24 19:26:24 +0000287 self.assertIsInstance(c, A)
288 self.assertIsInstance(c, (A,))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000289
Éric Araujo6c3787c2011-02-24 18:03:10 +0000290 def test_register_as_class_deco(self):
291 class A(metaclass=abc.ABCMeta):
292 pass
293 @A.register
294 class B(object):
295 pass
296 b = B()
297 self.assertTrue(issubclass(B, A))
298 self.assertTrue(issubclass(B, (A,)))
299 self.assertIsInstance(b, A)
300 self.assertIsInstance(b, (A,))
301 @A.register
302 class C(B):
303 pass
304 c = C()
305 self.assertTrue(issubclass(C, A))
306 self.assertTrue(issubclass(C, (A,)))
307 self.assertIsInstance(c, A)
308 self.assertIsInstance(c, (A,))
309 self.assertIs(C, A.register(C))
310
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000311 def test_isinstance_invalidation(self):
312 class A(metaclass=abc.ABCMeta):
313 pass
314 class B:
315 pass
316 b = B()
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000317 self.assertFalse(isinstance(b, A))
318 self.assertFalse(isinstance(b, (A,)))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000319 A.register(B)
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000320 self.assertTrue(isinstance(b, A))
321 self.assertTrue(isinstance(b, (A,)))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000322
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000323 def test_registration_builtins(self):
324 class A(metaclass=abc.ABCMeta):
325 pass
326 A.register(int)
Ezio Melottie9615932010-01-24 19:26:24 +0000327 self.assertIsInstance(42, A)
328 self.assertIsInstance(42, (A,))
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000329 self.assertTrue(issubclass(int, A))
330 self.assertTrue(issubclass(int, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000331 class B(A):
332 pass
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000333 B.register(str)
334 class C(str): pass
Ezio Melottie9615932010-01-24 19:26:24 +0000335 self.assertIsInstance("", A)
336 self.assertIsInstance("", (A,))
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000337 self.assertTrue(issubclass(str, A))
338 self.assertTrue(issubclass(str, (A,)))
339 self.assertTrue(issubclass(C, A))
340 self.assertTrue(issubclass(C, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000341
342 def test_registration_edge_cases(self):
343 class A(metaclass=abc.ABCMeta):
344 pass
345 A.register(A) # should pass silently
346 class A1(A):
347 pass
348 self.assertRaises(RuntimeError, A1.register, A) # cycles not allowed
Christian Heimes043d6f62008-01-07 17:19:16 +0000349 class B(object):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000350 pass
351 A1.register(B) # ok
352 A1.register(B) # should pass silently
353 class C(A):
354 pass
355 A.register(C) # should pass silently
356 self.assertRaises(RuntimeError, C.register, A) # cycles not allowed
357 C.register(B) # ok
358
Benjamin Petersond6326642010-01-27 02:25:58 +0000359 def test_register_non_class(self):
360 class A(metaclass=abc.ABCMeta):
361 pass
Ezio Melottied3a7d22010-12-01 02:32:32 +0000362 self.assertRaisesRegex(TypeError, "Can only register classes",
363 A.register, 4)
Benjamin Petersond6326642010-01-27 02:25:58 +0000364
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000365 def test_registration_transitiveness(self):
366 class A(metaclass=abc.ABCMeta):
367 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000368 self.assertTrue(issubclass(A, A))
369 self.assertTrue(issubclass(A, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000370 class B(metaclass=abc.ABCMeta):
371 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000372 self.assertFalse(issubclass(A, B))
373 self.assertFalse(issubclass(A, (B,)))
374 self.assertFalse(issubclass(B, A))
375 self.assertFalse(issubclass(B, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000376 class C(metaclass=abc.ABCMeta):
377 pass
378 A.register(B)
379 class B1(B):
380 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000381 self.assertTrue(issubclass(B1, A))
382 self.assertTrue(issubclass(B1, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000383 class C1(C):
384 pass
385 B1.register(C1)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000386 self.assertFalse(issubclass(C, B))
387 self.assertFalse(issubclass(C, (B,)))
388 self.assertFalse(issubclass(C, B1))
389 self.assertFalse(issubclass(C, (B1,)))
390 self.assertTrue(issubclass(C1, A))
391 self.assertTrue(issubclass(C1, (A,)))
392 self.assertTrue(issubclass(C1, B))
393 self.assertTrue(issubclass(C1, (B,)))
394 self.assertTrue(issubclass(C1, B1))
395 self.assertTrue(issubclass(C1, (B1,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000396 C1.register(int)
397 class MyInt(int):
398 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000399 self.assertTrue(issubclass(MyInt, A))
400 self.assertTrue(issubclass(MyInt, (A,)))
Ezio Melottie9615932010-01-24 19:26:24 +0000401 self.assertIsInstance(42, A)
402 self.assertIsInstance(42, (A,))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000403
Guido van Rossum894d35e2007-09-11 20:42:30 +0000404 def test_all_new_methods_are_called(self):
405 class A(metaclass=abc.ABCMeta):
406 pass
Christian Heimes043d6f62008-01-07 17:19:16 +0000407 class B(object):
Guido van Rossum894d35e2007-09-11 20:42:30 +0000408 counter = 0
409 def __new__(cls):
410 B.counter += 1
411 return super().__new__(cls)
412 class C(A, B):
413 pass
414 self.assertEqual(B.counter, 0)
415 C()
416 self.assertEqual(B.counter, 1)
417
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000418
419def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000420 support.run_unittest(TestABC)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000421
422
423if __name__ == "__main__":
424 unittest.main()