blob: 26b7d5283a2220b729b91cd237ec4a9c9d260c4f [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
Christian Heimes0449f632007-12-15 01:27:15 +000079class PropertyTests(unittest.TestCase):
80 def test_property_decorator_baseclass(self):
81 # see #1620
82 base = BaseClass()
83 self.assertEqual(base.spam, 5)
84 self.assertEqual(base._spam, 5)
85 base.spam = 10
86 self.assertEqual(base.spam, 10)
87 self.assertEqual(base._spam, 10)
88 delattr(base, "spam")
Benjamin Petersonc9c0f202009-06-30 23:06:06 +000089 self.assertTrue(not hasattr(base, "spam"))
90 self.assertTrue(not hasattr(base, "_spam"))
Christian Heimes0449f632007-12-15 01:27:15 +000091 base.spam = 20
92 self.assertEqual(base.spam, 20)
93 self.assertEqual(base._spam, 20)
Christian Heimes0449f632007-12-15 01:27:15 +000094
95 def test_property_decorator_subclass(self):
96 # see #1620
97 sub = SubClass()
98 self.assertRaises(PropertyGet, getattr, sub, "spam")
99 self.assertRaises(PropertySet, setattr, sub, "spam", None)
100 self.assertRaises(PropertyDel, delattr, sub, "spam")
R. David Murray378c0cf2010-02-24 01:46:21 +0000101
102 @unittest.skipIf(sys.flags.optimize >= 2,
103 "Docstrings are omitted with -O2 and above")
104 def test_property_decorator_subclass_doc(self):
105 sub = SubClass()
Christian Heimes0449f632007-12-15 01:27:15 +0000106 self.assertEqual(sub.__class__.spam.__doc__, "SubClass.getter")
107
R. David Murray378c0cf2010-02-24 01:46:21 +0000108 @unittest.skipIf(sys.flags.optimize >= 2,
109 "Docstrings are omitted with -O2 and above")
110 def test_property_decorator_baseclass_doc(self):
111 base = BaseClass()
112 self.assertEqual(base.__class__.spam.__doc__, "BaseClass.getter")
113
Christian Heimes0449f632007-12-15 01:27:15 +0000114 def test_property_decorator_doc(self):
115 base = PropertyDocBase()
116 sub = PropertyDocSub()
117 self.assertEqual(base.__class__.spam.__doc__, "spam spam spam")
118 self.assertEqual(sub.__class__.spam.__doc__, "spam spam spam")
119
Benjamin Peterson902d2bd2010-06-28 15:43:25 +0000120 @unittest.skipIf(sys.flags.optimize >= 2,
R. David Murray378c0cf2010-02-24 01:46:21 +0000121 "Docstrings are omitted with -O2 and above")
R. David Murrayb18500d2009-05-04 22:59:07 +0000122 def test_property_getter_doc_override(self):
123 newgettersub = PropertySubNewGetter()
124 self.assertEqual(newgettersub.spam, 5)
125 self.assertEqual(newgettersub.__class__.spam.__doc__, "new docstring")
126 newgetter = PropertyNewGetter()
127 self.assertEqual(newgetter.spam, 8)
128 self.assertEqual(newgetter.__class__.spam.__doc__, "new docstring")
129
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -0500130 def test_property___isabstractmethod__descriptor(self):
131 for val in (True, False, [], [1], '', '1'):
132 class C(object):
133 def foo(self):
134 pass
135 foo.__isabstractmethod__ = val
136 foo = property(foo)
137 self.assertIs(C.foo.__isabstractmethod__, bool(val))
138
139 # check that the property's __isabstractmethod__ descriptor does the
140 # right thing when presented with a value that fails truth testing:
141 class NotBool(object):
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +0200142 def __bool__(self):
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -0500143 raise ValueError()
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +0200144 __len__ = __bool__
Benjamin Petersonbfebb7b2011-12-15 15:34:02 -0500145 with self.assertRaises(ValueError):
146 class C(object):
147 def foo(self):
148 pass
149 foo.__isabstractmethod__ = NotBool()
150 foo = property(foo)
151 C.foo.__isabstractmethod__
152
Raymond Hettingereac503a2015-05-13 01:09:59 -0700153 @unittest.skipIf(sys.flags.optimize >= 2,
154 "Docstrings are omitted with -O2 and above")
155 def test_property_builtin_doc_writable(self):
156 p = property(doc='basic')
157 self.assertEqual(p.__doc__, 'basic')
158 p.__doc__ = 'extended'
159 self.assertEqual(p.__doc__, 'extended')
160
161 @unittest.skipIf(sys.flags.optimize >= 2,
162 "Docstrings are omitted with -O2 and above")
163 def test_property_decorator_doc_writable(self):
Berker Peksaga7d81272015-12-11 23:48:13 +0200164 class PropertyWritableDoc(object):
165
166 @property
167 def spam(self):
168 """Eggs"""
169 return "eggs"
170
Raymond Hettingereac503a2015-05-13 01:09:59 -0700171 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()