ยปCore Development>Code coverage>Lib/test/test_scope.py

Python code coverage for Lib/test/test_scope.py

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