test_decorators.py 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. # Test case for property
  2. # more tests are in test_descr
  3. import sys
  4. import unittest
  5. class PropertyBase(Exception):
  6. pass
  7. class PropertyGet(PropertyBase):
  8. pass
  9. class PropertySet(PropertyBase):
  10. pass
  11. class PropertyDel(PropertyBase):
  12. pass
  13. class BaseClass(object):
  14. def __init__(self):
  15. self._spam = 5
  16. @property
  17. def spam(self):
  18. """BaseClass.getter"""
  19. return self._spam
  20. @spam.setter
  21. def spam(self, value):
  22. self._spam = value
  23. @spam.deleter
  24. def spam(self):
  25. pass
  26. #del self._spam
  27. class SubClass(BaseClass):
  28. @BaseClass.spam.getter
  29. def spam(self):
  30. """SubClass.getter"""
  31. raise PropertyGet(self._spam)
  32. @spam.setter
  33. def spam(self, value):
  34. raise PropertySet(self._spam)
  35. @spam.deleter
  36. def spam(self):
  37. raise PropertyDel(self._spam)
  38. class PropertyDocBase(object):
  39. _spam = 1
  40. def _get_spam(self):
  41. return self._spam
  42. spam = property(_get_spam, doc="spam spam spam")
  43. class PropertyDocSub(PropertyDocBase):
  44. @PropertyDocBase.spam.getter
  45. def spam(self):
  46. """The decorator does not use this doc string"""
  47. return self._spam
  48. class PropertySubNewGetter(BaseClass):
  49. @BaseClass.spam.getter
  50. def spam(self):
  51. """new docstring"""
  52. return 5
  53. class PropertyNewGetter(object):
  54. @property
  55. def spam(self):
  56. """original docstring"""
  57. return 1
  58. @spam.getter
  59. def spam(self):
  60. """new docstring"""
  61. return 8
  62. class PropertyTests(unittest.TestCase):
  63. def test_property_decorator_baseclass(self):
  64. # see #1620
  65. base = BaseClass()
  66. self.assertEqual(base.spam, 5)
  67. self.assertEqual(base._spam, 5)
  68. base.spam = 10
  69. self.assertEqual(base.spam, 10)
  70. self.assertEqual(base._spam, 10)
  71. # delattr(base, "spam")
  72. # self.assertTrue(not hasattr(base, "spam"))
  73. # self.assertTrue(not hasattr(base, "_spam"))
  74. base.spam = 20
  75. self.assertEqual(base.spam, 20)
  76. self.assertEqual(base._spam, 20)
  77. def test_property_decorator_subclass(self):
  78. # see #1620
  79. sub = SubClass()
  80. self.assertRaises(PropertyGet, getattr, sub, "spam")
  81. self.assertRaises(PropertySet, setattr, sub, "spam", None)
  82. # self.assertRaises(PropertyDel, delattr, sub, "spam")
  83. # def test_property_decorator_subclass_doc(self):
  84. # sub = SubClass()
  85. # self.assertEqual(sub.__class__.spam.__doc__, "SubClass.getter")
  86. #
  87. # def test_property_decorator_baseclass_doc(self):
  88. # base = BaseClass()
  89. # self.assertEqual(base.__class__.spam.__doc__, "BaseClass.getter")
  90. # def test_property_decorator_doc(self):
  91. # base = PropertyDocBase()
  92. # sub = PropertyDocSub()
  93. # self.assertEqual(base.__class__.spam.__doc__, "spam spam spam")
  94. # self.assertEqual(sub.__class__.spam.__doc__, "spam spam spam")
  95. # def test_property_getter_doc_override(self):
  96. # newgettersub = PropertySubNewGetter()
  97. # self.assertEqual(newgettersub.spam, 5)
  98. # self.assertEqual(newgettersub.__class__.spam.__doc__, "new docstring")
  99. # newgetter = PropertyNewGetter()
  100. # self.assertEqual(newgetter.spam, 8)
  101. # self.assertEqual(newgetter.__class__.spam.__doc__, "new docstring")
  102. # def test_property___isabstractmethod__descriptor(self):
  103. # for val in (True, False, [], [1], '', '1'):
  104. # class C(object):
  105. # def foo(self):
  106. # pass
  107. # foo.__isabstractmethod__ = val
  108. # foo = property(foo)
  109. # self.assertIs(C.foo.__isabstractmethod__, bool(val))
  110. #
  111. # # check that the property's __isabstractmethod__ descriptor does the
  112. # # right thing when presented with a value that fails truth testing:
  113. # class NotBool(object):
  114. # def __bool__(self):
  115. # raise ValueError()
  116. # __len__ = __bool__
  117. # with self.assertRaises(ValueError):
  118. # class C(object):
  119. # def foo(self):
  120. # pass
  121. # foo.__isabstractmethod__ = NotBool()
  122. # foo = property(foo)
  123. # C.foo.__isabstractmethod__
  124. def test_property_builtin_doc_writable(self):
  125. p = property(doc='basic')
  126. self.assertEqual(p.__doc__, 'basic')
  127. p.__doc__ = 'extended'
  128. self.assertEqual(p.__doc__, 'extended')
  129. # def test_property_decorator_doc_writable(self):
  130. # class PropertyWritableDoc(object):
  131. #
  132. # @property
  133. # def spam(self):
  134. # """Eggs"""
  135. # return "eggs"
  136. #
  137. # sub = PropertyWritableDoc()
  138. # self.assertEqual(sub.__class__.spam.__doc__, 'Eggs')
  139. # sub.__class__.spam.__doc__ = 'Spam'
  140. # self.assertEqual(sub.__class__.spam.__doc__, 'Spam')
  141. # Issue 5890: subclasses of property do not preserve method __doc__ strings
  142. class PropertySub(property):
  143. """This is a subclass of property"""
  144. class PropertySubSlots(property):
  145. """This is a subclass of property that defines __slots__"""
  146. __slots__ = ()
  147. class Foo(object):
  148. def __init__(self): self._spam = 1
  149. @PropertySub
  150. def spam(self):
  151. """spam wrapped in property subclass"""
  152. return self._spam
  153. @spam.setter
  154. def spam(self, value):
  155. """this docstring is ignored"""
  156. self._spam = value
  157. class FooSub(Foo):
  158. @Foo.spam.setter
  159. def spam(self, value):
  160. """another ignored docstring"""
  161. self._spam = 'eggs'
  162. class PropertySubclassTests(unittest.TestCase):
  163. # def test_slots_docstring_copy_exception(self):
  164. # try:
  165. # class Foo(object):
  166. # @PropertySubSlots
  167. # def spam(self):
  168. # """Trying to copy this docstring will raise an exception"""
  169. # return 1
  170. # except AttributeError:
  171. # pass
  172. # else:
  173. # raise Exception("AttributeError not raised")
  174. #
  175. # def test_docstring_copy(self):
  176. # class Foo(object):
  177. # @PropertySub
  178. # def spam(self):
  179. # """spam wrapped in property subclass"""
  180. # return 1
  181. # self.assertEqual(
  182. # Foo.spam.__doc__,
  183. # "spam wrapped in property subclass")
  184. def test_property_setter_copies_getter_docstring(self):
  185. foo = Foo()
  186. self.assertEqual(foo.spam, 1)
  187. foo.spam = 2
  188. self.assertEqual(foo.spam, 2)
  189. # self.assertEqual(
  190. # Foo.spam.__doc__,
  191. # "spam wrapped in property subclass")
  192. foosub = FooSub()
  193. self.assertEqual(foosub.spam, 1)
  194. foosub.spam = 7
  195. self.assertEqual(foosub.spam, 'eggs')
  196. # self.assertEqual(
  197. # FooSub.spam.__doc__,
  198. # "spam wrapped in property subclass")
  199. # def test_property_new_getter_new_docstring(self):
  200. #
  201. # class Foo(object):
  202. # @PropertySub
  203. # def spam(self):
  204. # """a docstring"""
  205. # return 1
  206. # @spam.getter
  207. # def spam(self):
  208. # """a new docstring"""
  209. # return 2
  210. # self.assertEqual(Foo.spam.__doc__, "a new docstring")
  211. # class FooBase(object):
  212. # @PropertySub
  213. # def spam(self):
  214. # """a docstring"""
  215. # return 1
  216. # class Foo2(FooBase):
  217. # @FooBase.spam.getter
  218. # def spam(self):
  219. # """a new docstring"""
  220. # return 2
  221. # self.assertEqual(Foo.spam.__doc__, "a new docstring")
  222. class TestDecorators(unittest.TestCase):
  223. def test_single(self):
  224. class C(object):
  225. @staticmethod
  226. def foo(): return 42
  227. self.assertEqual(C.foo(), 42)
  228. self.assertEqual(C().foo(), 42)
  229. def test_staticmethods(self):
  230. # Testing static methods...
  231. class C(object):
  232. def foo(*a): return a
  233. goo = staticmethod(foo)
  234. c = C()
  235. self.assertEqual(C.goo(1), (1,))
  236. self.assertEqual(c.goo(1), (1,))
  237. self.assertEqual(c.foo(1), (c, 1,))
  238. class D(C):
  239. pass
  240. d = D()
  241. self.assertEqual(D.goo(1), (1,))
  242. self.assertEqual(d.goo(1), (1,))
  243. self.assertEqual(d.foo(1), (d, 1))
  244. self.assertEqual(D.foo(d, 1), (d, 1))
  245. def test_classmethods(self):
  246. # Testing class methods...
  247. class C(object):
  248. def foo(*a): return a
  249. goo = classmethod(foo)
  250. c = C()
  251. self.assertEqual(C.goo(1), (C, 1))
  252. self.assertEqual(c.goo(1), (C, 1))
  253. self.assertEqual(c.foo(1), (c, 1))
  254. class D(C):
  255. pass
  256. d = D()
  257. self.assertEqual(D.goo(1), (D, 1))
  258. self.assertEqual(d.goo(1), (D, 1))
  259. self.assertEqual(d.foo(1), (d, 1))
  260. self.assertEqual(D.foo(d, 1), (d, 1))
  261. # Test for a specific crash (SF bug 528132)
  262. def f(cls, arg): return (cls, arg)
  263. ff = classmethod(f)
  264. self.assertEqual(ff.__get__(0, int)(42), (int, 42))
  265. self.assertEqual(ff.__get__(0)(42), (int, 42))
  266. if __name__ == '__main__':
  267. unittest.main()