blob: 3a1d76b903417bf981e6609c07fc93cb7228236e [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
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000108 def test_registration_basics(self):
109 class A(metaclass=abc.ABCMeta):
110 pass
Christian Heimes043d6f62008-01-07 17:19:16 +0000111 class B(object):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000112 pass
113 b = B()
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000114 self.assertFalse(issubclass(B, A))
115 self.assertFalse(issubclass(B, (A,)))
Ezio Melottie9615932010-01-24 19:26:24 +0000116 self.assertNotIsInstance(b, A)
117 self.assertNotIsInstance(b, (A,))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000118 A.register(B)
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000119 self.assertTrue(issubclass(B, A))
120 self.assertTrue(issubclass(B, (A,)))
Ezio Melottie9615932010-01-24 19:26:24 +0000121 self.assertIsInstance(b, A)
122 self.assertIsInstance(b, (A,))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000123 class C(B):
124 pass
125 c = C()
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000126 self.assertTrue(issubclass(C, A))
127 self.assertTrue(issubclass(C, (A,)))
Ezio Melottie9615932010-01-24 19:26:24 +0000128 self.assertIsInstance(c, A)
129 self.assertIsInstance(c, (A,))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000130
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000131 def test_isinstance_invalidation(self):
132 class A(metaclass=abc.ABCMeta):
133 pass
134 class B:
135 pass
136 b = B()
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000137 self.assertFalse(isinstance(b, A))
138 self.assertFalse(isinstance(b, (A,)))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000139 A.register(B)
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000140 self.assertTrue(isinstance(b, A))
141 self.assertTrue(isinstance(b, (A,)))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000142
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000143 def test_registration_builtins(self):
144 class A(metaclass=abc.ABCMeta):
145 pass
146 A.register(int)
Ezio Melottie9615932010-01-24 19:26:24 +0000147 self.assertIsInstance(42, A)
148 self.assertIsInstance(42, (A,))
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000149 self.assertTrue(issubclass(int, A))
150 self.assertTrue(issubclass(int, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000151 class B(A):
152 pass
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000153 B.register(str)
154 class C(str): pass
Ezio Melottie9615932010-01-24 19:26:24 +0000155 self.assertIsInstance("", A)
156 self.assertIsInstance("", (A,))
Benjamin Peterson83cd3b92010-08-17 01:07:53 +0000157 self.assertTrue(issubclass(str, A))
158 self.assertTrue(issubclass(str, (A,)))
159 self.assertTrue(issubclass(C, A))
160 self.assertTrue(issubclass(C, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000161
162 def test_registration_edge_cases(self):
163 class A(metaclass=abc.ABCMeta):
164 pass
165 A.register(A) # should pass silently
166 class A1(A):
167 pass
168 self.assertRaises(RuntimeError, A1.register, A) # cycles not allowed
Christian Heimes043d6f62008-01-07 17:19:16 +0000169 class B(object):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000170 pass
171 A1.register(B) # ok
172 A1.register(B) # should pass silently
173 class C(A):
174 pass
175 A.register(C) # should pass silently
176 self.assertRaises(RuntimeError, C.register, A) # cycles not allowed
177 C.register(B) # ok
178
Benjamin Petersond6326642010-01-27 02:25:58 +0000179 def test_register_non_class(self):
180 class A(metaclass=abc.ABCMeta):
181 pass
182 self.assertRaisesRegexp(TypeError, "Can only register classes",
183 A.register, 4)
184
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000185 def test_registration_transitiveness(self):
186 class A(metaclass=abc.ABCMeta):
187 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000188 self.assertTrue(issubclass(A, A))
189 self.assertTrue(issubclass(A, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000190 class B(metaclass=abc.ABCMeta):
191 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000192 self.assertFalse(issubclass(A, B))
193 self.assertFalse(issubclass(A, (B,)))
194 self.assertFalse(issubclass(B, A))
195 self.assertFalse(issubclass(B, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000196 class C(metaclass=abc.ABCMeta):
197 pass
198 A.register(B)
199 class B1(B):
200 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000201 self.assertTrue(issubclass(B1, A))
202 self.assertTrue(issubclass(B1, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000203 class C1(C):
204 pass
205 B1.register(C1)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000206 self.assertFalse(issubclass(C, B))
207 self.assertFalse(issubclass(C, (B,)))
208 self.assertFalse(issubclass(C, B1))
209 self.assertFalse(issubclass(C, (B1,)))
210 self.assertTrue(issubclass(C1, A))
211 self.assertTrue(issubclass(C1, (A,)))
212 self.assertTrue(issubclass(C1, B))
213 self.assertTrue(issubclass(C1, (B,)))
214 self.assertTrue(issubclass(C1, B1))
215 self.assertTrue(issubclass(C1, (B1,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000216 C1.register(int)
217 class MyInt(int):
218 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000219 self.assertTrue(issubclass(MyInt, A))
220 self.assertTrue(issubclass(MyInt, (A,)))
Ezio Melottie9615932010-01-24 19:26:24 +0000221 self.assertIsInstance(42, A)
222 self.assertIsInstance(42, (A,))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000223
Guido van Rossum894d35e2007-09-11 20:42:30 +0000224 def test_all_new_methods_are_called(self):
225 class A(metaclass=abc.ABCMeta):
226 pass
Christian Heimes043d6f62008-01-07 17:19:16 +0000227 class B(object):
Guido van Rossum894d35e2007-09-11 20:42:30 +0000228 counter = 0
229 def __new__(cls):
230 B.counter += 1
231 return super().__new__(cls)
232 class C(A, B):
233 pass
234 self.assertEqual(B.counter, 0)
235 C()
236 self.assertEqual(B.counter, 1)
237
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000238
239def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000240 support.run_unittest(TestABC)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000241
242
243if __name__ == "__main__":
244 unittest.main()