blob: 1319a64ef7c22dc31ddd103a56e776d7a6c5850b [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
13class TestABC(unittest.TestCase):
14
15 def test_abstractmethod_basics(self):
16 @abc.abstractmethod
17 def foo(self): pass
Benjamin Peterson83cd3b92010-08-17 01:07:53 +000018 self.assertTrue(foo.__isabstractmethod__)
Guido van Rossumcd16bf62007-06-13 18:07:49 +000019 def bar(self): pass
Benjamin Peterson83cd3b92010-08-17 01:07:53 +000020 self.assertFalse(hasattr(bar, "__isabstractmethod__"))
Guido van Rossumcd16bf62007-06-13 18:07:49 +000021
Guido van Rossum70d2b892007-08-01 17:52:23 +000022 def test_abstractproperty_basics(self):
23 @abc.abstractproperty
24 def foo(self): pass
Benjamin Peterson83cd3b92010-08-17 01:07:53 +000025 self.assertTrue(foo.__isabstractmethod__)
Guido van Rossum70d2b892007-08-01 17:52:23 +000026 def bar(self): pass
Benjamin Peterson83cd3b92010-08-17 01:07:53 +000027 self.assertFalse(hasattr(bar, "__isabstractmethod__"))
Guido van Rossum70d2b892007-08-01 17:52:23 +000028
Guido van Rossumcd16bf62007-06-13 18:07:49 +000029 class C(metaclass=abc.ABCMeta):
Guido van Rossum70d2b892007-08-01 17:52:23 +000030 @abc.abstractproperty
31 def foo(self): return 3
Guido van Rossumcd16bf62007-06-13 18:07:49 +000032 class D(C):
Guido van Rossum70d2b892007-08-01 17:52:23 +000033 @property
34 def foo(self): return super().foo
35 self.assertEqual(D().foo, 3)
36
Benjamin Peterson45c257f2010-08-17 00:52:52 +000037 def test_abstractclassmethod_basics(self):
38 @abc.abstractclassmethod
39 def foo(cls): pass
Benjamin Peterson83cd3b92010-08-17 01:07:53 +000040 self.assertTrue(foo.__isabstractmethod__)
Benjamin Peterson45c257f2010-08-17 00:52:52 +000041 @classmethod
42 def bar(cls): pass
Benjamin Peterson83cd3b92010-08-17 01:07:53 +000043 self.assertFalse(hasattr(bar, "__isabstractmethod__"))
Benjamin Peterson45c257f2010-08-17 00:52:52 +000044
45 class C(metaclass=abc.ABCMeta):
46 @abc.abstractclassmethod
47 def foo(cls): return cls.__name__
48 self.assertRaises(TypeError, C)
49 class D(C):
50 @classmethod
51 def foo(cls): return super().foo()
52 self.assertEqual(D.foo(), 'D')
53 self.assertEqual(D().foo(), 'D')
54
55 def test_abstractstaticmethod_basics(self):
56 @abc.abstractstaticmethod
57 def foo(): pass
Benjamin Peterson83cd3b92010-08-17 01:07:53 +000058 self.assertTrue(foo.__isabstractmethod__)
Benjamin Peterson45c257f2010-08-17 00:52:52 +000059 @staticmethod
60 def bar(): pass
Benjamin Peterson83cd3b92010-08-17 01:07:53 +000061 self.assertFalse(hasattr(bar, "__isabstractmethod__"))
Benjamin Peterson45c257f2010-08-17 00:52:52 +000062
63 class C(metaclass=abc.ABCMeta):
64 @abc.abstractstaticmethod
65 def foo(): return 3
66 self.assertRaises(TypeError, C)
67 class D(C):
68 @staticmethod
69 def foo(): return 4
70 self.assertEqual(D.foo(), 4)
71 self.assertEqual(D().foo(), 4)
72
Guido van Rossum70d2b892007-08-01 17:52:23 +000073 def test_abstractmethod_integration(self):
Benjamin Peterson45c257f2010-08-17 00:52:52 +000074 for abstractthing in [abc.abstractmethod, abc.abstractproperty,
75 abc.abstractclassmethod,
76 abc.abstractstaticmethod]:
Guido van Rossum70d2b892007-08-01 17:52:23 +000077 class C(metaclass=abc.ABCMeta):
78 @abstractthing
79 def foo(self): pass # abstract
80 def bar(self): pass # concrete
81 self.assertEqual(C.__abstractmethods__, {"foo"})
82 self.assertRaises(TypeError, C) # because foo is abstract
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000083 self.assertTrue(isabstract(C))
Guido van Rossum70d2b892007-08-01 17:52:23 +000084 class D(C):
85 def bar(self): pass # concrete override of concrete
86 self.assertEqual(D.__abstractmethods__, {"foo"})
87 self.assertRaises(TypeError, D) # because foo is still abstract
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000088 self.assertTrue(isabstract(D))
Guido van Rossum70d2b892007-08-01 17:52:23 +000089 class E(D):
90 def foo(self): pass
91 self.assertEqual(E.__abstractmethods__, set())
92 E() # now foo is concrete, too
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000093 self.assertFalse(isabstract(E))
Guido van Rossum70d2b892007-08-01 17:52:23 +000094 class F(E):
95 @abstractthing
96 def bar(self): pass # abstract override of concrete
97 self.assertEqual(F.__abstractmethods__, {"bar"})
98 self.assertRaises(TypeError, F) # because bar is abstract now
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000099 self.assertTrue(isabstract(F))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000100
Benjamin Peterson970d1882010-10-02 17:55:47 +0000101 def test_metaclass_abc(self):
102 # Metaclasses can be ABCs, too.
103 class A(metaclass=abc.ABCMeta):
104 @abc.abstractmethod
105 def x(self):
106 pass
107 self.assertEqual(A.__abstractmethods__, {"x"})
108 class meta(type, A):
109 def x(self):
110 return 1
111 class C(metaclass=meta):
112 pass
113
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000114 def test_registration_basics(self):
115 class A(metaclass=abc.ABCMeta):
116 pass
Christian Heimes043d6f62008-01-07 17:19:16 +0000117 class B(object):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000118 pass
119 b = B()
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000120 self.assertFalse(issubclass(B, A))
121 self.assertFalse(issubclass(B, (A,)))
Ezio Melottie9615932010-01-24 19:26:24 +0000122 self.assertNotIsInstance(b, A)
123 self.assertNotIsInstance(b, (A,))
Éric Araujo6c3787c2011-02-24 18:03:10 +0000124 B1 = A.register(B)
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000125 self.assertTrue(issubclass(B, A))
126 self.assertTrue(issubclass(B, (A,)))
Ezio Melottie9615932010-01-24 19:26:24 +0000127 self.assertIsInstance(b, A)
128 self.assertIsInstance(b, (A,))
Éric Araujo6c3787c2011-02-24 18:03:10 +0000129 self.assertIs(B1, B)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000130 class C(B):
131 pass
132 c = C()
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000133 self.assertTrue(issubclass(C, A))
134 self.assertTrue(issubclass(C, (A,)))
Ezio Melottie9615932010-01-24 19:26:24 +0000135 self.assertIsInstance(c, A)
136 self.assertIsInstance(c, (A,))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000137
Éric Araujo6c3787c2011-02-24 18:03:10 +0000138 def test_register_as_class_deco(self):
139 class A(metaclass=abc.ABCMeta):
140 pass
141 @A.register
142 class B(object):
143 pass
144 b = B()
145 self.assertTrue(issubclass(B, A))
146 self.assertTrue(issubclass(B, (A,)))
147 self.assertIsInstance(b, A)
148 self.assertIsInstance(b, (A,))
149 @A.register
150 class C(B):
151 pass
152 c = C()
153 self.assertTrue(issubclass(C, A))
154 self.assertTrue(issubclass(C, (A,)))
155 self.assertIsInstance(c, A)
156 self.assertIsInstance(c, (A,))
157 self.assertIs(C, A.register(C))
158
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000159 def test_isinstance_invalidation(self):
160 class A(metaclass=abc.ABCMeta):
161 pass
162 class B:
163 pass
164 b = B()
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000165 self.assertFalse(isinstance(b, A))
166 self.assertFalse(isinstance(b, (A,)))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000167 A.register(B)
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000168 self.assertTrue(isinstance(b, A))
169 self.assertTrue(isinstance(b, (A,)))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000170
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000171 def test_registration_builtins(self):
172 class A(metaclass=abc.ABCMeta):
173 pass
174 A.register(int)
Ezio Melottie9615932010-01-24 19:26:24 +0000175 self.assertIsInstance(42, A)
176 self.assertIsInstance(42, (A,))
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000177 self.assertTrue(issubclass(int, A))
178 self.assertTrue(issubclass(int, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000179 class B(A):
180 pass
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000181 B.register(str)
182 class C(str): pass
Ezio Melottie9615932010-01-24 19:26:24 +0000183 self.assertIsInstance("", A)
184 self.assertIsInstance("", (A,))
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000185 self.assertTrue(issubclass(str, A))
186 self.assertTrue(issubclass(str, (A,)))
187 self.assertTrue(issubclass(C, A))
188 self.assertTrue(issubclass(C, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000189
190 def test_registration_edge_cases(self):
191 class A(metaclass=abc.ABCMeta):
192 pass
193 A.register(A) # should pass silently
194 class A1(A):
195 pass
196 self.assertRaises(RuntimeError, A1.register, A) # cycles not allowed
Christian Heimes043d6f62008-01-07 17:19:16 +0000197 class B(object):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000198 pass
199 A1.register(B) # ok
200 A1.register(B) # should pass silently
201 class C(A):
202 pass
203 A.register(C) # should pass silently
204 self.assertRaises(RuntimeError, C.register, A) # cycles not allowed
205 C.register(B) # ok
206
Benjamin Petersond6326642010-01-27 02:25:58 +0000207 def test_register_non_class(self):
208 class A(metaclass=abc.ABCMeta):
209 pass
Ezio Melottied3a7d22010-12-01 02:32:32 +0000210 self.assertRaisesRegex(TypeError, "Can only register classes",
211 A.register, 4)
Benjamin Petersond6326642010-01-27 02:25:58 +0000212
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000213 def test_registration_transitiveness(self):
214 class A(metaclass=abc.ABCMeta):
215 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000216 self.assertTrue(issubclass(A, A))
217 self.assertTrue(issubclass(A, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000218 class B(metaclass=abc.ABCMeta):
219 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000220 self.assertFalse(issubclass(A, B))
221 self.assertFalse(issubclass(A, (B,)))
222 self.assertFalse(issubclass(B, A))
223 self.assertFalse(issubclass(B, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000224 class C(metaclass=abc.ABCMeta):
225 pass
226 A.register(B)
227 class B1(B):
228 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000229 self.assertTrue(issubclass(B1, A))
230 self.assertTrue(issubclass(B1, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000231 class C1(C):
232 pass
233 B1.register(C1)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000234 self.assertFalse(issubclass(C, B))
235 self.assertFalse(issubclass(C, (B,)))
236 self.assertFalse(issubclass(C, B1))
237 self.assertFalse(issubclass(C, (B1,)))
238 self.assertTrue(issubclass(C1, A))
239 self.assertTrue(issubclass(C1, (A,)))
240 self.assertTrue(issubclass(C1, B))
241 self.assertTrue(issubclass(C1, (B,)))
242 self.assertTrue(issubclass(C1, B1))
243 self.assertTrue(issubclass(C1, (B1,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000244 C1.register(int)
245 class MyInt(int):
246 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000247 self.assertTrue(issubclass(MyInt, A))
248 self.assertTrue(issubclass(MyInt, (A,)))
Ezio Melottie9615932010-01-24 19:26:24 +0000249 self.assertIsInstance(42, A)
250 self.assertIsInstance(42, (A,))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000251
Guido van Rossum894d35e2007-09-11 20:42:30 +0000252 def test_all_new_methods_are_called(self):
253 class A(metaclass=abc.ABCMeta):
254 pass
Christian Heimes043d6f62008-01-07 17:19:16 +0000255 class B(object):
Guido van Rossum894d35e2007-09-11 20:42:30 +0000256 counter = 0
257 def __new__(cls):
258 B.counter += 1
259 return super().__new__(cls)
260 class C(A, B):
261 pass
262 self.assertEqual(B.counter, 0)
263 C()
264 self.assertEqual(B.counter, 1)
265
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000266
267def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000268 support.run_unittest(TestABC)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000269
270
271if __name__ == "__main__":
272 unittest.main()