py-cvs-rel2_1 (Rev 1.2) merge
[python/dscho.git] / Lib / test / test_scope.py
blobcb06036677db320eea57ef1d22ec376599ae4c0f
1 from test.test_support import verify, TestFailed, check_syntax
3 print "1. simple nesting"
5 def make_adder(x):
6 def adder(y):
7 return x + y
8 return adder
10 inc = make_adder(1)
11 plus10 = make_adder(10)
13 verify(inc(1) == 2)
14 verify(plus10(-2) == 8)
16 print "2. extra nesting"
18 def make_adder2(x):
19 def extra(): # check freevars passing through non-use scopes
20 def adder(y):
21 return x + y
22 return adder
23 return extra()
25 inc = make_adder2(1)
26 plus10 = make_adder2(10)
28 verify(inc(1) == 2)
29 verify(plus10(-2) == 8)
31 print "3. simple nesting + rebinding"
33 def make_adder3(x):
34 def adder(y):
35 return x + y
36 x = x + 1 # check tracking of assignment to x in defining scope
37 return adder
39 inc = make_adder3(0)
40 plus10 = make_adder3(9)
42 verify(inc(1) == 2)
43 verify(plus10(-2) == 8)
45 print "4. nesting with global but no free"
47 def make_adder4(): # XXX add exta level of indirection
48 def nest():
49 def nest():
50 def adder(y):
51 return global_x + y # check that plain old globals work
52 return adder
53 return nest()
54 return nest()
56 global_x = 1
57 adder = make_adder4()
58 verify(adder(1) == 2)
60 global_x = 10
61 verify(adder(-2) == 8)
63 print "5. nesting through class"
65 def make_adder5(x):
66 class Adder:
67 def __call__(self, y):
68 return x + y
69 return Adder()
71 inc = make_adder5(1)
72 plus10 = make_adder5(10)
74 verify(inc(1) == 2)
75 verify(plus10(-2) == 8)
77 print "6. nesting plus free ref to global"
79 def make_adder6(x):
80 global global_nest_x
81 def adder(y):
82 return global_nest_x + y
83 global_nest_x = x
84 return adder
86 inc = make_adder6(1)
87 plus10 = make_adder6(10)
89 verify(inc(1) == 11) # there's only one global
90 verify(plus10(-2) == 8)
92 print "7. nearest enclosing scope"
94 def f(x):
95 def g(y):
96 x = 42 # check that this masks binding in f()
97 def h(z):
98 return x + z
99 return h
100 return g(2)
102 test_func = f(10)
103 verify(test_func(5) == 47)
105 print "8. mixed freevars and cellvars"
107 def identity(x):
108 return x
110 def f(x, y, z):
111 def g(a, b, c):
112 a = a + x # 3
113 def h():
114 # z * (4 + 9)
115 # 3 * 13
116 return identity(z * (b + y))
117 y = c + z # 9
118 return h
119 return g
121 g = f(1, 2, 3)
122 h = g(2, 4, 6)
123 verify(h() == 39)
125 print "9. free variable in method"
127 def test():
128 method_and_var = "var"
129 class Test:
130 def method_and_var(self):
131 return "method"
132 def test(self):
133 return method_and_var
134 def actual_global(self):
135 return str("global")
136 def str(self):
137 return str(self)
138 return Test()
140 t = test()
141 verify(t.test() == "var")
142 verify(t.method_and_var() == "method")
143 verify(t.actual_global() == "global")
145 method_and_var = "var"
146 class Test:
147 # this class is not nested, so the rules are different
148 def method_and_var(self):
149 return "method"
150 def test(self):
151 return method_and_var
152 def actual_global(self):
153 return str("global")
154 def str(self):
155 return str(self)
157 t = Test()
158 verify(t.test() == "var")
159 verify(t.method_and_var() == "method")
160 verify(t.actual_global() == "global")
162 print "10. recursion"
164 def f(x):
165 def fact(n):
166 if n == 0:
167 return 1
168 else:
169 return n * fact(n - 1)
170 if x >= 0:
171 return fact(x)
172 else:
173 raise ValueError, "x must be >= 0"
175 verify(f(6) == 720)
178 print "11. unoptimized namespaces"
180 check_syntax("""\
181 def unoptimized_clash1(strip):
182 def f(s):
183 from string import *
184 return strip(s) # ambiguity: free or local
185 return f
186 """)
188 check_syntax("""\
189 def unoptimized_clash2():
190 from string import *
191 def f(s):
192 return strip(s) # ambiguity: global or local
193 return f
194 """)
196 check_syntax("""\
197 def unoptimized_clash2():
198 from string import *
199 def g():
200 def f(s):
201 return strip(s) # ambiguity: global or local
202 return f
203 """)
205 # XXX could allow this for exec with const argument, but what's the point
206 check_syntax("""\
207 def error(y):
208 exec "a = 1"
209 def f(x):
210 return x + y
211 return f
212 """)
214 check_syntax("""\
215 def f(x):
216 def g():
217 return x
218 del x # can't del name
219 """)
221 check_syntax("""\
222 def f():
223 def g():
224 from string import *
225 return strip # global or local?
226 """)
228 # and verify a few cases that should work
230 def noproblem1():
231 from string import *
232 f = lambda x:x
234 def noproblem2():
235 from string import *
236 def f(x):
237 return x + 1
239 def noproblem3():
240 from string import *
241 def f(x):
242 global y
243 y = x
245 print "12. lambdas"
247 f1 = lambda x: lambda y: x + y
248 inc = f1(1)
249 plus10 = f1(10)
250 verify(inc(1) == 2)
251 verify(plus10(5) == 15)
253 f2 = lambda x: (lambda : lambda y: x + y)()
254 inc = f2(1)
255 plus10 = f2(10)
256 verify(inc(1) == 2)
257 verify(plus10(5) == 15)
259 f3 = lambda x: lambda y: global_x + y
260 global_x = 1
261 inc = f3(None)
262 verify(inc(2) == 3)
264 f8 = lambda x, y, z: lambda a, b, c: lambda : z * (b + y)
265 g = f8(1, 2, 3)
266 h = g(2, 4, 6)
267 verify(h() == 18)
269 print "13. UnboundLocal"
271 def errorInOuter():
272 print y
273 def inner():
274 return y
275 y = 1
277 def errorInInner():
278 def inner():
279 return y
280 inner()
281 y = 1
283 try:
284 errorInOuter()
285 except UnboundLocalError:
286 pass
287 else:
288 raise TestFailed
290 try:
291 errorInInner()
292 except NameError:
293 pass
294 else:
295 raise TestFailed
297 print "14. complex definitions"
299 def makeReturner(*lst):
300 def returner():
301 return lst
302 return returner
304 verify(makeReturner(1,2,3)() == (1,2,3))
306 def makeReturner2(**kwargs):
307 def returner():
308 return kwargs
309 return returner
311 verify(makeReturner2(a=11)()['a'] == 11)
313 def makeAddPair((a, b)):
314 def addPair((c, d)):
315 return (a + c, b + d)
316 return addPair
318 verify(makeAddPair((1, 2))((100, 200)) == (101,202))
320 print "15. scope of global statements"
321 # Examples posted by Samuele Pedroni to python-dev on 3/1/2001
324 x = 7
325 def f():
326 x = 1
327 def g():
328 global x
329 def i():
330 def h():
331 return x
332 return h()
333 return i()
334 return g()
335 verify(f() == 7)
336 verify(x == 7)
338 # II
339 x = 7
340 def f():
341 x = 1
342 def g():
343 x = 2
344 def i():
345 def h():
346 return x
347 return h()
348 return i()
349 return g()
350 verify(f() == 2)
351 verify(x == 7)
353 # III
354 x = 7
355 def f():
356 x = 1
357 def g():
358 global x
359 x = 2
360 def i():
361 def h():
362 return x
363 return h()
364 return i()
365 return g()
366 verify(f() == 2)
367 verify(x == 2)
369 # IV
370 x = 7
371 def f():
372 x = 3
373 def g():
374 global x
375 x = 2
376 def i():
377 def h():
378 return x
379 return h()
380 return i()
381 return g()
382 verify(f() == 2)
383 verify(x == 2)
385 print "16. check leaks"
387 class Foo:
388 count = 0
390 def __init__(self):
391 Foo.count += 1
393 def __del__(self):
394 Foo.count -= 1
396 def f1():
397 x = Foo()
398 def f2():
399 return x
400 f2()
402 for i in range(100):
403 f1()
405 verify(Foo.count == 0)
407 print "17. class and global"
409 def test(x):
410 class Foo:
411 global x
412 def __call__(self, y):
413 return x + y
414 return Foo()
416 x = 0
417 verify(test(6)(2) == 8)
418 x = -1
419 verify(test(3)(2) == 5)
421 print "18. verify that locals() works"
423 def f(x):
424 def g(y):
425 def h(z):
426 return y + z
427 w = x + y
428 y += 3
429 return locals()
430 return g
432 d = f(2)(4)
433 verify(d.has_key('h'))
434 del d['h']
435 verify(d == {'x': 2, 'y': 7, 'w': 6})
437 print "19. var is bound and free in class"
439 def f(x):
440 class C:
441 def m(self):
442 return x
443 a = x
444 return C
446 inst = f(3)()
447 verify(inst.a == inst.m())
449 print "20. interaction with trace function"
451 import sys
452 def tracer(a,b,c):
453 return tracer
455 def adaptgetter(name, klass, getter):
456 kind, des = getter
457 if kind == 1: # AV happens when stepping from this line to next
458 if des == "":
459 des = "_%s__%s" % (klass.__name__, name)
460 return lambda obj: getattr(obj, des)
462 class TestClass:
463 pass
465 sys.settrace(tracer)
466 adaptgetter("foo", TestClass, (1, ""))
467 sys.settrace(None)