bpo-42904: Change search order of typing.get_type_hints eval (#25632)

While surprising (searching globals before locals in one specific case), this is needed for backwards compatibility.
This commit is contained in:
Ken Jin 2021-04-27 01:31:21 +08:00 committed by GitHub
parent 94549ee728
commit 1b1f9852bd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 17 additions and 3 deletions

View file

@ -1604,7 +1604,8 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False):
- If no dict arguments are passed, an attempt is made to use the
globals from obj (or the respective module's globals for classes),
and these are also used as the locals. If the object does not appear
to have globals, an empty dictionary is used.
to have globals, an empty dictionary is used. For classes, the search
order is globals first then locals.
- If one dict argument is passed, it is used for both globals and
locals.
@ -1628,6 +1629,14 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False):
base_globals = globalns
ann = base.__dict__.get('__annotations__', {})
base_locals = dict(vars(base)) if localns is None else localns
if localns is None and globalns is None:
# This is surprising, but required. Before Python 3.10,
# get_type_hints only evaluated the globalns of
# a class. To maintain backwards compatibility, we reverse
# the globalns and localns order so that eval() looks into
# *base_globals* first rather than *base_locals*.
# This only affects ForwardRefs.
base_globals, base_locals = base_locals, base_globals
for name, value in ann.items():
if value is None:
value = type(None)