Issue 17960: Clarify the required behaviour of locals() (original) (raw)

Since "soonish" turned out to be "4 years and counting", copying in the specifics of the proposal in from the old python-dev thread:

  1. While nominally undefined, in practice lots of Python programs depend on the locals() builtin behaving exactly how it behaves in CPython.

  2. PyPy at least has replicated that behaviour faithfully (to the extent of replicating our weird trace function related misbehaviour, as recently pointed out in issue #30744)

  3. For module scopes and class scopes (and the corresponding forms of exec and eval), the expected behaviour is relatively straightforward to both define and implement:

  1. For function scopes, the appropriate semantics are less clear, as what CPython currently does is fairly weird and quirky.

It would be a lot simpler to document the expected behaviour at function scope if locals() were to be updated to return a true snapshot (i.e. a copy of f_locals, rather than a direct reference), with direct access to the shared locals reference requiring going through the frame attribute. That way, trace functions could still modify local variables (since they use frame.f_locals), but setting a trace function wouldn't suddenly have the side effect of making modifications to locals() take effect at function scope.

Status update: I've posted an initial PR to issue 30744 that relies on the trace hook semantic change proposed in the PEP to resolve the trace hook/cell reference incompatibility reported there.

That provides confidence that it really is only the semantics of trace hooks that we need to change, rather than anything about locals() or frame.f_locals in general.

So the next steps will be to do a final editing pass on the current PEP to account for the reference implementation, and then send it to python-dev for official review and pronouncement.