blob: 349852450189ae8b906215117ae80cd8a446ecef [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
Andrew Svetlovb67596d2012-12-13 19:09:33 +020099 def test_ABC_helper(self):
100 # create an ABC using the helper class and perform basic checks
101 class C(abc.ABC):
102 @classmethod
103 @abc.abstractmethod
104 def foo(cls): return cls.__name__
105 self.assertEqual(type(C), abc.ABCMeta)
106 self.assertRaises(TypeError, C)
107 class D(C):
108 @classmethod
109 def foo(cls): return super().foo()
110 self.assertEqual(D.foo(), 'D')
111
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -0500112 def test_abstractmethod_basics(self):
113 @abc.abstractmethod
114 def foo(self): pass
115 self.assertTrue(foo.__isabstractmethod__)
116 def bar(self): pass
117 self.assertFalse(hasattr(bar, "__isabstractmethod__"))
118
119 def test_abstractproperty_basics(self):
120 @property
121 @abc.abstractmethod
122 def foo(self): pass
123 self.assertTrue(foo.__isabstractmethod__)
124 def bar(self): pass
125 self.assertFalse(getattr(bar, "__isabstractmethod__", False))
126
127 class C(metaclass=abc.ABCMeta):
128 @property
129 @abc.abstractmethod
130 def foo(self): return 3
131 self.assertRaises(TypeError, C)
132 class D(C):
133 @C.foo.getter
134 def foo(self): return super().foo
135 self.assertEqual(D().foo, 3)
136
137 def test_abstractclassmethod_basics(self):
138 @classmethod
139 @abc.abstractmethod
140 def foo(cls): pass
141 self.assertTrue(foo.__isabstractmethod__)
142 @classmethod
143 def bar(cls): pass
144 self.assertFalse(getattr(bar, "__isabstractmethod__", False))
145
146 class C(metaclass=abc.ABCMeta):
147 @classmethod
148 @abc.abstractmethod
149 def foo(cls): return cls.__name__
150 self.assertRaises(TypeError, C)
151 class D(C):
152 @classmethod
153 def foo(cls): return super().foo()
154 self.assertEqual(D.foo(), 'D')
155 self.assertEqual(D().foo(), 'D')
156
157 def test_abstractstaticmethod_basics(self):
158 @staticmethod
159 @abc.abstractmethod
160 def foo(): pass
161 self.assertTrue(foo.__isabstractmethod__)
162 @staticmethod
163 def bar(): pass
164 self.assertFalse(getattr(bar, "__isabstractmethod__", False))
165
166 class C(metaclass=abc.ABCMeta):
167 @staticmethod
168 @abc.abstractmethod
169 def foo(): return 3
170 self.assertRaises(TypeError, C)
171 class D(C):
172 @staticmethod
173 def foo(): return 4
174 self.assertEqual(D.foo(), 4)
175 self.assertEqual(D().foo(), 4)
176
177 def test_abstractmethod_integration(self):
178 for abstractthing in [abc.abstractmethod, abc.abstractproperty,
179 abc.abstractclassmethod,
180 abc.abstractstaticmethod]:
181 class C(metaclass=abc.ABCMeta):
182 @abstractthing
183 def foo(self): pass # abstract
184 def bar(self): pass # concrete
185 self.assertEqual(C.__abstractmethods__, {"foo"})
186 self.assertRaises(TypeError, C) # because foo is abstract
187 self.assertTrue(isabstract(C))
188 class D(C):
189 def bar(self): pass # concrete override of concrete
190 self.assertEqual(D.__abstractmethods__, {"foo"})
191 self.assertRaises(TypeError, D) # because foo is still abstract
192 self.assertTrue(isabstract(D))
193 class E(D):
194 def foo(self): pass
195 self.assertEqual(E.__abstractmethods__, set())
196 E() # now foo is concrete, too
197 self.assertFalse(isabstract(E))
198 class F(E):
199 @abstractthing
200 def bar(self): pass # abstract override of concrete
201 self.assertEqual(F.__abstractmethods__, {"bar"})
202 self.assertRaises(TypeError, F) # because bar is abstract now
203 self.assertTrue(isabstract(F))
204
205 def test_descriptors_with_abstractmethod(self):
206 class C(metaclass=abc.ABCMeta):
207 @property
208 @abc.abstractmethod
209 def foo(self): return 3
210 @foo.setter
211 @abc.abstractmethod
212 def foo(self, val): pass
213 self.assertRaises(TypeError, C)
214 class D(C):
215 @C.foo.getter
216 def foo(self): return super().foo
217 self.assertRaises(TypeError, D)
218 class E(D):
219 @D.foo.setter
220 def foo(self, val): pass
221 self.assertEqual(E().foo, 3)
222 # check that the property's __isabstractmethod__ descriptor does the
223 # right thing when presented with a value that fails truth testing:
224 class NotBool(object):
225 def __nonzero__(self):
226 raise ValueError()
227 __len__ = __nonzero__
228 with self.assertRaises(ValueError):
229 class F(C):
230 def bar(self):
231 pass
232 bar.__isabstractmethod__ = NotBool()
233 foo = property(bar)
234
235
236 def test_customdescriptors_with_abstractmethod(self):
237 class Descriptor:
238 def __init__(self, fget, fset=None):
239 self._fget = fget
240 self._fset = fset
241 def getter(self, callable):
242 return Descriptor(callable, self._fget)
243 def setter(self, callable):
244 return Descriptor(self._fget, callable)
245 @property
246 def __isabstractmethod__(self):
247 return (getattr(self._fget, '__isabstractmethod__', False)
248 or getattr(self._fset, '__isabstractmethod__', False))
249 class C(metaclass=abc.ABCMeta):
250 @Descriptor
251 @abc.abstractmethod
252 def foo(self): return 3
253 @foo.setter
254 @abc.abstractmethod
255 def foo(self, val): pass
256 self.assertRaises(TypeError, C)
257 class D(C):
258 @C.foo.getter
259 def foo(self): return super().foo
260 self.assertRaises(TypeError, D)
261 class E(D):
262 @D.foo.setter
263 def foo(self, val): pass
264 self.assertFalse(E.foo.__isabstractmethod__)
265
Benjamin Peterson970d1882010-10-02 17:55:47 +0000266 def test_metaclass_abc(self):
267 # Metaclasses can be ABCs, too.
268 class A(metaclass=abc.ABCMeta):
269 @abc.abstractmethod
270 def x(self):
271 pass
272 self.assertEqual(A.__abstractmethods__, {"x"})
273 class meta(type, A):
274 def x(self):
275 return 1
276 class C(metaclass=meta):
277 pass
278
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000279 def test_registration_basics(self):
280 class A(metaclass=abc.ABCMeta):
281 pass
Christian Heimes043d6f62008-01-07 17:19:16 +0000282 class B(object):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000283 pass
284 b = B()
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000285 self.assertFalse(issubclass(B, A))
286 self.assertFalse(issubclass(B, (A,)))
Ezio Melottie9615932010-01-24 19:26:24 +0000287 self.assertNotIsInstance(b, A)
288 self.assertNotIsInstance(b, (A,))
Éric Araujo6c3787c2011-02-24 18:03:10 +0000289 B1 = A.register(B)
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000290 self.assertTrue(issubclass(B, A))
291 self.assertTrue(issubclass(B, (A,)))
Ezio Melottie9615932010-01-24 19:26:24 +0000292 self.assertIsInstance(b, A)
293 self.assertIsInstance(b, (A,))
Éric Araujo6c3787c2011-02-24 18:03:10 +0000294 self.assertIs(B1, B)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000295 class C(B):
296 pass
297 c = C()
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000298 self.assertTrue(issubclass(C, A))
299 self.assertTrue(issubclass(C, (A,)))
Ezio Melottie9615932010-01-24 19:26:24 +0000300 self.assertIsInstance(c, A)
301 self.assertIsInstance(c, (A,))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000302
Éric Araujo6c3787c2011-02-24 18:03:10 +0000303 def test_register_as_class_deco(self):
304 class A(metaclass=abc.ABCMeta):
305 pass
306 @A.register
307 class B(object):
308 pass
309 b = B()
310 self.assertTrue(issubclass(B, A))
311 self.assertTrue(issubclass(B, (A,)))
312 self.assertIsInstance(b, A)
313 self.assertIsInstance(b, (A,))
314 @A.register
315 class C(B):
316 pass
317 c = C()
318 self.assertTrue(issubclass(C, A))
319 self.assertTrue(issubclass(C, (A,)))
320 self.assertIsInstance(c, A)
321 self.assertIsInstance(c, (A,))
322 self.assertIs(C, A.register(C))
323
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000324 def test_isinstance_invalidation(self):
325 class A(metaclass=abc.ABCMeta):
326 pass
327 class B:
328 pass
329 b = B()
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000330 self.assertFalse(isinstance(b, A))
331 self.assertFalse(isinstance(b, (A,)))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000332 A.register(B)
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000333 self.assertTrue(isinstance(b, A))
334 self.assertTrue(isinstance(b, (A,)))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000335
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000336 def test_registration_builtins(self):
337 class A(metaclass=abc.ABCMeta):
338 pass
339 A.register(int)
Ezio Melottie9615932010-01-24 19:26:24 +0000340 self.assertIsInstance(42, A)
341 self.assertIsInstance(42, (A,))
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000342 self.assertTrue(issubclass(int, A))
343 self.assertTrue(issubclass(int, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000344 class B(A):
345 pass
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000346 B.register(str)
347 class C(str): pass
Ezio Melottie9615932010-01-24 19:26:24 +0000348 self.assertIsInstance("", A)
349 self.assertIsInstance("", (A,))
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000350 self.assertTrue(issubclass(str, A))
351 self.assertTrue(issubclass(str, (A,)))
352 self.assertTrue(issubclass(C, A))
353 self.assertTrue(issubclass(C, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000354
355 def test_registration_edge_cases(self):
356 class A(metaclass=abc.ABCMeta):
357 pass
358 A.register(A) # should pass silently
359 class A1(A):
360 pass
361 self.assertRaises(RuntimeError, A1.register, A) # cycles not allowed
Christian Heimes043d6f62008-01-07 17:19:16 +0000362 class B(object):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000363 pass
364 A1.register(B) # ok
365 A1.register(B) # should pass silently
366 class C(A):
367 pass
368 A.register(C) # should pass silently
369 self.assertRaises(RuntimeError, C.register, A) # cycles not allowed
370 C.register(B) # ok
371
Benjamin Petersond6326642010-01-27 02:25:58 +0000372 def test_register_non_class(self):
373 class A(metaclass=abc.ABCMeta):
374 pass
Ezio Melottied3a7d22010-12-01 02:32:32 +0000375 self.assertRaisesRegex(TypeError, "Can only register classes",
376 A.register, 4)
Benjamin Petersond6326642010-01-27 02:25:58 +0000377
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000378 def test_registration_transitiveness(self):
379 class A(metaclass=abc.ABCMeta):
380 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000381 self.assertTrue(issubclass(A, A))
382 self.assertTrue(issubclass(A, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000383 class B(metaclass=abc.ABCMeta):
384 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000385 self.assertFalse(issubclass(A, B))
386 self.assertFalse(issubclass(A, (B,)))
387 self.assertFalse(issubclass(B, A))
388 self.assertFalse(issubclass(B, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000389 class C(metaclass=abc.ABCMeta):
390 pass
391 A.register(B)
392 class B1(B):
393 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000394 self.assertTrue(issubclass(B1, A))
395 self.assertTrue(issubclass(B1, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000396 class C1(C):
397 pass
398 B1.register(C1)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000399 self.assertFalse(issubclass(C, B))
400 self.assertFalse(issubclass(C, (B,)))
401 self.assertFalse(issubclass(C, B1))
402 self.assertFalse(issubclass(C, (B1,)))
403 self.assertTrue(issubclass(C1, A))
404 self.assertTrue(issubclass(C1, (A,)))
405 self.assertTrue(issubclass(C1, B))
406 self.assertTrue(issubclass(C1, (B,)))
407 self.assertTrue(issubclass(C1, B1))
408 self.assertTrue(issubclass(C1, (B1,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000409 C1.register(int)
410 class MyInt(int):
411 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000412 self.assertTrue(issubclass(MyInt, A))
413 self.assertTrue(issubclass(MyInt, (A,)))
Ezio Melottie9615932010-01-24 19:26:24 +0000414 self.assertIsInstance(42, A)
415 self.assertIsInstance(42, (A,))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000416
Guido van Rossum894d35e2007-09-11 20:42:30 +0000417 def test_all_new_methods_are_called(self):
418 class A(metaclass=abc.ABCMeta):
419 pass
Christian Heimes043d6f62008-01-07 17:19:16 +0000420 class B(object):
Guido van Rossum894d35e2007-09-11 20:42:30 +0000421 counter = 0
422 def __new__(cls):
423 B.counter += 1
424 return super().__new__(cls)
425 class C(A, B):
426 pass
427 self.assertEqual(B.counter, 0)
428 C()
429 self.assertEqual(B.counter, 1)
430
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000431
432def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000433 support.run_unittest(TestABC)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000434
435
436if __name__ == "__main__":
437 unittest.main()