1import unittest 2import weakref 3 4from test.support import check_syntax_error, cpython_only 5from test.support import gc_collect 6 7 8class ScopeTests(unittest.TestCase): 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 Adder: 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 Test: 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 Test: 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 Foo: 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 C: 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 C: 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 C: 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 C: 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 TestClass: 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 Special: 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 c: 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 c: 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 X: 775 locals()["x"] = 43 776 y = x 777 self.assertEqual(X.y, 43) 778 class X: 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 Tester: 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 814if __name__ == '__main__': 815 unittest.main() 816