Skip to content

The types of builtins.locals and types.FrameType.f_locals aren't correct #14584

@bzoracler

Description

@bzoracler

builtins.locals and types.FrameType.f_locals are currently typed with dict[str, Any], which is incorrect:

  • def locals() -> dict[str, Any]: ...

    Counterexample:

    from collections import UserDict
    
    class A(type):
        @classmethod
        def __prepare__(cls, name, bases): 
            return UserDict()
    
        def __new__(mcs, name, bases, namespace, /, **kw): 
            return super().__new__(mcs, name, bases, dict(namespace), **kw)
    
    class B(metaclass=A):
        assert isinstance(locals(), dict)  # AssertionError
  • typeshed/stdlib/types.pyi

    Lines 585 to 586 in 85a787b

    @property
    def f_locals(self) -> dict[str, Any]: ...

    Counterexample as a consequence of PEP 667 (Python >= 3.13):

    from inspect import currentframe
    
    def f():
        print(type(currentframe().f_locals))  # <class 'FrameLocalsProxy'>  (runtime type is `_collections_abc.framelocalsproxy`; not in `.pyi` stubs yet)
        assert isinstance(currentframe().f_locals, dict)  # AssertionError
    
    f()

However, I'm not sure what the actual type should be. From what I can gather, the type should implement a mapping interface, with a few (but not all?) MutableMapping methods (PEP 667 describes what these mutable mapping methods are for FrameType.f_locals, but I'm not sure what's exactly expected of builtins.locals()).

In addition, collections.abc.Mapping and collections.abc.MutableMapping themselves are unsuitable, because they're nominal types, although this could be fixed by defining a Protocol which looks like a Mapping.

So, what should the types of builtins.locals and types.FrameType.f_locals be?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions