blob: 4965c4277dba73c6f47558a046a554bad8104510 [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
Christian Heimesbe5b30b2008-03-03 19:18:51 +000045 self.assert_(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
Christian Heimesbe5b30b2008-03-03 19:18:51 +000050 self.assert_(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
Christian Heimesbe5b30b2008-03-03 19:18:51 +000055 self.failIf(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
Christian Heimesbe5b30b2008-03-03 19:18:51 +000061 self.assert_(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)
Guido van Rossumcd16bf62007-06-13 18:07:49 +000079 self.assertEqual(isinstance(b, A), False)
Antoine Pitrouec569b72008-08-26 22:40:48 +000080 self.assertEqual(isinstance(b, (A,)), False)
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)
Guido van Rossumcd16bf62007-06-13 18:07:49 +000084 self.assertEqual(isinstance(b, A), True)
Antoine Pitrouec569b72008-08-26 22:40:48 +000085 self.assertEqual(isinstance(b, (A,)), True)
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)
Guido van Rossumcd16bf62007-06-13 18:07:49 +000091 self.assertEqual(isinstance(c, A), True)
Antoine Pitrouec569b72008-08-26 22:40:48 +000092 self.assertEqual(isinstance(c, (A,)), True)
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)
110 self.assertEqual(isinstance(42, A), True)
Antoine Pitrouec569b72008-08-26 22:40:48 +0000111 self.assertEqual(isinstance(42, (A,)), True)
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
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000118 self.assertEqual(isinstance("", A), True)
Antoine Pitrouec569b72008-08-26 22:40:48 +0000119 self.assertEqual(isinstance("", (A,)), True)
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
145 self.failUnless(issubclass(A, A))
Antoine Pitrouec569b72008-08-26 22:40:48 +0000146 self.failUnless(issubclass(A, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000147 class B(metaclass=abc.ABCMeta):
148 pass
149 self.failIf(issubclass(A, B))
Antoine Pitrouec569b72008-08-26 22:40:48 +0000150 self.failIf(issubclass(A, (B,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000151 self.failIf(issubclass(B, A))
Antoine Pitrouec569b72008-08-26 22:40:48 +0000152 self.failIf(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
158 self.failUnless(issubclass(B1, A))
Antoine Pitrouec569b72008-08-26 22:40:48 +0000159 self.failUnless(issubclass(B1, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000160 class C1(C):
161 pass
162 B1.register(C1)
163 self.failIf(issubclass(C, B))
Antoine Pitrouec569b72008-08-26 22:40:48 +0000164 self.failIf(issubclass(C, (B,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000165 self.failIf(issubclass(C, B1))
Antoine Pitrouec569b72008-08-26 22:40:48 +0000166 self.failIf(issubclass(C, (B1,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000167 self.failUnless(issubclass(C1, A))
Antoine Pitrouec569b72008-08-26 22:40:48 +0000168 self.failUnless(issubclass(C1, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000169 self.failUnless(issubclass(C1, B))
Antoine Pitrouec569b72008-08-26 22:40:48 +0000170 self.failUnless(issubclass(C1, (B,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000171 self.failUnless(issubclass(C1, B1))
Antoine Pitrouec569b72008-08-26 22:40:48 +0000172 self.failUnless(issubclass(C1, (B1,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000173 C1.register(int)
174 class MyInt(int):
175 pass
176 self.failUnless(issubclass(MyInt, A))
Antoine Pitrouec569b72008-08-26 22:40:48 +0000177 self.failUnless(issubclass(MyInt, (A,)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000178 self.failUnless(isinstance(42, A))
Antoine Pitrouec569b72008-08-26 22:40:48 +0000179 self.failUnless(isinstance(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()