• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Test case for property
2# more tests are in test_descr
3
4import sys
5import unittest
6from test.test_support import run_unittest
7
8class PropertyBase(Exception):
9    pass
10
11class PropertyGet(PropertyBase):
12    pass
13
14class PropertySet(PropertyBase):
15    pass
16
17class PropertyDel(PropertyBase):
18    pass
19
20class BaseClass(object):
21    def __init__(self):
22        self._spam = 5
23
24    @property
25    def spam(self):
26        """BaseClass.getter"""
27        return self._spam
28
29    @spam.setter
30    def spam(self, value):
31        self._spam = value
32
33    @spam.deleter
34    def spam(self):
35        del self._spam
36
37class SubClass(BaseClass):
38
39    @BaseClass.spam.getter
40    def spam(self):
41        """SubClass.getter"""
42        raise PropertyGet(self._spam)
43
44    @spam.setter
45    def spam(self, value):
46        raise PropertySet(self._spam)
47
48    @spam.deleter
49    def spam(self):
50        raise PropertyDel(self._spam)
51
52class PropertyDocBase(object):
53    _spam = 1
54    def _get_spam(self):
55        return self._spam
56    spam = property(_get_spam, doc="spam spam spam")
57
58class PropertyDocSub(PropertyDocBase):
59    @PropertyDocBase.spam.getter
60    def spam(self):
61        """The decorator does not use this doc string"""
62        return self._spam
63
64class PropertySubNewGetter(BaseClass):
65    @BaseClass.spam.getter
66    def spam(self):
67        """new docstring"""
68        return 5
69
70class PropertyNewGetter(object):
71    @property
72    def spam(self):
73        """original docstring"""
74        return 1
75    @spam.getter
76    def spam(self):
77        """new docstring"""
78        return 8
79
80class PropertyTests(unittest.TestCase):
81    def test_property_decorator_baseclass(self):
82        # see #1620
83        base = BaseClass()
84        self.assertEqual(base.spam, 5)
85        self.assertEqual(base._spam, 5)
86        base.spam = 10
87        self.assertEqual(base.spam, 10)
88        self.assertEqual(base._spam, 10)
89        delattr(base, "spam")
90        self.assertTrue(not hasattr(base, "spam"))
91        self.assertTrue(not hasattr(base, "_spam"))
92        base.spam = 20
93        self.assertEqual(base.spam, 20)
94        self.assertEqual(base._spam, 20)
95
96    def test_property_decorator_subclass(self):
97        # see #1620
98        sub = SubClass()
99        self.assertRaises(PropertyGet, getattr, sub, "spam")
100        self.assertRaises(PropertySet, setattr, sub, "spam", None)
101        self.assertRaises(PropertyDel, delattr, sub, "spam")
102
103    @unittest.skipIf(sys.flags.optimize >= 2,
104                     "Docstrings are omitted with -O2 and above")
105    def test_property_decorator_subclass_doc(self):
106        sub = SubClass()
107        self.assertEqual(sub.__class__.spam.__doc__, "SubClass.getter")
108
109    @unittest.skipIf(sys.flags.optimize >= 2,
110                     "Docstrings are omitted with -O2 and above")
111    def test_property_decorator_baseclass_doc(self):
112        base = BaseClass()
113        self.assertEqual(base.__class__.spam.__doc__, "BaseClass.getter")
114
115    def test_property_decorator_doc(self):
116        base = PropertyDocBase()
117        sub = PropertyDocSub()
118        self.assertEqual(base.__class__.spam.__doc__, "spam spam spam")
119        self.assertEqual(sub.__class__.spam.__doc__, "spam spam spam")
120
121    @unittest.skipIf(sys.flags.optimize >= 2,
122                     "Docstrings are omitted with -O2 and above")
123    def test_property_getter_doc_override(self):
124        newgettersub = PropertySubNewGetter()
125        self.assertEqual(newgettersub.spam, 5)
126        self.assertEqual(newgettersub.__class__.spam.__doc__, "new docstring")
127        newgetter = PropertyNewGetter()
128        self.assertEqual(newgetter.spam, 8)
129        self.assertEqual(newgetter.__class__.spam.__doc__, "new docstring")
130
131
132# Issue 5890: subclasses of property do not preserve method __doc__ strings
133class PropertySub(property):
134    """This is a subclass of property"""
135
136class PropertySubSlots(property):
137    """This is a subclass of property that defines __slots__"""
138    __slots__ = ()
139
140class PropertySubclassTests(unittest.TestCase):
141
142    def test_slots_docstring_copy_exception(self):
143        try:
144            class Foo(object):
145                @PropertySubSlots
146                def spam(self):
147                    """Trying to copy this docstring will raise an exception"""
148                    return 1
149        except AttributeError:
150            pass
151        else:
152            raise Exception("AttributeError not raised")
153
154    @unittest.skipIf(sys.flags.optimize >= 2,
155                     "Docstrings are omitted with -O2 and above")
156    def test_docstring_copy(self):
157        class Foo(object):
158            @PropertySub
159            def spam(self):
160                """spam wrapped in property subclass"""
161                return 1
162        self.assertEqual(
163            Foo.spam.__doc__,
164            "spam wrapped in property subclass")
165
166    @unittest.skipIf(sys.flags.optimize >= 2,
167                     "Docstrings are omitted with -O2 and above")
168    def test_property_setter_copies_getter_docstring(self):
169        class Foo(object):
170            def __init__(self): self._spam = 1
171            @PropertySub
172            def spam(self):
173                """spam wrapped in property subclass"""
174                return self._spam
175            @spam.setter
176            def spam(self, value):
177                """this docstring is ignored"""
178                self._spam = value
179        foo = Foo()
180        self.assertEqual(foo.spam, 1)
181        foo.spam = 2
182        self.assertEqual(foo.spam, 2)
183        self.assertEqual(
184            Foo.spam.__doc__,
185            "spam wrapped in property subclass")
186        class FooSub(Foo):
187            @Foo.spam.setter
188            def spam(self, value):
189                """another ignored docstring"""
190                self._spam = 'eggs'
191        foosub = FooSub()
192        self.assertEqual(foosub.spam, 1)
193        foosub.spam = 7
194        self.assertEqual(foosub.spam, 'eggs')
195        self.assertEqual(
196            FooSub.spam.__doc__,
197            "spam wrapped in property subclass")
198
199    @unittest.skipIf(sys.flags.optimize >= 2,
200                     "Docstrings are omitted with -O2 and above")
201    def test_property_new_getter_new_docstring(self):
202
203        class Foo(object):
204            @PropertySub
205            def spam(self):
206                """a docstring"""
207                return 1
208            @spam.getter
209            def spam(self):
210                """a new docstring"""
211                return 2
212        self.assertEqual(Foo.spam.__doc__, "a new docstring")
213        class FooBase(object):
214            @PropertySub
215            def spam(self):
216                """a docstring"""
217                return 1
218        class Foo2(FooBase):
219            @FooBase.spam.getter
220            def spam(self):
221                """a new docstring"""
222                return 2
223        self.assertEqual(Foo.spam.__doc__, "a new docstring")
224
225
226
227def test_main():
228    run_unittest(PropertyTests, PropertySubclassTests)
229
230if __name__ == '__main__':
231    test_main()
232