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

Side by Side Diff: Lib/test/test_abc.py

Issue 11610: Improving property to accept abstract methods
Patch Set: Created 8 years, 4 months 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:
View unified diff | Download patch
OLDNEW
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 TestABC(unittest.TestCase):
14 14
15 def test_abstractmethod_basics(self): 15 def test_abstractmethod_basics(self):
16 @abc.abstractmethod 16 @abc.abstractmethod
17 def foo(self): pass 17 def foo(self): pass
18 self.assertTrue(foo.__isabstractmethod__) 18 self.assertTrue(foo.__isabstractmethod__)
19 def bar(self): pass 19 def bar(self): pass
20 self.assertFalse(hasattr(bar, "__isabstractmethod__")) 20 self.assertFalse(getattr(bar, "__isabstractmethod__", False))
Benjamin Peterson 2011/11/29 17:27:46 Why is the default needed?
dsdale24 2011/11/29 17:40:05 Because function objects do not define __isabstrac
21 21
22 def test_abstractproperty_basics(self): 22 def test_abstractproperty_basics(self):
23 @abc.abstractproperty 23 @property
24 @abc.abstractmethod
24 def foo(self): pass 25 def foo(self): pass
25 self.assertTrue(foo.__isabstractmethod__) 26 self.assertTrue(foo.__isabstractmethod__)
26 def bar(self): pass 27 def bar(self): pass
27 self.assertFalse(hasattr(bar, "__isabstractmethod__")) 28 self.assertFalse(getattr(bar, "__isabstractmethod__", False))
28 29
29 class C(metaclass=abc.ABCMeta): 30 class C(metaclass=abc.ABCMeta):
30 @abc.abstractproperty 31 @property
32 @abc.abstractmethod
31 def foo(self): return 3 33 def foo(self): return 3
34 self.assertRaises(TypeError, C)
32 class D(C): 35 class D(C):
33 @property 36 @C.foo.getter
34 def foo(self): return super().foo 37 def foo(self): return super().foo
35 self.assertEqual(D().foo, 3) 38 self.assertEqual(D().foo, 3)
36 39
37 def test_abstractclassmethod_basics(self): 40 def test_abstractclassmethod_basics(self):
38 @abc.abstractclassmethod 41 @classmethod
42 @abc.abstractmethod
39 def foo(cls): pass 43 def foo(cls): pass
40 self.assertTrue(foo.__isabstractmethod__) 44 self.assertTrue(foo.__isabstractmethod__)
41 @classmethod 45 @classmethod
42 def bar(cls): pass 46 def bar(cls): pass
43 self.assertFalse(hasattr(bar, "__isabstractmethod__")) 47 self.assertFalse(getattr(bar, "__isabstractmethod__", False))
44 48
45 class C(metaclass=abc.ABCMeta): 49 class C(metaclass=abc.ABCMeta):
46 @abc.abstractclassmethod 50 @classmethod
51 @abc.abstractmethod
47 def foo(cls): return cls.__name__ 52 def foo(cls): return cls.__name__
48 self.assertRaises(TypeError, C) 53 self.assertRaises(TypeError, C)
49 class D(C): 54 class D(C):
50 @classmethod 55 @classmethod
51 def foo(cls): return super().foo() 56 def foo(cls): return super().foo()
52 self.assertEqual(D.foo(), 'D') 57 self.assertEqual(D.foo(), 'D')
53 self.assertEqual(D().foo(), 'D') 58 self.assertEqual(D().foo(), 'D')
54 59
55 def test_abstractstaticmethod_basics(self): 60 def test_abstractstaticmethod_basics(self):
56 @abc.abstractstaticmethod 61 @staticmethod
62 @abc.abstractmethod
57 def foo(): pass 63 def foo(): pass
58 self.assertTrue(foo.__isabstractmethod__) 64 self.assertTrue(foo.__isabstractmethod__)
59 @staticmethod 65 @staticmethod
60 def bar(): pass 66 def bar(): pass
61 self.assertFalse(hasattr(bar, "__isabstractmethod__")) 67 self.assertFalse(getattr(bar, "__isabstractmethod__", False))
62 68
63 class C(metaclass=abc.ABCMeta): 69 class C(metaclass=abc.ABCMeta):
64 @abc.abstractstaticmethod 70 @staticmethod
71 @abc.abstractmethod
65 def foo(): return 3 72 def foo(): return 3
66 self.assertRaises(TypeError, C) 73 self.assertRaises(TypeError, C)
67 class D(C): 74 class D(C):
68 @staticmethod 75 @staticmethod
69 def foo(): return 4 76 def foo(): return 4
70 self.assertEqual(D.foo(), 4) 77 self.assertEqual(D.foo(), 4)
71 self.assertEqual(D().foo(), 4) 78 self.assertEqual(D().foo(), 4)
72 79
73 def test_abstractmethod_integration(self): 80 def test_abstractmethod_integration(self):
74 for abstractthing in [abc.abstractmethod, abc.abstractproperty,
75 abc.abstractclassmethod,
76 abc.abstractstaticmethod]:
77 class C(metaclass=abc.ABCMeta): 81 class C(metaclass=abc.ABCMeta):
78 @abstractthing 82 @abc.abstractmethod
79 def foo(self): pass # abstract 83 def foo(self): pass # abstract
80 def bar(self): pass # concrete 84 def bar(self): pass # concrete
81 self.assertEqual(C.__abstractmethods__, {"foo"}) 85 self.assertEqual(C.__abstractmethods__, {"foo"})
82 self.assertRaises(TypeError, C) # because foo is abstract 86 self.assertRaises(TypeError, C) # because foo is abstract
83 self.assertTrue(isabstract(C)) 87 self.assertTrue(isabstract(C))
84 class D(C): 88 class D(C):
85 def bar(self): pass # concrete override of concrete 89 def bar(self): pass # concrete override of concrete
86 self.assertEqual(D.__abstractmethods__, {"foo"}) 90 self.assertEqual(D.__abstractmethods__, {"foo"})
87 self.assertRaises(TypeError, D) # because foo is still abstract 91 self.assertRaises(TypeError, D) # because foo is still abstract
88 self.assertTrue(isabstract(D)) 92 self.assertTrue(isabstract(D))
89 class E(D): 93 class E(D):
90 def foo(self): pass 94 def foo(self): pass
91 self.assertEqual(E.__abstractmethods__, set()) 95 self.assertEqual(E.__abstractmethods__, set())
92 E() # now foo is concrete, too 96 E() # now foo is concrete, too
93 self.assertFalse(isabstract(E)) 97 self.assertFalse(isabstract(E))
94 class F(E): 98 class F(E):
95 @abstractthing 99 @abc.abstractmethod
96 def bar(self): pass # abstract override of concrete 100 def bar(self): pass # abstract override of concrete
97 self.assertEqual(F.__abstractmethods__, {"bar"}) 101 self.assertEqual(F.__abstractmethods__, {"bar"})
98 self.assertRaises(TypeError, F) # because bar is abstract now 102 self.assertRaises(TypeError, F) # because bar is abstract now
99 self.assertTrue(isabstract(F)) 103 self.assertTrue(isabstract(F))
100 104
105 def test_descriptors_with_abstractmethod(self):
106 class C(metaclass=abc.ABCMeta):
107 @property
108 @abc.abstractmethod
109 def foo(self): return 3
110 @foo.setter
111 @abc.abstractmethod
112 def foo(self, val): pass
113 self.assertRaises(TypeError, C)
114 class D(C):
115 @C.foo.getter
116 def foo(self): return super().foo
117 self.assertRaises(TypeError, D)
118 class E(D):
119 @D.foo.setter
120 def foo(self, val): pass
121 self.assertEqual(E().foo, 3)
122 # check that the property's __isabstractmethod__ descriptor does the
123 # right thing when presented with a value that fails truth testing:
124 class NotBool(object):
125 def __nonzero__(self):
126 raise ValueError()
127 __len__ = __nonzero__
128 with self.assertRaises(ValueError):
129 class F(C):
130 def bar(self):
131 pass
132 bar.__isabstractmethod__ = NotBool()
133 foo = property(bar)
134
135
136 def test_customdescriptors_with_abstractmethod(self):
137 class Descriptor:
138 def __init__(self, fget, fset=None):
139 self._fget = fget
140 self._fset = fset
141 def getter(self, callable): return Descriptor(callable, self._fget)
Benjamin Peterson 2011/11/29 02:45:54 Split lines.
142 def setter(self, callable): return Descriptor(self._fget, callable)
143 @property
144 def __isabstractmethod__(self):
145 return (getattr(self._fget, '__isabstractmethod__', False)
146 or getattr(self._fset, '__isabstractmethod__', False))
147 class C(metaclass=abc.ABCMeta):
148 @Descriptor
149 @abc.abstractmethod
150 def foo(self): return 3
151 @foo.setter
152 @abc.abstractmethod
153 def foo(self, val): pass
154 self.assertRaises(TypeError, C)
155 class D(C):
156 @C.foo.getter
157 def foo(self): return super().foo
158 self.assertRaises(TypeError, D)
159 class E(D):
160 @D.foo.setter
161 def foo(self, val): pass
162 self.assertEqual(E.foo.__isabstractmethod__, False)
Benjamin Peterson 2011/11/29 02:45:54 Use assertFalse instead.
163
101 def test_metaclass_abc(self): 164 def test_metaclass_abc(self):
102 # Metaclasses can be ABCs, too. 165 # Metaclasses can be ABCs, too.
103 class A(metaclass=abc.ABCMeta): 166 class A(metaclass=abc.ABCMeta):
104 @abc.abstractmethod 167 @abc.abstractmethod
105 def x(self): 168 def x(self):
106 pass 169 pass
107 self.assertEqual(A.__abstractmethods__, {"x"}) 170 self.assertEqual(A.__abstractmethods__, {"x"})
108 class meta(type, A): 171 class meta(type, A):
109 def x(self): 172 def x(self):
110 return 1 173 return 1
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 C() 326 C()
264 self.assertEqual(B.counter, 1) 327 self.assertEqual(B.counter, 1)
265 328
266 329
267 def test_main(): 330 def test_main():
268 support.run_unittest(TestABC) 331 support.run_unittest(TestABC)
269 332
270 333
271 if __name__ == "__main__": 334 if __name__ == "__main__":
272 unittest.main() 335 unittest.main()
OLDNEW

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