[3.12] gh-105340: include hidden fast-locals in locals() (GH-105715) (#106470)

gh-105340: include hidden fast-locals in locals() (GH-105715)

* gh-105340: include hidden fast-locals in locals()
(cherry picked from commit 104d7b760f)

Co-authored-by: Carl Meyer <carl@oddbird.net>
This commit is contained in:
Miss Islington (bot) 2023-07-05 16:31:37 -07:00 committed by GitHub
parent a49a29f22b
commit bb17e6f5de
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 160 additions and 44 deletions

View file

@ -1199,15 +1199,28 @@ frame_get_var(_PyInterpreterFrame *frame, PyCodeObject *co, int i,
return 1;
}
int
_PyFrame_FastToLocalsWithError(_PyInterpreterFrame *frame)
PyObject *
_PyFrame_GetLocals(_PyInterpreterFrame *frame, int include_hidden)
{
/* Merge fast locals into f->f_locals */
PyObject *locals = frame->f_locals;
if (locals == NULL) {
locals = frame->f_locals = PyDict_New();
if (locals == NULL) {
return -1;
return NULL;
}
}
PyObject *hidden = NULL;
/* If include_hidden, "hidden" fast locals (from inlined comprehensions in
module/class scopes) will be included in the returned dict, but not in
frame->f_locals; the returned dict will be a modified copy. Non-hidden
locals will still be updated in frame->f_locals. */
if (include_hidden) {
hidden = PyDict_New();
if (hidden == NULL) {
return NULL;
}
}
@ -1223,6 +1236,11 @@ _PyFrame_FastToLocalsWithError(_PyInterpreterFrame *frame)
PyObject *name = PyTuple_GET_ITEM(co->co_localsplusnames, i);
_PyLocals_Kind kind = _PyLocals_GetKind(co->co_localspluskinds, i);
if (kind & CO_FAST_HIDDEN) {
if (include_hidden && value != NULL) {
if (PyObject_SetItem(hidden, name, value) != 0) {
goto error;
}
}
continue;
}
if (value == NULL) {
@ -1231,16 +1249,53 @@ _PyFrame_FastToLocalsWithError(_PyInterpreterFrame *frame)
PyErr_Clear();
}
else {
return -1;
goto error;
}
}
}
else {
if (PyObject_SetItem(locals, name, value) != 0) {
return -1;
goto error;
}
}
}
if (include_hidden && PyDict_Size(hidden)) {
PyObject *innerlocals = PyDict_New();
if (innerlocals == NULL) {
goto error;
}
if (PyDict_Merge(innerlocals, locals, 1) != 0) {
Py_DECREF(innerlocals);
goto error;
}
if (PyDict_Merge(innerlocals, hidden, 1) != 0) {
Py_DECREF(innerlocals);
goto error;
}
locals = innerlocals;
}
else {
Py_INCREF(locals);
}
Py_CLEAR(hidden);
return locals;
error:
Py_XDECREF(hidden);
return NULL;
}
int
_PyFrame_FastToLocalsWithError(_PyInterpreterFrame *frame)
{
PyObject *locals = _PyFrame_GetLocals(frame, 0);
if (locals == NULL) {
return -1;
}
Py_DECREF(locals);
return 0;
}