@@ -759,11 +759,18 @@ def call_annotate_function(annotate, format, *, owner=None, _is_evaluate=False):
759759 # reconstruct the source. But in the dictionary that we eventually return, we
760760 # want to return objects with more user-friendly behavior, such as an __eq__
761761 # that returns a bool and an defined set of attributes.
762- namespace = {** annotate .__builtins__ , ** annotate .__globals__ }
762+ annotate_globals = _get_annotate_attr (annotate , "__globals__" , {})
763+ annotate_code = _get_annotate_attr (annotate , "__code__" , None )
764+ annotate_defaults = _get_annotate_attr (annotate , "__defaults__" , None )
765+ annotate_kwdefaults = _get_annotate_attr (annotate , "__kwdefaults__" , None )
766+ namespace = {
767+ ** _get_annotate_attr (annotate , "__builtins__" , {}),
768+ ** annotate_globals
769+ }
763770 is_class = isinstance (owner , type )
764771 globals = _StringifierDict (
765772 namespace ,
766- globals = annotate . __globals__ ,
773+ globals = annotate_globals ,
767774 owner = owner ,
768775 is_class = is_class ,
769776 format = format ,
@@ -772,14 +779,17 @@ def call_annotate_function(annotate, format, *, owner=None, _is_evaluate=False):
772779 annotate , owner , is_class , globals , allow_evaluation = True
773780 )
774781 func = types .FunctionType (
775- annotate . __code__ ,
782+ annotate_code ,
776783 globals ,
777784 closure = closure ,
778- argdefs = annotate . __defaults__ ,
779- kwdefaults = annotate . __kwdefaults__ ,
785+ argdefs = annotate_defaults ,
786+ kwdefaults = annotate_kwdefaults ,
780787 )
781788 try :
782- result = func (Format .VALUE_WITH_FAKE_GLOBALS )
789+ if isinstance (annotate .__call__ , types .MethodType ):
790+ result = func (annotate .__call__ .__self__ , Format .VALUE_WITH_FAKE_GLOBALS )
791+ else :
792+ result = func (Format .VALUE_WITH_FAKE_GLOBALS )
783793 except NotImplementedError :
784794 # FORWARDREF and VALUE_WITH_FAKE_GLOBALS not supported, fall back to VALUE
785795 return annotate (Format .VALUE )
@@ -793,7 +803,7 @@ def call_annotate_function(annotate, format, *, owner=None, _is_evaluate=False):
793803 # a value in certain cases where an exception gets raised during evaluation.
794804 globals = _StringifierDict (
795805 {},
796- globals = annotate . __globals__ ,
806+ globals = annotate_globals ,
797807 owner = owner ,
798808 is_class = is_class ,
799809 format = format ,
@@ -802,13 +812,16 @@ def call_annotate_function(annotate, format, *, owner=None, _is_evaluate=False):
802812 annotate , owner , is_class , globals , allow_evaluation = False
803813 )
804814 func = types .FunctionType (
805- annotate . __code__ ,
815+ annotate_code ,
806816 globals ,
807817 closure = closure ,
808- argdefs = annotate . __defaults__ ,
809- kwdefaults = annotate . __kwdefaults__ ,
818+ argdefs = annotate_defaults ,
819+ kwdefaults = annotate_kwdefaults ,
810820 )
811- result = func (Format .VALUE_WITH_FAKE_GLOBALS )
821+ if isinstance (annotate .__call__ , types .MethodType ):
822+ result = func (annotate .__call__ .__self__ , Format .VALUE_WITH_FAKE_GLOBALS )
823+ else :
824+ result = func (Format .VALUE_WITH_FAKE_GLOBALS )
812825 globals .transmogrify (cell_dict )
813826 if _is_evaluate :
814827 if isinstance (result , ForwardRef ):
@@ -833,12 +846,13 @@ def call_annotate_function(annotate, format, *, owner=None, _is_evaluate=False):
833846
834847
835848def _build_closure (annotate , owner , is_class , stringifier_dict , * , allow_evaluation ):
836- if not annotate .__closure__ :
849+ closure = _get_annotate_attr (annotate , "__closure__" , None )
850+ if not closure :
837851 return None , None
838852 freevars = annotate .__code__ .co_freevars
839853 new_closure = []
840854 cell_dict = {}
841- for i , cell in enumerate (annotate . __closure__ ):
855+ for i , cell in enumerate (closure ):
842856 if i < len (freevars ):
843857 name = freevars [i ]
844858 else :
@@ -857,7 +871,7 @@ def _build_closure(annotate, owner, is_class, stringifier_dict, *, allow_evaluat
857871 name ,
858872 cell = cell ,
859873 owner = owner ,
860- globals = annotate . __globals__ ,
874+ globals = _get_annotate_attr ( annotate , " __globals__" , {}) ,
861875 is_class = is_class ,
862876 stringifier_dict = stringifier_dict ,
863877 )
@@ -879,6 +893,17 @@ def _stringify_single(anno):
879893 return repr (anno )
880894
881895
896+ def _get_annotate_attr (annotate , attr , default ):
897+ if (value := getattr (annotate , attr , None )) is not None :
898+ return value
899+
900+ if call_method := getattr (annotate , "__call__" , None ):
901+ if call_func := getattr (call_method , "__func__" , None ):
902+ return getattr (call_func , attr , default )
903+
904+ return default
905+
906+
882907def get_annotate_from_class_namespace (obj ):
883908 """Retrieve the annotate function from a class namespace dictionary.
884909
0 commit comments