Commit eeb5506b authored by Jeremy Hylton's avatar Jeremy Hylton

Fix SF bug #505315: Make free and cell vars show up consistently in locals().

PyFrame_FastToLocals() and PyFrame_LocalsToFast() had a return if
f_nlocals was 0.  I think this was a holdover from the pre 2.1 days
when regular locals were the only kind of local variables.

The change makes it possible to use a free variable in eval or exec if
it the variable is also used elsewhere in the same block, which is
what the documentation says.
parent 1f434c89
...@@ -416,8 +416,6 @@ PyFrame_FastToLocals(PyFrameObject *f) ...@@ -416,8 +416,6 @@ PyFrame_FastToLocals(PyFrameObject *f)
return; return;
} }
} }
if (f->f_nlocals == 0)
return;
map = f->f_code->co_varnames; map = f->f_code->co_varnames;
if (!PyDict_Check(locals) || !PyTuple_Check(map)) if (!PyDict_Check(locals) || !PyTuple_Check(map))
return; return;
...@@ -426,6 +424,7 @@ PyFrame_FastToLocals(PyFrameObject *f) ...@@ -426,6 +424,7 @@ PyFrame_FastToLocals(PyFrameObject *f)
j = PyTuple_Size(map); j = PyTuple_Size(map);
if (j > f->f_nlocals) if (j > f->f_nlocals)
j = f->f_nlocals; j = f->f_nlocals;
if (f->f_nlocals)
map_to_dict(map, j, locals, fast, 0); map_to_dict(map, j, locals, fast, 0);
if (f->f_ncells || f->f_nfreevars) { if (f->f_ncells || f->f_nfreevars) {
if (!(PyTuple_Check(f->f_code->co_cellvars) if (!(PyTuple_Check(f->f_code->co_cellvars)
...@@ -455,7 +454,7 @@ PyFrame_LocalsToFast(PyFrameObject *f, int clear) ...@@ -455,7 +454,7 @@ PyFrame_LocalsToFast(PyFrameObject *f, int clear)
return; return;
locals = f->f_locals; locals = f->f_locals;
map = f->f_code->co_varnames; map = f->f_code->co_varnames;
if (locals == NULL || f->f_code->co_nlocals == 0) if (locals == NULL)
return; return;
if (!PyDict_Check(locals) || !PyTuple_Check(map)) if (!PyDict_Check(locals) || !PyTuple_Check(map))
return; return;
...@@ -464,6 +463,7 @@ PyFrame_LocalsToFast(PyFrameObject *f, int clear) ...@@ -464,6 +463,7 @@ PyFrame_LocalsToFast(PyFrameObject *f, int clear)
j = PyTuple_Size(map); j = PyTuple_Size(map);
if (j > f->f_nlocals) if (j > f->f_nlocals)
j = f->f_nlocals; j = f->f_nlocals;
if (f->f_nlocals)
dict_to_map(f->f_code->co_varnames, j, locals, fast, 0, clear); dict_to_map(f->f_code->co_varnames, j, locals, fast, 0, clear);
if (f->f_ncells || f->f_nfreevars) { if (f->f_ncells || f->f_nfreevars) {
if (!(PyTuple_Check(f->f_code->co_cellvars) if (!(PyTuple_Check(f->f_code->co_cellvars)
...@@ -474,7 +474,8 @@ PyFrame_LocalsToFast(PyFrameObject *f, int clear) ...@@ -474,7 +474,8 @@ PyFrame_LocalsToFast(PyFrameObject *f, int clear)
locals, fast + f->f_nlocals, 1, clear); locals, fast + f->f_nlocals, 1, clear);
dict_to_map(f->f_code->co_freevars, dict_to_map(f->f_code->co_freevars,
PyTuple_GET_SIZE(f->f_code->co_freevars), PyTuple_GET_SIZE(f->f_code->co_freevars),
locals, fast + f->f_nlocals + f->f_ncells, 1, clear); locals, fast + f->f_nlocals + f->f_ncells, 1,
clear);
} }
PyErr_Restore(error_type, error_value, error_traceback); PyErr_Restore(error_type, error_value, error_traceback);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment