diff options
Diffstat (limited to 'Lib/test/test_scope.py')
-rw-r--r-- | Lib/test/test_scope.py | 675 |
1 files changed, 343 insertions, 332 deletions
diff --git a/Lib/test/test_scope.py b/Lib/test/test_scope.py index e4e592a..777e85a 100644 --- a/Lib/test/test_scope.py +++ b/Lib/test/test_scope.py @@ -1,186 +1,190 @@ -from test.test_support import verify, TestFailed, check_syntax, vereq +import unittest +from test.test_support import check_syntax_error, run_unittest import warnings +warnings.filterwarnings("ignore", r"import \*", SyntaxWarning, "<test string>") warnings.filterwarnings("ignore", r"import \*", SyntaxWarning, "<string>") -print "1. simple nesting" +class ScopeTests(unittest.TestCase): -def make_adder(x): - def adder(y): - return x + y - return adder + def testSimpleNesting(self): -inc = make_adder(1) -plus10 = make_adder(10) + def make_adder(x): + def adder(y): + return x + y + return adder -vereq(inc(1), 2) -vereq(plus10(-2), 8) + inc = make_adder(1) + plus10 = make_adder(10) -print "2. extra nesting" + self.assertEqual(inc(1), 2) + self.assertEqual(plus10(-2), 8) -def make_adder2(x): - def extra(): # check freevars passing through non-use scopes - def adder(y): - return x + y - return adder - return extra() + def testExtraNesting(self): -inc = make_adder2(1) -plus10 = make_adder2(10) + def make_adder2(x): + def extra(): # check freevars passing through non-use scopes + def adder(y): + return x + y + return adder + return extra() -vereq(inc(1), 2) -vereq(plus10(-2), 8) + inc = make_adder2(1) + plus10 = make_adder2(10) -print "3. simple nesting + rebinding" + self.assertEqual(inc(1), 2) + self.assertEqual(plus10(-2), 8) -def make_adder3(x): - def adder(y): - return x + y - x = x + 1 # check tracking of assignment to x in defining scope - return adder + def testSimpleAndRebinding(self): -inc = make_adder3(0) -plus10 = make_adder3(9) + def make_adder3(x): + def adder(y): + return x + y + x = x + 1 # check tracking of assignment to x in defining scope + return adder -vereq(inc(1), 2) -vereq(plus10(-2), 8) + inc = make_adder3(0) + plus10 = make_adder3(9) -print "4. nesting with global but no free" + self.assertEqual(inc(1), 2) + self.assertEqual(plus10(-2), 8) -def make_adder4(): # XXX add exta level of indirection - def nest(): - def nest(): - def adder(y): - return global_x + y # check that plain old globals work - return adder - return nest() - return nest() + def testNestingGlobalNoFree(self): -global_x = 1 -adder = make_adder4() -vereq(adder(1), 2) + def make_adder4(): # XXX add exta level of indirection + def nest(): + def nest(): + def adder(y): + return global_x + y # check that plain old globals work + return adder + return nest() + return nest() -global_x = 10 -vereq(adder(-2), 8) + global_x = 1 + adder = make_adder4() + self.assertEqual(adder(1), 2) -print "5. nesting through class" + global_x = 10 + self.assertEqual(adder(-2), 8) -def make_adder5(x): - class Adder: - def __call__(self, y): - return x + y - return Adder() + def testNestingThroughClass(self): -inc = make_adder5(1) -plus10 = make_adder5(10) + def make_adder5(x): + class Adder: + def __call__(self, y): + return x + y + return Adder() -vereq(inc(1), 2) -vereq(plus10(-2), 8) + inc = make_adder5(1) + plus10 = make_adder5(10) -print "6. nesting plus free ref to global" + self.assertEqual(inc(1), 2) + self.assertEqual(plus10(-2), 8) -def make_adder6(x): - global global_nest_x - def adder(y): - return global_nest_x + y - global_nest_x = x - return adder + def testNestingPlusFreeRefToGlobal(self): -inc = make_adder6(1) -plus10 = make_adder6(10) + def make_adder6(x): + global global_nest_x + def adder(y): + return global_nest_x + y + global_nest_x = x + return adder -vereq(inc(1), 11) # there's only one global -vereq(plus10(-2), 8) + inc = make_adder6(1) + plus10 = make_adder6(10) -print "7. nearest enclosing scope" + self.assertEqual(inc(1), 11) # there's only one global + self.assertEqual(plus10(-2), 8) -def f(x): - def g(y): - x = 42 # check that this masks binding in f() - def h(z): - return x + z - return h - return g(2) - -test_func = f(10) -vereq(test_func(5), 47) - -print "8. mixed freevars and cellvars" - -def identity(x): - return x - -def f(x, y, z): - def g(a, b, c): - a = a + x # 3 - def h(): - # z * (4 + 9) - # 3 * 13 - return identity(z * (b + y)) - y = c + z # 9 - return h - return g - -g = f(1, 2, 3) -h = g(2, 4, 6) -vereq(h(), 39) - -print "9. free variable in method" - -def test(): - method_and_var = "var" - class Test: - def method_and_var(self): - return "method" - def test(self): - return method_and_var - def actual_global(self): - return str("global") - def str(self): - return str(self) - return Test() - -t = test() -vereq(t.test(), "var") -vereq(t.method_and_var(), "method") -vereq(t.actual_global(), "global") - -method_and_var = "var" -class Test: - # this class is not nested, so the rules are different - def method_and_var(self): - return "method" - def test(self): - return method_and_var - def actual_global(self): - return str("global") - def str(self): - return str(self) - -t = Test() -vereq(t.test(), "var") -vereq(t.method_and_var(), "method") -vereq(t.actual_global(), "global") - -print "10. recursion" + def testNearestEnclosingScope(self): -def f(x): - def fact(n): - if n == 0: - return 1 - else: - return n * fact(n - 1) - if x >= 0: - return fact(x) - else: - raise ValueError, "x must be >= 0" + def f(x): + def g(y): + x = 42 # check that this masks binding in f() + def h(z): + return x + z + return h + return g(2) -vereq(f(6), 720) + test_func = f(10) + self.assertEqual(test_func(5), 47) + def testMixedFreevarsAndCellvars(self): -print "11. unoptimized namespaces" + def identity(x): + return x -check_syntax("""\ + def f(x, y, z): + def g(a, b, c): + a = a + x # 3 + def h(): + # z * (4 + 9) + # 3 * 13 + return identity(z * (b + y)) + y = c + z # 9 + return h + return g + + g = f(1, 2, 3) + h = g(2, 4, 6) + self.assertEqual(h(), 39) + + def testFreeVarInMethod(self): + + def test(): + method_and_var = "var" + class Test: + def method_and_var(self): + return "method" + def test(self): + return method_and_var + def actual_global(self): + return str("global") + def str(self): + return str(self) + return Test() + + t = test() + self.assertEqual(t.test(), "var") + self.assertEqual(t.method_and_var(), "method") + self.assertEqual(t.actual_global(), "global") + + method_and_var = "var" + class Test: + # this class is not nested, so the rules are different + def method_and_var(self): + return "method" + def test(self): + return method_and_var + def actual_global(self): + return str("global") + def str(self): + return str(self) + + t = Test() + self.assertEqual(t.test(), "var") + self.assertEqual(t.method_and_var(), "method") + self.assertEqual(t.actual_global(), "global") + + def testRecursion(self): + + def f(x): + def fact(n): + if n == 0: + return 1 + else: + return n * fact(n - 1) + if x >= 0: + return fact(x) + else: + raise ValueError, "x must be >= 0" + + self.assertEqual(f(6), 720) + + + def testUnoptimizedNamespaces(self): + + check_syntax_error(self, """\ def unoptimized_clash1(strip): def f(s): from string import * @@ -188,7 +192,7 @@ def unoptimized_clash1(strip): return f """) -check_syntax("""\ + check_syntax_error(self, """\ def unoptimized_clash2(): from string import * def f(s): @@ -196,7 +200,7 @@ def unoptimized_clash2(): return f """) -check_syntax("""\ + check_syntax_error(self, """\ def unoptimized_clash2(): from string import * def g(): @@ -205,23 +209,23 @@ def unoptimized_clash2(): return f """) -check_syntax("""\ + check_syntax_error(self, """\ def f(x): def g(): return x del x # can't del name """) -check_syntax("""\ + check_syntax_error(self, """\ def f(): def g(): - from string import * - return strip # global or local? + from string import * + return strip # global or local? """) -# and verify a few cases that should work + # and verify a few cases that should work -exec(""" + exec(""" def noproblem1(): from string import * f = lambda x:x @@ -238,59 +242,60 @@ def noproblem3(): y = x """) -print "12. lambdas" - -f1 = lambda x: lambda y: x + y -inc = f1(1) -plus10 = f1(10) -vereq(inc(1), 2) -vereq(plus10(5), 15) - -f2 = lambda x: (lambda : lambda y: x + y)() -inc = f2(1) -plus10 = f2(10) -vereq(inc(1), 2) -vereq(plus10(5), 15) - -f3 = lambda x: lambda y: global_x + y -global_x = 1 -inc = f3(None) -vereq(inc(2), 3) - -f8 = lambda x, y, z: lambda a, b, c: lambda : z * (b + y) -g = f8(1, 2, 3) -h = g(2, 4, 6) -vereq(h(), 18) - -print "13. UnboundLocal" - -def errorInOuter(): - print y - def inner(): - return y - y = 1 - -def errorInInner(): - def inner(): - return y - inner() - y = 1 - -try: - errorInOuter() -except UnboundLocalError: - pass -else: - raise TestFailed + def testLambdas(self): + + f1 = lambda x: lambda y: x + y + inc = f1(1) + plus10 = f1(10) + self.assertEqual(inc(1), 2) + self.assertEqual(plus10(5), 15) + + f2 = lambda x: (lambda : lambda y: x + y)() + inc = f2(1) + plus10 = f2(10) + self.assertEqual(inc(1), 2) + self.assertEqual(plus10(5), 15) + + f3 = lambda x: lambda y: global_x + y + global_x = 1 + inc = f3(None) + self.assertEqual(inc(2), 3) + + f8 = lambda x, y, z: lambda a, b, c: lambda : z * (b + y) + g = f8(1, 2, 3) + h = g(2, 4, 6) + self.assertEqual(h(), 18) + + def testUnboundLocal(self): + + def errorInOuter(): + print y + def inner(): + return y + y = 1 + + def errorInInner(): + def inner(): + return y + inner() + y = 1 + + try: + errorInOuter() + except UnboundLocalError: + pass + else: + self.fail() -try: - errorInInner() -except NameError: - pass -else: - raise TestFailed + try: + errorInInner() + except NameError: + pass + else: + self.fail() -# test for bug #1501934: incorrect LOAD/STORE_GLOBAL generation + # test for bug #1501934: incorrect LOAD/STORE_GLOBAL generation + exec(""" global_x = 1 def f(): global_x += 1 @@ -299,34 +304,36 @@ try: except UnboundLocalError: pass else: - raise TestFailed, 'scope of global_x not correctly determined' + fail('scope of global_x not correctly determined') +""", {'fail': self.fail}) -print "14. complex definitions" + def testComplexDefinitions(self): -def makeReturner(*lst): - def returner(): - return lst - return returner + def makeReturner(*lst): + def returner(): + return lst + return returner -vereq(makeReturner(1,2,3)(), (1,2,3)) + self.assertEqual(makeReturner(1,2,3)(), (1,2,3)) -def makeReturner2(**kwargs): - def returner(): - return kwargs - return returner + def makeReturner2(**kwargs): + def returner(): + return kwargs + return returner -vereq(makeReturner2(a=11)()['a'], 11) + self.assertEqual(makeReturner2(a=11)()['a'], 11) -def makeAddPair((a, b)): - def addPair((c, d)): - return (a + c, b + d) - return addPair + def makeAddPair((a, b)): + def addPair((c, d)): + return (a + c, b + d) + return addPair -vereq(makeAddPair((1, 2))((100, 200)), (101,202)) + self.assertEqual(makeAddPair((1, 2))((100, 200)), (101,202)) -print "15. scope of global statements" + def testScopeOfGlobalStmt(self): # Examples posted by Samuele Pedroni to python-dev on 3/1/2001 + exec("""\ # I x = 7 def f(): @@ -339,8 +346,8 @@ def f(): return h() return i() return g() -vereq(f(), 7) -vereq(x, 7) +self.assertEqual(f(), 7) +self.assertEqual(x, 7) # II x = 7 @@ -354,8 +361,8 @@ def f(): return h() return i() return g() -vereq(f(), 2) -vereq(x, 7) +self.assertEqual(f(), 2) +self.assertEqual(x, 7) # III x = 7 @@ -370,8 +377,8 @@ def f(): return h() return i() return g() -vereq(f(), 2) -vereq(x, 2) +self.assertEqual(f(), 2) +self.assertEqual(x, 2) # IV x = 7 @@ -386,8 +393,8 @@ def f(): return h() return i() return g() -vereq(f(), 2) -vereq(x, 2) +self.assertEqual(f(), 2) +self.assertEqual(x, 2) # XXX what about global statements in class blocks? # do they affect methods? @@ -402,34 +409,36 @@ class Global: return x g = Global() -vereq(g.get(), 13) +self.assertEqual(g.get(), 13) g.set(15) -vereq(g.get(), 13) +self.assertEqual(g.get(), 13) +""") -print "16. check leaks" + def testLeaks(self): -class Foo: - count = 0 + class Foo: + count = 0 - def __init__(self): - Foo.count += 1 + def __init__(self): + Foo.count += 1 - def __del__(self): - Foo.count -= 1 + def __del__(self): + Foo.count -= 1 -def f1(): - x = Foo() - def f2(): - return x - f2() + def f1(): + x = Foo() + def f2(): + return x + f2() -for i in range(100): - f1() + for i in range(100): + f1() -vereq(Foo.count, 0) + self.assertEqual(Foo.count, 0) -print "17. class and global" + def testClassAndGlobal(self): + exec("""\ def test(x): class Foo: global x @@ -438,9 +447,9 @@ def test(x): return Foo() x = 0 -vereq(test(6)(2), 8) +self.assertEqual(test(6)(2), 8) x = -1 -vereq(test(3)(2), 5) +self.assertEqual(test(3)(2), 5) looked_up_by_load_name = False class X: @@ -449,104 +458,106 @@ class X: locals()['looked_up_by_load_name'] = True passed = looked_up_by_load_name -verify(X.passed) +self.assert_(X.passed) +""") -print "18. verify that locals() works" + def testLocalsFunction(self): -def f(x): - def g(y): - def h(z): - return y + z - w = x + y - y += 3 - return locals() - return g + def f(x): + def g(y): + def h(z): + return y + z + w = x + y + y += 3 + return locals() + return g -d = f(2)(4) -verify('h' in d) -del d['h'] -vereq(d, {'x': 2, 'y': 7, 'w': 6}) + d = f(2)(4) + self.assert_('h' in d) + del d['h'] + self.assertEqual(d, {'x': 2, 'y': 7, 'w': 6}) -print "19. var is bound and free in class" + def testBoundAndFree(self): + # var is bound and free in class -def f(x): - class C: - def m(self): - return x - a = x - return C + def f(x): + class C: + def m(self): + return x + a = x + return C -inst = f(3)() -vereq(inst.a, inst.m()) + inst = f(3)() + self.assertEqual(inst.a, inst.m()) -print "20. interaction with trace function" + def testInteractionWithTraceFunc(self): -import sys -def tracer(a,b,c): - return tracer + import sys + def tracer(a,b,c): + return tracer -def adaptgetter(name, klass, getter): - kind, des = getter - if kind == 1: # AV happens when stepping from this line to next - if des == "": - des = "_%s__%s" % (klass.__name__, name) - return lambda obj: getattr(obj, des) + def adaptgetter(name, klass, getter): + kind, des = getter + if kind == 1: # AV happens when stepping from this line to next + if des == "": + des = "_%s__%s" % (klass.__name__, name) + return lambda obj: getattr(obj, des) -class TestClass: - pass + class TestClass: + pass -sys.settrace(tracer) -adaptgetter("foo", TestClass, (1, "")) -sys.settrace(None) + sys.settrace(tracer) + adaptgetter("foo", TestClass, (1, "")) + sys.settrace(None) -try: sys.settrace() -except TypeError: pass -else: raise TestFailed, 'sys.settrace() did not raise TypeError' + self.assertRaises(TypeError, sys.settrace) -print "20. eval and exec with free variables" + def testEvalExecFreeVars(self): -def f(x): - return lambda: x + 1 + def f(x): + return lambda: x + 1 -g = f(3) -try: - eval(g.func_code) -except TypeError: - pass -else: - print "eval() should have failed, because code contained free vars" + g = f(3) + self.assertRaises(TypeError, eval, g.func_code) -try: - exec(g.func_code) -except TypeError: - pass -else: - print "exec should have failed, because code contained free vars" + try: + exec(g.func_code, {}) + except TypeError: + pass + else: + self.fail("exec should have failed, because code contained free vars") -print "21. list comprehension with local variables" + def testListCompLocalVars(self): -try: - print bad -except NameError: - pass -else: - print "bad should not be defined" + try: + print bad + except NameError: + pass + else: + print "bad should not be defined" -def x(): - [bad for s in 'a b' for bad in s.split()] + def x(): + [bad for s in 'a b' for bad in s.split()] -x() -try: - print bad -except NameError: - pass + x() + try: + print bad + except NameError: + pass -print "22. eval with free variables" + def testEvalFreeVars(self): -def f(x): - def g(): - x - eval("x + 1") - return g + def f(x): + def g(): + x + eval("x + 1") + return g + + f(4)() + + +def test_main(): + run_unittest(ScopeTests) -f(4)() +if __name__ == '__main__': + test_main() |