+++ /dev/null
-import unittest\r
-from test.test_support import check_syntax_error, check_py3k_warnings, \\r
- check_warnings, run_unittest\r
-\r
-\r
-class ScopeTests(unittest.TestCase):\r
-\r
- def testSimpleNesting(self):\r
-\r
- def make_adder(x):\r
- def adder(y):\r
- return x + y\r
- return adder\r
-\r
- inc = make_adder(1)\r
- plus10 = make_adder(10)\r
-\r
- self.assertEqual(inc(1), 2)\r
- self.assertEqual(plus10(-2), 8)\r
-\r
- def testExtraNesting(self):\r
-\r
- def make_adder2(x):\r
- def extra(): # check freevars passing through non-use scopes\r
- def adder(y):\r
- return x + y\r
- return adder\r
- return extra()\r
-\r
- inc = make_adder2(1)\r
- plus10 = make_adder2(10)\r
-\r
- self.assertEqual(inc(1), 2)\r
- self.assertEqual(plus10(-2), 8)\r
-\r
- def testSimpleAndRebinding(self):\r
-\r
- def make_adder3(x):\r
- def adder(y):\r
- return x + y\r
- x = x + 1 # check tracking of assignment to x in defining scope\r
- return adder\r
-\r
- inc = make_adder3(0)\r
- plus10 = make_adder3(9)\r
-\r
- self.assertEqual(inc(1), 2)\r
- self.assertEqual(plus10(-2), 8)\r
-\r
- def testNestingGlobalNoFree(self):\r
-\r
- def make_adder4(): # XXX add exta level of indirection\r
- def nest():\r
- def nest():\r
- def adder(y):\r
- return global_x + y # check that plain old globals work\r
- return adder\r
- return nest()\r
- return nest()\r
-\r
- global_x = 1\r
- adder = make_adder4()\r
- self.assertEqual(adder(1), 2)\r
-\r
- global_x = 10\r
- self.assertEqual(adder(-2), 8)\r
-\r
- def testNestingThroughClass(self):\r
-\r
- def make_adder5(x):\r
- class Adder:\r
- def __call__(self, y):\r
- return x + y\r
- return Adder()\r
-\r
- inc = make_adder5(1)\r
- plus10 = make_adder5(10)\r
-\r
- self.assertEqual(inc(1), 2)\r
- self.assertEqual(plus10(-2), 8)\r
-\r
- def testNestingPlusFreeRefToGlobal(self):\r
-\r
- def make_adder6(x):\r
- global global_nest_x\r
- def adder(y):\r
- return global_nest_x + y\r
- global_nest_x = x\r
- return adder\r
-\r
- inc = make_adder6(1)\r
- plus10 = make_adder6(10)\r
-\r
- self.assertEqual(inc(1), 11) # there's only one global\r
- self.assertEqual(plus10(-2), 8)\r
-\r
- def testNearestEnclosingScope(self):\r
-\r
- def f(x):\r
- def g(y):\r
- x = 42 # check that this masks binding in f()\r
- def h(z):\r
- return x + z\r
- return h\r
- return g(2)\r
-\r
- test_func = f(10)\r
- self.assertEqual(test_func(5), 47)\r
-\r
- def testMixedFreevarsAndCellvars(self):\r
-\r
- def identity(x):\r
- return x\r
-\r
- def f(x, y, z):\r
- def g(a, b, c):\r
- a = a + x # 3\r
- def h():\r
- # z * (4 + 9)\r
- # 3 * 13\r
- return identity(z * (b + y))\r
- y = c + z # 9\r
- return h\r
- return g\r
-\r
- g = f(1, 2, 3)\r
- h = g(2, 4, 6)\r
- self.assertEqual(h(), 39)\r
-\r
- def testFreeVarInMethod(self):\r
-\r
- def test():\r
- method_and_var = "var"\r
- class Test:\r
- def method_and_var(self):\r
- return "method"\r
- def test(self):\r
- return method_and_var\r
- def actual_global(self):\r
- return str("global")\r
- def str(self):\r
- return str(self)\r
- return Test()\r
-\r
- t = test()\r
- self.assertEqual(t.test(), "var")\r
- self.assertEqual(t.method_and_var(), "method")\r
- self.assertEqual(t.actual_global(), "global")\r
-\r
- method_and_var = "var"\r
- class Test:\r
- # this class is not nested, so the rules are different\r
- def method_and_var(self):\r
- return "method"\r
- def test(self):\r
- return method_and_var\r
- def actual_global(self):\r
- return str("global")\r
- def str(self):\r
- return str(self)\r
-\r
- t = Test()\r
- self.assertEqual(t.test(), "var")\r
- self.assertEqual(t.method_and_var(), "method")\r
- self.assertEqual(t.actual_global(), "global")\r
-\r
- def testRecursion(self):\r
-\r
- def f(x):\r
- def fact(n):\r
- if n == 0:\r
- return 1\r
- else:\r
- return n * fact(n - 1)\r
- if x >= 0:\r
- return fact(x)\r
- else:\r
- raise ValueError, "x must be >= 0"\r
-\r
- self.assertEqual(f(6), 720)\r
-\r
-\r
- def testUnoptimizedNamespaces(self):\r
-\r
- check_syntax_error(self, """\\r
-def unoptimized_clash1(strip):\r
- def f(s):\r
- from string import *\r
- return strip(s) # ambiguity: free or local\r
- return f\r
-""")\r
-\r
- check_syntax_error(self, """\\r
-def unoptimized_clash2():\r
- from string import *\r
- def f(s):\r
- return strip(s) # ambiguity: global or local\r
- return f\r
-""")\r
-\r
- check_syntax_error(self, """\\r
-def unoptimized_clash2():\r
- from string import *\r
- def g():\r
- def f(s):\r
- return strip(s) # ambiguity: global or local\r
- return f\r
-""")\r
-\r
- # XXX could allow this for exec with const argument, but what's the point\r
- check_syntax_error(self, """\\r
-def error(y):\r
- exec "a = 1"\r
- def f(x):\r
- return x + y\r
- return f\r
-""")\r
-\r
- check_syntax_error(self, """\\r
-def f(x):\r
- def g():\r
- return x\r
- del x # can't del name\r
-""")\r
-\r
- check_syntax_error(self, """\\r
-def f():\r
- def g():\r
- from string import *\r
- return strip # global or local?\r
-""")\r
-\r
- # and verify a few cases that should work\r
-\r
- exec """\r
-def noproblem1():\r
- from string import *\r
- f = lambda x:x\r
-\r
-def noproblem2():\r
- from string import *\r
- def f(x):\r
- return x + 1\r
-\r
-def noproblem3():\r
- from string import *\r
- def f(x):\r
- global y\r
- y = x\r
-"""\r
-\r
- def testLambdas(self):\r
-\r
- f1 = lambda x: lambda y: x + y\r
- inc = f1(1)\r
- plus10 = f1(10)\r
- self.assertEqual(inc(1), 2)\r
- self.assertEqual(plus10(5), 15)\r
-\r
- f2 = lambda x: (lambda : lambda y: x + y)()\r
- inc = f2(1)\r
- plus10 = f2(10)\r
- self.assertEqual(inc(1), 2)\r
- self.assertEqual(plus10(5), 15)\r
-\r
- f3 = lambda x: lambda y: global_x + y\r
- global_x = 1\r
- inc = f3(None)\r
- self.assertEqual(inc(2), 3)\r
-\r
- f8 = lambda x, y, z: lambda a, b, c: lambda : z * (b + y)\r
- g = f8(1, 2, 3)\r
- h = g(2, 4, 6)\r
- self.assertEqual(h(), 18)\r
-\r
- def testUnboundLocal(self):\r
-\r
- def errorInOuter():\r
- print y\r
- def inner():\r
- return y\r
- y = 1\r
-\r
- def errorInInner():\r
- def inner():\r
- return y\r
- inner()\r
- y = 1\r
-\r
- self.assertRaises(UnboundLocalError, errorInOuter)\r
- self.assertRaises(NameError, errorInInner)\r
-\r
- # test for bug #1501934: incorrect LOAD/STORE_GLOBAL generation\r
- exec """\r
-global_x = 1\r
-def f():\r
- global_x += 1\r
-try:\r
- f()\r
-except UnboundLocalError:\r
- pass\r
-else:\r
- fail('scope of global_x not correctly determined')\r
-""" in {'fail': self.fail}\r
-\r
- def testComplexDefinitions(self):\r
-\r
- def makeReturner(*lst):\r
- def returner():\r
- return lst\r
- return returner\r
-\r
- self.assertEqual(makeReturner(1,2,3)(), (1,2,3))\r
-\r
- def makeReturner2(**kwargs):\r
- def returner():\r
- return kwargs\r
- return returner\r
-\r
- self.assertEqual(makeReturner2(a=11)()['a'], 11)\r
-\r
- with check_py3k_warnings(("tuple parameter unpacking has been removed",\r
- SyntaxWarning)):\r
- exec """\\r
-def makeAddPair((a, b)):\r
- def addPair((c, d)):\r
- return (a + c, b + d)\r
- return addPair\r
-""" in locals()\r
- self.assertEqual(makeAddPair((1, 2))((100, 200)), (101,202))\r
-\r
- def testScopeOfGlobalStmt(self):\r
-# Examples posted by Samuele Pedroni to python-dev on 3/1/2001\r
-\r
- exec """\\r
-# I\r
-x = 7\r
-def f():\r
- x = 1\r
- def g():\r
- global x\r
- def i():\r
- def h():\r
- return x\r
- return h()\r
- return i()\r
- return g()\r
-self.assertEqual(f(), 7)\r
-self.assertEqual(x, 7)\r
-\r
-# II\r
-x = 7\r
-def f():\r
- x = 1\r
- def g():\r
- x = 2\r
- def i():\r
- def h():\r
- return x\r
- return h()\r
- return i()\r
- return g()\r
-self.assertEqual(f(), 2)\r
-self.assertEqual(x, 7)\r
-\r
-# III\r
-x = 7\r
-def f():\r
- x = 1\r
- def g():\r
- global x\r
- x = 2\r
- def i():\r
- def h():\r
- return x\r
- return h()\r
- return i()\r
- return g()\r
-self.assertEqual(f(), 2)\r
-self.assertEqual(x, 2)\r
-\r
-# IV\r
-x = 7\r
-def f():\r
- x = 3\r
- def g():\r
- global x\r
- x = 2\r
- def i():\r
- def h():\r
- return x\r
- return h()\r
- return i()\r
- return g()\r
-self.assertEqual(f(), 2)\r
-self.assertEqual(x, 2)\r
-\r
-# XXX what about global statements in class blocks?\r
-# do they affect methods?\r
-\r
-x = 12\r
-class Global:\r
- global x\r
- x = 13\r
- def set(self, val):\r
- x = val\r
- def get(self):\r
- return x\r
-\r
-g = Global()\r
-self.assertEqual(g.get(), 13)\r
-g.set(15)\r
-self.assertEqual(g.get(), 13)\r
-"""\r
-\r
- def testLeaks(self):\r
-\r
- class Foo:\r
- count = 0\r
-\r
- def __init__(self):\r
- Foo.count += 1\r
-\r
- def __del__(self):\r
- Foo.count -= 1\r
-\r
- def f1():\r
- x = Foo()\r
- def f2():\r
- return x\r
- f2()\r
-\r
- for i in range(100):\r
- f1()\r
-\r
- self.assertEqual(Foo.count, 0)\r
-\r
- def testClassAndGlobal(self):\r
-\r
- exec """\\r
-def test(x):\r
- class Foo:\r
- global x\r
- def __call__(self, y):\r
- return x + y\r
- return Foo()\r
-\r
-x = 0\r
-self.assertEqual(test(6)(2), 8)\r
-x = -1\r
-self.assertEqual(test(3)(2), 5)\r
-\r
-looked_up_by_load_name = False\r
-class X:\r
- # Implicit globals inside classes are be looked up by LOAD_NAME, not\r
- # LOAD_GLOBAL.\r
- locals()['looked_up_by_load_name'] = True\r
- passed = looked_up_by_load_name\r
-\r
-self.assertTrue(X.passed)\r
-"""\r
-\r
- def testLocalsFunction(self):\r
-\r
- def f(x):\r
- def g(y):\r
- def h(z):\r
- return y + z\r
- w = x + y\r
- y += 3\r
- return locals()\r
- return g\r
-\r
- d = f(2)(4)\r
- self.assertIn('h', d)\r
- del d['h']\r
- self.assertEqual(d, {'x': 2, 'y': 7, 'w': 6})\r
-\r
- def testLocalsClass(self):\r
- # This test verifies that calling locals() does not pollute\r
- # the local namespace of the class with free variables. Old\r
- # versions of Python had a bug, where a free variable being\r
- # passed through a class namespace would be inserted into\r
- # locals() by locals() or exec or a trace function.\r
- #\r
- # The real bug lies in frame code that copies variables\r
- # between fast locals and the locals dict, e.g. when executing\r
- # a trace function.\r
-\r
- def f(x):\r
- class C:\r
- x = 12\r
- def m(self):\r
- return x\r
- locals()\r
- return C\r
-\r
- self.assertEqual(f(1).x, 12)\r
-\r
- def f(x):\r
- class C:\r
- y = x\r
- def m(self):\r
- return x\r
- z = list(locals())\r
- return C\r
-\r
- varnames = f(1).z\r
- self.assertNotIn("x", varnames)\r
- self.assertIn("y", varnames)\r
-\r
- def testLocalsClass_WithTrace(self):\r
- # Issue23728: after the trace function returns, the locals()\r
- # dictionary is used to update all variables, this used to\r
- # include free variables. But in class statements, free\r
- # variables are not inserted...\r
- import sys\r
- sys.settrace(lambda a,b,c:None)\r
- try:\r
- x = 12\r
-\r
- class C:\r
- def f(self):\r
- return x\r
-\r
- self.assertEqual(x, 12) # Used to raise UnboundLocalError\r
- finally:\r
- sys.settrace(None)\r
-\r
- def testBoundAndFree(self):\r
- # var is bound and free in class\r
-\r
- def f(x):\r
- class C:\r
- def m(self):\r
- return x\r
- a = x\r
- return C\r
-\r
- inst = f(3)()\r
- self.assertEqual(inst.a, inst.m())\r
-\r
- def testInteractionWithTraceFunc(self):\r
-\r
- import sys\r
- def tracer(a,b,c):\r
- return tracer\r
-\r
- def adaptgetter(name, klass, getter):\r
- kind, des = getter\r
- if kind == 1: # AV happens when stepping from this line to next\r
- if des == "":\r
- des = "_%s__%s" % (klass.__name__, name)\r
- return lambda obj: getattr(obj, des)\r
-\r
- class TestClass:\r
- pass\r
-\r
- sys.settrace(tracer)\r
- adaptgetter("foo", TestClass, (1, ""))\r
- sys.settrace(None)\r
-\r
- self.assertRaises(TypeError, sys.settrace)\r
-\r
- def testEvalExecFreeVars(self):\r
-\r
- def f(x):\r
- return lambda: x + 1\r
-\r
- g = f(3)\r
- self.assertRaises(TypeError, eval, g.func_code)\r
-\r
- try:\r
- exec g.func_code in {}\r
- except TypeError:\r
- pass\r
- else:\r
- self.fail("exec should have failed, because code contained free vars")\r
-\r
- def testListCompLocalVars(self):\r
-\r
- try:\r
- print bad\r
- except NameError:\r
- pass\r
- else:\r
- print "bad should not be defined"\r
-\r
- def x():\r
- [bad for s in 'a b' for bad in s.split()]\r
-\r
- x()\r
- try:\r
- print bad\r
- except NameError:\r
- pass\r
-\r
- def testEvalFreeVars(self):\r
-\r
- def f(x):\r
- def g():\r
- x\r
- eval("x + 1")\r
- return g\r
-\r
- f(4)()\r
-\r
- def testFreeingCell(self):\r
- # Test what happens when a finalizer accesses\r
- # the cell where the object was stored.\r
- class Special:\r
- def __del__(self):\r
- nestedcell_get()\r
-\r
- def f():\r
- global nestedcell_get\r
- def nestedcell_get():\r
- return c\r
-\r
- c = (Special(),)\r
- c = 2\r
-\r
- f() # used to crash the interpreter...\r
-\r
- def testGlobalInParallelNestedFunctions(self):\r
- # A symbol table bug leaked the global statement from one\r
- # function to other nested functions in the same block.\r
- # This test verifies that a global statement in the first\r
- # function does not affect the second function.\r
- CODE = """def f():\r
- y = 1\r
- def g():\r
- global y\r
- return y\r
- def h():\r
- return y + 1\r
- return g, h\r
-\r
-y = 9\r
-g, h = f()\r
-result9 = g()\r
-result2 = h()\r
-"""\r
- local_ns = {}\r
- global_ns = {}\r
- exec CODE in local_ns, global_ns\r
- self.assertEqual(2, global_ns["result2"])\r
- self.assertEqual(9, global_ns["result9"])\r
-\r
- def testTopIsNotSignificant(self):\r
- # See #9997.\r
- def top(a):\r
- pass\r
- def b():\r
- global a\r
-\r
-\r
-def test_main():\r
- with check_warnings(("import \* only allowed at module level",\r
- SyntaxWarning)):\r
- run_unittest(ScopeTests)\r
-\r
-if __name__ == '__main__':\r
- test_main()\r