Just adding a datapoint, searching our internal codebase at work, I only
found two things that I'd consider to be uses of PyEval_GetLocals() outside
of CPython itself:

https://github.com/earwig/mwparserfromhell/blob/develop/src/mwparserfromhell/parser/ctokenizer/tokenizer.c#L220
https://github.com/numba/numba/blob/master/numba/_dispatcher.cpp#L664

The bulk of uses are naturally with CPython's own ceval.c and similar.

-gps

On Mon, Aug 23, 2021 at 9:02 AM Guido van Rossum <gu...@python.org> wrote:

> On Mon, Aug 23, 2021 at 8:46 AM Mark Shannon <m...@hotpy.org> wrote:
>
>> Hi Guido,
>>
>> On 23/08/2021 3:53 pm, Guido van Rossum wrote:
>> > On Mon, Aug 23, 2021 at 4:38 AM Mark Shannon <m...@hotpy.org
>> > <mailto:m...@hotpy.org>> wrote:
>> >
>> >     Hi Nick,
>> >
>> >     On 22/08/2021 4:51 am, Nick Coghlan wrote:
>> >
>> >      > If Mark's claim that PyEval_GetLocals() could not be fixed was
>> >     true then
>> >      > I would be more sympathetic to his proposal, but I know it isn't
>> >     true,
>> >      > because it still works fine in the PEP 558 implementation (it
>> even
>> >      > immediately sees changes made via proxies, and proxies see
>> >     changes to
>> >      > extra variables). The only truly unfixable public API is
>> >      > PyFrame_LocalsToFast().
>> >
>> >     You are making claims that seem inconsistent with each other.
>> >     Namely, you are claiming that:
>> >
>> >     1. That the result of locals() is ephemeral.
>> >     2. That PyEval_GetLocals() returns a borrowed reference.
>> >
>> >     This seems impossible, as you can't return a borrowed reference to
>> >     an emphemeral object. That's just a pointer to freed memory.
>> >
>> >     Do `locals()` and `PyEval_GetLocals()` behave differently?
>> >
>> >
>> > That is my understanding, yes. in PEP 558 locals() returns a snapshot
>> > dict, the Python-level f_locals property returns a fresh proxy that has
>> > no state except a pointer to the frame, and PyEval_GetLocals() returns
>> a
>> > borrowed reference to the dict that's stored on the frame's C-level
>> > f_locals attribute
>>
>> Can we avoid describing the C structs in any of these PEPs?
>>
>> It confuses readers having Python attributes and "C-level attributes"
>> (C struct fields?).
>> It also restricts the implementation unnecessarily.
>>
>> (E.g. the PyFrameObject doesn't have a `f_locals` field in 3.11:
>>
>> https://github.com/python/cpython/blob/main/Include/cpython/frameobject.h#L7
>> )
>>
>
> I'd be happy to. Nick's PEP still references it (and indeed it is very
> confusing) and I took it from him. And honestly it would be nice to have a
> specific short name for it, rather than circumscribing it with "an internal
> dynamic snapshot stored on the frame object " :-)
>
>
>> >
>> > (In my "crazy" proposal all that is the same.)
>>
>> >
>> >     Is the result of `PyEval_GetLocals()` cached, but `locals()` not?
>> >
>> >
>> > I wouldn't call it a cache -- deleting it would affect the semantics,
>> > not just the performance. But yes, it returns a reference to an object
>> > that is owned by the frame, just as it does in 3.10 and before.
>> >
>> >     If that were the case, then it is a bit confusing, but could work.
>> >
>> >
>> > Yes, see my "crazy" proposal.
>> >
>> >     Would PyEval_GetLocals() be defined as something like this?
>> >
>> >     (add _locals_cache attribute to the frame which is initialized to
>> NULL).
>> >
>> >     def PyEval_GetLocals():
>> >           frame._locals_cache attribute = locals()
>> >           return borrow(frame._locals_cache attribute)
>> >
>> >
>> > Nah, the dict returned by PyEval_GetLocals() is stored in the frame's
>> > C-level f_locals attribute, which is consulted by the Python-level
>> > f_locals proxy -- primarily to store "extra" variables, but IIUC in
>> > Nick's latest version it is also still used to cache by that proxy.
>> > Nick's locals() just returns dict(sys._getframe().f_locals).
>>
>> The "extra" variables must be distinct from the result of locals() as
>> that includes both extras and "proper" variables.
>> If we want to cache the locals(), it needs to be distinct from the extra
>> variables.
>>
>
> I don't care that much about caching locals(), but it seems we're bound to
> cache any non-NULL result from PyEval_GetLocals(), since it returns a
> borrowed reference. So they may be different things, with different
> semantics, if we don't cache locals().
>
>
>> A debugger setting extra variables in a function that that is also
>> accessed by a C call to PyEval_GetLocals() is going to be incredibly
>> rare. Let's not worry about efficiency here.
>>
>
> Agreed.
>
> >
>> >     None of this is clear (at least not to me) from PEP 558.
>> >
>> >
>> > One problem with PEP 558 is that it's got too many words, and it's
>> > lacking a section that crisply describes the semantics of the proposed
>> > implementation. I've suggested to Nick that he add a section with
>> > pseudo-code for the implementation, like you did in yours.
>> >
>> > (PS, did you read my PS about what locals() should do in class scope
>> > when __prepare__ returns a non-dict?)
>>
>> Yes, but no harm in a reminder :)
>> I'll update my PEP to fix the semantics of locals().
>>
>
> I'm in suspense as to what semantics you chose. :-)
>
> PS. Another point where you seem to have missed some detail is in the
> mapping from (proper) variable names to "frame locals" -- you use
> co_varnames, but that (currently, at least) doesn't include cells.
>
> --
> --Guido van Rossum (python.org/~guido)
> *Pronouns: he/him **(why is my pronoun here?)*
> <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
> _______________________________________________
> Python-Dev mailing list -- python-dev@python.org
> To unsubscribe send an email to python-dev-le...@python.org
> https://mail.python.org/mailman3/lists/python-dev.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-dev@python.org/message/AK23IEZKC3DQBPYBTKA7NHDPUNSV55WZ/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/37SMUITK5QIWQZNUCTCWZBNUP36RDHOM/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to