14adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# Test case for property 24adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# more tests are in test_descr 34adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 44adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport sys 54adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport unittest 64adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaofrom test.test_support import run_unittest 74adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 84adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass PropertyBase(Exception): 94adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao pass 104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass PropertyGet(PropertyBase): 124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao pass 134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass PropertySet(PropertyBase): 154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao pass 164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass PropertyDel(PropertyBase): 184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao pass 194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass BaseClass(object): 214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __init__(self): 224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._spam = 5 234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao @property 254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def spam(self): 264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """BaseClass.getter""" 274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return self._spam 284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao @spam.setter 304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def spam(self, value): 314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._spam = value 324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao @spam.deleter 344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def spam(self): 354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao del self._spam 364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass SubClass(BaseClass): 384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao @BaseClass.spam.getter 404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def spam(self): 414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """SubClass.getter""" 424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise PropertyGet(self._spam) 434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao @spam.setter 454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def spam(self, value): 464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise PropertySet(self._spam) 474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao @spam.deleter 494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def spam(self): 504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise PropertyDel(self._spam) 514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass PropertyDocBase(object): 534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao _spam = 1 544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def _get_spam(self): 554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return self._spam 564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao spam = property(_get_spam, doc="spam spam spam") 574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass PropertyDocSub(PropertyDocBase): 594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao @PropertyDocBase.spam.getter 604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def spam(self): 614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """The decorator does not use this doc string""" 624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return self._spam 634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass PropertySubNewGetter(BaseClass): 654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao @BaseClass.spam.getter 664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def spam(self): 674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """new docstring""" 684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return 5 694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass PropertyNewGetter(object): 714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao @property 724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def spam(self): 734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """original docstring""" 744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return 1 754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao @spam.getter 764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def spam(self): 774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """new docstring""" 784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return 8 794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass PropertyTests(unittest.TestCase): 814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def test_property_decorator_baseclass(self): 824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # see #1620 834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao base = BaseClass() 844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual(base.spam, 5) 854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual(base._spam, 5) 864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao base.spam = 10 874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual(base.spam, 10) 884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual(base._spam, 10) 894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao delattr(base, "spam") 904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertTrue(not hasattr(base, "spam")) 914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertTrue(not hasattr(base, "_spam")) 924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao base.spam = 20 934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual(base.spam, 20) 944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual(base._spam, 20) 954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def test_property_decorator_subclass(self): 974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # see #1620 984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao sub = SubClass() 994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertRaises(PropertyGet, getattr, sub, "spam") 1004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertRaises(PropertySet, setattr, sub, "spam", None) 1014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertRaises(PropertyDel, delattr, sub, "spam") 1024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao @unittest.skipIf(sys.flags.optimize >= 2, 1044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao "Docstrings are omitted with -O2 and above") 1054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def test_property_decorator_subclass_doc(self): 1064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao sub = SubClass() 1074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual(sub.__class__.spam.__doc__, "SubClass.getter") 1084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao @unittest.skipIf(sys.flags.optimize >= 2, 1104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao "Docstrings are omitted with -O2 and above") 1114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def test_property_decorator_baseclass_doc(self): 1124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao base = BaseClass() 1134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual(base.__class__.spam.__doc__, "BaseClass.getter") 1144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def test_property_decorator_doc(self): 1164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao base = PropertyDocBase() 1174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao sub = PropertyDocSub() 1184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual(base.__class__.spam.__doc__, "spam spam spam") 1194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual(sub.__class__.spam.__doc__, "spam spam spam") 1204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao @unittest.skipIf(sys.flags.optimize >= 2, 1224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao "Docstrings are omitted with -O2 and above") 1234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def test_property_getter_doc_override(self): 1244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao newgettersub = PropertySubNewGetter() 1254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual(newgettersub.spam, 5) 1264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual(newgettersub.__class__.spam.__doc__, "new docstring") 1274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao newgetter = PropertyNewGetter() 1284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual(newgetter.spam, 8) 1294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual(newgetter.__class__.spam.__doc__, "new docstring") 1304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# Issue 5890: subclasses of property do not preserve method __doc__ strings 1334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass PropertySub(property): 1344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """This is a subclass of property""" 1354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass PropertySubSlots(property): 1374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """This is a subclass of property that defines __slots__""" 1384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao __slots__ = () 1394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass PropertySubclassTests(unittest.TestCase): 1414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def test_slots_docstring_copy_exception(self): 1434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao try: 1444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao class Foo(object): 1454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao @PropertySubSlots 1464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def spam(self): 1474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """Trying to copy this docstring will raise an exception""" 1484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return 1 1494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao except AttributeError: 1504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao pass 1514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao else: 1524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise Exception("AttributeError not raised") 1534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao @unittest.skipIf(sys.flags.optimize >= 2, 1554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao "Docstrings are omitted with -O2 and above") 1564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def test_docstring_copy(self): 1574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao class Foo(object): 1584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao @PropertySub 1594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def spam(self): 1604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """spam wrapped in property subclass""" 1614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return 1 1624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual( 1634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao Foo.spam.__doc__, 1644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao "spam wrapped in property subclass") 1654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao @unittest.skipIf(sys.flags.optimize >= 2, 1674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao "Docstrings are omitted with -O2 and above") 1684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def test_property_setter_copies_getter_docstring(self): 1694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao class Foo(object): 1704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __init__(self): self._spam = 1 1714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao @PropertySub 1724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def spam(self): 1734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """spam wrapped in property subclass""" 1744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return self._spam 1754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao @spam.setter 1764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def spam(self, value): 1774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """this docstring is ignored""" 1784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._spam = value 1794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao foo = Foo() 1804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual(foo.spam, 1) 1814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao foo.spam = 2 1824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual(foo.spam, 2) 1834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual( 1844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao Foo.spam.__doc__, 1854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao "spam wrapped in property subclass") 1864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao class FooSub(Foo): 1874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao @Foo.spam.setter 1884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def spam(self, value): 1894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """another ignored docstring""" 1904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._spam = 'eggs' 1914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao foosub = FooSub() 1924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual(foosub.spam, 1) 1934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao foosub.spam = 7 1944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual(foosub.spam, 'eggs') 1954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual( 1964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao FooSub.spam.__doc__, 1974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao "spam wrapped in property subclass") 1984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao @unittest.skipIf(sys.flags.optimize >= 2, 2004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao "Docstrings are omitted with -O2 and above") 2014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def test_property_new_getter_new_docstring(self): 2024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao class Foo(object): 2044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao @PropertySub 2054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def spam(self): 2064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """a docstring""" 2074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return 1 2084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao @spam.getter 2094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def spam(self): 2104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """a new docstring""" 2114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return 2 2124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual(Foo.spam.__doc__, "a new docstring") 2134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao class FooBase(object): 2144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao @PropertySub 2154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def spam(self): 2164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """a docstring""" 2174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return 1 2184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao class Foo2(FooBase): 2194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao @FooBase.spam.getter 2204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def spam(self): 2214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """a new docstring""" 2224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return 2 2234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.assertEqual(Foo.spam.__doc__, "a new docstring") 2244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef test_main(): 2284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao run_unittest(PropertyTests, PropertySubclassTests) 2294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoif __name__ == '__main__': 2314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao test_main() 232