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 
      7 class PropertyBase(Exception):
      8     pass
      9 
     10 class PropertyGet(PropertyBase):
     11     pass
     12 
     13 class PropertySet(PropertyBase):
     14     pass
     15 
     16 class PropertyDel(PropertyBase):
     17     pass
     18 
     19 class 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 
     36 class 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 
     51 class PropertyDocBase(object):
     52     _spam = 1
     53     def _get_spam(self):
     54         return self._spam
     55     spam = property(_get_spam, doc="spam spam spam")
     56 
     57 class PropertyDocSub(PropertyDocBase):
     58     @PropertyDocBase.spam.getter
     59     def spam(self):
     60         """The decorator does not use this doc string"""
     61         return self._spam
     62 
     63 class PropertySubNewGetter(BaseClass):
     64     @BaseClass.spam.getter
     65     def spam(self):
     66         """new docstring"""
     67         return 5
     68 
     69 class 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 
     79 class 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")
     89         self.assertTrue(not hasattr(base, "spam"))
     90         self.assertTrue(not hasattr(base, "_spam"))
     91         base.spam = 20
     92         self.assertEqual(base.spam, 20)
     93         self.assertEqual(base._spam, 20)
     94 
     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")
    101 
    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()
    106         self.assertEqual(sub.__class__.spam.__doc__, "SubClass.getter")
    107 
    108     @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 
    114     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 
    120     @unittest.skipIf(sys.flags.optimize >= 2,
    121                      "Docstrings are omitted with -O2 and above")
    122     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 
    130     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):
    142             def __bool__(self):
    143                 raise ValueError()
    144             __len__ = __bool__
    145         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 
    153     @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):
    164         class PropertyWritableDoc(object):
    165 
    166             @property
    167             def spam(self):
    168                 """Eggs"""
    169                 return "eggs"
    170 
    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')
    175 
    176 # Issue 5890: subclasses of property do not preserve method __doc__ strings
    177 class PropertySub(property):
    178     """This is a subclass of property"""
    179 
    180 class PropertySubSlots(property):
    181     """This is a subclass of property that defines __slots__"""
    182     __slots__ = ()
    183 
    184 class PropertySubclassTests(unittest.TestCase):
    185 
    186     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 
    198     @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 
    210     @unittest.skipIf(sys.flags.optimize >= 2,
    211                      "Docstrings are omitted with -O2 and above")
    212     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 
    243     @unittest.skipIf(sys.flags.optimize >= 2,
    244                      "Docstrings are omitted with -O2 and above")
    245     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 
    271 if __name__ == '__main__':
    272     unittest.main()
    273