blob: 3e0955fd75ffcb6d009ae6c1a89db1d10641d5ea [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
Christian Heimes608c1d82008-03-03 18:28:04 +000047 self.assert_(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
Christian Heimes608c1d82008-03-03 18:28:04 +000052 self.assert_(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
Christian Heimes608c1d82008-03-03 18:28:04 +000057 self.failIf(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
Christian Heimes608c1d82008-03-03 18:28:04 +000063 self.assert_(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
155 self.failUnless(issubclass(A, A))
Antoine Pitrou0668c622008-08-26 22:42:08 +0000156 self.failUnless(issubclass(A, (A,)))
Guido van Rossumb5591132007-09-10 22:36:02 +0000157 class B:
158 __metaclass__ = abc.ABCMeta
159 self.failIf(issubclass(A, B))
Antoine Pitrou0668c622008-08-26 22:42:08 +0000160 self.failIf(issubclass(A, (B,)))
Guido van Rossumb5591132007-09-10 22:36:02 +0000161 self.failIf(issubclass(B, A))
Antoine Pitrou0668c622008-08-26 22:42:08 +0000162 self.failIf(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
168 self.failUnless(issubclass(B1, A))
Antoine Pitrou0668c622008-08-26 22:42:08 +0000169 self.failUnless(issubclass(B1, (A,)))
Guido van Rossumb5591132007-09-10 22:36:02 +0000170 class C1(C):
171 pass
172 B1.register(C1)
173 self.failIf(issubclass(C, B))
Antoine Pitrou0668c622008-08-26 22:42:08 +0000174 self.failIf(issubclass(C, (B,)))
Guido van Rossumb5591132007-09-10 22:36:02 +0000175 self.failIf(issubclass(C, B1))
Antoine Pitrou0668c622008-08-26 22:42:08 +0000176 self.failIf(issubclass(C, (B1,)))
Guido van Rossumb5591132007-09-10 22:36:02 +0000177 self.failUnless(issubclass(C1, A))
Antoine Pitrou0668c622008-08-26 22:42:08 +0000178 self.failUnless(issubclass(C1, (A,)))
Guido van Rossumb5591132007-09-10 22:36:02 +0000179 self.failUnless(issubclass(C1, B))
Antoine Pitrou0668c622008-08-26 22:42:08 +0000180 self.failUnless(issubclass(C1, (B,)))
Guido van Rossumb5591132007-09-10 22:36:02 +0000181 self.failUnless(issubclass(C1, B1))
Antoine Pitrou0668c622008-08-26 22:42:08 +0000182 self.failUnless(issubclass(C1, (B1,)))
Guido van Rossumb5591132007-09-10 22:36:02 +0000183 C1.register(int)
184 class MyInt(int):
185 pass
186 self.failUnless(issubclass(MyInt, A))
Antoine Pitrou0668c622008-08-26 22:42:08 +0000187 self.failUnless(issubclass(MyInt, (A,)))
Guido van Rossumb5591132007-09-10 22:36:02 +0000188 self.failUnless(isinstance(42, A))
Antoine Pitrou0668c622008-08-26 22:42:08 +0000189 self.failUnless(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()