LEFT | RIGHT |
1 # Copyright 2007 Google, Inc. All Rights Reserved. | 1 # Copyright 2007 Google, Inc. All Rights Reserved. |
2 # Licensed to PSF under a Contributor Agreement. | 2 # Licensed to PSF under a Contributor Agreement. |
3 | 3 |
4 """Unit tests for abc.py.""" | 4 """Unit tests for abc.py.""" |
5 | 5 |
6 import unittest | 6 import unittest |
7 from test import support | 7 from test import support |
8 | 8 |
9 import abc | 9 import abc |
10 from inspect import isabstract | 10 from inspect import isabstract |
11 | 11 |
12 | 12 |
13 class TestABC(unittest.TestCase): | 13 class TestLegacyAPI(unittest.TestCase): |
14 | |
15 def test_abstractmethod_basics(self): | |
16 @abc.abstractmethod | |
17 def foo(self): pass | |
18 self.assertTrue(foo.__isabstractmethod__) | |
19 def bar(self): pass | |
20 self.assertFalse(hasattr(bar, "__isabstractmethod__")) | |
21 | 14 |
22 def test_abstractproperty_basics(self): | 15 def test_abstractproperty_basics(self): |
23 "abstractproperty is deprecated in python-3.3" | |
24 @abc.abstractproperty | 16 @abc.abstractproperty |
25 def foo(self): pass | 17 def foo(self): pass |
26 self.assertTrue(foo.__isabstractmethod__) | 18 self.assertTrue(foo.__isabstractmethod__) |
27 def bar(self): pass | 19 def bar(self): pass |
28 self.assertFalse(hasattr(bar, "__isabstractmethod__")) | 20 self.assertFalse(hasattr(bar, "__isabstractmethod__")) |
29 | 21 |
30 class C(metaclass=abc.ABCMeta): | 22 class C(metaclass=abc.ABCMeta): |
31 @abc.abstractproperty | 23 @abc.abstractproperty |
32 def foo(self): return 3 | 24 def foo(self): return 3 |
33 self.assertRaises(TypeError, C) | 25 self.assertRaises(TypeError, C) |
34 class D(C): | 26 class D(C): |
35 @property | 27 @property |
36 def foo(self): return super().foo | 28 def foo(self): return super().foo |
37 self.assertEqual(D().foo, 3) | 29 self.assertEqual(D().foo, 3) |
| 30 self.assertFalse(getattr(D.foo, "__isabstractmethod__", False)) |
38 | 31 |
39 def test_abstractclassmethod_basics(self): | 32 def test_abstractclassmethod_basics(self): |
40 @abc.abstractclassmethod | 33 @abc.abstractclassmethod |
41 def foo(cls): pass | 34 def foo(cls): pass |
42 self.assertTrue(foo.__isabstractmethod__) | 35 self.assertTrue(foo.__isabstractmethod__) |
43 @classmethod | 36 @classmethod |
44 def bar(cls): pass | 37 def bar(cls): pass |
45 self.assertFalse(hasattr(bar, "__isabstractmethod__")) | 38 self.assertFalse(getattr(bar, "__isabstractmethod__", False)) |
46 | 39 |
47 class C(metaclass=abc.ABCMeta): | 40 class C(metaclass=abc.ABCMeta): |
48 @abc.abstractclassmethod | 41 @abc.abstractclassmethod |
49 def foo(cls): return cls.__name__ | 42 def foo(cls): return cls.__name__ |
50 self.assertRaises(TypeError, C) | 43 self.assertRaises(TypeError, C) |
51 class D(C): | 44 class D(C): |
52 @classmethod | 45 @classmethod |
53 def foo(cls): return super().foo() | 46 def foo(cls): return super().foo() |
54 self.assertEqual(D.foo(), 'D') | 47 self.assertEqual(D.foo(), 'D') |
55 self.assertEqual(D().foo(), 'D') | 48 self.assertEqual(D().foo(), 'D') |
56 | 49 |
57 def test_abstractstaticmethod_basics(self): | 50 def test_abstractstaticmethod_basics(self): |
58 @abc.abstractstaticmethod | 51 @abc.abstractstaticmethod |
59 def foo(): pass | 52 def foo(): pass |
60 self.assertTrue(foo.__isabstractmethod__) | 53 self.assertTrue(foo.__isabstractmethod__) |
61 @staticmethod | 54 @staticmethod |
62 def bar(): pass | 55 def bar(): pass |
63 self.assertFalse(hasattr(bar, "__isabstractmethod__")) | 56 self.assertFalse(getattr(bar, "__isabstractmethod__", False)) |
64 | 57 |
65 class C(metaclass=abc.ABCMeta): | 58 class C(metaclass=abc.ABCMeta): |
66 @abc.abstractstaticmethod | 59 @abc.abstractstaticmethod |
67 def foo(): return 3 | 60 def foo(): return 3 |
68 self.assertRaises(TypeError, C) | 61 self.assertRaises(TypeError, C) |
69 class D(C): | 62 class D(C): |
70 @staticmethod | 63 @staticmethod |
71 def foo(): return 4 | 64 def foo(): return 4 |
72 self.assertEqual(D.foo(), 4) | 65 self.assertEqual(D.foo(), 4) |
73 self.assertEqual(D().foo(), 4) | 66 self.assertEqual(D().foo(), 4) |
(...skipping 19 matching lines...) Expand all Loading... |
93 self.assertEqual(E.__abstractmethods__, set()) | 86 self.assertEqual(E.__abstractmethods__, set()) |
94 E() # now foo is concrete, too | 87 E() # now foo is concrete, too |
95 self.assertFalse(isabstract(E)) | 88 self.assertFalse(isabstract(E)) |
96 class F(E): | 89 class F(E): |
97 @abstractthing | 90 @abstractthing |
98 def bar(self): pass # abstract override of concrete | 91 def bar(self): pass # abstract override of concrete |
99 self.assertEqual(F.__abstractmethods__, {"bar"}) | 92 self.assertEqual(F.__abstractmethods__, {"bar"}) |
100 self.assertRaises(TypeError, F) # because bar is abstract now | 93 self.assertRaises(TypeError, F) # because bar is abstract now |
101 self.assertTrue(isabstract(F)) | 94 self.assertTrue(isabstract(F)) |
102 | 95 |
| 96 |
| 97 class TestABC(unittest.TestCase): |
| 98 |
| 99 def test_abstractmethod_basics(self): |
| 100 @abc.abstractmethod |
| 101 def foo(self): pass |
| 102 self.assertTrue(foo.__isabstractmethod__) |
| 103 def bar(self): pass |
| 104 self.assertFalse(hasattr(bar, "__isabstractmethod__")) |
| 105 |
| 106 def test_abstractproperty_basics(self): |
| 107 @property |
| 108 @abc.abstractmethod |
| 109 def foo(self): pass |
| 110 self.assertTrue(foo.__isabstractmethod__) |
| 111 def bar(self): pass |
| 112 self.assertFalse(getattr(bar, "__isabstractmethod__", False)) |
| 113 |
| 114 class C(metaclass=abc.ABCMeta): |
| 115 @property |
| 116 @abc.abstractmethod |
| 117 def foo(self): return 3 |
| 118 self.assertRaises(TypeError, C) |
| 119 class D(C): |
| 120 @C.foo.getter |
| 121 def foo(self): return super().foo |
| 122 self.assertEqual(D().foo, 3) |
| 123 |
| 124 def test_abstractclassmethod_basics(self): |
| 125 @classmethod |
| 126 @abc.abstractmethod |
| 127 def foo(cls): pass |
| 128 self.assertTrue(foo.__isabstractmethod__) |
| 129 @classmethod |
| 130 def bar(cls): pass |
| 131 self.assertFalse(getattr(bar, "__isabstractmethod__", False)) |
| 132 |
| 133 class C(metaclass=abc.ABCMeta): |
| 134 @classmethod |
| 135 @abc.abstractmethod |
| 136 def foo(cls): return cls.__name__ |
| 137 self.assertRaises(TypeError, C) |
| 138 class D(C): |
| 139 @classmethod |
| 140 def foo(cls): return super().foo() |
| 141 self.assertEqual(D.foo(), 'D') |
| 142 self.assertEqual(D().foo(), 'D') |
| 143 |
| 144 def test_abstractstaticmethod_basics(self): |
| 145 @staticmethod |
| 146 @abc.abstractmethod |
| 147 def foo(): pass |
| 148 self.assertTrue(foo.__isabstractmethod__) |
| 149 @staticmethod |
| 150 def bar(): pass |
| 151 self.assertFalse(getattr(bar, "__isabstractmethod__", False)) |
| 152 |
| 153 class C(metaclass=abc.ABCMeta): |
| 154 @staticmethod |
| 155 @abc.abstractmethod |
| 156 def foo(): return 3 |
| 157 self.assertRaises(TypeError, C) |
| 158 class D(C): |
| 159 @staticmethod |
| 160 def foo(): return 4 |
| 161 self.assertEqual(D.foo(), 4) |
| 162 self.assertEqual(D().foo(), 4) |
| 163 |
| 164 def test_abstractmethod_integration(self): |
| 165 for abstractthing in [abc.abstractmethod, abc.abstractproperty, |
| 166 abc.abstractclassmethod, |
| 167 abc.abstractstaticmethod]: |
| 168 class C(metaclass=abc.ABCMeta): |
| 169 @abstractthing |
| 170 def foo(self): pass # abstract |
| 171 def bar(self): pass # concrete |
| 172 self.assertEqual(C.__abstractmethods__, {"foo"}) |
| 173 self.assertRaises(TypeError, C) # because foo is abstract |
| 174 self.assertTrue(isabstract(C)) |
| 175 class D(C): |
| 176 def bar(self): pass # concrete override of concrete |
| 177 self.assertEqual(D.__abstractmethods__, {"foo"}) |
| 178 self.assertRaises(TypeError, D) # because foo is still abstract |
| 179 self.assertTrue(isabstract(D)) |
| 180 class E(D): |
| 181 def foo(self): pass |
| 182 self.assertEqual(E.__abstractmethods__, set()) |
| 183 E() # now foo is concrete, too |
| 184 self.assertFalse(isabstract(E)) |
| 185 class F(E): |
| 186 @abstractthing |
| 187 def bar(self): pass # abstract override of concrete |
| 188 self.assertEqual(F.__abstractmethods__, {"bar"}) |
| 189 self.assertRaises(TypeError, F) # because bar is abstract now |
| 190 self.assertTrue(isabstract(F)) |
| 191 |
103 def test_descriptors_with_abstractmethod(self): | 192 def test_descriptors_with_abstractmethod(self): |
104 class C(metaclass=abc.ABCMeta): | 193 class C(metaclass=abc.ABCMeta): |
105 @property | 194 @property |
106 @abc.abstractmethod | 195 @abc.abstractmethod |
107 def foo(self): return 3 | 196 def foo(self): return 3 |
108 @foo.setter | 197 @foo.setter |
109 @abc.abstractmethod | 198 @abc.abstractmethod |
110 def foo(self, val): pass | 199 def foo(self, val): pass |
111 self.assertRaises(TypeError, C) | 200 self.assertRaises(TypeError, C) |
112 class D(C): | 201 class D(C): |
113 @C.foo.getter | 202 @C.foo.getter |
114 def foo(self): return super().foo | 203 def foo(self): return super().foo |
115 self.assertRaises(TypeError, D) | 204 self.assertRaises(TypeError, D) |
116 class E(D): | 205 class E(D): |
117 @D.foo.setter | 206 @D.foo.setter |
118 def foo(self, val): pass | 207 def foo(self, val): pass |
119 self.assertEqual(E().foo, 3) | 208 self.assertEqual(E().foo, 3) |
120 class F(C): | 209 # check that the property's __isabstractmethod__ descriptor does the |
| 210 # right thing when presented with a value that fails truth testing: |
| 211 class NotBool(object): |
| 212 def __nonzero__(self): |
| 213 raise ValueError() |
| 214 __len__ = __nonzero__ |
| 215 with self.assertRaises(ValueError): |
| 216 class F(C): |
| 217 def bar(self): |
| 218 pass |
| 219 bar.__isabstractmethod__ = NotBool() |
| 220 foo = property(bar) |
| 221 |
| 222 |
| 223 def test_customdescriptors_with_abstractmethod(self): |
| 224 class Descriptor: |
| 225 def __init__(self, fget, fset=None): |
| 226 self._fget = fget |
| 227 self._fset = fset |
| 228 def getter(self, callable): |
| 229 return Descriptor(callable, self._fget) |
| 230 def setter(self, callable): |
| 231 return Descriptor(self._fget, callable) |
121 @property | 232 @property |
| 233 def __isabstractmethod__(self): |
| 234 return (getattr(self._fget, '__isabstractmethod__', False) |
| 235 or getattr(self._fset, '__isabstractmethod__', False)) |
| 236 class C(metaclass=abc.ABCMeta): |
| 237 @Descriptor |
| 238 @abc.abstractmethod |
122 def foo(self): return 3 | 239 def foo(self): return 3 |
123 self.assertRaises(TypeError, F) | 240 @foo.setter |
124 | 241 @abc.abstractmethod |
125 def test_pathologically_named_descriptors(self): | 242 def foo(self, val): pass |
126 """Test that attribute names containing "." doesn't choke ABCMeta""" | |
127 class MyProperty(property): | |
128 pass | |
129 class C(metaclass=abc.ABCMeta): | |
130 @MyProperty | |
131 @abc.abstractmethod | |
132 def foo(self): return 1 | |
133 setattr(foo, 'pathological.desc_method', None) | |
134 @MyProperty | |
135 def bar(self): return | |
136 setattr(bar, 'pathological.desc_method', None) | |
137 setattr(self, 'pathological.bar', foo) | |
138 self.assertRaises(TypeError, C) | 243 self.assertRaises(TypeError, C) |
139 class D(C): | 244 class D(C): |
140 @C.foo.getter | 245 @C.foo.getter |
141 def foo(self): return 2 | 246 def foo(self): return super().foo |
142 self.assertEqual(D().foo, 2) | 247 self.assertRaises(TypeError, D) |
| 248 class E(D): |
| 249 @D.foo.setter |
| 250 def foo(self, val): pass |
| 251 self.assertFalse(E.foo.__isabstractmethod__) |
143 | 252 |
144 def test_metaclass_abc(self): | 253 def test_metaclass_abc(self): |
145 # Metaclasses can be ABCs, too. | 254 # Metaclasses can be ABCs, too. |
146 class A(metaclass=abc.ABCMeta): | 255 class A(metaclass=abc.ABCMeta): |
147 @abc.abstractmethod | 256 @abc.abstractmethod |
148 def x(self): | 257 def x(self): |
149 pass | 258 pass |
150 self.assertEqual(A.__abstractmethods__, {"x"}) | 259 self.assertEqual(A.__abstractmethods__, {"x"}) |
151 class meta(type, A): | 260 class meta(type, A): |
152 def x(self): | 261 def x(self): |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 C() | 415 C() |
307 self.assertEqual(B.counter, 1) | 416 self.assertEqual(B.counter, 1) |
308 | 417 |
309 | 418 |
310 def test_main(): | 419 def test_main(): |
311 support.run_unittest(TestABC) | 420 support.run_unittest(TestABC) |
312 | 421 |
313 | 422 |
314 if __name__ == "__main__": | 423 if __name__ == "__main__": |
315 unittest.main() | 424 unittest.main() |
LEFT | RIGHT |