blob: e72eb55647b16d4f708dc7674460b5458f04fadb [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
R. David Murrayb18500d2009-05-04 22:59:07 +0000153
154# Issue 5890: subclasses of property do not preserve method __doc__ strings
155class PropertySub(property):
156 """This is a subclass of property"""
157
158class PropertySubSlots(property):
159 """This is a subclass of property that defines __slots__"""
160 __slots__ = ()
161
162class PropertySubclassTests(unittest.TestCase):
163
R. David Murrayb18500d2009-05-04 22:59:07 +0000164 def test_slots_docstring_copy_exception(self):
165 try:
166 class Foo(object):
167 @PropertySubSlots
168 def spam(self):
169 """Trying to copy this docstring will raise an exception"""
170 return 1
171 except AttributeError:
172 pass
173 else:
174 raise Exception("AttributeError not raised")
175
R. David Murray378c0cf2010-02-24 01:46:21 +0000176 @unittest.skipIf(sys.flags.optimize >= 2,
177 "Docstrings are omitted with -O2 and above")
178 def test_docstring_copy(self):
179 class Foo(object):
180 @PropertySub
181 def spam(self):
182 """spam wrapped in property subclass"""
183 return 1
184 self.assertEqual(
185 Foo.spam.__doc__,
186 "spam wrapped in property subclass")
187
Serhiy Storchaka8e0ae2a2013-01-28 13:25:44 +0200188 @unittest.skipIf(sys.flags.optimize >= 2,
R. David Murray378c0cf2010-02-24 01:46:21 +0000189 "Docstrings are omitted with -O2 and above")
R. David Murrayb18500d2009-05-04 22:59:07 +0000190 def test_property_setter_copies_getter_docstring(self):
191 class Foo(object):
192 def __init__(self): self._spam = 1
193 @PropertySub
194 def spam(self):
195 """spam wrapped in property subclass"""
196 return self._spam
197 @spam.setter
198 def spam(self, value):
199 """this docstring is ignored"""
200 self._spam = value
201 foo = Foo()
202 self.assertEqual(foo.spam, 1)
203 foo.spam = 2
204 self.assertEqual(foo.spam, 2)
205 self.assertEqual(
206 Foo.spam.__doc__,
207 "spam wrapped in property subclass")
208 class FooSub(Foo):
209 @Foo.spam.setter
210 def spam(self, value):
211 """another ignored docstring"""
212 self._spam = 'eggs'
213 foosub = FooSub()
214 self.assertEqual(foosub.spam, 1)
215 foosub.spam = 7
216 self.assertEqual(foosub.spam, 'eggs')
217 self.assertEqual(
218 FooSub.spam.__doc__,
219 "spam wrapped in property subclass")
220
Serhiy Storchaka8e0ae2a2013-01-28 13:25:44 +0200221 @unittest.skipIf(sys.flags.optimize >= 2,
R. David Murray378c0cf2010-02-24 01:46:21 +0000222 "Docstrings are omitted with -O2 and above")
R. David Murrayb18500d2009-05-04 22:59:07 +0000223 def test_property_new_getter_new_docstring(self):
224
225 class Foo(object):
226 @PropertySub
227 def spam(self):
228 """a docstring"""
229 return 1
230 @spam.getter
231 def spam(self):
232 """a new docstring"""
233 return 2
234 self.assertEqual(Foo.spam.__doc__, "a new docstring")
235 class FooBase(object):
236 @PropertySub
237 def spam(self):
238 """a docstring"""
239 return 1
240 class Foo2(FooBase):
241 @FooBase.spam.getter
242 def spam(self):
243 """a new docstring"""
244 return 2
245 self.assertEqual(Foo.spam.__doc__, "a new docstring")
246
247
248
Christian Heimes0449f632007-12-15 01:27:15 +0000249if __name__ == '__main__':
Zachary Ware38c707e2015-04-13 15:00:43 -0500250 unittest.main()