@@ -8944,7 +8944,147 @@ def test_pep_695_generics_with_future_annotations_nested_in_function(self):
89448944 set (results .generic_func .__type_params__ )
89458945 )
89468946
8947- class TestEvaluateForwardRefs (BaseTestCase ):
8947+
8948+ class EvaluateForwardRefTests (BaseTestCase ):
8949+ def test_evaluate_forward_ref (self ):
8950+ int_ref = typing_extensions .ForwardRef ('int' )
8951+ self .assertIs (typing_extensions .evaluate_forward_ref (int_ref ), int )
8952+ self .assertIs (
8953+ typing_extensions .evaluate_forward_ref (int_ref , type_params = ()),
8954+ int ,
8955+ )
8956+ self .assertIs (
8957+ typing_extensions .evaluate_forward_ref (int_ref , format = typing_extensions .Format .VALUE ),
8958+ int ,
8959+ )
8960+ self .assertIs (
8961+ typing_extensions .evaluate_forward_ref (
8962+ int_ref , format = typing_extensions .Format .FORWARDREF ,
8963+ ),
8964+ int ,
8965+ )
8966+ self .assertEqual (
8967+ typing_extensions .evaluate_forward_ref (
8968+ int_ref , format = typing_extensions .Format .STRING ,
8969+ ),
8970+ 'int' ,
8971+ )
8972+
8973+ def test_evaluate_forward_ref_undefined (self ):
8974+ missing = typing_extensions .ForwardRef ('missing' )
8975+ with self .assertRaises (NameError ):
8976+ typing_extensions .evaluate_forward_ref (missing )
8977+ self .assertIs (
8978+ typing_extensions .evaluate_forward_ref (
8979+ missing , format = typing_extensions .Format .FORWARDREF ,
8980+ ),
8981+ missing ,
8982+ )
8983+ self .assertEqual (
8984+ typing_extensions .evaluate_forward_ref (
8985+ missing , format = typing_extensions .Format .STRING ,
8986+ ),
8987+ "missing" ,
8988+ )
8989+
8990+ def test_evaluate_forward_ref_nested (self ):
8991+ ref = typing_extensions .ForwardRef ("Union[int, list['str']]" )
8992+ ns = {"Union" : Union }
8993+ if sys .version_info >= (3 , 11 ):
8994+ expected = Union [int , list [str ]]
8995+ else :
8996+ expected = Union [int , list ['str' ]] # TODO: evaluate nested forward refs in Python < 3.11
8997+ self .assertEqual (
8998+ typing_extensions .evaluate_forward_ref (ref , globals = ns ),
8999+ expected ,
9000+ )
9001+ self .assertEqual (
9002+ typing_extensions .evaluate_forward_ref (
9003+ ref , globals = ns , format = typing_extensions .Format .FORWARDREF
9004+ ),
9005+ expected ,
9006+ )
9007+ self .assertEqual (
9008+ typing_extensions .evaluate_forward_ref (ref , format = typing_extensions .Format .STRING ),
9009+ "Union[int, list['str']]" ,
9010+ )
9011+
9012+ why = typing_extensions .ForwardRef ('"\' str\' "' )
9013+ self .assertIs (typing_extensions .evaluate_forward_ref (why ), str )
9014+
9015+ @skipUnless (sys .version_info >= (3 , 10 ), "Relies on PEP 604" )
9016+ def test_evaluate_forward_ref_nested_pep604 (self ):
9017+ ref = typing_extensions .ForwardRef ("int | list['str']" )
9018+ if sys .version_info >= (3 , 11 ):
9019+ expected = int | list [str ]
9020+ else :
9021+ expected = int | list ['str' ] # TODO: evaluate nested forward refs in Python < 3.11
9022+ self .assertEqual (
9023+ typing_extensions .evaluate_forward_ref (ref ),
9024+ expected ,
9025+ )
9026+ self .assertEqual (
9027+ typing_extensions .evaluate_forward_ref (ref , format = typing_extensions .Format .FORWARDREF ),
9028+ expected ,
9029+ )
9030+ self .assertEqual (
9031+ typing_extensions .evaluate_forward_ref (ref , format = typing_extensions .Format .STRING ),
9032+ "int | list['str']" ,
9033+ )
9034+
9035+ def test_evaluate_forward_ref_none (self ):
9036+ none_ref = typing_extensions .ForwardRef ('None' )
9037+ self .assertIs (typing_extensions .evaluate_forward_ref (none_ref ), None )
9038+
9039+ def test_globals (self ):
9040+ A = "str"
9041+ ref = typing_extensions .ForwardRef ('list[A]' )
9042+ with self .assertRaises (NameError ):
9043+ typing_extensions .evaluate_forward_ref (ref )
9044+ self .assertEqual (
9045+ typing_extensions .evaluate_forward_ref (ref , globals = {'A' : A }),
9046+ list [str ] if sys .version_info >= (3 , 11 ) else list ['str' ],
9047+ )
9048+
9049+ def test_owner (self ):
9050+ ref = typing_extensions .ForwardRef ("A" )
9051+
9052+ with self .assertRaises (NameError ):
9053+ typing_extensions .evaluate_forward_ref (ref )
9054+
9055+ # We default to the globals of `owner`,
9056+ # so it no longer raises `NameError`
9057+ self .assertIs (
9058+ typing_extensions .evaluate_forward_ref (ref , owner = Loop ), A
9059+ )
9060+
9061+ @skipUnless (sys .version_info >= (3 , 14 ), "Not yet implemented in Python < 3.14" )
9062+ def test_inherited_owner (self ):
9063+ # owner passed to evaluate_forward_ref
9064+ ref = typing_extensions .ForwardRef ("list['A']" )
9065+ self .assertEqual (
9066+ typing_extensions .evaluate_forward_ref (ref , owner = Loop ),
9067+ list [A ],
9068+ )
9069+
9070+ # owner set on the ForwardRef
9071+ ref = typing_extensions .ForwardRef ("list['A']" , owner = Loop )
9072+ self .assertEqual (
9073+ typing_extensions .evaluate_forward_ref (ref ),
9074+ list [A ],
9075+ )
9076+
9077+ @skipUnless (sys .version_info >= (3 , 14 ), "Not yet implemented in Python < 3.14" )
9078+ def test_partial_evaluation (self ):
9079+ ref = typing_extensions .ForwardRef ("list[A]" )
9080+ with self .assertRaises (NameError ):
9081+ typing_extensions .evaluate_forward_ref (ref )
9082+
9083+ self .assertEqual (
9084+ typing_extensions .evaluate_forward_ref (ref , format = typing_extensions .Format .FORWARDREF ),
9085+ list [EqualToForwardRef ('A' )],
9086+ )
9087+
89489088 def test_global_constant (self ):
89499089 if sys .version_info [:3 ] > (3 , 10 , 0 ):
89509090 self .assertTrue (_FORWARD_REF_HAS_CLASS )
@@ -9107,30 +9247,17 @@ class Y(Generic[Tx]):
91079247 self .assertEqual (get_args (evaluated_ref3 ), (Z [str ],))
91089248
91099249 def test_invalid_special_forms (self ):
9110- # tests _lax_type_check to raise errors the same way as the typing module.
9111- # Regex capture "< class 'module.name'> and "module.name"
9112- with self .assertRaisesRegex (
9113- TypeError , r"Plain .*Protocol('>)? is not valid as type argument"
9114- ):
9115- evaluate_forward_ref (typing .ForwardRef ("Protocol" ), globals = vars (typing ))
9116- with self .assertRaisesRegex (
9117- TypeError , r"Plain .*Generic('>)? is not valid as type argument"
9118- ):
9119- evaluate_forward_ref (typing .ForwardRef ("Generic" ), globals = vars (typing ))
9120- with self .assertRaisesRegex (TypeError , r"Plain typing(_extensions)?\.Final is not valid as type argument" ):
9121- evaluate_forward_ref (typing .ForwardRef ("Final" ), globals = vars (typing ))
9122- with self .assertRaisesRegex (TypeError , r"Plain typing(_extensions)?\.ClassVar is not valid as type argument" ):
9123- evaluate_forward_ref (typing .ForwardRef ("ClassVar" ), globals = vars (typing ))
9250+ for name in ("Protocol" , "Final" , "ClassVar" , "Generic" ):
9251+ with self .subTest (name = name ):
9252+ self .assertIs (
9253+ evaluate_forward_ref (typing .ForwardRef (name ), globals = vars (typing )),
9254+ getattr (typing , name ),
9255+ )
91249256 if _FORWARD_REF_HAS_CLASS :
91259257 self .assertIs (evaluate_forward_ref (typing .ForwardRef ("Final" , is_class = True ), globals = vars (typing )), Final )
91269258 self .assertIs (evaluate_forward_ref (typing .ForwardRef ("ClassVar" , is_class = True ), globals = vars (typing )), ClassVar )
9127- with self .assertRaisesRegex (TypeError , r"Plain typing(_extensions)?\.Final is not valid as type argument" ):
9128- evaluate_forward_ref (typing .ForwardRef ("Final" , is_argument = False ), globals = vars (typing ))
9129- with self .assertRaisesRegex (TypeError , r"Plain typing(_extensions)?\.ClassVar is not valid as type argument" ):
9130- evaluate_forward_ref (typing .ForwardRef ("ClassVar" , is_argument = False ), globals = vars (typing ))
9131- else :
9132- self .assertIs (evaluate_forward_ref (typing .ForwardRef ("Final" , is_argument = False ), globals = vars (typing )), Final )
9133- self .assertIs (evaluate_forward_ref (typing .ForwardRef ("ClassVar" , is_argument = False ), globals = vars (typing )), ClassVar )
9259+ self .assertIs (evaluate_forward_ref (typing .ForwardRef ("Final" , is_argument = False ), globals = vars (typing )), Final )
9260+ self .assertIs (evaluate_forward_ref (typing .ForwardRef ("ClassVar" , is_argument = False ), globals = vars (typing )), ClassVar )
91349261
91359262
91369263class TestSentinels (BaseTestCase ):
0 commit comments