blob: 5addd363ed4f4e74a2d2ef1571c3592d999b52d3 [file] [log] [blame]
Christian Heimes0449f632007-12-15 01:27:15 +00001# Test case for property
2# more tests are in test_descr
3
R. David Murray378c0cf2010-02-24 01:46:21 +00004import sys
Christian Heimes0449f632007-12-15 01:27:15 +00005import unittest
Christian Heimes0449f632007-12-15 01:27:15 +00006
7class PropertyBase(Exception):
8 pass
9
10class PropertyGet(PropertyBase):
11 pass
12
13class PropertySet(PropertyBase):
14 pass
15
16class PropertyDel(PropertyBase):
17 pass
18
19class BaseClass(object):
20 def __init__(self):
21 self._spam = 5
22
23 @property
24 def spam(self):
25 """BaseClass.getter"""
26 return self._spam
27
28 @spam.setter
29 def spam(self, value):
30 self._spam = value
31
32 @spam.deleter
33 def spam(self):
34 del self._spam
35
36class SubClass(BaseClass):
37
38 @BaseClass.spam.getter
39 def spam(self):
40 """SubClass.getter"""
41 raise PropertyGet(self._spam)
42
43 @spam.setter
44 def spam(self, value):
45 raise PropertySet(self._spam)
46
47 @spam.deleter
48 def spam(self):
49 raise PropertyDel(self._spam)
50
51class PropertyDocBase(object):
52 _spam = 1
53 def _get_spam(self):
54 return self._spam
55 spam = property(_get_spam, doc="spam spam spam")
56
57class PropertyDocSub(PropertyDocBase):
58 @PropertyDocBase.spam.getter
59 def spam(self):
60 """The decorator does not use this doc string"""
61 return self._spam
62
R. David Murrayb18500d2009-05-04 22:59:07 +000063class PropertySubNewGetter(BaseClass):
64 @BaseClass.spam.getter
65 def spam(self):
66 """new docstring"""
67 return 5
68
69class PropertyNewGetter(object):
70 @property
71 def spam(self):
72 """original docstring"""
73 return 1
74 @spam.getter
75 def spam(self):
76 """new docstring"""
77 return 8
78
Raymond Hettingereac503a2015-05-13 01:09:59 -070079class PropertyWritableDoc(object):
80
81 @property
82 def spam(self):
83 """Eggs"""
84 return "eggs"
85
Christian Heimes0449f632007-12-15 01:27:15 +000086class PropertyTests(unittest.TestCase):
87 def test_property_decorator_baseclass(self):
88 # see #1620
89 base = BaseClass()
90 self.assertEqual(base.spam, 5)
91 self.assertEqual(base._spam, 5)
92 base.spam = 10
93 self.assertEqual(base.spam, 10)
94 self.assertEqual(base._spam, 10)
95 delattr(base, "spam")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000096 self.assertTrue(not hasattr(base, "spam"))
97 self.assertTrue(not hasattr(base, "_spam"))
Christian Heimes0449f632007-12-15 01:27:15 +000098 base.spam = 20
99 self.assertEqual(base.spam, 20)
100 self.assertEqual(base._spam, 20)
Christian Heimes0449f632007-12-15 01:27:15 +0000101
102 def test_property_decorator_subclass(self):
103 # see #1620
104 sub = SubClass()
105 self.assertRaises(PropertyGet, getattr, sub, "spam")
106 self.assertRaises(PropertySet, setattr, sub, "spam", None)
107 self.assertRaises(PropertyDel, delattr, sub, "spam")
R. David Murray378c0cf2010-02-24 01:46:21 +0000108
109 @unittest.skipIf(sys.flags.optimize >= 2,
110 "Docstrings are omitted with -O2 and above")
111 def test_property_decorator_subclass_doc(self):
112 sub = SubClass()
Christian Heimes0449f632007-12-15 01:27:15 +0000113 self.assertEqual(sub.__class__.spam.__doc__, "SubClass.getter")
114
R. David Murray378c0cf2010-02-24 01:46:21 +0000115 @unittest.skipIf(sys.flags.optimize >= 2,
116 "Docstrings are omitted with -O2 and above")
117 def test_property_decorator_baseclass_doc(self):
118 base = BaseClass()
119 self.assertEqual(base.__class__.spam.__doc__, "BaseClass.getter")
120
Christian Heimes0449f632007-12-15 01:27:15 +0000121 def test_property_decorator_doc(self):
122 base = PropertyDocBase()
123 sub = PropertyDocSub()
124 self.assertEqual(base.__class__.spam.__doc__, "spam spam spam")
125 self.assertEqual(sub.__class__.spam.__doc__, "spam spam spam")
126
Benjamin Peterson902d2bd2010-06-28 15:43:25 +0000127 @unittest.skipIf(sys.flags.optimize >= 2,
R. David Murray378c0cf2010-02-24 01:46:21 +0000128 "Docstrings are omitted with -O2 and above")
R. David Murrayb18500d2009-05-04 22:59:07 +0000129 def test_property_getter_doc_override(self):
130 newgettersub = PropertySubNewGetter()
131 self.assertEqual(newgettersub.spam, 5)
132 self.assertEqual(newgettersub.__class__.spam.__doc__, "new docstring")
133 newgetter = PropertyNewGetter()
134 self.assertEqual(newgetter.spam, 8)
135 self.assertEqual(newgetter.__class__.spam.__doc__, "new docstring")
136
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -0500137 def test_property___isabstractmethod__descriptor(self):
138 for val in (True, False, [], [1], '', '1'):
139 class C(object):
140 def foo(self):
141 pass
142 foo.__isabstractmethod__ = val
143 foo = property(foo)
144 self.assertIs(C.foo.__isabstractmethod__, bool(val))
145
146 # check that the property's __isabstractmethod__ descriptor does the
147 # right thing when presented with a value that fails truth testing:
148 class NotBool(object):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +0200149 def __bool__(self):
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -0500150 raise ValueError()
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +0200151 __len__ = __bool__
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -0500152 with self.assertRaises(ValueError):
153 class C(object):
154 def foo(self):
155 pass
156 foo.__isabstractmethod__ = NotBool()
157 foo = property(foo)
158 C.foo.__isabstractmethod__
159
Raymond Hettingereac503a2015-05-13 01:09:59 -0700160 @unittest.skipIf(sys.flags.optimize >= 2,
161 "Docstrings are omitted with -O2 and above")
162 def test_property_builtin_doc_writable(self):
163 p = property(doc='basic')
164 self.assertEqual(p.__doc__, 'basic')
165 p.__doc__ = 'extended'
166 self.assertEqual(p.__doc__, 'extended')
167
168 @unittest.skipIf(sys.flags.optimize >= 2,
169 "Docstrings are omitted with -O2 and above")
170 def test_property_decorator_doc_writable(self):
171 sub = PropertyWritableDoc()
172 self.assertEqual(sub.__class__.spam.__doc__, 'Eggs')
173 sub.__class__.spam.__doc__ = 'Spam'
174 self.assertEqual(sub.__class__.spam.__doc__, 'Spam')
R. David Murrayb18500d2009-05-04 22:59:07 +0000175
176# Issue 5890: subclasses of property do not preserve method __doc__ strings
177class PropertySub(property):
178 """This is a subclass of property"""
179
180class PropertySubSlots(property):
181 """This is a subclass of property that defines __slots__"""
182 __slots__ = ()
183
184class PropertySubclassTests(unittest.TestCase):
185
R. David Murrayb18500d2009-05-04 22:59:07 +0000186 def test_slots_docstring_copy_exception(self):
187 try:
188 class Foo(object):
189 @PropertySubSlots
190 def spam(self):
191 """Trying to copy this docstring will raise an exception"""
192 return 1
193 except AttributeError:
194 pass
195 else:
196 raise Exception("AttributeError not raised")
197
R. David Murray378c0cf2010-02-24 01:46:21 +0000198 @unittest.skipIf(sys.flags.optimize >= 2,
199 "Docstrings are omitted with -O2 and above")
200 def test_docstring_copy(self):
201 class Foo(object):
202 @PropertySub
203 def spam(self):
204 """spam wrapped in property subclass"""
205 return 1
206 self.assertEqual(
207 Foo.spam.__doc__,
208 "spam wrapped in property subclass")
209
Serhiy Storchaka8e0ae2a2013-01-28 13:25:44 +0200210 @unittest.skipIf(sys.flags.optimize >= 2,
R. David Murray378c0cf2010-02-24 01:46:21 +0000211 "Docstrings are omitted with -O2 and above")
R. David Murrayb18500d2009-05-04 22:59:07 +0000212 def test_property_setter_copies_getter_docstring(self):
213 class Foo(object):
214 def __init__(self): self._spam = 1
215 @PropertySub
216 def spam(self):
217 """spam wrapped in property subclass"""
218 return self._spam
219 @spam.setter
220 def spam(self, value):
221 """this docstring is ignored"""
222 self._spam = value
223 foo = Foo()
224 self.assertEqual(foo.spam, 1)
225 foo.spam = 2
226 self.assertEqual(foo.spam, 2)
227 self.assertEqual(
228 Foo.spam.__doc__,
229 "spam wrapped in property subclass")
230 class FooSub(Foo):
231 @Foo.spam.setter
232 def spam(self, value):
233 """another ignored docstring"""
234 self._spam = 'eggs'
235 foosub = FooSub()
236 self.assertEqual(foosub.spam, 1)
237 foosub.spam = 7
238 self.assertEqual(foosub.spam, 'eggs')
239 self.assertEqual(
240 FooSub.spam.__doc__,
241 "spam wrapped in property subclass")
242
Serhiy Storchaka8e0ae2a2013-01-28 13:25:44 +0200243 @unittest.skipIf(sys.flags.optimize >= 2,
R. David Murray378c0cf2010-02-24 01:46:21 +0000244 "Docstrings are omitted with -O2 and above")
R. David Murrayb18500d2009-05-04 22:59:07 +0000245 def test_property_new_getter_new_docstring(self):
246
247 class Foo(object):
248 @PropertySub
249 def spam(self):
250 """a docstring"""
251 return 1
252 @spam.getter
253 def spam(self):
254 """a new docstring"""
255 return 2
256 self.assertEqual(Foo.spam.__doc__, "a new docstring")
257 class FooBase(object):
258 @PropertySub
259 def spam(self):
260 """a docstring"""
261 return 1
262 class Foo2(FooBase):
263 @FooBase.spam.getter
264 def spam(self):
265 """a new docstring"""
266 return 2
267 self.assertEqual(Foo.spam.__doc__, "a new docstring")
268
269
270
Christian Heimes0449f632007-12-15 01:27:15 +0000271if __name__ == '__main__':
Zachary Ware38c707e2015-04-13 15:00:43 -0500272 unittest.main()