@@ -244,14 +244,16 @@ def inner(*args, **kwds):
244
244
return inner
245
245
246
246
247
- def _eval_type (t , globalns , localns ):
247
+ def _eval_type (t , globalns , localns , recursive_guard = frozenset () ):
248
248
"""Evaluate all forward reverences in the given type t.
249
249
For use of globalns and localns see the docstring for get_type_hints().
250
+ recursive_guard is used to prevent prevent infinite recursion
251
+ with recursive ForwardRef.
250
252
"""
251
253
if isinstance (t , ForwardRef ):
252
- return t ._evaluate (globalns , localns )
254
+ return t ._evaluate (globalns , localns , recursive_guard )
253
255
if isinstance (t , (_GenericAlias , GenericAlias )):
254
- ev_args = tuple (_eval_type (a , globalns , localns ) for a in t .__args__ )
256
+ ev_args = tuple (_eval_type (a , globalns , localns , recursive_guard ) for a in t .__args__ )
255
257
if ev_args == t .__args__ :
256
258
return t
257
259
if isinstance (t , GenericAlias ):
@@ -477,18 +479,24 @@ def __init__(self, arg, is_argument=True):
477
479
self .__forward_value__ = None
478
480
self .__forward_is_argument__ = is_argument
479
481
480
- def _evaluate (self , globalns , localns ):
482
+ def _evaluate (self , globalns , localns , recursive_guard ):
483
+ if self .__forward_arg__ in recursive_guard :
484
+ return self
481
485
if not self .__forward_evaluated__ or localns is not globalns :
482
486
if globalns is None and localns is None :
483
487
globalns = localns = {}
484
488
elif globalns is None :
485
489
globalns = localns
486
490
elif localns is None :
487
491
localns = globalns
488
- self . __forward_value__ = _type_check (
492
+ type_ = _type_check (
489
493
eval (self .__forward_code__ , globalns , localns ),
490
494
"Forward references must evaluate to types." ,
491
- is_argument = self .__forward_is_argument__ )
495
+ is_argument = self .__forward_is_argument__ ,
496
+ )
497
+ self .__forward_value__ = _eval_type (
498
+ type_ , globalns , localns , recursive_guard | {self .__forward_arg__ }
499
+ )
492
500
self .__forward_evaluated__ = True
493
501
return self .__forward_value__
494
502
0 commit comments