[Python-Dev] PEP 558: Defined semantics for locals()
Currently f_locals is documented as readonly .
The PEP says:
> * "Don't change what isn't broken": the current tracing mode problems are caused
> by a requirement that's specific to tracing mode (support for external
> rebinding of function local variable references), so it made sense to also
> restrict any related fixes to tracing mode
> However, actually attempting to implement and document that dynamic approach
> highlighted the fact that it makes for a really subtle runtime state dependent
> behaviour distinction in how ``frame.f_locals`` works, and creates several
> new edge cases around how ``f_locals`` behaves as trace functions are added
> and removed.
> Accordingly, the design was switched to the current one, where
> ``frame.f_locals`` is always a write-through proxy, and ``locals()`` is always
> a dynamic snapshot, which is both simpler to implement and easier to explain.
Do these edge cases still exist when f_locals write access is restricted to code executed by the tracing function (which is more restrictive than 'tracing mode') ?
We can use the condition frame->f_trace not NULL and tstate->tracing true (tstate being a pointer to the PyThreadState structure) to know when code is executed by the tracing function :
* The condition on tstate->tracing allows to figure out if we are running a frame executed by the trace function as opposed to a frame that is being traced or a frame executed in 'regular operation'.
* The condition on frame->f_trace removes the ambiguity whether tstate->tracing is set by a tracing function or by a profiling function.
 In section 'Frame objects' at https://github.com/python/cpython/blob/master/Doc/reference/datamodel.rst#the-standard-type-hierarchy
 Except that frame->f_trace is NULL in a 'PyTrace_CALL' trace event, so f_locals would remain readonly in that case. But this event is always followed by a 'PyTrace_LINE' event anyway so this limitation is not important IMO.