summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2023-09-12 13:50:29 (GMT)
committerGitHub <noreply@github.com>2023-09-12 13:50:29 (GMT)
commitd533ab17ec37b457a5cc286f30c7559e358492bf (patch)
tree2260c776dd98ec4e61519099c2b82169fdabe092
parentaf83d1e8214efc806488226d206c24462686bd1d (diff)
downloadcpython-d533ab17ec37b457a5cc286f30c7559e358492bf.zip
cpython-d533ab17ec37b457a5cc286f30c7559e358492bf.tar.gz
cpython-d533ab17ec37b457a5cc286f30c7559e358492bf.tar.bz2
[3.12] gh-108732: include comprehension locals in frame.f_locals (GH-109026) (#109097)
gh-108732: include comprehension locals in frame.f_locals (GH-109026) (cherry picked from commit f2584eade378910b9ea18072bb1dab3dd58e23bb) Co-authored-by: Carl Meyer <carl@oddbird.net> Co-authored-by: Radislav Chugunov <52372310+chgnrdv@users.noreply.github.com> Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
-rw-r--r--Lib/test/test_listcomps.py7
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2023-09-06-13-28-42.gh-issue-108732.I6DkEQ.rst2
-rw-r--r--Objects/frameobject.c14
3 files changed, 19 insertions, 4 deletions
diff --git a/Lib/test/test_listcomps.py b/Lib/test/test_listcomps.py
index bedd99b..c108957 100644
--- a/Lib/test/test_listcomps.py
+++ b/Lib/test/test_listcomps.py
@@ -596,6 +596,13 @@ class ListComprehensionTest(unittest.TestCase):
"""
self._check_in_scopes(code, {"value": [1, None]})
+ def test_frame_locals(self):
+ code = """
+ val = [sys._getframe().f_locals for a in [0]][0]["a"]
+ """
+ import sys
+ self._check_in_scopes(code, {"val": 0}, ns={"sys": sys})
+
__test__ = {'doctests' : doctests}
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-09-06-13-28-42.gh-issue-108732.I6DkEQ.rst b/Misc/NEWS.d/next/Core and Builtins/2023-09-06-13-28-42.gh-issue-108732.I6DkEQ.rst
new file mode 100644
index 0000000..94a143b
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-09-06-13-28-42.gh-issue-108732.I6DkEQ.rst
@@ -0,0 +1,2 @@
+Make iteration variables of module- and class-scoped comprehensions visible
+to pdb and other tools that use ``frame.f_locals`` again.
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index ba36575..30c8d3c 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -24,10 +24,16 @@ static PyMemberDef frame_memberlist[] = {
static PyObject *
frame_getlocals(PyFrameObject *f, void *closure)
{
- if (PyFrame_FastToLocalsWithError(f) < 0)
+ if (f == NULL) {
+ PyErr_BadInternalCall();
return NULL;
- PyObject *locals = f->f_frame->f_locals;
- return Py_NewRef(locals);
+ }
+ assert(!_PyFrame_IsIncomplete(f->f_frame));
+ PyObject *locals = _PyFrame_GetLocals(f->f_frame, 1);
+ if (locals) {
+ f->f_fast_as_locals = 1;
+ }
+ return locals;
}
int
@@ -1351,11 +1357,11 @@ PyFrame_GetVarString(PyFrameObject *frame, const char *name)
int
PyFrame_FastToLocalsWithError(PyFrameObject *f)
{
- assert(!_PyFrame_IsIncomplete(f->f_frame));
if (f == NULL) {
PyErr_BadInternalCall();
return -1;
}
+ assert(!_PyFrame_IsIncomplete(f->f_frame));
int err = _PyFrame_FastToLocalsWithError(f->f_frame);
if (err == 0) {
f->f_fast_as_locals = 1;