blob: c9deb4b96775b795db4a3073ce19b240428aef7b [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
142 def test_registration_transitiveness(self):
143 class A(metaclass=abc.ABCMeta):
144 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000145 self.assertTrue(issubclass(A, A))
146 self.assertTrue(issubclass(A, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000147 class B(metaclass=abc.ABCMeta):
148 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000149 self.assertFalse(issubclass(A, B))
150 self.assertFalse(issubclass(A, (B,)))
151 self.assertFalse(issubclass(B, A))
152 self.assertFalse(issubclass(B, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000153 class C(metaclass=abc.ABCMeta):
154 pass
155 A.register(B)
156 class B1(B):
157 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000158 self.assertTrue(issubclass(B1, A))
159 self.assertTrue(issubclass(B1, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000160 class C1(C):
161 pass
162 B1.register(C1)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000163 self.assertFalse(issubclass(C, B))
164 self.assertFalse(issubclass(C, (B,)))
165 self.assertFalse(issubclass(C, B1))
166 self.assertFalse(issubclass(C, (B1,)))
167 self.assertTrue(issubclass(C1, A))
168 self.assertTrue(issubclass(C1, (A,)))
169 self.assertTrue(issubclass(C1, B))
170 self.assertTrue(issubclass(C1, (B,)))
171 self.assertTrue(issubclass(C1, B1))
172 self.assertTrue(issubclass(C1, (B1,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000173 C1.register(int)
174 class MyInt(int):
175 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000176 self.assertTrue(issubclass(MyInt, A))
177 self.assertTrue(issubclass(MyInt, (A,)))
Ezio Melottie9615932010-01-24 19:26:24 +0000178 self.assertIsInstance(42, A)
179 self.assertIsInstance(42, (A,))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000180
Guido van Rossum894d35e2007-09-11 20:42:30 +0000181 def test_all_new_methods_are_called(self):
182 class A(metaclass=abc.ABCMeta):
183 pass
Christian Heimes043d6f62008-01-07 17:19:16 +0000184 class B(object):
Guido van Rossum894d35e2007-09-11 20:42:30 +0000185 counter = 0
186 def __new__(cls):
187 B.counter += 1
188 return super().__new__(cls)
189 class C(A, B):
190 pass
191 self.assertEqual(B.counter, 0)
192 C()
193 self.assertEqual(B.counter, 1)
194
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000195
196def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000197 support.run_unittest(TestABC)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000198
199
200if __name__ == "__main__":
201 unittest.main()