blob: fb5379067d68c0813f476535acba96f4313d69d9 [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 Hylton5941d192001-02-27 20:23:58 +0000182check_syntax("""from __future__ import nested_scopes
183def unoptimized_clash1(strip):
Jeremy Hylton4588c782001-01-25 20:11:23 +0000184 def f(s):
185 from string import *
186 return strip(s) # ambiguity: free or local
187 return f
Jeremy Hylton97a01672001-02-09 22:56:46 +0000188""")
Jeremy Hylton4588c782001-01-25 20:11:23 +0000189
Jeremy Hylton5941d192001-02-27 20:23:58 +0000190check_syntax("""from __future__ import nested_scopes
191def unoptimized_clash2():
Jeremy Hylton4588c782001-01-25 20:11:23 +0000192 from string import *
193 def f(s):
194 return strip(s) # ambiguity: global or local
195 return f
Jeremy Hylton97a01672001-02-09 22:56:46 +0000196""")
Jeremy Hylton4588c782001-01-25 20:11:23 +0000197
Jeremy Hylton5941d192001-02-27 20:23:58 +0000198check_syntax("""from __future__ import nested_scopes
199def unoptimized_clash2():
Jeremy Hylton97a01672001-02-09 22:56:46 +0000200 from string import *
201 def g():
202 def f(s):
203 return strip(s) # ambiguity: global or local
204 return f
205""")
206
Tim Peters0e6d2132001-02-15 23:56:39 +0000207# XXX could allow this for exec with const argument, but what's the point
Jeremy Hylton5941d192001-02-27 20:23:58 +0000208check_syntax("""from __future__ import nested_scopes
209def error(y):
Jeremy Hylton4588c782001-01-25 20:11:23 +0000210 exec "a = 1"
211 def f(x):
212 return x + y
213 return f
Jeremy Hylton97a01672001-02-09 22:56:46 +0000214""")
Jeremy Hylton4588c782001-01-25 20:11:23 +0000215
Jeremy Hylton5941d192001-02-27 20:23:58 +0000216check_syntax("""from __future__ import nested_scopes
217def f(x):
Jeremy Hylton4588c782001-01-25 20:11:23 +0000218 def g():
219 return x
Jeremy Hylton97a01672001-02-09 22:56:46 +0000220 del x # can't del name
221""")
222
Jeremy Hylton5941d192001-02-27 20:23:58 +0000223check_syntax("""from __future__ import nested_scopes
224def f():
Jeremy Hylton97a01672001-02-09 22:56:46 +0000225 def g():
226 from string import *
227 return strip # global or local?
Tim Peters0e6d2132001-02-15 23:56:39 +0000228""")
Jeremy Hylton97a01672001-02-09 22:56:46 +0000229
230# and verify a few cases that should work
231
232def noproblem1():
233 from string import *
234 f = lambda x:x
235
236def noproblem2():
237 from string import *
238 def f(x):
239 return x + 1
240
241def noproblem3():
242 from string import *
243 def f(x):
244 global y
245 y = x
Jeremy Hylton4588c782001-01-25 20:11:23 +0000246
247print "12. lambdas"
248
249f1 = lambda x: lambda y: x + y
250inc = f1(1)
251plus10 = f1(10)
252verify(inc(1) == 2)
253verify(plus10(5) == 15)
254
255f2 = lambda x: (lambda : lambda y: x + y)()
256inc = f2(1)
257plus10 = f2(10)
258verify(inc(1) == 2)
259verify(plus10(5) == 15)
260
261f3 = lambda x: lambda y: global_x + y
262global_x = 1
263inc = f3(None)
264verify(inc(2) == 3)
265
266f8 = lambda x, y, z: lambda a, b, c: lambda : z * (b + y)
267g = f8(1, 2, 3)
268h = g(2, 4, 6)
269verify(h() == 18)
Jeremy Hyltonde602482001-02-05 17:35:20 +0000270
271print "13. UnboundLocal"
272
273def errorInOuter():
274 print y
275 def inner():
276 return y
277 y = 1
278
279def errorInInner():
280 def inner():
281 return y
282 inner()
283 y = 1
284
285try:
286 errorInOuter()
287except UnboundLocalError:
288 pass
289else:
290 raise TestFailed
291
292try:
293 errorInInner()
Jeremy Hyltonc76770c2001-04-13 16:51:46 +0000294except NameError:
Jeremy Hyltonde602482001-02-05 17:35:20 +0000295 pass
296else:
297 raise TestFailed
Jeremy Hylton97a01672001-02-09 22:56:46 +0000298
299print "14. complex definitions"
300
301def makeReturner(*lst):
302 def returner():
303 return lst
304 return returner
Tim Peters0e6d2132001-02-15 23:56:39 +0000305
Jeremy Hylton97a01672001-02-09 22:56:46 +0000306verify(makeReturner(1,2,3)() == (1,2,3))
Tim Peters0e6d2132001-02-15 23:56:39 +0000307
Jeremy Hylton97a01672001-02-09 22:56:46 +0000308def makeReturner2(**kwargs):
309 def returner():
310 return kwargs
311 return returner
312
313verify(makeReturner2(a=11)()['a'] == 11)
314
315def makeAddPair((a, b)):
316 def addPair((c, d)):
317 return (a + c, b + d)
318 return addPair
319
320verify(makeAddPair((1, 2))((100, 200)) == (101,202))
Guido van Rossum9aa643c2001-03-01 20:35:45 +0000321
322print "15. scope of global statements"
323# Examples posted by Samuele Pedroni to python-dev on 3/1/2001
324
325# I
326x = 7
327def f():
328 x = 1
329 def g():
330 global x
331 def i():
332 def h():
333 return x
334 return h()
335 return i()
336 return g()
337verify(f() == 7)
338verify(x == 7)
339
340# II
341x = 7
342def f():
343 x = 1
344 def g():
345 x = 2
346 def i():
347 def h():
348 return x
349 return h()
350 return i()
351 return g()
352verify(f() == 2)
353verify(x == 7)
354
355# III
356x = 7
357def f():
358 x = 1
359 def g():
360 global x
361 x = 2
362 def i():
363 def h():
364 return x
365 return h()
366 return i()
367 return g()
368verify(f() == 2)
369verify(x == 2)
370
371# IV
372x = 7
373def f():
374 x = 3
375 def g():
376 global x
377 x = 2
378 def i():
379 def h():
380 return x
381 return h()
382 return i()
383 return g()
384verify(f() == 2)
385verify(x == 2)
Jeremy Hylton5b44a672001-03-13 02:01:12 +0000386
387print "16. check leaks"
388
389class Foo:
390 count = 0
Tim Peters30edd232001-03-16 08:29:48 +0000391
Jeremy Hylton5b44a672001-03-13 02:01:12 +0000392 def __init__(self):
393 Foo.count += 1
394
395 def __del__(self):
396 Foo.count -= 1
397
398def f1():
399 x = Foo()
400 def f2():
401 return x
402 f2()
Tim Peters30edd232001-03-16 08:29:48 +0000403
Jeremy Hylton5b44a672001-03-13 02:01:12 +0000404for i in range(100):
405 f1()
406
407verify(Foo.count == 0)
Jeremy Hylton5c7a2512001-03-21 16:44:39 +0000408
409print "17. class and global"
410
411def test(x):
412 class Foo:
413 global x
414 def __call__(self, y):
415 return x + y
416 return Foo()
417
418x = 0
419verify(test(6)(2) == 8)
420x = -1
421verify(test(3)(2) == 5)
422
423print "18. verify that locals() works"
424
425def f(x):
426 def g(y):
427 def h(z):
428 return y + z
429 w = x + y
430 y += 3
431 return locals()
432 return g
433
434d = f(2)(4)
435verify(d.has_key('h'))
436del d['h']
437verify(d == {'x': 2, 'y': 7, 'w': 6})
Jeremy Hyltonc76770c2001-04-13 16:51:46 +0000438
Jeremy Hyltonddc4fd02001-04-27 02:29:40 +0000439print "19. var is bound and free in class"
440
441def f(x):
442 class C:
443 def m(self):
444 return x
445 a = x
446 return C
447
448inst = f(3)()
449verify(inst.a == inst.m())
Jeremy Hylton4c889012001-05-08 04:08:59 +0000450
451print "20. interaction with trace function"
452
453import sys
454def tracer(a,b,c):
455 return tracer
456
457def adaptgetter(name, klass, getter):
458 kind, des = getter
459 if kind == 1: # AV happens when stepping from this line to next
460 if des == "":
461 des = "_%s__%s" % (klass.__name__, name)
462 return lambda obj: getattr(obj, des)
463
464class TestClass:
465 pass
466
467sys.settrace(tracer)
468adaptgetter("foo", TestClass, (1, ""))
469sys.settrace(None)