@@ -172,16 +172,16 @@ def __getattr__(self, attr):
172172_lazy_annotationlib = _LazyAnnotationLib ()
173173
174174
175- def _type_convert (arg , module = None , * , allow_special_forms = False ):
175+ def _type_convert (arg , module = None , * , allow_special_forms = False , owner = None ):
176176 """For converting None to type(None), and strings to ForwardRef."""
177177 if arg is None :
178178 return type (None )
179179 if isinstance (arg , str ):
180- return _make_forward_ref (arg , module = module , is_class = allow_special_forms )
180+ return _make_forward_ref (arg , module = module , is_class = allow_special_forms , owner = owner )
181181 return arg
182182
183183
184- def _type_check (arg , msg , is_argument = True , module = None , * , allow_special_forms = False ):
184+ def _type_check (arg , msg , is_argument = True , module = None , * , allow_special_forms = False , owner = None ):
185185 """Check that the argument is a type, and return it (internal helper).
186186
187187 As a special case, accept None and return type(None) instead. Also wrap strings
@@ -199,7 +199,7 @@ def _type_check(arg, msg, is_argument=True, module=None, *, allow_special_forms=
199199 if is_argument :
200200 invalid_generic_forms += (Final ,)
201201
202- arg = _type_convert (arg , module = module , allow_special_forms = allow_special_forms )
202+ arg = _type_convert (arg , module = module , allow_special_forms = allow_special_forms , owner = owner )
203203 if (isinstance (arg , _GenericAlias ) and
204204 arg .__origin__ in invalid_generic_forms ):
205205 raise TypeError (f"{ arg } is not valid as type argument" )
@@ -431,7 +431,7 @@ def __repr__(self):
431431
432432
433433def _eval_type (t , globalns , localns , type_params = _sentinel , * , recursive_guard = frozenset (),
434- format = None , owner = None , parent_fwdref = None ):
434+ format = None , owner = None , parent_fwdref = None , prefer_fwd_module = False ):
435435 """Evaluate all forward references in the given type t.
436436
437437 For use of globalns and localns see the docstring for get_type_hints().
@@ -444,8 +444,20 @@ def _eval_type(t, globalns, localns, type_params=_sentinel, *, recursive_guard=f
444444 if isinstance (t , _lazy_annotationlib .ForwardRef ):
445445 # If the forward_ref has __forward_module__ set, evaluate() infers the globals
446446 # from the module, and it will probably pick better than the globals we have here.
447- if t .__forward_module__ is not None :
447+ # We do this only for calls from get_type_hints() (which opts in through the
448+ # prefer_fwd_module flag), so that the default behavior remains more straightforward.
449+ if prefer_fwd_module and t .__forward_module__ is not None :
448450 globalns = None
451+ # If there are type params on the owner, we need to add them back, because
452+ # annotationlib won't.
453+ if owner_type_params := getattr (owner , "__type_params__" , None ):
454+ globalns = getattr (
455+ sys .modules .get (t .__forward_module__ , None ), "__dict__" , None
456+ )
457+ if globalns is not None :
458+ globalns = dict (globalns )
459+ for type_param in owner_type_params :
460+ globalns [type_param .__name__ ] = type_param
449461 return evaluate_forward_ref (t , globals = globalns , locals = localns ,
450462 type_params = type_params , owner = owner ,
451463 _recursive_guard = recursive_guard , format = format )
@@ -466,7 +478,7 @@ def _eval_type(t, globalns, localns, type_params=_sentinel, *, recursive_guard=f
466478 ev_args = tuple (
467479 _eval_type (
468480 a , globalns , localns , type_params , recursive_guard = recursive_guard ,
469- format = format , owner = owner ,
481+ format = format , owner = owner , prefer_fwd_module = prefer_fwd_module ,
470482 )
471483 for a in t .__args__
472484 )
@@ -2363,7 +2375,7 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False,
23632375 if isinstance (value , str ):
23642376 value = _make_forward_ref (value , is_argument = False , is_class = True )
23652377 value = _eval_type (value , base_globals , base_locals , (),
2366- format = format , owner = obj )
2378+ format = format , owner = obj , prefer_fwd_module = True )
23672379 if value is None :
23682380 value = type (None )
23692381 hints [name ] = value
@@ -2408,7 +2420,7 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False,
24082420 is_argument = not isinstance (obj , types .ModuleType ),
24092421 is_class = False ,
24102422 )
2411- value = _eval_type (value , globalns , localns , (), format = format , owner = obj )
2423+ value = _eval_type (value , globalns , localns , (), format = format , owner = obj , prefer_fwd_module = True )
24122424 if value is None :
24132425 value = type (None )
24142426 hints [name ] = value
@@ -3147,7 +3159,7 @@ def __new__(cls, name, bases, ns, total=True):
31473159 own_annotations = {}
31483160 msg = "TypedDict('Name', {f0: t0, f1: t1, ...}); each t must be a type"
31493161 own_checked_annotations = {
3150- n : _type_check (tp , msg , module = tp_dict .__module__ )
3162+ n : _type_check (tp , msg , owner = tp_dict , module = tp_dict .__module__ )
31513163 for n , tp in own_annotations .items ()
31523164 }
31533165 required_keys = set ()
0 commit comments