test_funcattrs.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. import textwrap
  2. import types
  3. import unittest
  4. def global_function():
  5. def inner_function():
  6. class LocalClass:
  7. pass
  8. global inner_global_function
  9. def inner_global_function():
  10. def inner_function2():
  11. pass
  12. return inner_function2
  13. return LocalClass
  14. return lambda: inner_function
  15. class FuncAttrsTest(unittest.TestCase):
  16. def setUp(self):
  17. class F:
  18. def a(self):
  19. pass
  20. def b():
  21. return 3
  22. self.fi = F()
  23. self.F = F
  24. self.b = b
  25. def cannot_set_attr(self, obj, name, value, exceptions):
  26. try:
  27. setattr(obj, name, value)
  28. except exceptions:
  29. pass
  30. else:
  31. self.fail("shouldn't be able to set %s to %r" % (name, value))
  32. try:
  33. delattr(obj, name)
  34. except exceptions:
  35. pass
  36. else:
  37. self.fail("shouldn't be able to del %s" % name)
  38. class FunctionPropertiesTest(FuncAttrsTest):
  39. # Include the external setUp method that is common to all tests
  40. def test_module(self):
  41. self.assertEqual(self.b.__module__, __name__)
  42. def test_dir_includes_correct_attrs(self):
  43. self.b.known_attr = 7
  44. self.assertIn('known_attr', dir(self.b),
  45. "set attributes not in dir listing of method")
  46. # Test on underlying function object of method
  47. self.F.a.known_attr = 7
  48. self.assertIn('known_attr', dir(self.fi.a), "set attribute on function "
  49. "implementations, should show up in next dir")
  50. def test_duplicate_function_equality(self):
  51. # Body of `duplicate' is the exact same as self.b
  52. def duplicate():
  53. 'my docstring'
  54. return 3
  55. self.assertNotEqual(self.b, duplicate)
  56. def test_copying___code__(self):
  57. def test(): pass
  58. self.assertEqual(test(), None)
  59. test.__code__ = self.b.__code__
  60. self.assertEqual(test(), 3) # self.b always returns 3, arbitrarily
  61. def test___globals__(self):
  62. self.assertIs(self.b.__globals__, globals())
  63. self.cannot_set_attr(self.b, '__globals__', 2,
  64. (AttributeError, TypeError))
  65. def test___builtins__(self):
  66. self.assertIs(self.b.__builtins__, __builtins__)
  67. self.cannot_set_attr(self.b, '__builtins__', 2,
  68. (AttributeError, TypeError))
  69. # bpo-42990: If globals is specified and has no "__builtins__" key,
  70. # a function inherits the current builtins namespace.
  71. def func(s): return len(s)
  72. ns = {}
  73. func2 = type(func)(func.__code__, ns)
  74. self.assertIs(func2.__globals__, ns)
  75. self.assertIs(func2.__builtins__, __builtins__)
  76. # Make sure that the function actually works.
  77. self.assertEqual(func2("abc"), 3)
  78. self.assertEqual(ns, {})
  79. # Define functions using exec() with different builtins,
  80. # and test inheritance when globals has no "__builtins__" key
  81. code = textwrap.dedent("""
  82. def func3(s): pass
  83. func4 = type(func3)(func3.__code__, {})
  84. """)
  85. safe_builtins = {'None': None}
  86. ns = {'type': type, '__builtins__': safe_builtins}
  87. exec(code, ns)
  88. self.assertIs(ns['func3'].__builtins__, safe_builtins)
  89. self.assertIs(ns['func4'].__builtins__, safe_builtins)
  90. self.assertIs(ns['func3'].__globals__['__builtins__'], safe_builtins)
  91. self.assertNotIn('__builtins__', ns['func4'].__globals__)
  92. def test___closure__(self):
  93. a = 12
  94. def f(): print(a)
  95. c = f.__closure__
  96. self.assertIsInstance(c, tuple)
  97. self.assertEqual(len(c), 1)
  98. # don't have a type object handy
  99. self.assertEqual(c[0].__class__.__name__, "cell")
  100. self.cannot_set_attr(f, "__closure__", c, AttributeError)
  101. def test_cell_new(self):
  102. cell_obj = types.CellType(1)
  103. self.assertEqual(cell_obj.cell_contents, 1)
  104. cell_obj = types.CellType()
  105. msg = "shouldn't be able to read an empty cell"
  106. with self.assertRaises(ValueError, msg=msg):
  107. cell_obj.cell_contents
  108. def test_empty_cell(self):
  109. def f(): print(a)
  110. try:
  111. f.__closure__[0].cell_contents
  112. except ValueError:
  113. pass
  114. else:
  115. self.fail("shouldn't be able to read an empty cell")
  116. a = 12
  117. def test_set_cell(self):
  118. a = 12
  119. def f(): return a
  120. c = f.__closure__
  121. c[0].cell_contents = 9
  122. self.assertEqual(c[0].cell_contents, 9)
  123. self.assertEqual(f(), 9)
  124. self.assertEqual(a, 9)
  125. del c[0].cell_contents
  126. try:
  127. c[0].cell_contents
  128. except ValueError:
  129. pass
  130. else:
  131. self.fail("shouldn't be able to read an empty cell")
  132. with self.assertRaises(NameError):
  133. f()
  134. with self.assertRaises(UnboundLocalError):
  135. print(a)
  136. def test___name__(self):
  137. self.assertEqual(self.b.__name__, 'b')
  138. self.b.__name__ = 'c'
  139. self.assertEqual(self.b.__name__, 'c')
  140. self.b.__name__ = 'd'
  141. self.assertEqual(self.b.__name__, 'd')
  142. # __name__ and __name__ must be a string
  143. self.cannot_set_attr(self.b, '__name__', 7, TypeError)
  144. # __name__ must be available when in restricted mode. Exec will raise
  145. # AttributeError if __name__ is not available on f.
  146. s = """def f(): pass\nf.__name__"""
  147. exec(s, {'__builtins__': {}})
  148. # Test on methods, too
  149. self.assertEqual(self.fi.a.__name__, 'a')
  150. self.cannot_set_attr(self.fi.a, "__name__", 'a', AttributeError)
  151. def test___qualname__(self):
  152. # PEP 3155
  153. self.assertEqual(self.b.__qualname__, 'FuncAttrsTest.setUp.<locals>.b')
  154. self.assertEqual(FuncAttrsTest.setUp.__qualname__, 'FuncAttrsTest.setUp')
  155. self.assertEqual(global_function.__qualname__, 'global_function')
  156. self.assertEqual(global_function().__qualname__,
  157. 'global_function.<locals>.<lambda>')
  158. self.assertEqual(global_function()().__qualname__,
  159. 'global_function.<locals>.inner_function')
  160. self.assertEqual(global_function()()().__qualname__,
  161. 'global_function.<locals>.inner_function.<locals>.LocalClass')
  162. self.assertEqual(inner_global_function.__qualname__, 'inner_global_function')
  163. self.assertEqual(inner_global_function().__qualname__, 'inner_global_function.<locals>.inner_function2')
  164. self.b.__qualname__ = 'c'
  165. self.assertEqual(self.b.__qualname__, 'c')
  166. self.b.__qualname__ = 'd'
  167. self.assertEqual(self.b.__qualname__, 'd')
  168. # __qualname__ must be a string
  169. self.cannot_set_attr(self.b, '__qualname__', 7, TypeError)
  170. def test___code__(self):
  171. num_one, num_two = 7, 8
  172. def a(): pass
  173. def b(): return 12
  174. def c(): return num_one
  175. def d(): return num_two
  176. def e(): return num_one, num_two
  177. for func in [a, b, c, d, e]:
  178. self.assertEqual(type(func.__code__), types.CodeType)
  179. self.assertEqual(c(), 7)
  180. self.assertEqual(d(), 8)
  181. d.__code__ = c.__code__
  182. self.assertEqual(c.__code__, d.__code__)
  183. self.assertEqual(c(), 7)
  184. # self.assertEqual(d(), 7)
  185. try:
  186. b.__code__ = c.__code__
  187. except ValueError:
  188. pass
  189. else:
  190. self.fail("__code__ with different numbers of free vars should "
  191. "not be possible")
  192. try:
  193. e.__code__ = d.__code__
  194. except ValueError:
  195. pass
  196. else:
  197. self.fail("__code__ with different numbers of free vars should "
  198. "not be possible")
  199. def test_blank_func_defaults(self):
  200. self.assertEqual(self.b.__defaults__, None)
  201. del self.b.__defaults__
  202. self.assertEqual(self.b.__defaults__, None)
  203. def test_func_default_args(self):
  204. def first_func(a, b):
  205. return a+b
  206. def second_func(a=1, b=2):
  207. return a+b
  208. self.assertEqual(first_func.__defaults__, None)
  209. self.assertEqual(second_func.__defaults__, (1, 2))
  210. first_func.__defaults__ = (1, 2)
  211. self.assertEqual(first_func.__defaults__, (1, 2))
  212. self.assertEqual(first_func(), 3)
  213. self.assertEqual(first_func(3), 5)
  214. self.assertEqual(first_func(3, 5), 8)
  215. del second_func.__defaults__
  216. self.assertEqual(second_func.__defaults__, None)
  217. try:
  218. second_func()
  219. except TypeError:
  220. pass
  221. else:
  222. self.fail("__defaults__ does not update; deleting it does not "
  223. "remove requirement")
  224. class InstancemethodAttrTest(FuncAttrsTest):
  225. def test___class__(self):
  226. self.assertEqual(self.fi.a.__self__.__class__, self.F)
  227. self.cannot_set_attr(self.fi.a, "__class__", self.F, TypeError)
  228. def test___func__(self):
  229. self.assertEqual(self.fi.a.__func__, self.F.a)
  230. self.cannot_set_attr(self.fi.a, "__func__", self.F.a, AttributeError)
  231. def test___self__(self):
  232. self.assertEqual(self.fi.a.__self__, self.fi)
  233. self.cannot_set_attr(self.fi.a, "__self__", self.fi, AttributeError)
  234. def test___func___non_method(self):
  235. # Behavior should be the same when a method is added via an attr
  236. # assignment
  237. self.fi.id = types.MethodType(id, self.fi)
  238. self.assertEqual(self.fi.id(), id(self.fi))
  239. # Test usage
  240. try:
  241. self.fi.id.unknown_attr
  242. except AttributeError:
  243. pass
  244. else:
  245. self.fail("using unknown attributes should raise AttributeError")
  246. # Test assignment and deletion
  247. self.cannot_set_attr(self.fi.id, 'unknown_attr', 2, AttributeError)
  248. class ArbitraryFunctionAttrTest(FuncAttrsTest):
  249. def test_set_attr(self):
  250. self.b.known_attr = 7
  251. self.assertEqual(self.b.known_attr, 7)
  252. try:
  253. self.fi.a.known_attr = 7
  254. except AttributeError:
  255. pass
  256. else:
  257. self.fail("setting attributes on methods should raise error")
  258. def test_delete_unknown_attr(self):
  259. try:
  260. del self.b.unknown_attr
  261. except AttributeError:
  262. pass
  263. else:
  264. self.fail("deleting unknown attribute should raise TypeError")
  265. def test_unset_attr(self):
  266. for func in [self.b, self.fi.a]:
  267. try:
  268. func.non_existent_attr
  269. except AttributeError:
  270. pass
  271. else:
  272. self.fail("using unknown attributes should raise "
  273. "AttributeError")
  274. class FunctionDictsTest(FuncAttrsTest):
  275. def test_setting_dict_to_invalid(self):
  276. self.cannot_set_attr(self.b, '__dict__', None, TypeError)
  277. from collections import UserDict
  278. d = UserDict({'known_attr': 7})
  279. self.cannot_set_attr(self.fi.a.__func__, '__dict__', d, TypeError)
  280. def test_setting_dict_to_valid(self):
  281. d = {'known_attr': 7}
  282. self.b.__dict__ = d
  283. # Test assignment
  284. self.assertIs(d, self.b.__dict__)
  285. # ... and on all the different ways of referencing the method's func
  286. self.F.a.__dict__ = d
  287. self.assertIs(d, self.fi.a.__func__.__dict__)
  288. self.assertIs(d, self.fi.a.__dict__)
  289. # Test value
  290. self.assertEqual(self.b.known_attr, 7)
  291. self.assertEqual(self.b.__dict__['known_attr'], 7)
  292. # ... and again, on all the different method's names
  293. self.assertEqual(self.fi.a.__func__.known_attr, 7)
  294. self.assertEqual(self.fi.a.known_attr, 7)
  295. def test_delete___dict__(self):
  296. try:
  297. del self.b.__dict__
  298. except TypeError:
  299. pass
  300. else:
  301. self.fail("deleting function dictionary should raise TypeError")
  302. def test_unassigned_dict(self):
  303. self.assertEqual(self.b.__dict__, {})
  304. def test_func_as_dict_key(self):
  305. value = "Some string"
  306. d = {}
  307. d[self.b] = value
  308. self.assertEqual(d[self.b], value)
  309. class FunctionDocstringTest(FuncAttrsTest):
  310. def test_set_docstring_attr(self):
  311. self.assertEqual(self.b.__doc__, None)
  312. docstr = "A test method that does nothing"
  313. self.b.__doc__ = docstr
  314. self.F.a.__doc__ = docstr
  315. self.assertEqual(self.b.__doc__, docstr)
  316. self.assertEqual(self.fi.a.__doc__, docstr)
  317. self.cannot_set_attr(self.fi.a, "__doc__", docstr, AttributeError)
  318. def test_delete_docstring(self):
  319. self.b.__doc__ = "The docstring"
  320. del self.b.__doc__
  321. self.assertEqual(self.b.__doc__, None)
  322. def cell(value):
  323. """Create a cell containing the given value."""
  324. def f():
  325. print(a)
  326. a = value
  327. return f.__closure__[0]
  328. def empty_cell(empty=True):
  329. """Create an empty cell."""
  330. def f():
  331. print(a)
  332. # the intent of the following line is simply "if False:"; it's
  333. # spelt this way to avoid the danger that a future optimization
  334. # might simply remove an "if False:" code block.
  335. if not empty:
  336. a = 1729
  337. return f.__closure__[0]
  338. class CellTest(unittest.TestCase):
  339. def test_comparison(self):
  340. # These tests are here simply to exercise the comparison code;
  341. # their presence should not be interpreted as providing any
  342. # guarantees about the semantics (or even existence) of cell
  343. # comparisons in future versions of CPython.
  344. self.assertTrue(cell(2) < cell(3))
  345. self.assertTrue(empty_cell() < cell('saturday'))
  346. self.assertTrue(empty_cell() == empty_cell())
  347. self.assertTrue(cell(-36) == cell(-36.0))
  348. self.assertTrue(cell(True) > empty_cell())
  349. class StaticMethodAttrsTest(unittest.TestCase):
  350. def test_func_attribute(self):
  351. def f():
  352. pass
  353. c = classmethod(f)
  354. self.assertTrue(c.__func__ is f)
  355. s = staticmethod(f)
  356. self.assertTrue(s.__func__ is f)
  357. class BuiltinFunctionPropertiesTest(unittest.TestCase):
  358. # XXX Not sure where this should really go since I can't find a
  359. # test module specifically for builtin_function_or_method.
  360. def test_builtin__qualname__(self):
  361. import time
  362. # builtin function:
  363. self.assertEqual(len.__qualname__, 'len')
  364. self.assertEqual(time.time.__qualname__, 'time')
  365. # builtin classmethod:
  366. self.assertEqual(dict.fromkeys.__qualname__, 'dict.fromkeys')
  367. self.assertEqual(float.__getformat__.__qualname__,
  368. 'float.__getformat__')
  369. # builtin staticmethod:
  370. self.assertEqual(str.maketrans.__qualname__, 'str.maketrans')
  371. self.assertEqual(bytes.maketrans.__qualname__, 'bytes.maketrans')
  372. # builtin bound instance method:
  373. self.assertEqual([1, 2, 3].append.__qualname__, 'list.append')
  374. self.assertEqual({'foo': 'bar'}.pop.__qualname__, 'dict.pop')
  375. if __name__ == "__main__":
  376. unittest.main()