@@ -171,16 +171,16 @@ def __getattr__(self, attr):
171171_lazy_annotationlib = _LazyAnnotationLib ()
172172
173173
174- def _type_convert (arg , module = None , * , allow_special_forms = False ):
174+ def _type_convert (arg , module = None , * , allow_special_forms = False , owner = None ):
175175 """For converting None to type(None), and strings to ForwardRef."""
176176 if arg is None :
177177 return type (None )
178178 if isinstance (arg , str ):
179- return _make_forward_ref (arg , module = module , is_class = allow_special_forms )
179+ return _make_forward_ref (arg , module = module , is_class = allow_special_forms , owner = owner )
180180 return arg
181181
182182
183- def _type_check (arg , msg , is_argument = True , module = None , * , allow_special_forms = False ):
183+ def _type_check (arg , msg , is_argument = True , module = None , * , allow_special_forms = False , owner = None ):
184184 """Check that the argument is a type, and return it (internal helper).
185185
186186 As a special case, accept None and return type(None) instead. Also wrap strings
@@ -198,7 +198,7 @@ def _type_check(arg, msg, is_argument=True, module=None, *, allow_special_forms=
198198 if is_argument :
199199 invalid_generic_forms += (Final ,)
200200
201- arg = _type_convert (arg , module = module , allow_special_forms = allow_special_forms )
201+ arg = _type_convert (arg , module = module , allow_special_forms = allow_special_forms , owner = owner )
202202 if (isinstance (arg , _GenericAlias ) and
203203 arg .__origin__ in invalid_generic_forms ):
204204 raise TypeError (f"{ arg } is not valid as type argument" )
@@ -454,7 +454,7 @@ def _deprecation_warning_for_no_type_params_passed(funcname: str) -> None:
454454
455455
456456def _eval_type (t , globalns , localns , type_params , * , recursive_guard = frozenset (),
457- format = None , owner = None , parent_fwdref = None ):
457+ format = None , owner = None , parent_fwdref = None , prefer_fwd_module = False ):
458458 """Evaluate all forward references in the given type t.
459459
460460 For use of globalns and localns see the docstring for get_type_hints().
@@ -464,8 +464,20 @@ def _eval_type(t, globalns, localns, type_params, *, recursive_guard=frozenset()
464464 if isinstance (t , _lazy_annotationlib .ForwardRef ):
465465 # If the forward_ref has __forward_module__ set, evaluate() infers the globals
466466 # from the module, and it will probably pick better than the globals we have here.
467- if t .__forward_module__ is not None :
467+ # We do this only for calls from get_type_hints() (which opts in through the
468+ # prefer_fwd_module flag), so that the default behavior remains more straightforward.
469+ if prefer_fwd_module and t .__forward_module__ is not None :
468470 globalns = None
471+ # If there are type params on the owner, we need to add them back, because
472+ # annotationlib won't.
473+ if owner_type_params := getattr (owner , "__type_params__" , None ):
474+ globalns = getattr (
475+ sys .modules .get (t .__forward_module__ , None ), "__dict__" , None
476+ )
477+ if globalns is not None :
478+ globalns = dict (globalns )
479+ for type_param in owner_type_params :
480+ globalns [type_param .__name__ ] = type_param
469481 return evaluate_forward_ref (t , globals = globalns , locals = localns ,
470482 type_params = type_params , owner = owner ,
471483 _recursive_guard = recursive_guard , format = format )
@@ -481,7 +493,7 @@ def _eval_type(t, globalns, localns, type_params, *, recursive_guard=frozenset()
481493 ev_args = tuple (
482494 _eval_type (
483495 a , globalns , localns , type_params , recursive_guard = recursive_guard ,
484- format = format , owner = owner ,
496+ format = format , owner = owner , prefer_fwd_module = prefer_fwd_module ,
485497 )
486498 for a in args
487499 )
@@ -2369,7 +2381,7 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False,
23692381 if isinstance (value , str ):
23702382 value = _make_forward_ref (value , is_argument = False , is_class = True )
23712383 value = _eval_type (value , base_globals , base_locals , (),
2372- format = format , owner = obj )
2384+ format = format , owner = obj , prefer_fwd_module = True )
23732385 if value is None :
23742386 value = type (None )
23752387 hints [name ] = value
@@ -2414,7 +2426,7 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False,
24142426 is_argument = not isinstance (obj , types .ModuleType ),
24152427 is_class = False ,
24162428 )
2417- value = _eval_type (value , globalns , localns , (), format = format , owner = obj )
2429+ value = _eval_type (value , globalns , localns , (), format = format , owner = obj , prefer_fwd_module = True )
24182430 if value is None :
24192431 value = type (None )
24202432 hints [name ] = value
@@ -3111,7 +3123,7 @@ def __new__(cls, name, bases, ns, total=True):
31113123 own_annotations = {}
31123124 msg = "TypedDict('Name', {f0: t0, f1: t1, ...}); each t must be a type"
31133125 own_checked_annotations = {
3114- n : _type_check (tp , msg , module = tp_dict .__module__ )
3126+ n : _type_check (tp , msg , owner = tp_dict , module = tp_dict .__module__ )
31153127 for n , tp in own_annotations .items ()
31163128 }
31173129 required_keys = set ()
0 commit comments