Any function returning a borrowed reference is already broken, IMO.
Sadly there are quite a few of them :(
Might as well fix `PyEval_GetLocals()` as we are changing its semantics
A quick search of GitHub shows that most uses erroneously fail to
increment the reference. So changing `PyEval_GetLocals()` to return a
real reference would convert a possible crash into a memory leak.
Maybe that's an improvement, maybe not, but it is a reasonable change IMO.
If the idea I had yesterday works out, then `PyEval_GetLocals()` will end up having exactly the same behavior as it does in 3.8, but we'll have a potential path towards some day deprecating and removing it (since there will be better behaved APIs offering equivalent functionality).
> The proposed APIs instead aim to make it possible to access the Python
> locals without needing to acquire a frame object reference at all.
Why would you need to do that? An addition to the C API needs a much
stronger justification than "it might be handy for someone".
The latest iteration of the PEP goes into more detail, but the key point is that the Python semantics are difficult to handle from the point of view of extension module code, because you can't tell just from looking at the code whether the locals() equivalent is going to return a copy or not.
So the proposed C API instead lets the consuming code choose between:
* get a read-only view
* get a shallow copy
* use the Python level semantics (with a query function to find out what those semantics are in the running frame)
That way, it will be easier to write extension module code that behaves the same way in all scopes, or at least fails loudly if it doesn't work properly in the running frame.