blob: 718d903ac0df35d1803fd196ab0afcb2fe91c248 [file] [log] [blame]
Guido van Rossumb5591132007-09-10 22:36:02 +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 Rossumb5591132007-09-10 22:36:02 +00006import unittest
7from test import test_support
8
9import abc
Christian Heimes608c1d82008-03-03 18:28:04 +000010from inspect import isabstract
Guido van Rossumb5591132007-09-10 22:36:02 +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
22 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
29 class C:
30 __metaclass__ = abc.ABCMeta
31 @abc.abstractproperty
32 def foo(self): return 3
33 class D(C):
34 @property
35 def foo(self): return super(D, self).foo
36 self.assertEqual(D().foo, 3)
37
38 def test_abstractmethod_integration(self):
39 for abstractthing in [abc.abstractmethod, abc.abstractproperty]:
40 class C:
41 __metaclass__ = abc.ABCMeta
42 @abstractthing
43 def foo(self): pass # abstract
44 def bar(self): pass # concrete
45 self.assertEqual(C.__abstractmethods__, set(["foo"]))
46 self.assertRaises(TypeError, C) # because foo is abstract
Benjamin Peterson5c8da862009-06-30 22:57:08 +000047 self.assertTrue(isabstract(C))
Guido van Rossumb5591132007-09-10 22:36:02 +000048 class D(C):
49 def bar(self): pass # concrete override of concrete
50 self.assertEqual(D.__abstractmethods__, set(["foo"]))
51 self.assertRaises(TypeError, D) # because foo is still abstract
Benjamin Peterson5c8da862009-06-30 22:57:08 +000052 self.assertTrue(isabstract(D))
Guido van Rossumb5591132007-09-10 22:36:02 +000053 class E(D):
54 def foo(self): pass
55 self.assertEqual(E.__abstractmethods__, set())
56 E() # now foo is concrete, too
Benjamin Peterson5c8da862009-06-30 22:57:08 +000057 self.assertFalse(isabstract(E))
Guido van Rossumb5591132007-09-10 22:36:02 +000058 class F(E):
59 @abstractthing
60 def bar(self): pass # abstract override of concrete
61 self.assertEqual(F.__abstractmethods__, set(["bar"]))
62 self.assertRaises(TypeError, F) # because bar is abstract now
Benjamin Peterson5c8da862009-06-30 22:57:08 +000063 self.assertTrue(isabstract(F))
Guido van Rossumb5591132007-09-10 22:36:02 +000064
Jeffrey Yasskinfd1c2452008-01-07 06:09:40 +000065 def test_subclass_oldstyle_class(self):
66 class A:
67 __metaclass__ = abc.ABCMeta
68 class OldstyleClass:
69 pass
70 self.assertFalse(issubclass(OldstyleClass, A))
71 self.assertFalse(issubclass(A, OldstyleClass))
72
Jeffrey Yasskinb9e15f72008-03-17 16:31:21 +000073 def test_isinstance_class(self):
74 class A:
75 __metaclass__ = abc.ABCMeta
76 class OldstyleClass:
77 pass
78 self.assertFalse(isinstance(OldstyleClass, A))
79 self.assertTrue(isinstance(OldstyleClass, type(OldstyleClass)))
80 self.assertFalse(isinstance(A, OldstyleClass))
81 # This raises a recursion depth error, but is low-priority:
82 # self.assertTrue(isinstance(A, abc.ABCMeta))
83
Guido van Rossumb5591132007-09-10 22:36:02 +000084 def test_registration_basics(self):
85 class A:
86 __metaclass__ = abc.ABCMeta
Jeffrey Yasskinfd1c2452008-01-07 06:09:40 +000087 class B(object):
Guido van Rossumb5591132007-09-10 22:36:02 +000088 pass
89 b = B()
90 self.assertEqual(issubclass(B, A), False)
Antoine Pitrou0668c622008-08-26 22:42:08 +000091 self.assertEqual(issubclass(B, (A,)), False)
Guido van Rossumb5591132007-09-10 22:36:02 +000092 self.assertEqual(isinstance(b, A), False)
Antoine Pitrou0668c622008-08-26 22:42:08 +000093 self.assertEqual(isinstance(b, (A,)), False)
Guido van Rossumb5591132007-09-10 22:36:02 +000094 A.register(B)
95 self.assertEqual(issubclass(B, A), True)
Antoine Pitrou0668c622008-08-26 22:42:08 +000096 self.assertEqual(issubclass(B, (A,)), True)
Guido van Rossumb5591132007-09-10 22:36:02 +000097 self.assertEqual(isinstance(b, A), True)
Antoine Pitrou0668c622008-08-26 22:42:08 +000098 self.assertEqual(isinstance(b, (A,)), True)
Guido van Rossumb5591132007-09-10 22:36:02 +000099 class C(B):
100 pass
101 c = C()
102 self.assertEqual(issubclass(C, A), True)
Antoine Pitrou0668c622008-08-26 22:42:08 +0000103 self.assertEqual(issubclass(C, (A,)), True)
Guido van Rossumb5591132007-09-10 22:36:02 +0000104 self.assertEqual(isinstance(c, A), True)
Antoine Pitrou0668c622008-08-26 22:42:08 +0000105 self.assertEqual(isinstance(c, (A,)), True)
Guido van Rossumb5591132007-09-10 22:36:02 +0000106
Jeffrey Yasskin57bd60b2008-02-13 17:58:04 +0000107 def test_isinstance_invalidation(self):
108 class A:
109 __metaclass__ = abc.ABCMeta
110 class B(object):
111 pass
112 b = B()
113 self.assertEqual(isinstance(b, A), False)
Antoine Pitrou0668c622008-08-26 22:42:08 +0000114 self.assertEqual(isinstance(b, (A,)), False)
Jeffrey Yasskin57bd60b2008-02-13 17:58:04 +0000115 A.register(B)
116 self.assertEqual(isinstance(b, A), True)
Antoine Pitrou0668c622008-08-26 22:42:08 +0000117 self.assertEqual(isinstance(b, (A,)), True)
Jeffrey Yasskin57bd60b2008-02-13 17:58:04 +0000118
Guido van Rossumb5591132007-09-10 22:36:02 +0000119 def test_registration_builtins(self):
120 class A:
121 __metaclass__ = abc.ABCMeta
122 A.register(int)
123 self.assertEqual(isinstance(42, A), True)
Antoine Pitrou0668c622008-08-26 22:42:08 +0000124 self.assertEqual(isinstance(42, (A,)), True)
Guido van Rossumb5591132007-09-10 22:36:02 +0000125 self.assertEqual(issubclass(int, A), True)
Antoine Pitrou0668c622008-08-26 22:42:08 +0000126 self.assertEqual(issubclass(int, (A,)), True)
Guido van Rossumb5591132007-09-10 22:36:02 +0000127 class B(A):
128 pass
129 B.register(basestring)
130 self.assertEqual(isinstance("", A), True)
Antoine Pitrou0668c622008-08-26 22:42:08 +0000131 self.assertEqual(isinstance("", (A,)), True)
Guido van Rossumb5591132007-09-10 22:36:02 +0000132 self.assertEqual(issubclass(str, A), True)
Antoine Pitrou0668c622008-08-26 22:42:08 +0000133 self.assertEqual(issubclass(str, (A,)), True)
Guido van Rossumb5591132007-09-10 22:36:02 +0000134
135 def test_registration_edge_cases(self):
136 class A:
137 __metaclass__ = abc.ABCMeta
138 A.register(A) # should pass silently
139 class A1(A):
140 pass
141 self.assertRaises(RuntimeError, A1.register, A) # cycles not allowed
Jeffrey Yasskinfd1c2452008-01-07 06:09:40 +0000142 class B(object):
Guido van Rossumb5591132007-09-10 22:36:02 +0000143 pass
144 A1.register(B) # ok
145 A1.register(B) # should pass silently
146 class C(A):
147 pass
148 A.register(C) # should pass silently
149 self.assertRaises(RuntimeError, C.register, A) # cycles not allowed
150 C.register(B) # ok
151
152 def test_registration_transitiveness(self):
153 class A:
154 __metaclass__ = abc.ABCMeta
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000155 self.assertTrue(issubclass(A, A))
156 self.assertTrue(issubclass(A, (A,)))
Guido van Rossumb5591132007-09-10 22:36:02 +0000157 class B:
158 __metaclass__ = abc.ABCMeta
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000159 self.assertFalse(issubclass(A, B))
160 self.assertFalse(issubclass(A, (B,)))
161 self.assertFalse(issubclass(B, A))
162 self.assertFalse(issubclass(B, (A,)))
Guido van Rossumb5591132007-09-10 22:36:02 +0000163 class C:
164 __metaclass__ = abc.ABCMeta
165 A.register(B)
166 class B1(B):
167 pass
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000168 self.assertTrue(issubclass(B1, A))
169 self.assertTrue(issubclass(B1, (A,)))
Guido van Rossumb5591132007-09-10 22:36:02 +0000170 class C1(C):
171 pass
172 B1.register(C1)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000173 self.assertFalse(issubclass(C, B))
174 self.assertFalse(issubclass(C, (B,)))
175 self.assertFalse(issubclass(C, B1))
176 self.assertFalse(issubclass(C, (B1,)))
177 self.assertTrue(issubclass(C1, A))
178 self.assertTrue(issubclass(C1, (A,)))
179 self.assertTrue(issubclass(C1, B))
180 self.assertTrue(issubclass(C1, (B,)))
181 self.assertTrue(issubclass(C1, B1))
182 self.assertTrue(issubclass(C1, (B1,)))
Guido van Rossumb5591132007-09-10 22:36:02 +0000183 C1.register(int)
184 class MyInt(int):
185 pass
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000186 self.assertTrue(issubclass(MyInt, A))
187 self.assertTrue(issubclass(MyInt, (A,)))
188 self.assertTrue(isinstance(42, A))
189 self.assertTrue(isinstance(42, (A,)))
Guido van Rossumb5591132007-09-10 22:36:02 +0000190
Guido van Rossum64c06e32007-11-22 00:55:51 +0000191 def test_all_new_methods_are_called(self):
192 class A:
193 __metaclass__ = abc.ABCMeta
Jeffrey Yasskinfd1c2452008-01-07 06:09:40 +0000194 class B(object):
Guido van Rossum64c06e32007-11-22 00:55:51 +0000195 counter = 0
196 def __new__(cls):
197 B.counter += 1
198 return super(B, cls).__new__(cls)
199 class C(A, B):
200 pass
201 self.assertEqual(B.counter, 0)
202 C()
203 self.assertEqual(B.counter, 1)
204
Guido van Rossumb5591132007-09-10 22:36:02 +0000205
206def test_main():
207 test_support.run_unittest(TestABC)
208
209
210if __name__ == "__main__":
211 unittest.main()