diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2014-07-05 00:24:13 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2014-07-05 00:24:13 (GMT) |
commit | acc8cf2cfa18c445e8c9b324206eb7c5e392bcb7 (patch) | |
tree | 0c8300eb1c66c97fcf29404ef008b3d544aeefdb /Lib | |
parent | e865128605faf64c63cd216507a0875e4c5a424b (diff) | |
download | cpython-acc8cf2cfa18c445e8c9b324206eb7c5e392bcb7.zip cpython-acc8cf2cfa18c445e8c9b324206eb7c5e392bcb7.tar.gz cpython-acc8cf2cfa18c445e8c9b324206eb7c5e392bcb7.tar.bz2 |
Issue #21897: Fix a crash with the f_locals attribute with closure variables when frame.clear() has been called.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/test/test_frame.py | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/Lib/test/test_frame.py b/Lib/test/test_frame.py index 2dd5780..c402ec3 100644 --- a/Lib/test/test_frame.py +++ b/Lib/test/test_frame.py @@ -1,5 +1,6 @@ import gc import sys +import types import unittest import weakref @@ -109,6 +110,57 @@ class ClearTest(unittest.TestCase): self.assertIs(None, wr()) +class FrameLocalsTest(unittest.TestCase): + """ + Tests for the .f_locals attribute. + """ + + def make_frames(self): + def outer(): + x = 5 + y = 6 + def inner(): + z = x + 2 + 1/0 + t = 9 + return inner() + try: + outer() + except ZeroDivisionError as e: + tb = e.__traceback__ + frames = [] + while tb: + frames.append(tb.tb_frame) + tb = tb.tb_next + return frames + + def test_locals(self): + f, outer, inner = self.make_frames() + outer_locals = outer.f_locals + self.assertIsInstance(outer_locals.pop('inner'), types.FunctionType) + self.assertEqual(outer_locals, {'x': 5, 'y': 6}) + inner_locals = inner.f_locals + self.assertEqual(inner_locals, {'x': 5, 'z': 7}) + + def test_clear_locals(self): + # Test f_locals after clear() (issue #21897) + f, outer, inner = self.make_frames() + outer.clear() + inner.clear() + self.assertEqual(outer.f_locals, {}) + self.assertEqual(inner.f_locals, {}) + + def test_locals_clear_locals(self): + # Test f_locals before and after clear() (to exercise caching) + f, outer, inner = self.make_frames() + outer.f_locals + inner.f_locals + outer.clear() + inner.clear() + self.assertEqual(outer.f_locals, {}) + self.assertEqual(inner.f_locals, {}) + + def test_main(): support.run_unittest(__name__) |