Skip to content

Commit

Permalink
Issue python#21897: Fix a crash with the f_locals attribute with clos…
Browse files Browse the repository at this point in the history
…ure variables when frame.clear() has been called.
  • Loading branch information
pitrou committed Jul 5, 2014
2 parents 92e8dee + acc8cf2 commit a93342b
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 1 deletion.
52 changes: 52 additions & 0 deletions Lib/test/test_frame.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import gc
import sys
import types
import unittest
import weakref

Expand Down Expand Up @@ -109,6 +110,57 @@ class C:
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__)

Expand Down
3 changes: 3 additions & 0 deletions Misc/NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ Release date: TBA
Core and Builtins
-----------------

- Issue #21897: Fix a crash with the f_locals attribute with closure
variables when frame.clear() has been called.

- Issue #21205: Add a new ``__qualname__`` attribute to generator, the
qualified name, and use it in the representation of a generator
(``repr(gen)``). The default name of the generator (``__name__`` attribute)
Expand Down
2 changes: 1 addition & 1 deletion Objects/frameobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,7 @@ map_to_dict(PyObject *map, Py_ssize_t nmap, PyObject *dict, PyObject **values,
PyObject *key = PyTuple_GET_ITEM(map, j);
PyObject *value = values[j];
assert(PyUnicode_Check(key));
if (deref) {
if (deref && value != NULL) {
assert(PyCell_Check(value));
value = PyCell_GET(value);
}
Expand Down

0 comments on commit a93342b

Please sign in to comment.