(root)/
Python-3.11.7/
Lib/
test/
test_scope.py
       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()