1 import unittest
2 import weakref
3
4 from test.support import check_syntax_error, cpython_only
5 from test.support import gc_collect
6
7
8 class ESC[4;38;5;81mScopeTests(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
9
10 def testSimpleNesting(self):
11
12 def make_adder(x):
13 def adder(y):
14 return x + y
15 return adder
16
17 inc = make_adder(1)
18 plus10 = make_adder(10)
19
20 self.assertEqual(inc(1), 2)
21 self.assertEqual(plus10(-2), 8)
22
23 def testExtraNesting(self):
24
25 def make_adder2(x):
26 def extra(): # check freevars passing through non-use scopes
27 def adder(y):
28 return x + y
29 return adder
30 return extra()
31
32 inc = make_adder2(1)
33 plus10 = make_adder2(10)
34
35 self.assertEqual(inc(1), 2)
36 self.assertEqual(plus10(-2), 8)
37
38 def testSimpleAndRebinding(self):
39
40 def make_adder3(x):
41 def adder(y):
42 return x + y
43 x = x + 1 # check tracking of assignment to x in defining scope
44 return adder
45
46 inc = make_adder3(0)
47 plus10 = make_adder3(9)
48
49 self.assertEqual(inc(1), 2)
50 self.assertEqual(plus10(-2), 8)
51
52 def testNestingGlobalNoFree(self):
53
54 def make_adder4(): # XXX add exta level of indirection
55 def nest():
56 def nest():
57 def adder(y):
58 return global_x + y # check that plain old globals work
59 return adder
60 return nest()
61 return nest()
62
63 global_x = 1
64 adder = make_adder4()
65 self.assertEqual(adder(1), 2)
66
67 global_x = 10
68 self.assertEqual(adder(-2), 8)
69
70 def testNestingThroughClass(self):
71
72 def make_adder5(x):
73 class ESC[4;38;5;81mAdder:
74 def __call__(self, y):
75 return x + y
76 return Adder()
77
78 inc = make_adder5(1)
79 plus10 = make_adder5(10)
80
81 self.assertEqual(inc(1), 2)
82 self.assertEqual(plus10(-2), 8)
83
84 def testNestingPlusFreeRefToGlobal(self):
85
86 def make_adder6(x):
87 global global_nest_x
88 def adder(y):
89 return global_nest_x + y
90 global_nest_x = x
91 return adder
92
93 inc = make_adder6(1)
94 plus10 = make_adder6(10)
95
96 self.assertEqual(inc(1), 11) # there's only one global
97 self.assertEqual(plus10(-2), 8)
98
99 def testNearestEnclosingScope(self):
100
101 def f(x):
102 def g(y):
103 x = 42 # check that this masks binding in f()
104 def h(z):
105 return x + z
106 return h
107 return g(2)
108
109 test_func = f(10)
110 self.assertEqual(test_func(5), 47)
111
112 def testMixedFreevarsAndCellvars(self):
113
114 def identity(x):
115 return x
116
117 def f(x, y, z):
118 def g(a, b, c):
119 a = a + x # 3
120 def h():
121 # z * (4 + 9)
122 # 3 * 13
123 return identity(z * (b + y))
124 y = c + z # 9
125 return h
126 return g
127
128 g = f(1, 2, 3)
129 h = g(2, 4, 6)
130 self.assertEqual(h(), 39)
131
132 def testFreeVarInMethod(self):
133
134 def test():
135 method_and_var = "var"
136 class ESC[4;38;5;81mTest:
137 def method_and_var(self):
138 return "method"
139 def test(self):
140 return method_and_var
141 def actual_global(self):
142 return str("global")
143 def str(self):
144 return str(self)
145 return Test()
146
147 t = test()
148 self.assertEqual(t.test(), "var")
149 self.assertEqual(t.method_and_var(), "method")
150 self.assertEqual(t.actual_global(), "global")
151
152 method_and_var = "var"
153 class ESC[4;38;5;81mTest:
154 # this class is not nested, so the rules are different
155 def method_and_var(self):
156 return "method"
157 def test(self):
158 return method_and_var
159 def actual_global(self):
160 return str("global")
161 def str(self):
162 return str(self)
163
164 t = Test()
165 self.assertEqual(t.test(), "var")
166 self.assertEqual(t.method_and_var(), "method")
167 self.assertEqual(t.actual_global(), "global")
168
169 def testCellIsKwonlyArg(self):
170 # Issue 1409: Initialisation of a cell value,
171 # when it comes from a keyword-only parameter
172 def foo(*, a=17):
173 def bar():
174 return a + 5
175 return bar() + 3
176
177 self.assertEqual(foo(a=42), 50)
178 self.assertEqual(foo(), 25)
179
180 def testCellIsArgAndEscapes(self):
181 # We need to be sure that a cell passed in as an arg still
182 # gets wrapped in a new cell if the arg escapes into an
183 # inner function (closure).
184
185 def external():
186 value = 42
187 def inner():
188 return value
189 cell, = inner.__closure__
190 return cell
191 cell_ext = external()
192
193 def spam(arg):
194 def eggs():
195 return arg
196 return eggs
197
198 eggs = spam(cell_ext)
199 cell_closure, = eggs.__closure__
200 cell_eggs = eggs()
201
202 self.assertIs(cell_eggs, cell_ext)
203 self.assertIsNot(cell_eggs, cell_closure)
204
205 def testCellIsLocalAndEscapes(self):
206 # We need to be sure that a cell bound to a local still
207 # gets wrapped in a new cell if the local escapes into an
208 # inner function (closure).
209
210 def external():
211 value = 42
212 def inner():
213 return value
214 cell, = inner.__closure__
215 return cell
216 cell_ext = external()
217
218 def spam(arg):
219 cell = arg
220 def eggs():
221 return cell
222 return eggs
223
224 eggs = spam(cell_ext)
225 cell_closure, = eggs.__closure__
226 cell_eggs = eggs()
227
228 self.assertIs(cell_eggs, cell_ext)
229 self.assertIsNot(cell_eggs, cell_closure)
230
231 def testRecursion(self):
232
233 def f(x):
234 def fact(n):
235 if n == 0:
236 return 1
237 else:
238 return n * fact(n - 1)
239 if x >= 0:
240 return fact(x)
241 else:
242 raise ValueError("x must be >= 0")
243
244 self.assertEqual(f(6), 720)
245
246
247 def testUnoptimizedNamespaces(self):
248
249 check_syntax_error(self, """if 1:
250 def unoptimized_clash1(strip):
251 def f(s):
252 from sys import *
253 return getrefcount(s) # ambiguity: free or local
254 return f
255 """)
256
257 check_syntax_error(self, """if 1:
258 def unoptimized_clash2():
259 from sys import *
260 def f(s):
261 return getrefcount(s) # ambiguity: global or local
262 return f
263 """)
264
265 check_syntax_error(self, """if 1:
266 def unoptimized_clash2():
267 from sys import *
268 def g():
269 def f(s):
270 return getrefcount(s) # ambiguity: global or local
271 return f
272 """)
273
274 check_syntax_error(self, """if 1:
275 def f():
276 def g():
277 from sys import *
278 return getrefcount # global or local?
279 """)
280
281 def testLambdas(self):
282
283 f1 = lambda x: lambda y: x + y
284 inc = f1(1)
285 plus10 = f1(10)
286 self.assertEqual(inc(1), 2)
287 self.assertEqual(plus10(5), 15)
288
289 f2 = lambda x: (lambda : lambda y: x + y)()
290 inc = f2(1)
291 plus10 = f2(10)
292 self.assertEqual(inc(1), 2)
293 self.assertEqual(plus10(5), 15)
294
295 f3 = lambda x: lambda y: global_x + y
296 global_x = 1
297 inc = f3(None)
298 self.assertEqual(inc(2), 3)
299
300 f8 = lambda x, y, z: lambda a, b, c: lambda : z * (b + y)
301 g = f8(1, 2, 3)
302 h = g(2, 4, 6)
303 self.assertEqual(h(), 18)
304
305 def testUnboundLocal(self):
306
307 def errorInOuter():
308 print(y)
309 def inner():
310 return y
311 y = 1
312
313 def errorInInner():
314 def inner():
315 return y
316 inner()
317 y = 1
318
319 self.assertRaises(UnboundLocalError, errorInOuter)
320 self.assertRaises(NameError, errorInInner)
321
322 def testUnboundLocal_AfterDel(self):
323 # #4617: It is now legal to delete a cell variable.
324 # The following functions must obviously compile,
325 # and give the correct error when accessing the deleted name.
326 def errorInOuter():
327 y = 1
328 del y
329 print(y)
330 def inner():
331 return y
332
333 def errorInInner():
334 def inner():
335 return y
336 y = 1
337 del y
338 inner()
339
340 self.assertRaises(UnboundLocalError, errorInOuter)
341 self.assertRaises(NameError, errorInInner)
342
343 def testUnboundLocal_AugAssign(self):
344 # test for bug #1501934: incorrect LOAD/STORE_GLOBAL generation
345 exec("""if 1:
346 global_x = 1
347 def f():
348 global_x += 1
349 try:
350 f()
351 except UnboundLocalError:
352 pass
353 else:
354 fail('scope of global_x not correctly determined')
355 """, {'fail': self.fail})
356
357 def testComplexDefinitions(self):
358
359 def makeReturner(*lst):
360 def returner():
361 return lst
362 return returner
363
364 self.assertEqual(makeReturner(1,2,3)(), (1,2,3))
365
366 def makeReturner2(**kwargs):
367 def returner():
368 return kwargs
369 return returner
370
371 self.assertEqual(makeReturner2(a=11)()['a'], 11)
372
373 def testScopeOfGlobalStmt(self):
374 # Examples posted by Samuele Pedroni to python-dev on 3/1/2001
375
376 exec("""if 1:
377 # I
378 x = 7
379 def f():
380 x = 1
381 def g():
382 global x
383 def i():
384 def h():
385 return x
386 return h()
387 return i()
388 return g()
389 self.assertEqual(f(), 7)
390 self.assertEqual(x, 7)
391
392 # II
393 x = 7
394 def f():
395 x = 1
396 def g():
397 x = 2
398 def i():
399 def h():
400 return x
401 return h()
402 return i()
403 return g()
404 self.assertEqual(f(), 2)
405 self.assertEqual(x, 7)
406
407 # III
408 x = 7
409 def f():
410 x = 1
411 def g():
412 global x
413 x = 2
414 def i():
415 def h():
416 return x
417 return h()
418 return i()
419 return g()
420 self.assertEqual(f(), 2)
421 self.assertEqual(x, 2)
422
423 # IV
424 x = 7
425 def f():
426 x = 3
427 def g():
428 global x
429 x = 2
430 def i():
431 def h():
432 return x
433 return h()
434 return i()
435 return g()
436 self.assertEqual(f(), 2)
437 self.assertEqual(x, 2)
438
439 # XXX what about global statements in class blocks?
440 # do they affect methods?
441
442 x = 12
443 class Global:
444 global x
445 x = 13
446 def set(self, val):
447 x = val
448 def get(self):
449 return x
450
451 g = Global()
452 self.assertEqual(g.get(), 13)
453 g.set(15)
454 self.assertEqual(g.get(), 13)
455 """)
456
457 def testLeaks(self):
458
459 class ESC[4;38;5;81mFoo:
460 count = 0
461
462 def __init__(self):
463 Foo.count += 1
464
465 def __del__(self):
466 Foo.count -= 1
467
468 def f1():
469 x = Foo()
470 def f2():
471 return x
472 f2()
473
474 for i in range(100):
475 f1()
476
477 gc_collect() # For PyPy or other GCs.
478 self.assertEqual(Foo.count, 0)
479
480 def testClassAndGlobal(self):
481
482 exec("""if 1:
483 def test(x):
484 class Foo:
485 global x
486 def __call__(self, y):
487 return x + y
488 return Foo()
489
490 x = 0
491 self.assertEqual(test(6)(2), 8)
492 x = -1
493 self.assertEqual(test(3)(2), 5)
494
495 looked_up_by_load_name = False
496 class X:
497 # Implicit globals inside classes are be looked up by LOAD_NAME, not
498 # LOAD_GLOBAL.
499 locals()['looked_up_by_load_name'] = True
500 passed = looked_up_by_load_name
501
502 self.assertTrue(X.passed)
503 """)
504
505 def testLocalsFunction(self):
506
507 def f(x):
508 def g(y):
509 def h(z):
510 return y + z
511 w = x + y
512 y += 3
513 return locals()
514 return g
515
516 d = f(2)(4)
517 self.assertIn('h', d)
518 del d['h']
519 self.assertEqual(d, {'x': 2, 'y': 7, 'w': 6})
520
521 def testLocalsClass(self):
522 # This test verifies that calling locals() does not pollute
523 # the local namespace of the class with free variables. Old
524 # versions of Python had a bug, where a free variable being
525 # passed through a class namespace would be inserted into
526 # locals() by locals() or exec or a trace function.
527 #
528 # The real bug lies in frame code that copies variables
529 # between fast locals and the locals dict, e.g. when executing
530 # a trace function.
531
532 def f(x):
533 class ESC[4;38;5;81mC:
534 x = 12
535 def m(self):
536 return x
537 locals()
538 return C
539
540 self.assertEqual(f(1).x, 12)
541
542 def f(x):
543 class ESC[4;38;5;81mC:
544 y = x
545 def m(self):
546 return x
547 z = list(locals())
548 return C
549
550 varnames = f(1).z
551 self.assertNotIn("x", varnames)
552 self.assertIn("y", varnames)
553
554 @cpython_only
555 def testLocalsClass_WithTrace(self):
556 # Issue23728: after the trace function returns, the locals()
557 # dictionary is used to update all variables, this used to
558 # include free variables. But in class statements, free
559 # variables are not inserted...
560 import sys
561 self.addCleanup(sys.settrace, sys.gettrace())
562 sys.settrace(lambda a,b,c:None)
563 x = 12
564
565 class ESC[4;38;5;81mC:
566 def f(self):
567 return x
568
569 self.assertEqual(x, 12) # Used to raise UnboundLocalError
570
571 def testBoundAndFree(self):
572 # var is bound and free in class
573
574 def f(x):
575 class ESC[4;38;5;81mC:
576 def m(self):
577 return x
578 a = x
579 return C
580
581 inst = f(3)()
582 self.assertEqual(inst.a, inst.m())
583
584 @cpython_only
585 def testInteractionWithTraceFunc(self):
586
587 import sys
588 def tracer(a,b,c):
589 return tracer
590
591 def adaptgetter(name, klass, getter):
592 kind, des = getter
593 if kind == 1: # AV happens when stepping from this line to next
594 if des == "":
595 des = "_%s__%s" % (klass.__name__, name)
596 return lambda obj: getattr(obj, des)
597
598 class ESC[4;38;5;81mTestClass:
599 pass
600
601 self.addCleanup(sys.settrace, sys.gettrace())
602 sys.settrace(tracer)
603 adaptgetter("foo", TestClass, (1, ""))
604 sys.settrace(None)
605
606 self.assertRaises(TypeError, sys.settrace)
607
608 def testEvalExecFreeVars(self):
609
610 def f(x):
611 return lambda: x + 1
612
613 g = f(3)
614 self.assertRaises(TypeError, eval, g.__code__)
615
616 try:
617 exec(g.__code__, {})
618 except TypeError:
619 pass
620 else:
621 self.fail("exec should have failed, because code contained free vars")
622
623 def testListCompLocalVars(self):
624
625 try:
626 print(bad)
627 except NameError:
628 pass
629 else:
630 print("bad should not be defined")
631
632 def x():
633 [bad for s in 'a b' for bad in s.split()]
634
635 x()
636 try:
637 print(bad)
638 except NameError:
639 pass
640
641 def testEvalFreeVars(self):
642
643 def f(x):
644 def g():
645 x
646 eval("x + 1")
647 return g
648
649 f(4)()
650
651 def testFreeingCell(self):
652 # Test what happens when a finalizer accesses
653 # the cell where the object was stored.
654 class ESC[4;38;5;81mSpecial:
655 def __del__(self):
656 nestedcell_get()
657
658 def testNonLocalFunction(self):
659
660 def f(x):
661 def inc():
662 nonlocal x
663 x += 1
664 return x
665 def dec():
666 nonlocal x
667 x -= 1
668 return x
669 return inc, dec
670
671 inc, dec = f(0)
672 self.assertEqual(inc(), 1)
673 self.assertEqual(inc(), 2)
674 self.assertEqual(dec(), 1)
675 self.assertEqual(dec(), 0)
676
677 def testNonLocalMethod(self):
678 def f(x):
679 class ESC[4;38;5;81mc:
680 def inc(self):
681 nonlocal x
682 x += 1
683 return x
684 def dec(self):
685 nonlocal x
686 x -= 1
687 return x
688 return c()
689 c = f(0)
690 self.assertEqual(c.inc(), 1)
691 self.assertEqual(c.inc(), 2)
692 self.assertEqual(c.dec(), 1)
693 self.assertEqual(c.dec(), 0)
694
695 def testGlobalInParallelNestedFunctions(self):
696 # A symbol table bug leaked the global statement from one
697 # function to other nested functions in the same block.
698 # This test verifies that a global statement in the first
699 # function does not affect the second function.
700 local_ns = {}
701 global_ns = {}
702 exec("""if 1:
703 def f():
704 y = 1
705 def g():
706 global y
707 return y
708 def h():
709 return y + 1
710 return g, h
711 y = 9
712 g, h = f()
713 result9 = g()
714 result2 = h()
715 """, local_ns, global_ns)
716 self.assertEqual(2, global_ns["result2"])
717 self.assertEqual(9, global_ns["result9"])
718
719 def testNonLocalClass(self):
720
721 def f(x):
722 class ESC[4;38;5;81mc:
723 nonlocal x
724 x += 1
725 def get(self):
726 return x
727 return c()
728
729 c = f(0)
730 self.assertEqual(c.get(), 1)
731 self.assertNotIn("x", c.__class__.__dict__)
732
733
734 def testNonLocalGenerator(self):
735
736 def f(x):
737 def g(y):
738 nonlocal x
739 for i in range(y):
740 x += 1
741 yield x
742 return g
743
744 g = f(0)
745 self.assertEqual(list(g(5)), [1, 2, 3, 4, 5])
746
747 def testNestedNonLocal(self):
748
749 def f(x):
750 def g():
751 nonlocal x
752 x -= 2
753 def h():
754 nonlocal x
755 x += 4
756 return x
757 return h
758 return g
759
760 g = f(1)
761 h = g()
762 self.assertEqual(h(), 3)
763
764 def testTopIsNotSignificant(self):
765 # See #9997.
766 def top(a):
767 pass
768 def b():
769 global a
770
771 def testClassNamespaceOverridesClosure(self):
772 # See #17853.
773 x = 42
774 class ESC[4;38;5;81mX:
775 locals()["x"] = 43
776 y = x
777 self.assertEqual(X.y, 43)
778 class ESC[4;38;5;81mX:
779 locals()["x"] = 43
780 del x
781 self.assertFalse(hasattr(X, "x"))
782 self.assertEqual(x, 42)
783
784 @cpython_only
785 def testCellLeak(self):
786 # Issue 17927.
787 #
788 # The issue was that if self was part of a cycle involving the
789 # frame of a method call, *and* the method contained a nested
790 # function referencing self, thereby forcing 'self' into a
791 # cell, setting self to None would not be enough to break the
792 # frame -- the frame had another reference to the instance,
793 # which could not be cleared by the code running in the frame
794 # (though it will be cleared when the frame is collected).
795 # Without the lambda, setting self to None is enough to break
796 # the cycle.
797 class ESC[4;38;5;81mTester:
798 def dig(self):
799 if 0:
800 lambda: self
801 try:
802 1/0
803 except Exception as exc:
804 self.exc = exc
805 self = None # Break the cycle
806 tester = Tester()
807 tester.dig()
808 ref = weakref.ref(tester)
809 del tester
810 gc_collect() # For PyPy or other GCs.
811 self.assertIsNone(ref())
812
813
814 if __name__ == '__main__':
815 unittest.main()