Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(169630)

Delta Between Two Patch Sets: Lib/test/test_abc.py

Issue 11610: Improving property to accept abstract methods
Left Patch Set: Created 8 years, 6 months ago
Right Patch Set: Created 8 years ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « Lib/numbers.py ('k') | Lib/test/test_property.py » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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
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
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()
LEFTRIGHT

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+