Update version number and release date.
[python/dscho.git] / Lib / test / test_scope.py
blobbf9a658478b20d6c3e5f8891200b37321bee428f
1 from test.test_support import verify, TestFailed, check_syntax
3 import warnings
4 warnings.filterwarnings("ignore", r"import \*", SyntaxWarning, "<string>")
6 print "1. simple nesting"
8 def make_adder(x):
9 def adder(y):
10 return x + y
11 return adder
13 inc = make_adder(1)
14 plus10 = make_adder(10)
16 verify(inc(1) == 2)
17 verify(plus10(-2) == 8)
19 print "2. extra nesting"
21 def make_adder2(x):
22 def extra(): # check freevars passing through non-use scopes
23 def adder(y):
24 return x + y
25 return adder
26 return extra()
28 inc = make_adder2(1)
29 plus10 = make_adder2(10)
31 verify(inc(1) == 2)
32 verify(plus10(-2) == 8)
34 print "3. simple nesting + rebinding"
36 def make_adder3(x):
37 def adder(y):
38 return x + y
39 x = x + 1 # check tracking of assignment to x in defining scope
40 return adder
42 inc = make_adder3(0)
43 plus10 = make_adder3(9)
45 verify(inc(1) == 2)
46 verify(plus10(-2) == 8)
48 print "4. nesting with global but no free"
50 def make_adder4(): # XXX add exta level of indirection
51 def nest():
52 def nest():
53 def adder(y):
54 return global_x + y # check that plain old globals work
55 return adder
56 return nest()
57 return nest()
59 global_x = 1
60 adder = make_adder4()
61 verify(adder(1) == 2)
63 global_x = 10
64 verify(adder(-2) == 8)
66 print "5. nesting through class"
68 def make_adder5(x):
69 class Adder:
70 def __call__(self, y):
71 return x + y
72 return Adder()
74 inc = make_adder5(1)
75 plus10 = make_adder5(10)
77 verify(inc(1) == 2)
78 verify(plus10(-2) == 8)
80 print "6. nesting plus free ref to global"
82 def make_adder6(x):
83 global global_nest_x
84 def adder(y):
85 return global_nest_x + y
86 global_nest_x = x
87 return adder
89 inc = make_adder6(1)
90 plus10 = make_adder6(10)
92 verify(inc(1) == 11) # there's only one global
93 verify(plus10(-2) == 8)
95 print "7. nearest enclosing scope"
97 def f(x):
98 def g(y):
99 x = 42 # check that this masks binding in f()
100 def h(z):
101 return x + z
102 return h
103 return g(2)
105 test_func = f(10)
106 verify(test_func(5) == 47)
108 print "8. mixed freevars and cellvars"
110 def identity(x):
111 return x
113 def f(x, y, z):
114 def g(a, b, c):
115 a = a + x # 3
116 def h():
117 # z * (4 + 9)
118 # 3 * 13
119 return identity(z * (b + y))
120 y = c + z # 9
121 return h
122 return g
124 g = f(1, 2, 3)
125 h = g(2, 4, 6)
126 verify(h() == 39)
128 print "9. free variable in method"
130 def test():
131 method_and_var = "var"
132 class Test:
133 def method_and_var(self):
134 return "method"
135 def test(self):
136 return method_and_var
137 def actual_global(self):
138 return str("global")
139 def str(self):
140 return str(self)
141 return Test()
143 t = test()
144 verify(t.test() == "var")
145 verify(t.method_and_var() == "method")
146 verify(t.actual_global() == "global")
148 method_and_var = "var"
149 class Test:
150 # this class is not nested, so the rules are different
151 def method_and_var(self):
152 return "method"
153 def test(self):
154 return method_and_var
155 def actual_global(self):
156 return str("global")
157 def str(self):
158 return str(self)
160 t = Test()
161 verify(t.test() == "var")
162 verify(t.method_and_var() == "method")
163 verify(t.actual_global() == "global")
165 print "10. recursion"
167 def f(x):
168 def fact(n):
169 if n == 0:
170 return 1
171 else:
172 return n * fact(n - 1)
173 if x >= 0:
174 return fact(x)
175 else:
176 raise ValueError, "x must be >= 0"
178 verify(f(6) == 720)
181 print "11. unoptimized namespaces"
183 check_syntax("""\
184 def unoptimized_clash1(strip):
185 def f(s):
186 from string import *
187 return strip(s) # ambiguity: free or local
188 return f
189 """)
191 check_syntax("""\
192 def unoptimized_clash2():
193 from string import *
194 def f(s):
195 return strip(s) # ambiguity: global or local
196 return f
197 """)
199 check_syntax("""\
200 def unoptimized_clash2():
201 from string import *
202 def g():
203 def f(s):
204 return strip(s) # ambiguity: global or local
205 return f
206 """)
208 # XXX could allow this for exec with const argument, but what's the point
209 check_syntax("""\
210 def error(y):
211 exec "a = 1"
212 def f(x):
213 return x + y
214 return f
215 """)
217 check_syntax("""\
218 def f(x):
219 def g():
220 return x
221 del x # can't del name
222 """)
224 check_syntax("""\
225 def f():
226 def g():
227 from string import *
228 return strip # global or local?
229 """)
231 # and verify a few cases that should work
233 exec """
234 def noproblem1():
235 from string import *
236 f = lambda x:x
238 def noproblem2():
239 from string import *
240 def f(x):
241 return x + 1
243 def noproblem3():
244 from string import *
245 def f(x):
246 global y
247 y = x
250 print "12. lambdas"
252 f1 = lambda x: lambda y: x + y
253 inc = f1(1)
254 plus10 = f1(10)
255 verify(inc(1) == 2)
256 verify(plus10(5) == 15)
258 f2 = lambda x: (lambda : lambda y: x + y)()
259 inc = f2(1)
260 plus10 = f2(10)
261 verify(inc(1) == 2)
262 verify(plus10(5) == 15)
264 f3 = lambda x: lambda y: global_x + y
265 global_x = 1
266 inc = f3(None)
267 verify(inc(2) == 3)
269 f8 = lambda x, y, z: lambda a, b, c: lambda : z * (b + y)
270 g = f8(1, 2, 3)
271 h = g(2, 4, 6)
272 verify(h() == 18)
274 print "13. UnboundLocal"
276 def errorInOuter():
277 print y
278 def inner():
279 return y
280 y = 1
282 def errorInInner():
283 def inner():
284 return y
285 inner()
286 y = 1
288 try:
289 errorInOuter()
290 except UnboundLocalError:
291 pass
292 else:
293 raise TestFailed
295 try:
296 errorInInner()
297 except NameError:
298 pass
299 else:
300 raise TestFailed
302 print "14. complex definitions"
304 def makeReturner(*lst):
305 def returner():
306 return lst
307 return returner
309 verify(makeReturner(1,2,3)() == (1,2,3))
311 def makeReturner2(**kwargs):
312 def returner():
313 return kwargs
314 return returner
316 verify(makeReturner2(a=11)()['a'] == 11)
318 def makeAddPair((a, b)):
319 def addPair((c, d)):
320 return (a + c, b + d)
321 return addPair
323 verify(makeAddPair((1, 2))((100, 200)) == (101,202))
325 print "15. scope of global statements"
326 # Examples posted by Samuele Pedroni to python-dev on 3/1/2001
329 x = 7
330 def f():
331 x = 1
332 def g():
333 global x
334 def i():
335 def h():
336 return x
337 return h()
338 return i()
339 return g()
340 verify(f() == 7)
341 verify(x == 7)
343 # II
344 x = 7
345 def f():
346 x = 1
347 def g():
348 x = 2
349 def i():
350 def h():
351 return x
352 return h()
353 return i()
354 return g()
355 verify(f() == 2)
356 verify(x == 7)
358 # III
359 x = 7
360 def f():
361 x = 1
362 def g():
363 global x
364 x = 2
365 def i():
366 def h():
367 return x
368 return h()
369 return i()
370 return g()
371 verify(f() == 2)
372 verify(x == 2)
374 # IV
375 x = 7
376 def f():
377 x = 3
378 def g():
379 global x
380 x = 2
381 def i():
382 def h():
383 return x
384 return h()
385 return i()
386 return g()
387 verify(f() == 2)
388 verify(x == 2)
390 print "16. check leaks"
392 class Foo:
393 count = 0
395 def __init__(self):
396 Foo.count += 1
398 def __del__(self):
399 Foo.count -= 1
401 def f1():
402 x = Foo()
403 def f2():
404 return x
405 f2()
407 for i in range(100):
408 f1()
410 verify(Foo.count == 0)
412 print "17. class and global"
414 def test(x):
415 class Foo:
416 global x
417 def __call__(self, y):
418 return x + y
419 return Foo()
421 x = 0
422 verify(test(6)(2) == 8)
423 x = -1
424 verify(test(3)(2) == 5)
426 print "18. verify that locals() works"
428 def f(x):
429 def g(y):
430 def h(z):
431 return y + z
432 w = x + y
433 y += 3
434 return locals()
435 return g
437 d = f(2)(4)
438 verify(d.has_key('h'))
439 del d['h']
440 verify(d == {'x': 2, 'y': 7, 'w': 6})
442 print "19. var is bound and free in class"
444 def f(x):
445 class C:
446 def m(self):
447 return x
448 a = x
449 return C
451 inst = f(3)()
452 verify(inst.a == inst.m())
454 print "20. interaction with trace function"
456 import sys
457 def tracer(a,b,c):
458 return tracer
460 def adaptgetter(name, klass, getter):
461 kind, des = getter
462 if kind == 1: # AV happens when stepping from this line to next
463 if des == "":
464 des = "_%s__%s" % (klass.__name__, name)
465 return lambda obj: getattr(obj, des)
467 class TestClass:
468 pass
470 sys.settrace(tracer)
471 adaptgetter("foo", TestClass, (1, ""))
472 sys.settrace(None)
474 try: sys.settrace()
475 except TypeError: pass
476 else: raise TestFailed, 'sys.settrace() did not raise TypeError'
478 print "20. eval and exec with free variables"
480 def f(x):
481 return lambda: x + 1
483 g = f(3)
484 try:
485 eval(g.func_code)
486 except TypeError:
487 pass
488 else:
489 print "eval() should have failed, because code contained free vars"
491 try:
492 exec g.func_code
493 except TypeError:
494 pass
495 else:
496 print "exec should have failed, because code contained free vars"
498 print "21. list comprehension with local variables"
500 try:
501 print bad
502 except NameError:
503 pass
504 else:
505 print "bad should not be defined"
507 def x():
508 [bad for s in 'a b' for bad in s.split()]
511 try:
512 print bad
513 except NameError:
514 pass
516 print "22. eval with free variables"
518 def f(x):
519 def g():
521 eval("x + 1")
522 return g
524 f(4)()