Skip to content

Commit 6e31007

Browse files
committed
Support placeholders in functools.partial annotate functions
1 parent 4703e8d commit 6e31007

File tree

1 file changed

+10
-7
lines changed

1 file changed

+10
-7
lines changed

Lib/annotationlib.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -897,8 +897,8 @@ def _get_annotate_attr(annotate, attr, default):
897897
elif isinstance(annotate, type):
898898
return getattr(annotate.__init__, attr, default)
899899
elif (
900-
"functools" in sys.modules
901-
and isinstance(annotate, sys.modules["functools"].partial)
900+
(functools := sys.modules.get("functools", None))
901+
and isinstance(annotate, functools.partial)
902902
):
903903
return getattr(annotate.func, attr, default)
904904

@@ -912,16 +912,19 @@ def _direct_call_annotate(func, annotate, format):
912912
):
913913
return func(self, format)
914914

915+
# If annotate is a class, `func` is the __init__ method, so we still need to call
916+
# __new__() to create the instance
915917
if isinstance(annotate, type):
916918
inst = annotate.__new__(annotate)
917919
func(inst, format)
918920
return inst
919921

920-
if (
921-
"functools" in sys.modules
922-
and isinstance(annotate, sys.modules["functools"].partial)
923-
):
924-
return func(*annotate.args, format, **annotate.keywords)
922+
# If annotate is a partial function, re-create it with the new function object.
923+
# We could call the function directly, but then we'd have to handle placeholders,
924+
# and this way should be more robust for future changes.
925+
if functools := sys.modules.get("functools", None):
926+
if isinstance(annotate, functools.partial):
927+
return functools.partial(func, *annotate.args, **annotate.keywords)(format)
925928

926929
return func(format)
927930

0 commit comments

Comments
 (0)