blob: d64cead91d8b67dd02f655be01a4bfd55e710722 [file] [log] [blame]
Jeremy Hylton29906ee2001-02-27 04:23:34 +00001from __future__ import nested_scopes
2
Jeremy Hylton47793992001-02-19 15:35:26 +00003from test.test_support import verify, TestFailed, check_syntax
Jeremy Hylton4588c782001-01-25 20:11:23 +00004
5print "1. simple nesting"
6
7def make_adder(x):
8 def adder(y):
9 return x + y
10 return adder
11
12inc = make_adder(1)
13plus10 = make_adder(10)
14
15verify(inc(1) == 2)
16verify(plus10(-2) == 8)
17
18print "2. extra nesting"
19
20def make_adder2(x):
21 def extra(): # check freevars passing through non-use scopes
22 def adder(y):
23 return x + y
24 return adder
25 return extra()
26
27inc = make_adder2(1)
28plus10 = make_adder2(10)
29
30verify(inc(1) == 2)
31verify(plus10(-2) == 8)
32
33print "3. simple nesting + rebinding"
34
35def make_adder3(x):
36 def adder(y):
37 return x + y
38 x = x + 1 # check tracking of assignment to x in defining scope
39 return adder
40
41inc = make_adder3(0)
42plus10 = make_adder3(9)
43
44verify(inc(1) == 2)
45verify(plus10(-2) == 8)
46
47print "4. nesting with global but no free"
48
49def make_adder4(): # XXX add exta level of indirection
50 def nest():
51 def nest():
52 def adder(y):
53 return global_x + y # check that plain old globals work
54 return adder
55 return nest()
56 return nest()
57
58global_x = 1
59adder = make_adder4()
60verify(adder(1) == 2)
61
62global_x = 10
63verify(adder(-2) == 8)
64
65print "5. nesting through class"
66
67def make_adder5(x):
68 class Adder:
69 def __call__(self, y):
70 return x + y
71 return Adder()
72
73inc = make_adder5(1)
74plus10 = make_adder5(10)
75
76verify(inc(1) == 2)
77verify(plus10(-2) == 8)
78
79print "6. nesting plus free ref to global"
80
81def make_adder6(x):
82 global global_nest_x
83 def adder(y):
84 return global_nest_x + y
85 global_nest_x = x
86 return adder
87
88inc = make_adder6(1)
89plus10 = make_adder6(10)
90
Jeremy Hylton251ef962001-01-30 01:26:53 +000091verify(inc(1) == 11) # there's only one global
Jeremy Hylton4588c782001-01-25 20:11:23 +000092verify(plus10(-2) == 8)
93
94print "7. nearest enclosing scope"
95
96def f(x):
97 def g(y):
98 x = 42 # check that this masks binding in f()
99 def h(z):
100 return x + z
101 return h
102 return g(2)
103
104test_func = f(10)
105verify(test_func(5) == 47)
106
107print "8. mixed freevars and cellvars"
108
109def identity(x):
Tim Peters10fb3862001-02-09 20:17:14 +0000110 return x
Jeremy Hylton4588c782001-01-25 20:11:23 +0000111
112def f(x, y, z):
113 def g(a, b, c):
114 a = a + x # 3
115 def h():
Tim Peters10fb3862001-02-09 20:17:14 +0000116 # z * (4 + 9)
117 # 3 * 13
Jeremy Hylton4588c782001-01-25 20:11:23 +0000118 return identity(z * (b + y))
119 y = c + z # 9
120 return h
121 return g
122
123g = f(1, 2, 3)
124h = g(2, 4, 6)
Tim Peters10fb3862001-02-09 20:17:14 +0000125verify(h() == 39)
Jeremy Hylton4588c782001-01-25 20:11:23 +0000126
127print "9. free variable in method"
128
129def test():
130 method_and_var = "var"
131 class Test:
132 def method_and_var(self):
133 return "method"
134 def test(self):
135 return method_and_var
136 def actual_global(self):
137 return str("global")
138 def str(self):
139 return str(self)
140 return Test()
141
142t = test()
143verify(t.test() == "var")
144verify(t.method_and_var() == "method")
145verify(t.actual_global() == "global")
146
147method_and_var = "var"
148class Test:
149 # this class is not nested, so the rules are different
150 def method_and_var(self):
151 return "method"
152 def test(self):
153 return method_and_var
154 def actual_global(self):
155 return str("global")
156 def str(self):
157 return str(self)
158
Jeremy Hyltonde602482001-02-05 17:35:20 +0000159t = Test()
Jeremy Hylton4588c782001-01-25 20:11:23 +0000160verify(t.test() == "var")
161verify(t.method_and_var() == "method")
162verify(t.actual_global() == "global")
163
164print "10. recursion"
165
166def f(x):
167 def fact(n):
168 if n == 0:
169 return 1
170 else:
171 return n * fact(n - 1)
172 if x >= 0:
173 return fact(x)
174 else:
175 raise ValueError, "x must be >= 0"
176
177verify(f(6) == 720)
178
179
180print "11. unoptimized namespaces"
181
Jeremy Hylton97a01672001-02-09 22:56:46 +0000182check_syntax("""def unoptimized_clash1(strip):
Jeremy Hylton4588c782001-01-25 20:11:23 +0000183 def f(s):
184 from string import *
185 return strip(s) # ambiguity: free or local
186 return f
Jeremy Hylton97a01672001-02-09 22:56:46 +0000187""")
Jeremy Hylton4588c782001-01-25 20:11:23 +0000188
Jeremy Hylton97a01672001-02-09 22:56:46 +0000189check_syntax("""def unoptimized_clash2():
Jeremy Hylton4588c782001-01-25 20:11:23 +0000190 from string import *
191 def f(s):
192 return strip(s) # ambiguity: global or local
193 return f
Jeremy Hylton97a01672001-02-09 22:56:46 +0000194""")
Jeremy Hylton4588c782001-01-25 20:11:23 +0000195
Jeremy Hylton97a01672001-02-09 22:56:46 +0000196check_syntax("""def unoptimized_clash2():
197 from string import *
198 def g():
199 def f(s):
200 return strip(s) # ambiguity: global or local
201 return f
202""")
203
Tim Peters0e6d2132001-02-15 23:56:39 +0000204# XXX could allow this for exec with const argument, but what's the point
Jeremy Hylton97a01672001-02-09 22:56:46 +0000205check_syntax("""def error(y):
Jeremy Hylton4588c782001-01-25 20:11:23 +0000206 exec "a = 1"
207 def f(x):
208 return x + y
209 return f
Jeremy Hylton97a01672001-02-09 22:56:46 +0000210""")
Jeremy Hylton4588c782001-01-25 20:11:23 +0000211
Jeremy Hylton97a01672001-02-09 22:56:46 +0000212check_syntax("""def f(x):
Jeremy Hylton4588c782001-01-25 20:11:23 +0000213 def g():
214 return x
Jeremy Hylton97a01672001-02-09 22:56:46 +0000215 del x # can't del name
216""")
217
218check_syntax("""def f():
219 def g():
220 from string import *
221 return strip # global or local?
Tim Peters0e6d2132001-02-15 23:56:39 +0000222""")
Jeremy Hylton97a01672001-02-09 22:56:46 +0000223
224# and verify a few cases that should work
225
226def noproblem1():
227 from string import *
228 f = lambda x:x
229
230def noproblem2():
231 from string import *
232 def f(x):
233 return x + 1
234
235def noproblem3():
236 from string import *
237 def f(x):
238 global y
239 y = x
Jeremy Hylton4588c782001-01-25 20:11:23 +0000240
241print "12. lambdas"
242
243f1 = lambda x: lambda y: x + y
244inc = f1(1)
245plus10 = f1(10)
246verify(inc(1) == 2)
247verify(plus10(5) == 15)
248
249f2 = lambda x: (lambda : lambda y: x + y)()
250inc = f2(1)
251plus10 = f2(10)
252verify(inc(1) == 2)
253verify(plus10(5) == 15)
254
255f3 = lambda x: lambda y: global_x + y
256global_x = 1
257inc = f3(None)
258verify(inc(2) == 3)
259
260f8 = lambda x, y, z: lambda a, b, c: lambda : z * (b + y)
261g = f8(1, 2, 3)
262h = g(2, 4, 6)
263verify(h() == 18)
Jeremy Hyltonde602482001-02-05 17:35:20 +0000264
265print "13. UnboundLocal"
266
267def errorInOuter():
268 print y
269 def inner():
270 return y
271 y = 1
272
273def errorInInner():
274 def inner():
275 return y
276 inner()
277 y = 1
278
279try:
280 errorInOuter()
281except UnboundLocalError:
282 pass
283else:
284 raise TestFailed
285
286try:
287 errorInInner()
288except UnboundLocalError:
289 pass
290else:
291 raise TestFailed
Jeremy Hylton97a01672001-02-09 22:56:46 +0000292
293print "14. complex definitions"
294
295def makeReturner(*lst):
296 def returner():
297 return lst
298 return returner
Tim Peters0e6d2132001-02-15 23:56:39 +0000299
Jeremy Hylton97a01672001-02-09 22:56:46 +0000300verify(makeReturner(1,2,3)() == (1,2,3))
Tim Peters0e6d2132001-02-15 23:56:39 +0000301
Jeremy Hylton97a01672001-02-09 22:56:46 +0000302def makeReturner2(**kwargs):
303 def returner():
304 return kwargs
305 return returner
306
307verify(makeReturner2(a=11)()['a'] == 11)
308
309def makeAddPair((a, b)):
310 def addPair((c, d)):
311 return (a + c, b + d)
312 return addPair
313
314verify(makeAddPair((1, 2))((100, 200)) == (101,202))