@@ -3928,6 +3928,95 @@ def get_annotations(obj, *, globals=None, locals=None, eval_str=False,
39283928 value if not isinstance (value , str ) else eval (value , globals , locals )
39293929 for key , value in ann .items () }
39303930 return return_value
3931+
3932+
3933+
3934+ if hasattr (typing , "evaluate_forward_ref" ):
3935+ evaluate_forward_ref = typing .evaluate_forward_ref
3936+ else :
3937+ if hasattr (typing , "_deprecation_warning_for_no_type_params_passed" ):
3938+ _deprecation_warning_for_no_type_params_passed = (
3939+ typing ._deprecation_warning_for_no_type_params_passed
3940+ )
3941+ else :
3942+ def _deprecation_warning_for_no_type_params_passed (funcname : str ) -> None :
3943+ import warnings
3944+
3945+ depr_message = (
3946+ f"Failing to pass a value to the 'type_params' parameter "
3947+ f"of { funcname !r} is deprecated, as it leads to incorrect behaviour "
3948+ f"when calling { funcname } on a stringified annotation "
3949+ f"that references a PEP 695 type parameter. "
3950+ f"It will be disallowed in Python 3.15."
3951+ )
3952+ warnings .warn (depr_message , category = DeprecationWarning , stacklevel = 3 )
3953+
3954+ def evaluate_forward_ref (
3955+ forward_ref ,
3956+ * ,
3957+ owner = None ,
3958+ globals = None ,
3959+ locals = None ,
3960+ type_params = _marker ,
3961+ format = Format .VALUE ,
3962+ _recursive_guard = frozenset (),
3963+ ):
3964+ """Evaluate a forward reference as a type hint.
3965+
3966+ This is similar to calling the ForwardRef.evaluate() method,
3967+ but unlike that method, evaluate_forward_ref() also:
3968+
3969+ * Recursively evaluates forward references nested within the type hint.
3970+ * Rejects certain objects that are not valid type hints.
3971+ * Replaces type hints that evaluate to None with types.NoneType.
3972+ * Supports the *FORWARDREF* and *STRING* formats.
3973+
3974+ *forward_ref* must be an instance of ForwardRef. *owner*, if given,
3975+ should be the object that holds the annotations that the forward reference
3976+ derived from, such as a module, class object, or function. It is used to
3977+ infer the namespaces to use for looking up names. *globals* and *locals*
3978+ can also be explicitly given to provide the global and local namespaces.
3979+ *type_params* is a tuple of type parameters that are in scope when
3980+ evaluating the forward reference. This parameter must be provided (though
3981+ it may be an empty tuple) if *owner* is not given and the forward reference
3982+ does not already have an owner set. *format* specifies the format of the
3983+ annotation and is a member of the annotationlib.Format enum.
3984+
3985+ """
3986+ if type_params is _sentinel :
3987+ _deprecation_warning_for_no_type_params_passed ("typing.evaluate_forward_ref" )
3988+ type_params = ()
3989+ if format == Format .STRING :
3990+ return forward_ref .__forward_arg__
3991+ if forward_ref .__forward_arg__ in _recursive_guard :
3992+ return forward_ref
3993+
3994+ try :
3995+ value = forward_ref .evaluate (
3996+ globals = globals , locals = locals , type_params = type_params , owner = owner
3997+ )
3998+ except NameError :
3999+ if format == Format .FORWARDREF :
4000+ return forward_ref
4001+ else :
4002+ raise
4003+
4004+ type_ = typing ._type_check (
4005+ value ,
4006+ "Forward references must evaluate to types." ,
4007+ is_argument = forward_ref .__forward_is_argument__ ,
4008+ allow_special_forms = forward_ref .__forward_is_class__ ,
4009+ )
4010+ return typing ._eval_type (
4011+ type_ ,
4012+ globals ,
4013+ locals ,
4014+ type_params ,
4015+ recursive_guard = _recursive_guard | {forward_ref .__forward_arg__ },
4016+ format = format ,
4017+ owner = owner ,
4018+ )
4019+
39314020
39324021# Aliases for items that have always been in typing.
39334022# Explicitly assign these (rather than using `from typing import *` at the top),
0 commit comments