Author: Armin Rigo <ar...@tunes.org> Branch: py3.5 Changeset: r88496:e7e2aa356442 Date: 2016-11-20 17:26 +0100 http://bitbucket.org/pypy/pypy/changeset/e7e2aa356442/
Log: Test and fix for frame.clear() diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py --- a/pypy/interpreter/pyframe.py +++ b/pypy/interpreter/pyframe.py @@ -782,8 +782,10 @@ def descr_clear(self, space): """F.clear(): clear most references held by the frame""" - # Clears a random subset of the attributes (e.g. the fast - # locals, but not f_locals). + # Clears a random subset of the attributes: the local variables + # and the w_locals. Note that CPython doesn't clear f_locals + # (which can create leaks) but it's hard to notice because + # the next Python-level read of 'frame.f_locals' will clear it. if not self.frame_finished_execution: if not self._is_generator_or_coroutine(): raise oefmt(space.w_RuntimeError, @@ -800,6 +802,8 @@ debug = self.getdebug() if debug is not None: debug.w_f_trace = None + if debug.w_locals is not None: + debug.w_locals = space.newdict() # clear the locals, including the cell/free vars, and the stack for i in range(len(self.locals_cells_stack_w)): diff --git a/pypy/interpreter/test/test_pyframe.py b/pypy/interpreter/test/test_pyframe.py --- a/pypy/interpreter/test/test_pyframe.py +++ b/pypy/interpreter/test/test_pyframe.py @@ -618,6 +618,15 @@ # raises(StopIteration, next, gen) + def test_frame_clear_really(self): + import sys + def f(x): + return sys._getframe() + frame = f(42) + assert frame.f_locals['x'] == 42 + frame.clear() + assert frame.f_locals == {} + def test_throw_trace_bug(self): import sys def f(): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit