blob: a6e7062418f7a9a859c36b5d5d9fc0975d6d6d88 [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
18 self.assertEqual(foo.__isabstractmethod__, True)
19 def bar(self): pass
20 self.assertEqual(hasattr(bar, "__isabstractmethod__"), False)
21
Guido van Rossum70d2b892007-08-01 17:52:23 +000022 def test_abstractproperty_basics(self):
23 @abc.abstractproperty
24 def foo(self): pass
25 self.assertEqual(foo.__isabstractmethod__, True)
26 def bar(self): pass
27 self.assertEqual(hasattr(bar, "__isabstractmethod__"), False)
28
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
Benjamin Petersonc9c0f202009-06-30 23:06:06 +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
Benjamin Petersonc9c0f202009-06-30 23:06:06 +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
Benjamin Petersonc9c0f202009-06-30 23:06:06 +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
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000061 self.assertTrue(isabstract(F))
Guido van Rossumcd16bf62007-06-13 18:07:49 +000062
Christian Heimes043d6f62008-01-07 17:19:16 +000063 def test_subclass_oldstyle_class(self):
64 class A:
65 __metaclass__ = abc.ABCMeta
66 class OldstyleClass:
67 pass
68 self.assertFalse(issubclass(OldstyleClass, A))
69 self.assertFalse(issubclass(A, OldstyleClass))
70
Guido van Rossumcd16bf62007-06-13 18:07:49 +000071 def test_registration_basics(self):
72 class A(metaclass=abc.ABCMeta):
73 pass
Christian Heimes043d6f62008-01-07 17:19:16 +000074 class B(object):
Guido van Rossumcd16bf62007-06-13 18:07:49 +000075 pass
76 b = B()
77 self.assertEqual(issubclass(B, A), False)
Antoine Pitrouec569b72008-08-26 22:40:48 +000078 self.assertEqual(issubclass(B, (A,)), False)
Ezio Melottie9615932010-01-24 19:26:24 +000079 self.assertNotIsInstance(b, A)
80 self.assertNotIsInstance(b, (A,))
Guido van Rossumcd16bf62007-06-13 18:07:49 +000081 A.register(B)
82 self.assertEqual(issubclass(B, A), True)
Antoine Pitrouec569b72008-08-26 22:40:48 +000083 self.assertEqual(issubclass(B, (A,)), True)
Ezio Melottie9615932010-01-24 19:26:24 +000084 self.assertIsInstance(b, A)
85 self.assertIsInstance(b, (A,))
Guido van Rossumcd16bf62007-06-13 18:07:49 +000086 class C(B):
87 pass
88 c = C()
89 self.assertEqual(issubclass(C, A), True)
Antoine Pitrouec569b72008-08-26 22:40:48 +000090 self.assertEqual(issubclass(C, (A,)), True)
Ezio Melottie9615932010-01-24 19:26:24 +000091 self.assertIsInstance(c, A)
92 self.assertIsInstance(c, (A,))
Guido van Rossumcd16bf62007-06-13 18:07:49 +000093
Christian Heimes68f5fbe2008-02-14 08:27:37 +000094 def test_isinstance_invalidation(self):
95 class A(metaclass=abc.ABCMeta):
96 pass
97 class B:
98 pass
99 b = B()
100 self.assertEqual(isinstance(b, A), False)
Antoine Pitrouec569b72008-08-26 22:40:48 +0000101 self.assertEqual(isinstance(b, (A,)), False)
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000102 A.register(B)
103 self.assertEqual(isinstance(b, A), True)
Antoine Pitrouec569b72008-08-26 22:40:48 +0000104 self.assertEqual(isinstance(b, (A,)), True)
Christian Heimes68f5fbe2008-02-14 08:27:37 +0000105
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000106 def test_registration_builtins(self):
107 class A(metaclass=abc.ABCMeta):
108 pass
109 A.register(int)
Ezio Melottie9615932010-01-24 19:26:24 +0000110 self.assertIsInstance(42, A)
111 self.assertIsInstance(42, (A,))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000112 self.assertEqual(issubclass(int, A), True)
Antoine Pitrouec569b72008-08-26 22:40:48 +0000113 self.assertEqual(issubclass(int, (A,)), True)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000114 class B(A):
115 pass
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000116 B.register(str)
117 class C(str): pass
Ezio Melottie9615932010-01-24 19:26:24 +0000118 self.assertIsInstance("", A)
119 self.assertIsInstance("", (A,))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000120 self.assertEqual(issubclass(str, A), True)
Antoine Pitrouec569b72008-08-26 22:40:48 +0000121 self.assertEqual(issubclass(str, (A,)), True)
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000122 self.assertEqual(issubclass(C, A), True)
Antoine Pitrouec569b72008-08-26 22:40:48 +0000123 self.assertEqual(issubclass(C, (A,)), True)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000124
125 def test_registration_edge_cases(self):
126 class A(metaclass=abc.ABCMeta):
127 pass
128 A.register(A) # should pass silently
129 class A1(A):
130 pass
131 self.assertRaises(RuntimeError, A1.register, A) # cycles not allowed
Christian Heimes043d6f62008-01-07 17:19:16 +0000132 class B(object):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000133 pass
134 A1.register(B) # ok
135 A1.register(B) # should pass silently
136 class C(A):
137 pass
138 A.register(C) # should pass silently
139 self.assertRaises(RuntimeError, C.register, A) # cycles not allowed
140 C.register(B) # ok
141
Benjamin Petersond6326642010-01-27 02:25:58 +0000142 def test_register_non_class(self):
143 class A(metaclass=abc.ABCMeta):
144 pass
145 self.assertRaisesRegexp(TypeError, "Can only register classes",
146 A.register, 4)
147
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000148 def test_registration_transitiveness(self):
149 class A(metaclass=abc.ABCMeta):
150 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000151 self.assertTrue(issubclass(A, A))
152 self.assertTrue(issubclass(A, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000153 class B(metaclass=abc.ABCMeta):
154 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000155 self.assertFalse(issubclass(A, B))
156 self.assertFalse(issubclass(A, (B,)))
157 self.assertFalse(issubclass(B, A))
158 self.assertFalse(issubclass(B, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000159 class C(metaclass=abc.ABCMeta):
160 pass
161 A.register(B)
162 class B1(B):
163 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000164 self.assertTrue(issubclass(B1, A))
165 self.assertTrue(issubclass(B1, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000166 class C1(C):
167 pass
168 B1.register(C1)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000169 self.assertFalse(issubclass(C, B))
170 self.assertFalse(issubclass(C, (B,)))
171 self.assertFalse(issubclass(C, B1))
172 self.assertFalse(issubclass(C, (B1,)))
173 self.assertTrue(issubclass(C1, A))
174 self.assertTrue(issubclass(C1, (A,)))
175 self.assertTrue(issubclass(C1, B))
176 self.assertTrue(issubclass(C1, (B,)))
177 self.assertTrue(issubclass(C1, B1))
178 self.assertTrue(issubclass(C1, (B1,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000179 C1.register(int)
180 class MyInt(int):
181 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000182 self.assertTrue(issubclass(MyInt, A))
183 self.assertTrue(issubclass(MyInt, (A,)))
Ezio Melottie9615932010-01-24 19:26:24 +0000184 self.assertIsInstance(42, A)
185 self.assertIsInstance(42, (A,))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000186
Guido van Rossum894d35e2007-09-11 20:42:30 +0000187 def test_all_new_methods_are_called(self):
188 class A(metaclass=abc.ABCMeta):
189 pass
Christian Heimes043d6f62008-01-07 17:19:16 +0000190 class B(object):
Guido van Rossum894d35e2007-09-11 20:42:30 +0000191 counter = 0
192 def __new__(cls):
193 B.counter += 1
194 return super().__new__(cls)
195 class C(A, B):
196 pass
197 self.assertEqual(B.counter, 0)
198 C()
199 self.assertEqual(B.counter, 1)
200
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000201
202def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000203 support.run_unittest(TestABC)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000204
205
206if __name__ == "__main__":
207 unittest.main()