Home | History | Annotate | Download | only in test
      1 # Test case for property
      2 # more tests are in test_descr
      3 
      4 import sys
      5 import unittest
      6 from test.test_support import run_unittest
      7 
      8 class PropertyBase(Exception):
      9     pass
     10 
     11 class PropertyGet(PropertyBase):
     12     pass
     13 
     14 class PropertySet(PropertyBase):
     15     pass
     16 
     17 class PropertyDel(PropertyBase):
     18     pass
     19 
     20 class 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 
     37 class 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 
     52 class PropertyDocBase(object):
     53     _spam = 1
     54     def _get_spam(self):
     55         return self._spam
     56     spam = property(_get_spam, doc="spam spam spam")
     57 
     58 class PropertyDocSub(PropertyDocBase):
     59     @PropertyDocBase.spam.getter
     60     def spam(self):
     61         """The decorator does not use this doc string"""
     62         return self._spam
     63 
     64 class PropertySubNewGetter(BaseClass):
     65     @BaseClass.spam.getter
     66     def spam(self):
     67         """new docstring"""
     68         return 5
     69 
     70 class 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 
     80 class 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
    133 class PropertySub(property):
    134     """This is a subclass of property"""
    135 
    136 class PropertySubSlots(property):
    137     """This is a subclass of property that defines __slots__"""
    138     __slots__ = ()
    139 
    140 class 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 
    227 def test_main():
    228     run_unittest(PropertyTests, PropertySubclassTests)
    229 
    230 if __name__ == '__main__':
    231     test_main()
    232