gh-119180: Only fetch globals and locals if necessary in annotationlib.get_annotations() (#135644)

This commit is contained in:
Victorien 2025-06-18 05:29:13 +02:00 committed by GitHub
parent e4ccd46bf7
commit 504ae606e1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 42 additions and 39 deletions

View file

@ -939,48 +939,49 @@ def get_annotations(
if not eval_str:
return dict(ann)
if isinstance(obj, type):
# class
obj_globals = None
module_name = getattr(obj, "__module__", None)
if module_name:
module = sys.modules.get(module_name, None)
if module:
obj_globals = getattr(module, "__dict__", None)
obj_locals = dict(vars(obj))
unwrap = obj
elif isinstance(obj, types.ModuleType):
# module
obj_globals = getattr(obj, "__dict__")
obj_locals = None
unwrap = None
elif callable(obj):
# this includes types.Function, types.BuiltinFunctionType,
# types.BuiltinMethodType, functools.partial, functools.singledispatch,
# "class funclike" from Lib/test/test_inspect... on and on it goes.
obj_globals = getattr(obj, "__globals__", None)
obj_locals = None
unwrap = obj
else:
obj_globals = obj_locals = unwrap = None
if globals is None or locals is None:
if isinstance(obj, type):
# class
obj_globals = None
module_name = getattr(obj, "__module__", None)
if module_name:
module = sys.modules.get(module_name, None)
if module:
obj_globals = getattr(module, "__dict__", None)
obj_locals = dict(vars(obj))
unwrap = obj
elif isinstance(obj, types.ModuleType):
# module
obj_globals = getattr(obj, "__dict__")
obj_locals = None
unwrap = None
elif callable(obj):
# this includes types.Function, types.BuiltinFunctionType,
# types.BuiltinMethodType, functools.partial, functools.singledispatch,
# "class funclike" from Lib/test/test_inspect... on and on it goes.
obj_globals = getattr(obj, "__globals__", None)
obj_locals = None
unwrap = obj
else:
obj_globals = obj_locals = unwrap = None
if unwrap is not None:
while True:
if hasattr(unwrap, "__wrapped__"):
unwrap = unwrap.__wrapped__
continue
if functools := sys.modules.get("functools"):
if isinstance(unwrap, functools.partial):
unwrap = unwrap.func
if unwrap is not None:
while True:
if hasattr(unwrap, "__wrapped__"):
unwrap = unwrap.__wrapped__
continue
break
if hasattr(unwrap, "__globals__"):
obj_globals = unwrap.__globals__
if functools := sys.modules.get("functools"):
if isinstance(unwrap, functools.partial):
unwrap = unwrap.func
continue
break
if hasattr(unwrap, "__globals__"):
obj_globals = unwrap.__globals__
if globals is None:
globals = obj_globals
if locals is None:
locals = obj_locals
if globals is None:
globals = obj_globals
if locals is None:
locals = obj_locals
# "Inject" type parameters into the local namespace
# (unless they are shadowed by assignments *in* the local namespace),

View file

@ -0,0 +1,2 @@
Only fetch globals and locals if necessary in
:func:`annotationlib.get_annotations`