test_scope.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664
  1. import unittest
  2. from test.test_support import check_syntax_error, check_py3k_warnings, \
  3. check_warnings, run_unittest
  4. class ScopeTests(unittest.TestCase):
  5. def testSimpleNesting(self):
  6. def make_adder(x):
  7. def adder(y):
  8. return x + y
  9. return adder
  10. inc = make_adder(1)
  11. plus10 = make_adder(10)
  12. self.assertEqual(inc(1), 2)
  13. self.assertEqual(plus10(-2), 8)
  14. def testExtraNesting(self):
  15. def make_adder2(x):
  16. def extra(): # check freevars passing through non-use scopes
  17. def adder(y):
  18. return x + y
  19. return adder
  20. return extra()
  21. inc = make_adder2(1)
  22. plus10 = make_adder2(10)
  23. self.assertEqual(inc(1), 2)
  24. self.assertEqual(plus10(-2), 8)
  25. def testSimpleAndRebinding(self):
  26. def make_adder3(x):
  27. def adder(y):
  28. return x + y
  29. x = x + 1 # check tracking of assignment to x in defining scope
  30. return adder
  31. inc = make_adder3(0)
  32. plus10 = make_adder3(9)
  33. self.assertEqual(inc(1), 2)
  34. self.assertEqual(plus10(-2), 8)
  35. def testNestingGlobalNoFree(self):
  36. def make_adder4(): # XXX add exta level of indirection
  37. def nest():
  38. def nest():
  39. def adder(y):
  40. return global_x + y # check that plain old globals work
  41. return adder
  42. return nest()
  43. return nest()
  44. global_x = 1
  45. adder = make_adder4()
  46. self.assertEqual(adder(1), 2)
  47. global_x = 10
  48. self.assertEqual(adder(-2), 8)
  49. def testNestingThroughClass(self):
  50. def make_adder5(x):
  51. class Adder:
  52. def __call__(self, y):
  53. return x + y
  54. return Adder()
  55. inc = make_adder5(1)
  56. plus10 = make_adder5(10)
  57. self.assertEqual(inc(1), 2)
  58. self.assertEqual(plus10(-2), 8)
  59. def testNestingPlusFreeRefToGlobal(self):
  60. def make_adder6(x):
  61. global global_nest_x
  62. def adder(y):
  63. return global_nest_x + y
  64. global_nest_x = x
  65. return adder
  66. inc = make_adder6(1)
  67. plus10 = make_adder6(10)
  68. self.assertEqual(inc(1), 11) # there's only one global
  69. self.assertEqual(plus10(-2), 8)
  70. def testNearestEnclosingScope(self):
  71. def f(x):
  72. def g(y):
  73. x = 42 # check that this masks binding in f()
  74. def h(z):
  75. return x + z
  76. return h
  77. return g(2)
  78. test_func = f(10)
  79. self.assertEqual(test_func(5), 47)
  80. def testMixedFreevarsAndCellvars(self):
  81. def identity(x):
  82. return x
  83. def f(x, y, z):
  84. def g(a, b, c):
  85. a = a + x # 3
  86. def h():
  87. # z * (4 + 9)
  88. # 3 * 13
  89. return identity(z * (b + y))
  90. y = c + z # 9
  91. return h
  92. return g
  93. g = f(1, 2, 3)
  94. h = g(2, 4, 6)
  95. self.assertEqual(h(), 39)
  96. def testFreeVarInMethod(self):
  97. def test():
  98. method_and_var = "var"
  99. class Test:
  100. def method_and_var(self):
  101. return "method"
  102. def test(self):
  103. return method_and_var
  104. def actual_global(self):
  105. return str("global")
  106. def str(self):
  107. return str(self)
  108. return Test()
  109. t = test()
  110. self.assertEqual(t.test(), "var")
  111. self.assertEqual(t.method_and_var(), "method")
  112. self.assertEqual(t.actual_global(), "global")
  113. method_and_var = "var"
  114. class Test:
  115. # this class is not nested, so the rules are different
  116. def method_and_var(self):
  117. return "method"
  118. def test(self):
  119. return method_and_var
  120. def actual_global(self):
  121. return str("global")
  122. def str(self):
  123. return str(self)
  124. t = Test()
  125. self.assertEqual(t.test(), "var")
  126. self.assertEqual(t.method_and_var(), "method")
  127. self.assertEqual(t.actual_global(), "global")
  128. def testRecursion(self):
  129. def f(x):
  130. def fact(n):
  131. if n == 0:
  132. return 1
  133. else:
  134. return n * fact(n - 1)
  135. if x >= 0:
  136. return fact(x)
  137. else:
  138. raise ValueError, "x must be >= 0"
  139. self.assertEqual(f(6), 720)
  140. def testUnoptimizedNamespaces(self):
  141. check_syntax_error(self, """\
  142. def unoptimized_clash1(strip):
  143. def f(s):
  144. from string import *
  145. return strip(s) # ambiguity: free or local
  146. return f
  147. """)
  148. check_syntax_error(self, """\
  149. def unoptimized_clash2():
  150. from string import *
  151. def f(s):
  152. return strip(s) # ambiguity: global or local
  153. return f
  154. """)
  155. check_syntax_error(self, """\
  156. def unoptimized_clash2():
  157. from string import *
  158. def g():
  159. def f(s):
  160. return strip(s) # ambiguity: global or local
  161. return f
  162. """)
  163. # XXX could allow this for exec with const argument, but what's the point
  164. check_syntax_error(self, """\
  165. def error(y):
  166. exec "a = 1"
  167. def f(x):
  168. return x + y
  169. return f
  170. """)
  171. check_syntax_error(self, """\
  172. def f(x):
  173. def g():
  174. return x
  175. del x # can't del name
  176. """)
  177. check_syntax_error(self, """\
  178. def f():
  179. def g():
  180. from string import *
  181. return strip # global or local?
  182. """)
  183. # and verify a few cases that should work
  184. exec """
  185. def noproblem1():
  186. from string import *
  187. f = lambda x:x
  188. def noproblem2():
  189. from string import *
  190. def f(x):
  191. return x + 1
  192. def noproblem3():
  193. from string import *
  194. def f(x):
  195. global y
  196. y = x
  197. """
  198. def testLambdas(self):
  199. f1 = lambda x: lambda y: x + y
  200. inc = f1(1)
  201. plus10 = f1(10)
  202. self.assertEqual(inc(1), 2)
  203. self.assertEqual(plus10(5), 15)
  204. f2 = lambda x: (lambda : lambda y: x + y)()
  205. inc = f2(1)
  206. plus10 = f2(10)
  207. self.assertEqual(inc(1), 2)
  208. self.assertEqual(plus10(5), 15)
  209. f3 = lambda x: lambda y: global_x + y
  210. global_x = 1
  211. inc = f3(None)
  212. self.assertEqual(inc(2), 3)
  213. f8 = lambda x, y, z: lambda a, b, c: lambda : z * (b + y)
  214. g = f8(1, 2, 3)
  215. h = g(2, 4, 6)
  216. self.assertEqual(h(), 18)
  217. def testUnboundLocal(self):
  218. def errorInOuter():
  219. print y
  220. def inner():
  221. return y
  222. y = 1
  223. def errorInInner():
  224. def inner():
  225. return y
  226. inner()
  227. y = 1
  228. self.assertRaises(UnboundLocalError, errorInOuter)
  229. self.assertRaises(NameError, errorInInner)
  230. # test for bug #1501934: incorrect LOAD/STORE_GLOBAL generation
  231. exec """
  232. global_x = 1
  233. def f():
  234. global_x += 1
  235. try:
  236. f()
  237. except UnboundLocalError:
  238. pass
  239. else:
  240. fail('scope of global_x not correctly determined')
  241. """ in {'fail': self.fail}
  242. def testComplexDefinitions(self):
  243. def makeReturner(*lst):
  244. def returner():
  245. return lst
  246. return returner
  247. self.assertEqual(makeReturner(1,2,3)(), (1,2,3))
  248. def makeReturner2(**kwargs):
  249. def returner():
  250. return kwargs
  251. return returner
  252. self.assertEqual(makeReturner2(a=11)()['a'], 11)
  253. with check_py3k_warnings(("tuple parameter unpacking has been removed",
  254. SyntaxWarning)):
  255. exec """\
  256. def makeAddPair((a, b)):
  257. def addPair((c, d)):
  258. return (a + c, b + d)
  259. return addPair
  260. """ in locals()
  261. self.assertEqual(makeAddPair((1, 2))((100, 200)), (101,202))
  262. def testScopeOfGlobalStmt(self):
  263. # Examples posted by Samuele Pedroni to python-dev on 3/1/2001
  264. exec """\
  265. # I
  266. x = 7
  267. def f():
  268. x = 1
  269. def g():
  270. global x
  271. def i():
  272. def h():
  273. return x
  274. return h()
  275. return i()
  276. return g()
  277. self.assertEqual(f(), 7)
  278. self.assertEqual(x, 7)
  279. # II
  280. x = 7
  281. def f():
  282. x = 1
  283. def g():
  284. x = 2
  285. def i():
  286. def h():
  287. return x
  288. return h()
  289. return i()
  290. return g()
  291. self.assertEqual(f(), 2)
  292. self.assertEqual(x, 7)
  293. # III
  294. x = 7
  295. def f():
  296. x = 1
  297. def g():
  298. global x
  299. x = 2
  300. def i():
  301. def h():
  302. return x
  303. return h()
  304. return i()
  305. return g()
  306. self.assertEqual(f(), 2)
  307. self.assertEqual(x, 2)
  308. # IV
  309. x = 7
  310. def f():
  311. x = 3
  312. def g():
  313. global x
  314. x = 2
  315. def i():
  316. def h():
  317. return x
  318. return h()
  319. return i()
  320. return g()
  321. self.assertEqual(f(), 2)
  322. self.assertEqual(x, 2)
  323. # XXX what about global statements in class blocks?
  324. # do they affect methods?
  325. x = 12
  326. class Global:
  327. global x
  328. x = 13
  329. def set(self, val):
  330. x = val
  331. def get(self):
  332. return x
  333. g = Global()
  334. self.assertEqual(g.get(), 13)
  335. g.set(15)
  336. self.assertEqual(g.get(), 13)
  337. """
  338. def testLeaks(self):
  339. class Foo:
  340. count = 0
  341. def __init__(self):
  342. Foo.count += 1
  343. def __del__(self):
  344. Foo.count -= 1
  345. def f1():
  346. x = Foo()
  347. def f2():
  348. return x
  349. f2()
  350. for i in range(100):
  351. f1()
  352. self.assertEqual(Foo.count, 0)
  353. def testClassAndGlobal(self):
  354. exec """\
  355. def test(x):
  356. class Foo:
  357. global x
  358. def __call__(self, y):
  359. return x + y
  360. return Foo()
  361. x = 0
  362. self.assertEqual(test(6)(2), 8)
  363. x = -1
  364. self.assertEqual(test(3)(2), 5)
  365. looked_up_by_load_name = False
  366. class X:
  367. # Implicit globals inside classes are be looked up by LOAD_NAME, not
  368. # LOAD_GLOBAL.
  369. locals()['looked_up_by_load_name'] = True
  370. passed = looked_up_by_load_name
  371. self.assertTrue(X.passed)
  372. """
  373. def testLocalsFunction(self):
  374. def f(x):
  375. def g(y):
  376. def h(z):
  377. return y + z
  378. w = x + y
  379. y += 3
  380. return locals()
  381. return g
  382. d = f(2)(4)
  383. self.assertIn('h', d)
  384. del d['h']
  385. self.assertEqual(d, {'x': 2, 'y': 7, 'w': 6})
  386. def testLocalsClass(self):
  387. # This test verifies that calling locals() does not pollute
  388. # the local namespace of the class with free variables. Old
  389. # versions of Python had a bug, where a free variable being
  390. # passed through a class namespace would be inserted into
  391. # locals() by locals() or exec or a trace function.
  392. #
  393. # The real bug lies in frame code that copies variables
  394. # between fast locals and the locals dict, e.g. when executing
  395. # a trace function.
  396. def f(x):
  397. class C:
  398. x = 12
  399. def m(self):
  400. return x
  401. locals()
  402. return C
  403. self.assertEqual(f(1).x, 12)
  404. def f(x):
  405. class C:
  406. y = x
  407. def m(self):
  408. return x
  409. z = list(locals())
  410. return C
  411. varnames = f(1).z
  412. self.assertNotIn("x", varnames)
  413. self.assertIn("y", varnames)
  414. def testLocalsClass_WithTrace(self):
  415. # Issue23728: after the trace function returns, the locals()
  416. # dictionary is used to update all variables, this used to
  417. # include free variables. But in class statements, free
  418. # variables are not inserted...
  419. import sys
  420. sys.settrace(lambda a,b,c:None)
  421. try:
  422. x = 12
  423. class C:
  424. def f(self):
  425. return x
  426. self.assertEqual(x, 12) # Used to raise UnboundLocalError
  427. finally:
  428. sys.settrace(None)
  429. def testBoundAndFree(self):
  430. # var is bound and free in class
  431. def f(x):
  432. class C:
  433. def m(self):
  434. return x
  435. a = x
  436. return C
  437. inst = f(3)()
  438. self.assertEqual(inst.a, inst.m())
  439. def testInteractionWithTraceFunc(self):
  440. import sys
  441. def tracer(a,b,c):
  442. return tracer
  443. def adaptgetter(name, klass, getter):
  444. kind, des = getter
  445. if kind == 1: # AV happens when stepping from this line to next
  446. if des == "":
  447. des = "_%s__%s" % (klass.__name__, name)
  448. return lambda obj: getattr(obj, des)
  449. class TestClass:
  450. pass
  451. sys.settrace(tracer)
  452. adaptgetter("foo", TestClass, (1, ""))
  453. sys.settrace(None)
  454. self.assertRaises(TypeError, sys.settrace)
  455. def testEvalExecFreeVars(self):
  456. def f(x):
  457. return lambda: x + 1
  458. g = f(3)
  459. self.assertRaises(TypeError, eval, g.func_code)
  460. try:
  461. exec g.func_code in {}
  462. except TypeError:
  463. pass
  464. else:
  465. self.fail("exec should have failed, because code contained free vars")
  466. def testListCompLocalVars(self):
  467. try:
  468. print bad
  469. except NameError:
  470. pass
  471. else:
  472. print "bad should not be defined"
  473. def x():
  474. [bad for s in 'a b' for bad in s.split()]
  475. x()
  476. try:
  477. print bad
  478. except NameError:
  479. pass
  480. def testEvalFreeVars(self):
  481. def f(x):
  482. def g():
  483. x
  484. eval("x + 1")
  485. return g
  486. f(4)()
  487. def testFreeingCell(self):
  488. # Test what happens when a finalizer accesses
  489. # the cell where the object was stored.
  490. class Special:
  491. def __del__(self):
  492. nestedcell_get()
  493. def f():
  494. global nestedcell_get
  495. def nestedcell_get():
  496. return c
  497. c = (Special(),)
  498. c = 2
  499. f() # used to crash the interpreter...
  500. def testGlobalInParallelNestedFunctions(self):
  501. # A symbol table bug leaked the global statement from one
  502. # function to other nested functions in the same block.
  503. # This test verifies that a global statement in the first
  504. # function does not affect the second function.
  505. CODE = """def f():
  506. y = 1
  507. def g():
  508. global y
  509. return y
  510. def h():
  511. return y + 1
  512. return g, h
  513. y = 9
  514. g, h = f()
  515. result9 = g()
  516. result2 = h()
  517. """
  518. local_ns = {}
  519. global_ns = {}
  520. exec CODE in local_ns, global_ns
  521. self.assertEqual(2, global_ns["result2"])
  522. self.assertEqual(9, global_ns["result9"])
  523. def testTopIsNotSignificant(self):
  524. # See #9997.
  525. def top(a):
  526. pass
  527. def b():
  528. global a
  529. def test_main():
  530. with check_warnings(("import \* only allowed at module level",
  531. SyntaxWarning)):
  532. run_unittest(ScopeTests)
  533. if __name__ == '__main__':
  534. test_main()