PEP 227 implementation

New tests cases for nested scopes.
This commit is contained in:
Jeremy Hylton 2001-01-25 20:11:23 +00:00
parent 5e2d0764cd
commit 4588c78faf
2 changed files with 262 additions and 0 deletions

View File

@ -0,0 +1,13 @@
test_scope
1. simple nesting
2. extra nesting
3. simple nesting + rebinding
4. nesting with global but no free
5. nesting through class
6. nesting plus free ref to global
7. nearest enclosing scope
8. mixed freevars and cellvars
9. free variable in method
10. recursion
11. unoptimized namespaces
12. lambdas

249
Lib/test/test_scope.py Normal file
View File

@ -0,0 +1,249 @@
from test.test_support import verify, TestFailed
print "1. simple nesting"
def make_adder(x):
def adder(y):
return x + y
return adder
inc = make_adder(1)
plus10 = make_adder(10)
verify(inc(1) == 2)
verify(plus10(-2) == 8)
print "2. extra nesting"
def make_adder2(x):
def extra(): # check freevars passing through non-use scopes
def adder(y):
return x + y
return adder
return extra()
inc = make_adder2(1)
plus10 = make_adder2(10)
verify(inc(1) == 2)
verify(plus10(-2) == 8)
print "3. simple nesting + rebinding"
def make_adder3(x):
def adder(y):
return x + y
x = x + 1 # check tracking of assignment to x in defining scope
return adder
inc = make_adder3(0)
plus10 = make_adder3(9)
verify(inc(1) == 2)
verify(plus10(-2) == 8)
print "4. nesting with global but no free"
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 = 1
adder = make_adder4()
verify(adder(1) == 2)
global_x = 10
verify(adder(-2) == 8)
print "5. nesting through class"
def make_adder5(x):
class Adder:
def __call__(self, y):
return x + y
return Adder()
inc = make_adder5(1)
plus10 = make_adder5(10)
verify(inc(1) == 2)
verify(plus10(-2) == 8)
print "6. nesting plus free ref to global"
def make_adder6(x):
global global_nest_x
def adder(y):
return global_nest_x + y
global_nest_x = x
return adder
inc = make_adder6(1)
plus10 = make_adder6(10)
verify(inc(1) == 2)
verify(plus10(-2) == 8)
print "7. nearest enclosing scope"
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)
verify(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)
verify(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()
verify(t.test() == "var")
verify(t.method_and_var() == "method")
verify(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()
verify(t.test() == "var")
verify(t.method_and_var() == "method")
verify(t.actual_global() == "global")
print "10. recursion"
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"
verify(f(6) == 720)
print "11. unoptimized namespaces"
def check_syntax(s):
try:
compile(s, '?', 'exec')
except SyntaxError:
pass
else:
raise TestFailed
# XXX for now, it is easiest to call this a syntax error:
# explicit is better than implicit...
test1 = \
"""def unoptimized_clash1(strip):
def f(s):
from string import *
return strip(s) # ambiguity: free or local
return f
"""
check_syntax(test1)
# a little harder to reject this one, but possible...
test2 = \
"""def unoptimized_clash2():
from string import *
def f(s):
return strip(s) # ambiguity: global or local
return f
"""
# check_syntax(test2)
# XXX could allow this for exec with const argument, but what's the point
test3 = \
"""def error(y):
exec "a = 1"
def f(x):
return x + y
return f
"""
check_syntax(test3)
test4 = \
"""def f(x):
def g():
return x
del x
"""
check_syntax(test4)
print "12. lambdas"
f1 = lambda x: lambda y: x + y
inc = f1(1)
plus10 = f1(10)
verify(inc(1) == 2)
verify(plus10(5) == 15)
f2 = lambda x: (lambda : lambda y: x + y)()
inc = f2(1)
plus10 = f2(10)
verify(inc(1) == 2)
verify(plus10(5) == 15)
f3 = lambda x: lambda y: global_x + y
global_x = 1
inc = f3(None)
verify(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)
verify(h() == 18)