17db96d56Sopenharmony_ciimport unittest 27db96d56Sopenharmony_ciimport weakref 37db96d56Sopenharmony_ci 47db96d56Sopenharmony_cifrom test.support import check_syntax_error, cpython_only 57db96d56Sopenharmony_cifrom test.support import gc_collect 67db96d56Sopenharmony_ci 77db96d56Sopenharmony_ci 87db96d56Sopenharmony_ciclass ScopeTests(unittest.TestCase): 97db96d56Sopenharmony_ci 107db96d56Sopenharmony_ci def testSimpleNesting(self): 117db96d56Sopenharmony_ci 127db96d56Sopenharmony_ci def make_adder(x): 137db96d56Sopenharmony_ci def adder(y): 147db96d56Sopenharmony_ci return x + y 157db96d56Sopenharmony_ci return adder 167db96d56Sopenharmony_ci 177db96d56Sopenharmony_ci inc = make_adder(1) 187db96d56Sopenharmony_ci plus10 = make_adder(10) 197db96d56Sopenharmony_ci 207db96d56Sopenharmony_ci self.assertEqual(inc(1), 2) 217db96d56Sopenharmony_ci self.assertEqual(plus10(-2), 8) 227db96d56Sopenharmony_ci 237db96d56Sopenharmony_ci def testExtraNesting(self): 247db96d56Sopenharmony_ci 257db96d56Sopenharmony_ci def make_adder2(x): 267db96d56Sopenharmony_ci def extra(): # check freevars passing through non-use scopes 277db96d56Sopenharmony_ci def adder(y): 287db96d56Sopenharmony_ci return x + y 297db96d56Sopenharmony_ci return adder 307db96d56Sopenharmony_ci return extra() 317db96d56Sopenharmony_ci 327db96d56Sopenharmony_ci inc = make_adder2(1) 337db96d56Sopenharmony_ci plus10 = make_adder2(10) 347db96d56Sopenharmony_ci 357db96d56Sopenharmony_ci self.assertEqual(inc(1), 2) 367db96d56Sopenharmony_ci self.assertEqual(plus10(-2), 8) 377db96d56Sopenharmony_ci 387db96d56Sopenharmony_ci def testSimpleAndRebinding(self): 397db96d56Sopenharmony_ci 407db96d56Sopenharmony_ci def make_adder3(x): 417db96d56Sopenharmony_ci def adder(y): 427db96d56Sopenharmony_ci return x + y 437db96d56Sopenharmony_ci x = x + 1 # check tracking of assignment to x in defining scope 447db96d56Sopenharmony_ci return adder 457db96d56Sopenharmony_ci 467db96d56Sopenharmony_ci inc = make_adder3(0) 477db96d56Sopenharmony_ci plus10 = make_adder3(9) 487db96d56Sopenharmony_ci 497db96d56Sopenharmony_ci self.assertEqual(inc(1), 2) 507db96d56Sopenharmony_ci self.assertEqual(plus10(-2), 8) 517db96d56Sopenharmony_ci 527db96d56Sopenharmony_ci def testNestingGlobalNoFree(self): 537db96d56Sopenharmony_ci 547db96d56Sopenharmony_ci def make_adder4(): # XXX add exta level of indirection 557db96d56Sopenharmony_ci def nest(): 567db96d56Sopenharmony_ci def nest(): 577db96d56Sopenharmony_ci def adder(y): 587db96d56Sopenharmony_ci return global_x + y # check that plain old globals work 597db96d56Sopenharmony_ci return adder 607db96d56Sopenharmony_ci return nest() 617db96d56Sopenharmony_ci return nest() 627db96d56Sopenharmony_ci 637db96d56Sopenharmony_ci global_x = 1 647db96d56Sopenharmony_ci adder = make_adder4() 657db96d56Sopenharmony_ci self.assertEqual(adder(1), 2) 667db96d56Sopenharmony_ci 677db96d56Sopenharmony_ci global_x = 10 687db96d56Sopenharmony_ci self.assertEqual(adder(-2), 8) 697db96d56Sopenharmony_ci 707db96d56Sopenharmony_ci def testNestingThroughClass(self): 717db96d56Sopenharmony_ci 727db96d56Sopenharmony_ci def make_adder5(x): 737db96d56Sopenharmony_ci class Adder: 747db96d56Sopenharmony_ci def __call__(self, y): 757db96d56Sopenharmony_ci return x + y 767db96d56Sopenharmony_ci return Adder() 777db96d56Sopenharmony_ci 787db96d56Sopenharmony_ci inc = make_adder5(1) 797db96d56Sopenharmony_ci plus10 = make_adder5(10) 807db96d56Sopenharmony_ci 817db96d56Sopenharmony_ci self.assertEqual(inc(1), 2) 827db96d56Sopenharmony_ci self.assertEqual(plus10(-2), 8) 837db96d56Sopenharmony_ci 847db96d56Sopenharmony_ci def testNestingPlusFreeRefToGlobal(self): 857db96d56Sopenharmony_ci 867db96d56Sopenharmony_ci def make_adder6(x): 877db96d56Sopenharmony_ci global global_nest_x 887db96d56Sopenharmony_ci def adder(y): 897db96d56Sopenharmony_ci return global_nest_x + y 907db96d56Sopenharmony_ci global_nest_x = x 917db96d56Sopenharmony_ci return adder 927db96d56Sopenharmony_ci 937db96d56Sopenharmony_ci inc = make_adder6(1) 947db96d56Sopenharmony_ci plus10 = make_adder6(10) 957db96d56Sopenharmony_ci 967db96d56Sopenharmony_ci self.assertEqual(inc(1), 11) # there's only one global 977db96d56Sopenharmony_ci self.assertEqual(plus10(-2), 8) 987db96d56Sopenharmony_ci 997db96d56Sopenharmony_ci def testNearestEnclosingScope(self): 1007db96d56Sopenharmony_ci 1017db96d56Sopenharmony_ci def f(x): 1027db96d56Sopenharmony_ci def g(y): 1037db96d56Sopenharmony_ci x = 42 # check that this masks binding in f() 1047db96d56Sopenharmony_ci def h(z): 1057db96d56Sopenharmony_ci return x + z 1067db96d56Sopenharmony_ci return h 1077db96d56Sopenharmony_ci return g(2) 1087db96d56Sopenharmony_ci 1097db96d56Sopenharmony_ci test_func = f(10) 1107db96d56Sopenharmony_ci self.assertEqual(test_func(5), 47) 1117db96d56Sopenharmony_ci 1127db96d56Sopenharmony_ci def testMixedFreevarsAndCellvars(self): 1137db96d56Sopenharmony_ci 1147db96d56Sopenharmony_ci def identity(x): 1157db96d56Sopenharmony_ci return x 1167db96d56Sopenharmony_ci 1177db96d56Sopenharmony_ci def f(x, y, z): 1187db96d56Sopenharmony_ci def g(a, b, c): 1197db96d56Sopenharmony_ci a = a + x # 3 1207db96d56Sopenharmony_ci def h(): 1217db96d56Sopenharmony_ci # z * (4 + 9) 1227db96d56Sopenharmony_ci # 3 * 13 1237db96d56Sopenharmony_ci return identity(z * (b + y)) 1247db96d56Sopenharmony_ci y = c + z # 9 1257db96d56Sopenharmony_ci return h 1267db96d56Sopenharmony_ci return g 1277db96d56Sopenharmony_ci 1287db96d56Sopenharmony_ci g = f(1, 2, 3) 1297db96d56Sopenharmony_ci h = g(2, 4, 6) 1307db96d56Sopenharmony_ci self.assertEqual(h(), 39) 1317db96d56Sopenharmony_ci 1327db96d56Sopenharmony_ci def testFreeVarInMethod(self): 1337db96d56Sopenharmony_ci 1347db96d56Sopenharmony_ci def test(): 1357db96d56Sopenharmony_ci method_and_var = "var" 1367db96d56Sopenharmony_ci class Test: 1377db96d56Sopenharmony_ci def method_and_var(self): 1387db96d56Sopenharmony_ci return "method" 1397db96d56Sopenharmony_ci def test(self): 1407db96d56Sopenharmony_ci return method_and_var 1417db96d56Sopenharmony_ci def actual_global(self): 1427db96d56Sopenharmony_ci return str("global") 1437db96d56Sopenharmony_ci def str(self): 1447db96d56Sopenharmony_ci return str(self) 1457db96d56Sopenharmony_ci return Test() 1467db96d56Sopenharmony_ci 1477db96d56Sopenharmony_ci t = test() 1487db96d56Sopenharmony_ci self.assertEqual(t.test(), "var") 1497db96d56Sopenharmony_ci self.assertEqual(t.method_and_var(), "method") 1507db96d56Sopenharmony_ci self.assertEqual(t.actual_global(), "global") 1517db96d56Sopenharmony_ci 1527db96d56Sopenharmony_ci method_and_var = "var" 1537db96d56Sopenharmony_ci class Test: 1547db96d56Sopenharmony_ci # this class is not nested, so the rules are different 1557db96d56Sopenharmony_ci def method_and_var(self): 1567db96d56Sopenharmony_ci return "method" 1577db96d56Sopenharmony_ci def test(self): 1587db96d56Sopenharmony_ci return method_and_var 1597db96d56Sopenharmony_ci def actual_global(self): 1607db96d56Sopenharmony_ci return str("global") 1617db96d56Sopenharmony_ci def str(self): 1627db96d56Sopenharmony_ci return str(self) 1637db96d56Sopenharmony_ci 1647db96d56Sopenharmony_ci t = Test() 1657db96d56Sopenharmony_ci self.assertEqual(t.test(), "var") 1667db96d56Sopenharmony_ci self.assertEqual(t.method_and_var(), "method") 1677db96d56Sopenharmony_ci self.assertEqual(t.actual_global(), "global") 1687db96d56Sopenharmony_ci 1697db96d56Sopenharmony_ci def testCellIsKwonlyArg(self): 1707db96d56Sopenharmony_ci # Issue 1409: Initialisation of a cell value, 1717db96d56Sopenharmony_ci # when it comes from a keyword-only parameter 1727db96d56Sopenharmony_ci def foo(*, a=17): 1737db96d56Sopenharmony_ci def bar(): 1747db96d56Sopenharmony_ci return a + 5 1757db96d56Sopenharmony_ci return bar() + 3 1767db96d56Sopenharmony_ci 1777db96d56Sopenharmony_ci self.assertEqual(foo(a=42), 50) 1787db96d56Sopenharmony_ci self.assertEqual(foo(), 25) 1797db96d56Sopenharmony_ci 1807db96d56Sopenharmony_ci def testCellIsArgAndEscapes(self): 1817db96d56Sopenharmony_ci # We need to be sure that a cell passed in as an arg still 1827db96d56Sopenharmony_ci # gets wrapped in a new cell if the arg escapes into an 1837db96d56Sopenharmony_ci # inner function (closure). 1847db96d56Sopenharmony_ci 1857db96d56Sopenharmony_ci def external(): 1867db96d56Sopenharmony_ci value = 42 1877db96d56Sopenharmony_ci def inner(): 1887db96d56Sopenharmony_ci return value 1897db96d56Sopenharmony_ci cell, = inner.__closure__ 1907db96d56Sopenharmony_ci return cell 1917db96d56Sopenharmony_ci cell_ext = external() 1927db96d56Sopenharmony_ci 1937db96d56Sopenharmony_ci def spam(arg): 1947db96d56Sopenharmony_ci def eggs(): 1957db96d56Sopenharmony_ci return arg 1967db96d56Sopenharmony_ci return eggs 1977db96d56Sopenharmony_ci 1987db96d56Sopenharmony_ci eggs = spam(cell_ext) 1997db96d56Sopenharmony_ci cell_closure, = eggs.__closure__ 2007db96d56Sopenharmony_ci cell_eggs = eggs() 2017db96d56Sopenharmony_ci 2027db96d56Sopenharmony_ci self.assertIs(cell_eggs, cell_ext) 2037db96d56Sopenharmony_ci self.assertIsNot(cell_eggs, cell_closure) 2047db96d56Sopenharmony_ci 2057db96d56Sopenharmony_ci def testCellIsLocalAndEscapes(self): 2067db96d56Sopenharmony_ci # We need to be sure that a cell bound to a local still 2077db96d56Sopenharmony_ci # gets wrapped in a new cell if the local escapes into an 2087db96d56Sopenharmony_ci # inner function (closure). 2097db96d56Sopenharmony_ci 2107db96d56Sopenharmony_ci def external(): 2117db96d56Sopenharmony_ci value = 42 2127db96d56Sopenharmony_ci def inner(): 2137db96d56Sopenharmony_ci return value 2147db96d56Sopenharmony_ci cell, = inner.__closure__ 2157db96d56Sopenharmony_ci return cell 2167db96d56Sopenharmony_ci cell_ext = external() 2177db96d56Sopenharmony_ci 2187db96d56Sopenharmony_ci def spam(arg): 2197db96d56Sopenharmony_ci cell = arg 2207db96d56Sopenharmony_ci def eggs(): 2217db96d56Sopenharmony_ci return cell 2227db96d56Sopenharmony_ci return eggs 2237db96d56Sopenharmony_ci 2247db96d56Sopenharmony_ci eggs = spam(cell_ext) 2257db96d56Sopenharmony_ci cell_closure, = eggs.__closure__ 2267db96d56Sopenharmony_ci cell_eggs = eggs() 2277db96d56Sopenharmony_ci 2287db96d56Sopenharmony_ci self.assertIs(cell_eggs, cell_ext) 2297db96d56Sopenharmony_ci self.assertIsNot(cell_eggs, cell_closure) 2307db96d56Sopenharmony_ci 2317db96d56Sopenharmony_ci def testRecursion(self): 2327db96d56Sopenharmony_ci 2337db96d56Sopenharmony_ci def f(x): 2347db96d56Sopenharmony_ci def fact(n): 2357db96d56Sopenharmony_ci if n == 0: 2367db96d56Sopenharmony_ci return 1 2377db96d56Sopenharmony_ci else: 2387db96d56Sopenharmony_ci return n * fact(n - 1) 2397db96d56Sopenharmony_ci if x >= 0: 2407db96d56Sopenharmony_ci return fact(x) 2417db96d56Sopenharmony_ci else: 2427db96d56Sopenharmony_ci raise ValueError("x must be >= 0") 2437db96d56Sopenharmony_ci 2447db96d56Sopenharmony_ci self.assertEqual(f(6), 720) 2457db96d56Sopenharmony_ci 2467db96d56Sopenharmony_ci 2477db96d56Sopenharmony_ci def testUnoptimizedNamespaces(self): 2487db96d56Sopenharmony_ci 2497db96d56Sopenharmony_ci check_syntax_error(self, """if 1: 2507db96d56Sopenharmony_ci def unoptimized_clash1(strip): 2517db96d56Sopenharmony_ci def f(s): 2527db96d56Sopenharmony_ci from sys import * 2537db96d56Sopenharmony_ci return getrefcount(s) # ambiguity: free or local 2547db96d56Sopenharmony_ci return f 2557db96d56Sopenharmony_ci """) 2567db96d56Sopenharmony_ci 2577db96d56Sopenharmony_ci check_syntax_error(self, """if 1: 2587db96d56Sopenharmony_ci def unoptimized_clash2(): 2597db96d56Sopenharmony_ci from sys import * 2607db96d56Sopenharmony_ci def f(s): 2617db96d56Sopenharmony_ci return getrefcount(s) # ambiguity: global or local 2627db96d56Sopenharmony_ci return f 2637db96d56Sopenharmony_ci """) 2647db96d56Sopenharmony_ci 2657db96d56Sopenharmony_ci check_syntax_error(self, """if 1: 2667db96d56Sopenharmony_ci def unoptimized_clash2(): 2677db96d56Sopenharmony_ci from sys import * 2687db96d56Sopenharmony_ci def g(): 2697db96d56Sopenharmony_ci def f(s): 2707db96d56Sopenharmony_ci return getrefcount(s) # ambiguity: global or local 2717db96d56Sopenharmony_ci return f 2727db96d56Sopenharmony_ci """) 2737db96d56Sopenharmony_ci 2747db96d56Sopenharmony_ci check_syntax_error(self, """if 1: 2757db96d56Sopenharmony_ci def f(): 2767db96d56Sopenharmony_ci def g(): 2777db96d56Sopenharmony_ci from sys import * 2787db96d56Sopenharmony_ci return getrefcount # global or local? 2797db96d56Sopenharmony_ci """) 2807db96d56Sopenharmony_ci 2817db96d56Sopenharmony_ci def testLambdas(self): 2827db96d56Sopenharmony_ci 2837db96d56Sopenharmony_ci f1 = lambda x: lambda y: x + y 2847db96d56Sopenharmony_ci inc = f1(1) 2857db96d56Sopenharmony_ci plus10 = f1(10) 2867db96d56Sopenharmony_ci self.assertEqual(inc(1), 2) 2877db96d56Sopenharmony_ci self.assertEqual(plus10(5), 15) 2887db96d56Sopenharmony_ci 2897db96d56Sopenharmony_ci f2 = lambda x: (lambda : lambda y: x + y)() 2907db96d56Sopenharmony_ci inc = f2(1) 2917db96d56Sopenharmony_ci plus10 = f2(10) 2927db96d56Sopenharmony_ci self.assertEqual(inc(1), 2) 2937db96d56Sopenharmony_ci self.assertEqual(plus10(5), 15) 2947db96d56Sopenharmony_ci 2957db96d56Sopenharmony_ci f3 = lambda x: lambda y: global_x + y 2967db96d56Sopenharmony_ci global_x = 1 2977db96d56Sopenharmony_ci inc = f3(None) 2987db96d56Sopenharmony_ci self.assertEqual(inc(2), 3) 2997db96d56Sopenharmony_ci 3007db96d56Sopenharmony_ci f8 = lambda x, y, z: lambda a, b, c: lambda : z * (b + y) 3017db96d56Sopenharmony_ci g = f8(1, 2, 3) 3027db96d56Sopenharmony_ci h = g(2, 4, 6) 3037db96d56Sopenharmony_ci self.assertEqual(h(), 18) 3047db96d56Sopenharmony_ci 3057db96d56Sopenharmony_ci def testUnboundLocal(self): 3067db96d56Sopenharmony_ci 3077db96d56Sopenharmony_ci def errorInOuter(): 3087db96d56Sopenharmony_ci print(y) 3097db96d56Sopenharmony_ci def inner(): 3107db96d56Sopenharmony_ci return y 3117db96d56Sopenharmony_ci y = 1 3127db96d56Sopenharmony_ci 3137db96d56Sopenharmony_ci def errorInInner(): 3147db96d56Sopenharmony_ci def inner(): 3157db96d56Sopenharmony_ci return y 3167db96d56Sopenharmony_ci inner() 3177db96d56Sopenharmony_ci y = 1 3187db96d56Sopenharmony_ci 3197db96d56Sopenharmony_ci self.assertRaises(UnboundLocalError, errorInOuter) 3207db96d56Sopenharmony_ci self.assertRaises(NameError, errorInInner) 3217db96d56Sopenharmony_ci 3227db96d56Sopenharmony_ci def testUnboundLocal_AfterDel(self): 3237db96d56Sopenharmony_ci # #4617: It is now legal to delete a cell variable. 3247db96d56Sopenharmony_ci # The following functions must obviously compile, 3257db96d56Sopenharmony_ci # and give the correct error when accessing the deleted name. 3267db96d56Sopenharmony_ci def errorInOuter(): 3277db96d56Sopenharmony_ci y = 1 3287db96d56Sopenharmony_ci del y 3297db96d56Sopenharmony_ci print(y) 3307db96d56Sopenharmony_ci def inner(): 3317db96d56Sopenharmony_ci return y 3327db96d56Sopenharmony_ci 3337db96d56Sopenharmony_ci def errorInInner(): 3347db96d56Sopenharmony_ci def inner(): 3357db96d56Sopenharmony_ci return y 3367db96d56Sopenharmony_ci y = 1 3377db96d56Sopenharmony_ci del y 3387db96d56Sopenharmony_ci inner() 3397db96d56Sopenharmony_ci 3407db96d56Sopenharmony_ci self.assertRaises(UnboundLocalError, errorInOuter) 3417db96d56Sopenharmony_ci self.assertRaises(NameError, errorInInner) 3427db96d56Sopenharmony_ci 3437db96d56Sopenharmony_ci def testUnboundLocal_AugAssign(self): 3447db96d56Sopenharmony_ci # test for bug #1501934: incorrect LOAD/STORE_GLOBAL generation 3457db96d56Sopenharmony_ci exec("""if 1: 3467db96d56Sopenharmony_ci global_x = 1 3477db96d56Sopenharmony_ci def f(): 3487db96d56Sopenharmony_ci global_x += 1 3497db96d56Sopenharmony_ci try: 3507db96d56Sopenharmony_ci f() 3517db96d56Sopenharmony_ci except UnboundLocalError: 3527db96d56Sopenharmony_ci pass 3537db96d56Sopenharmony_ci else: 3547db96d56Sopenharmony_ci fail('scope of global_x not correctly determined') 3557db96d56Sopenharmony_ci """, {'fail': self.fail}) 3567db96d56Sopenharmony_ci 3577db96d56Sopenharmony_ci def testComplexDefinitions(self): 3587db96d56Sopenharmony_ci 3597db96d56Sopenharmony_ci def makeReturner(*lst): 3607db96d56Sopenharmony_ci def returner(): 3617db96d56Sopenharmony_ci return lst 3627db96d56Sopenharmony_ci return returner 3637db96d56Sopenharmony_ci 3647db96d56Sopenharmony_ci self.assertEqual(makeReturner(1,2,3)(), (1,2,3)) 3657db96d56Sopenharmony_ci 3667db96d56Sopenharmony_ci def makeReturner2(**kwargs): 3677db96d56Sopenharmony_ci def returner(): 3687db96d56Sopenharmony_ci return kwargs 3697db96d56Sopenharmony_ci return returner 3707db96d56Sopenharmony_ci 3717db96d56Sopenharmony_ci self.assertEqual(makeReturner2(a=11)()['a'], 11) 3727db96d56Sopenharmony_ci 3737db96d56Sopenharmony_ci def testScopeOfGlobalStmt(self): 3747db96d56Sopenharmony_ci # Examples posted by Samuele Pedroni to python-dev on 3/1/2001 3757db96d56Sopenharmony_ci 3767db96d56Sopenharmony_ci exec("""if 1: 3777db96d56Sopenharmony_ci # I 3787db96d56Sopenharmony_ci x = 7 3797db96d56Sopenharmony_ci def f(): 3807db96d56Sopenharmony_ci x = 1 3817db96d56Sopenharmony_ci def g(): 3827db96d56Sopenharmony_ci global x 3837db96d56Sopenharmony_ci def i(): 3847db96d56Sopenharmony_ci def h(): 3857db96d56Sopenharmony_ci return x 3867db96d56Sopenharmony_ci return h() 3877db96d56Sopenharmony_ci return i() 3887db96d56Sopenharmony_ci return g() 3897db96d56Sopenharmony_ci self.assertEqual(f(), 7) 3907db96d56Sopenharmony_ci self.assertEqual(x, 7) 3917db96d56Sopenharmony_ci 3927db96d56Sopenharmony_ci # II 3937db96d56Sopenharmony_ci x = 7 3947db96d56Sopenharmony_ci def f(): 3957db96d56Sopenharmony_ci x = 1 3967db96d56Sopenharmony_ci def g(): 3977db96d56Sopenharmony_ci x = 2 3987db96d56Sopenharmony_ci def i(): 3997db96d56Sopenharmony_ci def h(): 4007db96d56Sopenharmony_ci return x 4017db96d56Sopenharmony_ci return h() 4027db96d56Sopenharmony_ci return i() 4037db96d56Sopenharmony_ci return g() 4047db96d56Sopenharmony_ci self.assertEqual(f(), 2) 4057db96d56Sopenharmony_ci self.assertEqual(x, 7) 4067db96d56Sopenharmony_ci 4077db96d56Sopenharmony_ci # III 4087db96d56Sopenharmony_ci x = 7 4097db96d56Sopenharmony_ci def f(): 4107db96d56Sopenharmony_ci x = 1 4117db96d56Sopenharmony_ci def g(): 4127db96d56Sopenharmony_ci global x 4137db96d56Sopenharmony_ci x = 2 4147db96d56Sopenharmony_ci def i(): 4157db96d56Sopenharmony_ci def h(): 4167db96d56Sopenharmony_ci return x 4177db96d56Sopenharmony_ci return h() 4187db96d56Sopenharmony_ci return i() 4197db96d56Sopenharmony_ci return g() 4207db96d56Sopenharmony_ci self.assertEqual(f(), 2) 4217db96d56Sopenharmony_ci self.assertEqual(x, 2) 4227db96d56Sopenharmony_ci 4237db96d56Sopenharmony_ci # IV 4247db96d56Sopenharmony_ci x = 7 4257db96d56Sopenharmony_ci def f(): 4267db96d56Sopenharmony_ci x = 3 4277db96d56Sopenharmony_ci def g(): 4287db96d56Sopenharmony_ci global x 4297db96d56Sopenharmony_ci x = 2 4307db96d56Sopenharmony_ci def i(): 4317db96d56Sopenharmony_ci def h(): 4327db96d56Sopenharmony_ci return x 4337db96d56Sopenharmony_ci return h() 4347db96d56Sopenharmony_ci return i() 4357db96d56Sopenharmony_ci return g() 4367db96d56Sopenharmony_ci self.assertEqual(f(), 2) 4377db96d56Sopenharmony_ci self.assertEqual(x, 2) 4387db96d56Sopenharmony_ci 4397db96d56Sopenharmony_ci # XXX what about global statements in class blocks? 4407db96d56Sopenharmony_ci # do they affect methods? 4417db96d56Sopenharmony_ci 4427db96d56Sopenharmony_ci x = 12 4437db96d56Sopenharmony_ci class Global: 4447db96d56Sopenharmony_ci global x 4457db96d56Sopenharmony_ci x = 13 4467db96d56Sopenharmony_ci def set(self, val): 4477db96d56Sopenharmony_ci x = val 4487db96d56Sopenharmony_ci def get(self): 4497db96d56Sopenharmony_ci return x 4507db96d56Sopenharmony_ci 4517db96d56Sopenharmony_ci g = Global() 4527db96d56Sopenharmony_ci self.assertEqual(g.get(), 13) 4537db96d56Sopenharmony_ci g.set(15) 4547db96d56Sopenharmony_ci self.assertEqual(g.get(), 13) 4557db96d56Sopenharmony_ci """) 4567db96d56Sopenharmony_ci 4577db96d56Sopenharmony_ci def testLeaks(self): 4587db96d56Sopenharmony_ci 4597db96d56Sopenharmony_ci class Foo: 4607db96d56Sopenharmony_ci count = 0 4617db96d56Sopenharmony_ci 4627db96d56Sopenharmony_ci def __init__(self): 4637db96d56Sopenharmony_ci Foo.count += 1 4647db96d56Sopenharmony_ci 4657db96d56Sopenharmony_ci def __del__(self): 4667db96d56Sopenharmony_ci Foo.count -= 1 4677db96d56Sopenharmony_ci 4687db96d56Sopenharmony_ci def f1(): 4697db96d56Sopenharmony_ci x = Foo() 4707db96d56Sopenharmony_ci def f2(): 4717db96d56Sopenharmony_ci return x 4727db96d56Sopenharmony_ci f2() 4737db96d56Sopenharmony_ci 4747db96d56Sopenharmony_ci for i in range(100): 4757db96d56Sopenharmony_ci f1() 4767db96d56Sopenharmony_ci 4777db96d56Sopenharmony_ci gc_collect() # For PyPy or other GCs. 4787db96d56Sopenharmony_ci self.assertEqual(Foo.count, 0) 4797db96d56Sopenharmony_ci 4807db96d56Sopenharmony_ci def testClassAndGlobal(self): 4817db96d56Sopenharmony_ci 4827db96d56Sopenharmony_ci exec("""if 1: 4837db96d56Sopenharmony_ci def test(x): 4847db96d56Sopenharmony_ci class Foo: 4857db96d56Sopenharmony_ci global x 4867db96d56Sopenharmony_ci def __call__(self, y): 4877db96d56Sopenharmony_ci return x + y 4887db96d56Sopenharmony_ci return Foo() 4897db96d56Sopenharmony_ci 4907db96d56Sopenharmony_ci x = 0 4917db96d56Sopenharmony_ci self.assertEqual(test(6)(2), 8) 4927db96d56Sopenharmony_ci x = -1 4937db96d56Sopenharmony_ci self.assertEqual(test(3)(2), 5) 4947db96d56Sopenharmony_ci 4957db96d56Sopenharmony_ci looked_up_by_load_name = False 4967db96d56Sopenharmony_ci class X: 4977db96d56Sopenharmony_ci # Implicit globals inside classes are be looked up by LOAD_NAME, not 4987db96d56Sopenharmony_ci # LOAD_GLOBAL. 4997db96d56Sopenharmony_ci locals()['looked_up_by_load_name'] = True 5007db96d56Sopenharmony_ci passed = looked_up_by_load_name 5017db96d56Sopenharmony_ci 5027db96d56Sopenharmony_ci self.assertTrue(X.passed) 5037db96d56Sopenharmony_ci """) 5047db96d56Sopenharmony_ci 5057db96d56Sopenharmony_ci def testLocalsFunction(self): 5067db96d56Sopenharmony_ci 5077db96d56Sopenharmony_ci def f(x): 5087db96d56Sopenharmony_ci def g(y): 5097db96d56Sopenharmony_ci def h(z): 5107db96d56Sopenharmony_ci return y + z 5117db96d56Sopenharmony_ci w = x + y 5127db96d56Sopenharmony_ci y += 3 5137db96d56Sopenharmony_ci return locals() 5147db96d56Sopenharmony_ci return g 5157db96d56Sopenharmony_ci 5167db96d56Sopenharmony_ci d = f(2)(4) 5177db96d56Sopenharmony_ci self.assertIn('h', d) 5187db96d56Sopenharmony_ci del d['h'] 5197db96d56Sopenharmony_ci self.assertEqual(d, {'x': 2, 'y': 7, 'w': 6}) 5207db96d56Sopenharmony_ci 5217db96d56Sopenharmony_ci def testLocalsClass(self): 5227db96d56Sopenharmony_ci # This test verifies that calling locals() does not pollute 5237db96d56Sopenharmony_ci # the local namespace of the class with free variables. Old 5247db96d56Sopenharmony_ci # versions of Python had a bug, where a free variable being 5257db96d56Sopenharmony_ci # passed through a class namespace would be inserted into 5267db96d56Sopenharmony_ci # locals() by locals() or exec or a trace function. 5277db96d56Sopenharmony_ci # 5287db96d56Sopenharmony_ci # The real bug lies in frame code that copies variables 5297db96d56Sopenharmony_ci # between fast locals and the locals dict, e.g. when executing 5307db96d56Sopenharmony_ci # a trace function. 5317db96d56Sopenharmony_ci 5327db96d56Sopenharmony_ci def f(x): 5337db96d56Sopenharmony_ci class C: 5347db96d56Sopenharmony_ci x = 12 5357db96d56Sopenharmony_ci def m(self): 5367db96d56Sopenharmony_ci return x 5377db96d56Sopenharmony_ci locals() 5387db96d56Sopenharmony_ci return C 5397db96d56Sopenharmony_ci 5407db96d56Sopenharmony_ci self.assertEqual(f(1).x, 12) 5417db96d56Sopenharmony_ci 5427db96d56Sopenharmony_ci def f(x): 5437db96d56Sopenharmony_ci class C: 5447db96d56Sopenharmony_ci y = x 5457db96d56Sopenharmony_ci def m(self): 5467db96d56Sopenharmony_ci return x 5477db96d56Sopenharmony_ci z = list(locals()) 5487db96d56Sopenharmony_ci return C 5497db96d56Sopenharmony_ci 5507db96d56Sopenharmony_ci varnames = f(1).z 5517db96d56Sopenharmony_ci self.assertNotIn("x", varnames) 5527db96d56Sopenharmony_ci self.assertIn("y", varnames) 5537db96d56Sopenharmony_ci 5547db96d56Sopenharmony_ci @cpython_only 5557db96d56Sopenharmony_ci def testLocalsClass_WithTrace(self): 5567db96d56Sopenharmony_ci # Issue23728: after the trace function returns, the locals() 5577db96d56Sopenharmony_ci # dictionary is used to update all variables, this used to 5587db96d56Sopenharmony_ci # include free variables. But in class statements, free 5597db96d56Sopenharmony_ci # variables are not inserted... 5607db96d56Sopenharmony_ci import sys 5617db96d56Sopenharmony_ci self.addCleanup(sys.settrace, sys.gettrace()) 5627db96d56Sopenharmony_ci sys.settrace(lambda a,b,c:None) 5637db96d56Sopenharmony_ci x = 12 5647db96d56Sopenharmony_ci 5657db96d56Sopenharmony_ci class C: 5667db96d56Sopenharmony_ci def f(self): 5677db96d56Sopenharmony_ci return x 5687db96d56Sopenharmony_ci 5697db96d56Sopenharmony_ci self.assertEqual(x, 12) # Used to raise UnboundLocalError 5707db96d56Sopenharmony_ci 5717db96d56Sopenharmony_ci def testBoundAndFree(self): 5727db96d56Sopenharmony_ci # var is bound and free in class 5737db96d56Sopenharmony_ci 5747db96d56Sopenharmony_ci def f(x): 5757db96d56Sopenharmony_ci class C: 5767db96d56Sopenharmony_ci def m(self): 5777db96d56Sopenharmony_ci return x 5787db96d56Sopenharmony_ci a = x 5797db96d56Sopenharmony_ci return C 5807db96d56Sopenharmony_ci 5817db96d56Sopenharmony_ci inst = f(3)() 5827db96d56Sopenharmony_ci self.assertEqual(inst.a, inst.m()) 5837db96d56Sopenharmony_ci 5847db96d56Sopenharmony_ci @cpython_only 5857db96d56Sopenharmony_ci def testInteractionWithTraceFunc(self): 5867db96d56Sopenharmony_ci 5877db96d56Sopenharmony_ci import sys 5887db96d56Sopenharmony_ci def tracer(a,b,c): 5897db96d56Sopenharmony_ci return tracer 5907db96d56Sopenharmony_ci 5917db96d56Sopenharmony_ci def adaptgetter(name, klass, getter): 5927db96d56Sopenharmony_ci kind, des = getter 5937db96d56Sopenharmony_ci if kind == 1: # AV happens when stepping from this line to next 5947db96d56Sopenharmony_ci if des == "": 5957db96d56Sopenharmony_ci des = "_%s__%s" % (klass.__name__, name) 5967db96d56Sopenharmony_ci return lambda obj: getattr(obj, des) 5977db96d56Sopenharmony_ci 5987db96d56Sopenharmony_ci class TestClass: 5997db96d56Sopenharmony_ci pass 6007db96d56Sopenharmony_ci 6017db96d56Sopenharmony_ci self.addCleanup(sys.settrace, sys.gettrace()) 6027db96d56Sopenharmony_ci sys.settrace(tracer) 6037db96d56Sopenharmony_ci adaptgetter("foo", TestClass, (1, "")) 6047db96d56Sopenharmony_ci sys.settrace(None) 6057db96d56Sopenharmony_ci 6067db96d56Sopenharmony_ci self.assertRaises(TypeError, sys.settrace) 6077db96d56Sopenharmony_ci 6087db96d56Sopenharmony_ci def testEvalExecFreeVars(self): 6097db96d56Sopenharmony_ci 6107db96d56Sopenharmony_ci def f(x): 6117db96d56Sopenharmony_ci return lambda: x + 1 6127db96d56Sopenharmony_ci 6137db96d56Sopenharmony_ci g = f(3) 6147db96d56Sopenharmony_ci self.assertRaises(TypeError, eval, g.__code__) 6157db96d56Sopenharmony_ci 6167db96d56Sopenharmony_ci try: 6177db96d56Sopenharmony_ci exec(g.__code__, {}) 6187db96d56Sopenharmony_ci except TypeError: 6197db96d56Sopenharmony_ci pass 6207db96d56Sopenharmony_ci else: 6217db96d56Sopenharmony_ci self.fail("exec should have failed, because code contained free vars") 6227db96d56Sopenharmony_ci 6237db96d56Sopenharmony_ci def testListCompLocalVars(self): 6247db96d56Sopenharmony_ci 6257db96d56Sopenharmony_ci try: 6267db96d56Sopenharmony_ci print(bad) 6277db96d56Sopenharmony_ci except NameError: 6287db96d56Sopenharmony_ci pass 6297db96d56Sopenharmony_ci else: 6307db96d56Sopenharmony_ci print("bad should not be defined") 6317db96d56Sopenharmony_ci 6327db96d56Sopenharmony_ci def x(): 6337db96d56Sopenharmony_ci [bad for s in 'a b' for bad in s.split()] 6347db96d56Sopenharmony_ci 6357db96d56Sopenharmony_ci x() 6367db96d56Sopenharmony_ci try: 6377db96d56Sopenharmony_ci print(bad) 6387db96d56Sopenharmony_ci except NameError: 6397db96d56Sopenharmony_ci pass 6407db96d56Sopenharmony_ci 6417db96d56Sopenharmony_ci def testEvalFreeVars(self): 6427db96d56Sopenharmony_ci 6437db96d56Sopenharmony_ci def f(x): 6447db96d56Sopenharmony_ci def g(): 6457db96d56Sopenharmony_ci x 6467db96d56Sopenharmony_ci eval("x + 1") 6477db96d56Sopenharmony_ci return g 6487db96d56Sopenharmony_ci 6497db96d56Sopenharmony_ci f(4)() 6507db96d56Sopenharmony_ci 6517db96d56Sopenharmony_ci def testFreeingCell(self): 6527db96d56Sopenharmony_ci # Test what happens when a finalizer accesses 6537db96d56Sopenharmony_ci # the cell where the object was stored. 6547db96d56Sopenharmony_ci class Special: 6557db96d56Sopenharmony_ci def __del__(self): 6567db96d56Sopenharmony_ci nestedcell_get() 6577db96d56Sopenharmony_ci 6587db96d56Sopenharmony_ci def testNonLocalFunction(self): 6597db96d56Sopenharmony_ci 6607db96d56Sopenharmony_ci def f(x): 6617db96d56Sopenharmony_ci def inc(): 6627db96d56Sopenharmony_ci nonlocal x 6637db96d56Sopenharmony_ci x += 1 6647db96d56Sopenharmony_ci return x 6657db96d56Sopenharmony_ci def dec(): 6667db96d56Sopenharmony_ci nonlocal x 6677db96d56Sopenharmony_ci x -= 1 6687db96d56Sopenharmony_ci return x 6697db96d56Sopenharmony_ci return inc, dec 6707db96d56Sopenharmony_ci 6717db96d56Sopenharmony_ci inc, dec = f(0) 6727db96d56Sopenharmony_ci self.assertEqual(inc(), 1) 6737db96d56Sopenharmony_ci self.assertEqual(inc(), 2) 6747db96d56Sopenharmony_ci self.assertEqual(dec(), 1) 6757db96d56Sopenharmony_ci self.assertEqual(dec(), 0) 6767db96d56Sopenharmony_ci 6777db96d56Sopenharmony_ci def testNonLocalMethod(self): 6787db96d56Sopenharmony_ci def f(x): 6797db96d56Sopenharmony_ci class c: 6807db96d56Sopenharmony_ci def inc(self): 6817db96d56Sopenharmony_ci nonlocal x 6827db96d56Sopenharmony_ci x += 1 6837db96d56Sopenharmony_ci return x 6847db96d56Sopenharmony_ci def dec(self): 6857db96d56Sopenharmony_ci nonlocal x 6867db96d56Sopenharmony_ci x -= 1 6877db96d56Sopenharmony_ci return x 6887db96d56Sopenharmony_ci return c() 6897db96d56Sopenharmony_ci c = f(0) 6907db96d56Sopenharmony_ci self.assertEqual(c.inc(), 1) 6917db96d56Sopenharmony_ci self.assertEqual(c.inc(), 2) 6927db96d56Sopenharmony_ci self.assertEqual(c.dec(), 1) 6937db96d56Sopenharmony_ci self.assertEqual(c.dec(), 0) 6947db96d56Sopenharmony_ci 6957db96d56Sopenharmony_ci def testGlobalInParallelNestedFunctions(self): 6967db96d56Sopenharmony_ci # A symbol table bug leaked the global statement from one 6977db96d56Sopenharmony_ci # function to other nested functions in the same block. 6987db96d56Sopenharmony_ci # This test verifies that a global statement in the first 6997db96d56Sopenharmony_ci # function does not affect the second function. 7007db96d56Sopenharmony_ci local_ns = {} 7017db96d56Sopenharmony_ci global_ns = {} 7027db96d56Sopenharmony_ci exec("""if 1: 7037db96d56Sopenharmony_ci def f(): 7047db96d56Sopenharmony_ci y = 1 7057db96d56Sopenharmony_ci def g(): 7067db96d56Sopenharmony_ci global y 7077db96d56Sopenharmony_ci return y 7087db96d56Sopenharmony_ci def h(): 7097db96d56Sopenharmony_ci return y + 1 7107db96d56Sopenharmony_ci return g, h 7117db96d56Sopenharmony_ci y = 9 7127db96d56Sopenharmony_ci g, h = f() 7137db96d56Sopenharmony_ci result9 = g() 7147db96d56Sopenharmony_ci result2 = h() 7157db96d56Sopenharmony_ci """, local_ns, global_ns) 7167db96d56Sopenharmony_ci self.assertEqual(2, global_ns["result2"]) 7177db96d56Sopenharmony_ci self.assertEqual(9, global_ns["result9"]) 7187db96d56Sopenharmony_ci 7197db96d56Sopenharmony_ci def testNonLocalClass(self): 7207db96d56Sopenharmony_ci 7217db96d56Sopenharmony_ci def f(x): 7227db96d56Sopenharmony_ci class c: 7237db96d56Sopenharmony_ci nonlocal x 7247db96d56Sopenharmony_ci x += 1 7257db96d56Sopenharmony_ci def get(self): 7267db96d56Sopenharmony_ci return x 7277db96d56Sopenharmony_ci return c() 7287db96d56Sopenharmony_ci 7297db96d56Sopenharmony_ci c = f(0) 7307db96d56Sopenharmony_ci self.assertEqual(c.get(), 1) 7317db96d56Sopenharmony_ci self.assertNotIn("x", c.__class__.__dict__) 7327db96d56Sopenharmony_ci 7337db96d56Sopenharmony_ci 7347db96d56Sopenharmony_ci def testNonLocalGenerator(self): 7357db96d56Sopenharmony_ci 7367db96d56Sopenharmony_ci def f(x): 7377db96d56Sopenharmony_ci def g(y): 7387db96d56Sopenharmony_ci nonlocal x 7397db96d56Sopenharmony_ci for i in range(y): 7407db96d56Sopenharmony_ci x += 1 7417db96d56Sopenharmony_ci yield x 7427db96d56Sopenharmony_ci return g 7437db96d56Sopenharmony_ci 7447db96d56Sopenharmony_ci g = f(0) 7457db96d56Sopenharmony_ci self.assertEqual(list(g(5)), [1, 2, 3, 4, 5]) 7467db96d56Sopenharmony_ci 7477db96d56Sopenharmony_ci def testNestedNonLocal(self): 7487db96d56Sopenharmony_ci 7497db96d56Sopenharmony_ci def f(x): 7507db96d56Sopenharmony_ci def g(): 7517db96d56Sopenharmony_ci nonlocal x 7527db96d56Sopenharmony_ci x -= 2 7537db96d56Sopenharmony_ci def h(): 7547db96d56Sopenharmony_ci nonlocal x 7557db96d56Sopenharmony_ci x += 4 7567db96d56Sopenharmony_ci return x 7577db96d56Sopenharmony_ci return h 7587db96d56Sopenharmony_ci return g 7597db96d56Sopenharmony_ci 7607db96d56Sopenharmony_ci g = f(1) 7617db96d56Sopenharmony_ci h = g() 7627db96d56Sopenharmony_ci self.assertEqual(h(), 3) 7637db96d56Sopenharmony_ci 7647db96d56Sopenharmony_ci def testTopIsNotSignificant(self): 7657db96d56Sopenharmony_ci # See #9997. 7667db96d56Sopenharmony_ci def top(a): 7677db96d56Sopenharmony_ci pass 7687db96d56Sopenharmony_ci def b(): 7697db96d56Sopenharmony_ci global a 7707db96d56Sopenharmony_ci 7717db96d56Sopenharmony_ci def testClassNamespaceOverridesClosure(self): 7727db96d56Sopenharmony_ci # See #17853. 7737db96d56Sopenharmony_ci x = 42 7747db96d56Sopenharmony_ci class X: 7757db96d56Sopenharmony_ci locals()["x"] = 43 7767db96d56Sopenharmony_ci y = x 7777db96d56Sopenharmony_ci self.assertEqual(X.y, 43) 7787db96d56Sopenharmony_ci class X: 7797db96d56Sopenharmony_ci locals()["x"] = 43 7807db96d56Sopenharmony_ci del x 7817db96d56Sopenharmony_ci self.assertFalse(hasattr(X, "x")) 7827db96d56Sopenharmony_ci self.assertEqual(x, 42) 7837db96d56Sopenharmony_ci 7847db96d56Sopenharmony_ci @cpython_only 7857db96d56Sopenharmony_ci def testCellLeak(self): 7867db96d56Sopenharmony_ci # Issue 17927. 7877db96d56Sopenharmony_ci # 7887db96d56Sopenharmony_ci # The issue was that if self was part of a cycle involving the 7897db96d56Sopenharmony_ci # frame of a method call, *and* the method contained a nested 7907db96d56Sopenharmony_ci # function referencing self, thereby forcing 'self' into a 7917db96d56Sopenharmony_ci # cell, setting self to None would not be enough to break the 7927db96d56Sopenharmony_ci # frame -- the frame had another reference to the instance, 7937db96d56Sopenharmony_ci # which could not be cleared by the code running in the frame 7947db96d56Sopenharmony_ci # (though it will be cleared when the frame is collected). 7957db96d56Sopenharmony_ci # Without the lambda, setting self to None is enough to break 7967db96d56Sopenharmony_ci # the cycle. 7977db96d56Sopenharmony_ci class Tester: 7987db96d56Sopenharmony_ci def dig(self): 7997db96d56Sopenharmony_ci if 0: 8007db96d56Sopenharmony_ci lambda: self 8017db96d56Sopenharmony_ci try: 8027db96d56Sopenharmony_ci 1/0 8037db96d56Sopenharmony_ci except Exception as exc: 8047db96d56Sopenharmony_ci self.exc = exc 8057db96d56Sopenharmony_ci self = None # Break the cycle 8067db96d56Sopenharmony_ci tester = Tester() 8077db96d56Sopenharmony_ci tester.dig() 8087db96d56Sopenharmony_ci ref = weakref.ref(tester) 8097db96d56Sopenharmony_ci del tester 8107db96d56Sopenharmony_ci gc_collect() # For PyPy or other GCs. 8117db96d56Sopenharmony_ci self.assertIsNone(ref()) 8127db96d56Sopenharmony_ci 8137db96d56Sopenharmony_ci 8147db96d56Sopenharmony_ciif __name__ == '__main__': 8157db96d56Sopenharmony_ci unittest.main() 816