Skip to content

Commit f2584ea

Browse files
carljmchgnrdvJelleZijlstra
authored
pythongh-108732: include comprehension locals in frame.f_locals (python#109026)
Co-authored-by: Radislav Chugunov <[email protected]> Co-authored-by: Jelle Zijlstra <[email protected]>
1 parent b72251d commit f2584ea

File tree

3 files changed

+19
-4
lines changed

3 files changed

+19
-4
lines changed

Lib/test/test_listcomps.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,13 @@ def test_exception_in_post_comp_call(self):
596596
"""
597597
self._check_in_scopes(code, {"value": [1, None]})
598598

599+
def test_frame_locals(self):
600+
code = """
601+
val = [sys._getframe().f_locals for a in [0]][0]["a"]
602+
"""
603+
import sys
604+
self._check_in_scopes(code, {"val": 0}, ns={"sys": sys})
605+
599606

600607
__test__ = {'doctests' : doctests}
601608

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Make iteration variables of module- and class-scoped comprehensions visible
2+
to pdb and other tools that use ``frame.f_locals`` again.

Objects/frameobject.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,16 @@ static PyMemberDef frame_memberlist[] = {
2525
static PyObject *
2626
frame_getlocals(PyFrameObject *f, void *closure)
2727
{
28-
if (PyFrame_FastToLocalsWithError(f) < 0)
28+
if (f == NULL) {
29+
PyErr_BadInternalCall();
2930
return NULL;
30-
PyObject *locals = f->f_frame->f_locals;
31-
return Py_NewRef(locals);
31+
}
32+
assert(!_PyFrame_IsIncomplete(f->f_frame));
33+
PyObject *locals = _PyFrame_GetLocals(f->f_frame, 1);
34+
if (locals) {
35+
f->f_fast_as_locals = 1;
36+
}
37+
return locals;
3238
}
3339

3440
int
@@ -1342,11 +1348,11 @@ PyFrame_GetVarString(PyFrameObject *frame, const char *name)
13421348
int
13431349
PyFrame_FastToLocalsWithError(PyFrameObject *f)
13441350
{
1345-
assert(!_PyFrame_IsIncomplete(f->f_frame));
13461351
if (f == NULL) {
13471352
PyErr_BadInternalCall();
13481353
return -1;
13491354
}
1355+
assert(!_PyFrame_IsIncomplete(f->f_frame));
13501356
int err = _PyFrame_FastToLocalsWithError(f->f_frame);
13511357
if (err == 0) {
13521358
f->f_fast_as_locals = 1;

0 commit comments

Comments
 (0)