diff options
Diffstat (limited to 'Lib/test')
-rw-r--r-- | Lib/test/test_scope.py | 29 | ||||
-rw-r--r-- | Lib/test/test_super.py | 13 |
2 files changed, 42 insertions, 0 deletions
diff --git a/Lib/test/test_scope.py b/Lib/test/test_scope.py index 129a18a..41678b5 100644 --- a/Lib/test/test_scope.py +++ b/Lib/test/test_scope.py @@ -1,4 +1,6 @@ import unittest +import weakref + from test.support import check_syntax_error, cpython_only, run_unittest @@ -713,6 +715,33 @@ 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_main(): diff --git a/Lib/test/test_super.py b/Lib/test/test_super.py index f6469cf..1e272ee 100644 --- a/Lib/test/test_super.py +++ b/Lib/test/test_super.py @@ -130,6 +130,19 @@ class TestSuper(unittest.TestCase): super() self.assertRaises(RuntimeError, X().f) + def test_cell_as_self(self): + class X: + def meth(self): + super() + + def f(): + k = X() + def g(): + return k + return g + c = f().__closure__[0] + self.assertRaises(TypeError, X.meth, c) + def test_main(): support.run_unittest(TestSuper) |