-
-
Notifications
You must be signed in to change notification settings - Fork 30.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
gh-125590: Allow FrameLocalsProxy to delete and pop keys from extra locals #125616
gh-125590: Allow FrameLocalsProxy to delete and pop keys from extra locals #125616
Conversation
@terryjreedy the only tests failed were Idle on MacOS-13, which is a bit weird. I can imagine changing |
Objects/frameobject.c
Outdated
if (default_value != NULL) { | ||
return Py_XNewRef(default_value); | ||
} else { | ||
PyErr_Format(PyExc_KeyError, "'%R'", key); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A tiny optimization to consider (though, it's more complex--feel free to reject this):
PyErr_Format(PyExc_KeyError, "'%R'", key); | |
PyObject *repr = PyObject_Repr(key); | |
if (repr == NULL) { | |
return NULL; | |
} | |
PyErr_SetObject(PyExc_KeyError, repr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just realized I could've used _PyErr_SetKeyError(key)
like dictobject.c
. I'll switch to that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, that sounds better. I wasn't aware of that, TIL!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I switched to _PyErr_SetKeyError(key)
when the key does not exist. However, for local variables cases, I think RuntimeError
would fit better. One important reason was KeyError
actually expects the "key" to be the explanation string, and giving a reason is a bit weird. Also in this case we have the key, we just can't remove it, so RuntimeError
might be better.
MacOS versions after 10 have various odd interactions with tkinter and python. Without a saved reference to the now-overwritten failing test, I cannot comment other than to note the following:
The first call must result in the second, which I have no memory of. There is no direct test of either function. I'm glad you found better code that worked on major systems |
I think this needs backporting to 3.13, as that's the version mentioned in the issue |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The exception types need changing from RuntimeError
to KeyError
.
Otherwise, looks good.
Objects/frameobject.c
Outdated
int i = framelocalsproxy_getkeyindex(frame, key, false); | ||
if (i == -2) { | ||
return -1; | ||
} | ||
if (i >= 0) { | ||
if (value == NULL) { | ||
PyErr_SetString(PyExc_RuntimeError, "cannot remove local variables from FrameLocalsProxy"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be a KeyError
.
Users will expect mapping types to raise a KeyError
. https://docs.python.org/3/library/stdtypes.html#mapping-types-dict
Objects/frameobject.c
Outdated
} | ||
|
||
if (i >= 0) { | ||
PyErr_SetString(PyExc_RuntimeError, "cannot remove local variables from FrameLocalsProxy"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto
When you're done making the requested changes, leave the comment: |
FTR, from this PR, the potential additions to PEP 667 would be:
I think this is what we want. k = KeyError(name)
k.add_note("Cannot delete local variable") |
From the documentation, it explains
I think there's a distinctive difference here. The key is in the mapping, we can even read it, |
I appreciate I guess the question is do we want: try:
del f.f_locals["local_name"]
except KeyError:
... to handle the exception or not? If not, then I think
Other than that, the PR looks ready to merge. |
I think we need two separate exceptions because I don't know what they would do in the
|
I also agree For python/peps#3845, I've described this with prose rather than the equivalent Python code:
(and then linked back to this PR and the associated bug report from the "Implementation Notes" section) For the main docs, looking at https://docs.python.org/dev/reference/datamodel.html#frame-objects there's nothing that currently goes into that level of detail. I've filed a separate docs issue (#125731) suggesting adding a 4th subsection there that talks more about the write-through proxy behaviour. |
Ok, let's go with ValueError. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks
Thanks @gaogaotiantian for the PR 🌮🎉.. I'm working now to backport this PR to: 3.13. |
Thanks @gaogaotiantian for the PR 🌮🎉.. I'm working now to backport this PR to: 3.13. |
…xtra locals (pythonGH-125616) (cherry picked from commit 5b7a872) Co-authored-by: Tian Gao <[email protected]>
GH-125797 is a backport of this pull request to the 3.13 branch. |
It's okay for us to pop/delete the keys that were added to
f_locals
manually, just ban the real fast variables.@ncoghlan not sure if there's any documentation that needs to be changed.
There are two types of exceptions that could be raised:
RuntimeError
when users trying to remove a local variableKeyError
when users trying to remove a key that does not exist