@@ -664,28 +664,38 @@ def get_annotations(
664664 if eval_str and format != Format .VALUE :
665665 raise ValueError ("eval_str=True is only supported with format=Format.VALUE" )
666666
667- # For VALUE format, we look at __annotations__ directly.
668- if format != Format .VALUE :
669- annotate = get_annotate_function (obj )
670- if annotate is not None :
671- ann = call_annotate_function (annotate , format , owner = obj )
672- if not isinstance (ann , dict ):
673- raise ValueError (f"{ obj !r} .__annotate__ returned a non-dict" )
674- return dict (ann )
675-
676- if isinstance (obj , type ):
677- try :
678- ann = _BASE_GET_ANNOTATIONS (obj )
679- except AttributeError :
680- # For static types, the descriptor raises AttributeError.
681- return {}
682- else :
683- ann = getattr (obj , "__annotations__" , None )
684- if ann is None :
685- return {}
686-
687- if not isinstance (ann , dict ):
688- raise ValueError (f"{ obj !r} .__annotations__ is neither a dict nor None" )
667+ match format :
668+ case Format .VALUE :
669+ # For VALUE, we only look at __annotations__
670+ ann = _get_dunder_annotations (obj )
671+ case Format .FORWARDREF :
672+ # For FORWARDREF, we use __annotations__ if it exists
673+ try :
674+ ann = _get_dunder_annotations (obj )
675+ except NameError :
676+ pass
677+ else :
678+ return dict (ann )
679+
680+ # But if __annotations__ threw a NameError, we try calling __annotate__
681+ ann = _get_and_call_annotate (obj , format )
682+ if ann is not None :
683+ return ann
684+
685+ # If that didn't work either, we have a very weird object: evaluating
686+ # __annotations__ threw NameError and there is no __annotate__. In that case,
687+ # we fall back to trying __annotations__ again.
688+ return dict (_get_dunder_annotations (obj ))
689+ case Format .SOURCE :
690+ # For SOURCE, we try to call __annotate__
691+ ann = _get_and_call_annotate (obj , format )
692+ if ann is not None :
693+ return ann
694+ # But if we didn't get it, we use __annotations__ instead.
695+ ann = _get_dunder_annotations (obj )
696+ return ann
697+ case _:
698+ raise ValueError (f"Unsupported format { format !r} " )
689699
690700 if not ann :
691701 return {}
@@ -750,3 +760,30 @@ def get_annotations(
750760 for key , value in ann .items ()
751761 }
752762 return return_value
763+
764+
765+ def _get_and_call_annotate (obj , format ):
766+ annotate = get_annotate_function (obj )
767+ if annotate is not None :
768+ ann = call_annotate_function (annotate , format , owner = obj )
769+ if not isinstance (ann , dict ):
770+ raise ValueError (f"{ obj !r} .__annotate__ returned a non-dict" )
771+ return dict (ann )
772+ return None
773+
774+
775+ def _get_dunder_annotations (obj ):
776+ if isinstance (obj , type ):
777+ try :
778+ ann = _BASE_GET_ANNOTATIONS (obj )
779+ except AttributeError :
780+ # For static types, the descriptor raises AttributeError.
781+ return {}
782+ else :
783+ ann = getattr (obj , "__annotations__" , None )
784+ if ann is None :
785+ return {}
786+
787+ if not isinstance (ann , dict ):
788+ raise ValueError (f"{ obj !r} .__annotations__ is neither a dict nor None" )
789+ return dict (ann )
0 commit comments