summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_scope.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/test/test_scope.py')
-rw-r--r--Lib/test/test_scope.py52
1 files changed, 43 insertions, 9 deletions
diff --git a/Lib/test/test_scope.py b/Lib/test/test_scope.py
index fbc87aa..26ce042 100644
--- a/Lib/test/test_scope.py
+++ b/Lib/test/test_scope.py
@@ -1,5 +1,7 @@
import unittest
-from test.support import check_syntax_error, run_unittest
+import weakref
+
+from test.support import check_syntax_error, cpython_only, run_unittest
class ScopeTests(unittest.TestCase):
@@ -496,23 +498,22 @@ class ScopeTests(unittest.TestCase):
self.assertNotIn("x", varnames)
self.assertIn("y", varnames)
+ @cpython_only
def testLocalsClass_WithTrace(self):
# Issue23728: after the trace function returns, the locals()
# dictionary is used to update all variables, this used to
# include free variables. But in class statements, free
# variables are not inserted...
import sys
+ self.addCleanup(sys.settrace, sys.gettrace())
sys.settrace(lambda a,b,c:None)
- try:
- x = 12
+ x = 12
- class C:
- def f(self):
- return x
+ class C:
+ def f(self):
+ return x
- self.assertEqual(x, 12) # Used to raise UnboundLocalError
- finally:
- sys.settrace(None)
+ self.assertEqual(x, 12) # Used to raise UnboundLocalError
def testBoundAndFree(self):
# var is bound and free in class
@@ -527,6 +528,7 @@ class ScopeTests(unittest.TestCase):
inst = f(3)()
self.assertEqual(inst.a, inst.m())
+ @cpython_only
def testInteractionWithTraceFunc(self):
import sys
@@ -543,6 +545,7 @@ class ScopeTests(unittest.TestCase):
class TestClass:
pass
+ self.addCleanup(sys.settrace, sys.gettrace())
sys.settrace(tracer)
adaptgetter("foo", TestClass, (1, ""))
sys.settrace(None)
@@ -712,6 +715,37 @@ class ScopeTests(unittest.TestCase):
def b():
global a
+ @cpython_only
+ def testCellLeak(self):
+ # Issue 17927.
+ #
+ # The issue was that if self was part of a cycle involving the
+ # frame of a method call, *and* the method contained a nested
+ # function referencing self, thereby forcing 'self' into a
+ # cell, setting self to None would not be enough to break the
+ # frame -- the frame had another reference to the instance,
+ # which could not be cleared by the code running in the frame
+ # (though it will be cleared when the frame is collected).
+ # Without the lambda, setting self to None is enough to break
+ # the cycle.
+ class Tester:
+ def dig(self):
+ if 0:
+ lambda: self
+ try:
+ 1/0
+ except Exception as exc:
+ self.exc = exc
+ self = None # Break the cycle
+ tester = Tester()
+ tester.dig()
+ ref = weakref.ref(tester)
+ del tester
+ self.assertIsNone(ref())
+
+ def test__Class__Global(self):
+ s = "class X:\n global __class__\n def f(self): super()"
+ self.assertRaises(SyntaxError, exec, s)
def test_main():