-
-
Notifications
You must be signed in to change notification settings - Fork 34.3k
Open
Labels
stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytopic-typingtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
Description
Bug report
Bug description:
annotationlib.get_annotations() hangs indefinitely when called with eval_str=True on a callable that has a circular __wrapped__ reference chain.
Reproducer
import annotationlib
def f(x: 'int') -> 'str': pass
f.__wrapped__ = f # self-referential cycle
# Hangs forever, never returns
annotationlib.get_annotations(f, eval_str=True)Two-node cycle also triggers it:
def g(): pass
f.__wrapped__ = g
g.__wrapped__ = f
annotationlib.get_annotations(f, eval_str=True) # hangsRoot Cause
In Lib/annotationlib.py, get_annotations() has an early-return guard at line 1010:
if not eval_str:
return dict(ann) # fast path, skips unwrap entirely for default eval_str=FalseWhen eval_str=True the code falls through to a while True: loop (lines 1039–1048)
that unwraps __wrapped__ chains with no cycle detection:
if unwrap is not None:
while True:
if hasattr(unwrap, "__wrapped__"):
unwrap = unwrap.__wrapped__ # no cycle detection
continue
if functools := sys.modules.get("functools"):
if isinstance(unwrap, functools.partial):
unwrap = unwrap.func # also no cycle detection
continue
breakFix
Apply the same cycle-detection pattern used by inspect.unwrap() (visited id-set):
if unwrap is not None:
seen = {id(unwrap)}
while True:
if hasattr(unwrap, "__wrapped__"):
candidate = unwrap.__wrapped__
if id(candidate) in seen:
break
seen.add(id(candidate))
unwrap = candidate
continue
if functools := sys.modules.get("functools"):
if isinstance(unwrap, functools.partial):
candidate = unwrap.func
if id(candidate) in seen:
break
seen.add(id(candidate))
unwrap = candidate
continue
break
if hasattr(unwrap, "__globals__"):
obj_globals = unwrap.__globals__CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux
Linked PRs
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytopic-typingtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error