blob: 3aef4a00f22a8d0ae87f6f1670550fec774f1e14 [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 Peterson14c61232010-08-17 01:14:01 +000018 self.assertTrue(foo.__isabstractmethod__)
Guido van Rossumcd16bf62007-06-13 18:07:49 +000019 def bar(self): pass
Benjamin Peterson14c61232010-08-17 01:14:01 +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 Peterson14c61232010-08-17 01:14:01 +000025 self.assertTrue(foo.__isabstractmethod__)
Guido van Rossum70d2b892007-08-01 17:52:23 +000026 def bar(self): pass
Benjamin Peterson14c61232010-08-17 01:14:01 +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
37 def test_abstractmethod_integration(self):
38 for abstractthing in [abc.abstractmethod, abc.abstractproperty]:
39 class C(metaclass=abc.ABCMeta):
40 @abstractthing
41 def foo(self): pass # abstract
42 def bar(self): pass # concrete
43 self.assertEqual(C.__abstractmethods__, {"foo"})
44 self.assertRaises(TypeError, C) # because foo is abstract
Georg Brandlab91fde2009-08-13 08:51:18 +000045 self.assertTrue(isabstract(C))
Guido van Rossum70d2b892007-08-01 17:52:23 +000046 class D(C):
47 def bar(self): pass # concrete override of concrete
48 self.assertEqual(D.__abstractmethods__, {"foo"})
49 self.assertRaises(TypeError, D) # because foo is still abstract
Georg Brandlab91fde2009-08-13 08:51:18 +000050 self.assertTrue(isabstract(D))
Guido van Rossum70d2b892007-08-01 17:52:23 +000051 class E(D):
52 def foo(self): pass
53 self.assertEqual(E.__abstractmethods__, set())
54 E() # now foo is concrete, too
Georg Brandlab91fde2009-08-13 08:51:18 +000055 self.assertFalse(isabstract(E))
Guido van Rossum70d2b892007-08-01 17:52:23 +000056 class F(E):
57 @abstractthing
58 def bar(self): pass # abstract override of concrete
59 self.assertEqual(F.__abstractmethods__, {"bar"})
60 self.assertRaises(TypeError, F) # because bar is abstract now
Georg Brandlab91fde2009-08-13 08:51:18 +000061 self.assertTrue(isabstract(F))
Guido van Rossumcd16bf62007-06-13 18:07:49 +000062
Benjamin Peterson0ad44fa2010-10-02 18:04:55 +000063 def test_metaclass_abc(self):
64 # Metaclasses can be ABCs, too.
65 class A(metaclass=abc.ABCMeta):
66 @abc.abstractmethod
67 def x(self):
68 pass
69 self.assertEqual(A.__abstractmethods__, {"x"})
70 class meta(type, A):
71 def x(self):
72 return 1
73 class C(metaclass=meta):
74 pass
75
Guido van Rossumcd16bf62007-06-13 18:07:49 +000076 def test_registration_basics(self):
77 class A(metaclass=abc.ABCMeta):
78 pass
Christian Heimes043d6f62008-01-07 17:19:16 +000079 class B(object):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000080 pass
81 b = B()
Benjamin Peterson14c61232010-08-17 01:14:01 +000082 self.assertFalse(issubclass(B, A))
83 self.assertFalse(issubclass(B, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +000084 self.assertEqual(isinstance(b, A), False)
Antoine Pitrouec569b72008-08-26 22:40:48 +000085 self.assertEqual(isinstance(b, (A,)), False)
Guido van Rossumcd16bf62007-06-13 18:07:49 +000086 A.register(B)
Benjamin Peterson14c61232010-08-17 01:14:01 +000087 self.assertTrue(issubclass(B, A))
88 self.assertTrue(issubclass(B, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +000089 self.assertEqual(isinstance(b, A), True)
Antoine Pitrouec569b72008-08-26 22:40:48 +000090 self.assertEqual(isinstance(b, (A,)), True)
Guido van Rossumcd16bf62007-06-13 18:07:49 +000091 class C(B):
92 pass
93 c = C()
Benjamin Peterson14c61232010-08-17 01:14:01 +000094 self.assertTrue(issubclass(C, A))
95 self.assertTrue(issubclass(C, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +000096 self.assertEqual(isinstance(c, A), True)
Antoine Pitrouec569b72008-08-26 22:40:48 +000097 self.assertEqual(isinstance(c, (A,)), True)
Guido van Rossumcd16bf62007-06-13 18:07:49 +000098
Christian Heimes68f5fbe2008-02-14 08:27:37 +000099 def test_isinstance_invalidation(self):
100 class A(metaclass=abc.ABCMeta):
101 pass
102 class B:
103 pass
104 b = B()
Benjamin Peterson14c61232010-08-17 01:14:01 +0000105 self.assertFalse(isinstance(b, A))
106 self.assertFalse(isinstance(b, (A,)))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000107 A.register(B)
Benjamin Peterson14c61232010-08-17 01:14:01 +0000108 self.assertTrue(isinstance(b, A))
109 self.assertTrue(isinstance(b, (A,)))
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000110
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000111 def test_registration_builtins(self):
112 class A(metaclass=abc.ABCMeta):
113 pass
114 A.register(int)
115 self.assertEqual(isinstance(42, A), True)
Antoine Pitrouec569b72008-08-26 22:40:48 +0000116 self.assertEqual(isinstance(42, (A,)), True)
Benjamin Peterson14c61232010-08-17 01:14:01 +0000117 self.assertTrue(issubclass(int, A))
118 self.assertTrue(issubclass(int, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000119 class B(A):
120 pass
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000121 B.register(str)
122 class C(str): pass
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000123 self.assertEqual(isinstance("", A), True)
Antoine Pitrouec569b72008-08-26 22:40:48 +0000124 self.assertEqual(isinstance("", (A,)), True)
Benjamin Peterson14c61232010-08-17 01:14:01 +0000125 self.assertTrue(issubclass(str, A))
126 self.assertTrue(issubclass(str, (A,)))
127 self.assertTrue(issubclass(C, A))
128 self.assertTrue(issubclass(C, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000129
130 def test_registration_edge_cases(self):
131 class A(metaclass=abc.ABCMeta):
132 pass
133 A.register(A) # should pass silently
134 class A1(A):
135 pass
136 self.assertRaises(RuntimeError, A1.register, A) # cycles not allowed
Christian Heimes043d6f62008-01-07 17:19:16 +0000137 class B(object):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000138 pass
139 A1.register(B) # ok
140 A1.register(B) # should pass silently
141 class C(A):
142 pass
143 A.register(C) # should pass silently
144 self.assertRaises(RuntimeError, C.register, A) # cycles not allowed
145 C.register(B) # ok
146
Benjamin Peterson69de1572010-01-27 02:28:22 +0000147 def test_register_non_class(self):
148 class A(metaclass=abc.ABCMeta):
149 pass
150 self.assertRaisesRegexp(TypeError, "Can only register classes",
151 A.register, 4)
152
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000153 def test_registration_transitiveness(self):
154 class A(metaclass=abc.ABCMeta):
155 pass
Georg Brandlab91fde2009-08-13 08:51:18 +0000156 self.assertTrue(issubclass(A, A))
157 self.assertTrue(issubclass(A, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000158 class B(metaclass=abc.ABCMeta):
159 pass
Georg Brandlab91fde2009-08-13 08:51:18 +0000160 self.assertFalse(issubclass(A, B))
161 self.assertFalse(issubclass(A, (B,)))
162 self.assertFalse(issubclass(B, A))
163 self.assertFalse(issubclass(B, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000164 class C(metaclass=abc.ABCMeta):
165 pass
166 A.register(B)
167 class B1(B):
168 pass
Georg Brandlab91fde2009-08-13 08:51:18 +0000169 self.assertTrue(issubclass(B1, A))
170 self.assertTrue(issubclass(B1, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000171 class C1(C):
172 pass
173 B1.register(C1)
Georg Brandlab91fde2009-08-13 08:51:18 +0000174 self.assertFalse(issubclass(C, B))
175 self.assertFalse(issubclass(C, (B,)))
176 self.assertFalse(issubclass(C, B1))
177 self.assertFalse(issubclass(C, (B1,)))
178 self.assertTrue(issubclass(C1, A))
179 self.assertTrue(issubclass(C1, (A,)))
180 self.assertTrue(issubclass(C1, B))
181 self.assertTrue(issubclass(C1, (B,)))
182 self.assertTrue(issubclass(C1, B1))
183 self.assertTrue(issubclass(C1, (B1,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000184 C1.register(int)
185 class MyInt(int):
186 pass
Georg Brandlab91fde2009-08-13 08:51:18 +0000187 self.assertTrue(issubclass(MyInt, A))
188 self.assertTrue(issubclass(MyInt, (A,)))
189 self.assertTrue(isinstance(42, A))
190 self.assertTrue(isinstance(42, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000191
Guido van Rossum894d35e2007-09-11 20:42:30 +0000192 def test_all_new_methods_are_called(self):
193 class A(metaclass=abc.ABCMeta):
194 pass
Christian Heimes043d6f62008-01-07 17:19:16 +0000195 class B(object):
Guido van Rossum894d35e2007-09-11 20:42:30 +0000196 counter = 0
197 def __new__(cls):
198 B.counter += 1
199 return super().__new__(cls)
200 class C(A, B):
201 pass
202 self.assertEqual(B.counter, 0)
203 C()
204 self.assertEqual(B.counter, 1)
205
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000206
207def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000208 support.run_unittest(TestABC)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000209
210
211if __name__ == "__main__":
212 unittest.main()