blob: 1b516445f205e70719cf506811db62b7c4a4fe15 [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 Petersonaec5fd12010-10-02 00:03:31 +0000101 def test_type_has_no_abstractmethods(self):
102 # type pretends not to have __abstractmethods__.
103 self.assertRaises(AttributeError, getattr, type, "__abstractmethods__")
104 class meta(type):
105 pass
106 self.assertRaises(AttributeError, getattr, meta, "__abstractmethods__")
107
Benjamin Peterson970d1882010-10-02 17:55:47 +0000108 def test_metaclass_abc(self):
109 # Metaclasses can be ABCs, too.
110 class A(metaclass=abc.ABCMeta):
111 @abc.abstractmethod
112 def x(self):
113 pass
114 self.assertEqual(A.__abstractmethods__, {"x"})
115 class meta(type, A):
116 def x(self):
117 return 1
118 class C(metaclass=meta):
119 pass
120
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000121 def test_registration_basics(self):
122 class A(metaclass=abc.ABCMeta):
123 pass
Christian Heimes043d6f62008-01-07 17:19:16 +0000124 class B(object):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000125 pass
126 b = B()
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000127 self.assertFalse(issubclass(B, A))
128 self.assertFalse(issubclass(B, (A,)))
Ezio Melottie9615932010-01-24 19:26:24 +0000129 self.assertNotIsInstance(b, A)
130 self.assertNotIsInstance(b, (A,))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000131 A.register(B)
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000132 self.assertTrue(issubclass(B, A))
133 self.assertTrue(issubclass(B, (A,)))
Ezio Melottie9615932010-01-24 19:26:24 +0000134 self.assertIsInstance(b, A)
135 self.assertIsInstance(b, (A,))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000136 class C(B):
137 pass
138 c = C()
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000139 self.assertTrue(issubclass(C, A))
140 self.assertTrue(issubclass(C, (A,)))
Ezio Melottie9615932010-01-24 19:26:24 +0000141 self.assertIsInstance(c, A)
142 self.assertIsInstance(c, (A,))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000143
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000144 def test_isinstance_invalidation(self):
145 class A(metaclass=abc.ABCMeta):
146 pass
147 class B:
148 pass
149 b = B()
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000150 self.assertFalse(isinstance(b, A))
151 self.assertFalse(isinstance(b, (A,)))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000152 A.register(B)
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000153 self.assertTrue(isinstance(b, A))
154 self.assertTrue(isinstance(b, (A,)))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000155
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000156 def test_registration_builtins(self):
157 class A(metaclass=abc.ABCMeta):
158 pass
159 A.register(int)
Ezio Melottie9615932010-01-24 19:26:24 +0000160 self.assertIsInstance(42, A)
161 self.assertIsInstance(42, (A,))
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000162 self.assertTrue(issubclass(int, A))
163 self.assertTrue(issubclass(int, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000164 class B(A):
165 pass
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000166 B.register(str)
167 class C(str): pass
Ezio Melottie9615932010-01-24 19:26:24 +0000168 self.assertIsInstance("", A)
169 self.assertIsInstance("", (A,))
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000170 self.assertTrue(issubclass(str, A))
171 self.assertTrue(issubclass(str, (A,)))
172 self.assertTrue(issubclass(C, A))
173 self.assertTrue(issubclass(C, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000174
175 def test_registration_edge_cases(self):
176 class A(metaclass=abc.ABCMeta):
177 pass
178 A.register(A) # should pass silently
179 class A1(A):
180 pass
181 self.assertRaises(RuntimeError, A1.register, A) # cycles not allowed
Christian Heimes043d6f62008-01-07 17:19:16 +0000182 class B(object):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000183 pass
184 A1.register(B) # ok
185 A1.register(B) # should pass silently
186 class C(A):
187 pass
188 A.register(C) # should pass silently
189 self.assertRaises(RuntimeError, C.register, A) # cycles not allowed
190 C.register(B) # ok
191
Benjamin Petersond6326642010-01-27 02:25:58 +0000192 def test_register_non_class(self):
193 class A(metaclass=abc.ABCMeta):
194 pass
195 self.assertRaisesRegexp(TypeError, "Can only register classes",
196 A.register, 4)
197
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000198 def test_registration_transitiveness(self):
199 class A(metaclass=abc.ABCMeta):
200 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000201 self.assertTrue(issubclass(A, A))
202 self.assertTrue(issubclass(A, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000203 class B(metaclass=abc.ABCMeta):
204 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000205 self.assertFalse(issubclass(A, B))
206 self.assertFalse(issubclass(A, (B,)))
207 self.assertFalse(issubclass(B, A))
208 self.assertFalse(issubclass(B, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000209 class C(metaclass=abc.ABCMeta):
210 pass
211 A.register(B)
212 class B1(B):
213 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000214 self.assertTrue(issubclass(B1, A))
215 self.assertTrue(issubclass(B1, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000216 class C1(C):
217 pass
218 B1.register(C1)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000219 self.assertFalse(issubclass(C, B))
220 self.assertFalse(issubclass(C, (B,)))
221 self.assertFalse(issubclass(C, B1))
222 self.assertFalse(issubclass(C, (B1,)))
223 self.assertTrue(issubclass(C1, A))
224 self.assertTrue(issubclass(C1, (A,)))
225 self.assertTrue(issubclass(C1, B))
226 self.assertTrue(issubclass(C1, (B,)))
227 self.assertTrue(issubclass(C1, B1))
228 self.assertTrue(issubclass(C1, (B1,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000229 C1.register(int)
230 class MyInt(int):
231 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000232 self.assertTrue(issubclass(MyInt, A))
233 self.assertTrue(issubclass(MyInt, (A,)))
Ezio Melottie9615932010-01-24 19:26:24 +0000234 self.assertIsInstance(42, A)
235 self.assertIsInstance(42, (A,))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000236
Guido van Rossum894d35e2007-09-11 20:42:30 +0000237 def test_all_new_methods_are_called(self):
238 class A(metaclass=abc.ABCMeta):
239 pass
Christian Heimes043d6f62008-01-07 17:19:16 +0000240 class B(object):
Guido van Rossum894d35e2007-09-11 20:42:30 +0000241 counter = 0
242 def __new__(cls):
243 B.counter += 1
244 return super().__new__(cls)
245 class C(A, B):
246 pass
247 self.assertEqual(B.counter, 0)
248 C()
249 self.assertEqual(B.counter, 1)
250
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000251
252def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000253 support.run_unittest(TestABC)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000254
255
256if __name__ == "__main__":
257 unittest.main()