mirror of
https://github.com/python/cpython
synced 2026-09-29 11:35:29 +03:00
gh-105340: include hidden fast-locals in locals() (#105715)
* gh-105340: include hidden fast-locals in locals()
This commit is contained in:
parent
838406b4fc
commit
104d7b760f
8 changed files with 160 additions and 44 deletions
|
|
@ -1200,15 +1200,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1224,6 +1237,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) {
|
||||
|
|
@ -1232,16 +1250,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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1690,13 +1690,15 @@ _dir_locals(void)
|
|||
PyObject *names;
|
||||
PyObject *locals;
|
||||
|
||||
locals = PyEval_GetLocals();
|
||||
locals = _PyEval_GetFrameLocals();
|
||||
if (locals == NULL)
|
||||
return NULL;
|
||||
|
||||
names = PyMapping_Keys(locals);
|
||||
if (!names)
|
||||
Py_DECREF(locals);
|
||||
if (!names) {
|
||||
return NULL;
|
||||
}
|
||||
if (!PyList_Check(names)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"dir(): expected keys() of locals to be a list, "
|
||||
|
|
@ -1708,7 +1710,6 @@ _dir_locals(void)
|
|||
Py_DECREF(names);
|
||||
return NULL;
|
||||
}
|
||||
/* the locals don't need to be DECREF'd */
|
||||
return names;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue