Coverage for fast_depends/_compat.py: 100%
32 statements
« prev ^ index » next coverage.py v7.17.3, created at 2026-11-13 05:19 +0000
« prev ^ index » next coverage.py v7.17.3, created at 2026-11-13 05:19 +0000
1import sys 1abcdefghijklmnopqrst
2import typing 1abcdefghijklmnopqrst
3from types import NoneType 1abcdefghijklmnopqrst
5__all__ = ( 1abcdefghijklmnopqrst
6 "ExceptionGroup",
7 "evaluate_forwardref",
8)
11if sys.version_info < (3, 11): 1abcdefghijklmnopqrst
12 from exceptiongroup import ExceptionGroup as ExceptionGroup 1abc
13else:
14 ExceptionGroup = ExceptionGroup 1defghijklmnopqrst
17def evaluate_forwardref( 1abcdefghijklmnopqrst
18 value: typing.Any,
19 globalns: dict[str, typing.Any] | None = None,
20 localns: dict[str, typing.Any] | None = None,
21 type_params: tuple[typing.Any, ...] | None = None,
22) -> typing.Any:
23 """Behaves like typing._eval_type, except it won't raise an error if a forward reference can't be resolved."""
24 if value is None: 1abcdefghijklmnopqrst
25 value = NoneType 1abcdefghijklmnopqrst
27 elif isinstance(value, str): 1abcdefghijklmnopqrst
28 value = typing.ForwardRef(value, is_argument=False, is_class=True) 1abcdefghijklmnopqrst
30 try: 1abcdefghijklmnopqrst
31 return eval_type_backport(value, globalns, localns, type_params=type_params) 1abcdefghijklmnopqrst
32 except NameError: 1abcdefghijklmnopqrst
33 # the point of this function is to be tolerant to this case
34 return value 1abcdefghijklmnopqrst
37def eval_type_backport( 1abcdefghijklmnopqrst
38 value: typing.Any,
39 globalns: dict[str, typing.Any] | None = None,
40 localns: dict[str, typing.Any] | None = None,
41 type_params: tuple[typing.Any, ...] | None = None,
42) -> typing.Any:
43 """Like `typing._eval_type`, but falls back to the `eval_type_backport` package if it's
44 installed to let older Python versions use newer typing features.
45 Specifically, this transforms `X | Y` into `typing.Union[X, Y]`
46 and `list[X]` into `typing.List[X]` etc. (for all the types made generic in PEP 585)
47 if the original syntax is not supported in the current Python version.
48 """
49 try: 1abcdefghijklmnopqrst
50 if sys.version_info >= (3, 13): 1abcdefghijklmnopqrst
51 return typing._eval_type( # type: ignore 1jklmnopqrt
52 value, globalns, localns, type_params=type_params
53 )
55 else:
56 return typing._eval_type( # type: ignore 1abcdefghis
57 value, globalns, localns
58 )
60 except TypeError as e: 1abcdefghijklmnopqrst
61 if not (isinstance(value, typing.ForwardRef) and is_backport_fixable_error(e)): 1abcdefghijklmnopqrst
62 raise 1abcdefghijklmnopqrst
64 try: 1abcdefghijklmnopqrst
65 from eval_type_backport import eval_type_backport as _eval_type_backport 1abcdefghijklmnopqrst
67 except ImportError: 1abcdefghijklmnopqrst
68 raise TypeError( 1abcdefghijklmnopqrst
69 f"You have a type annotation {value.__forward_arg__!r} "
70 f"which makes use of newer typing features than are supported in your version of Python. "
71 f"To handle this error, you should either remove the use of new syntax "
72 f"or install the `eval_type_backport` package."
73 ) from e
75 else:
76 return _eval_type_backport(value, globalns, localns, try_default=False) 1abcdefghijklmnopqrst
79def is_backport_fixable_error(e: TypeError) -> bool: 1abcdefghijklmnopqrst
80 msg = str(e) 1abcdefghijklmnopqrst
81 return ( 1abcdefghijklmnopqrst
82 msg.startswith("unsupported operand type(s) for |: ")
83 or "' object is not subscriptable" in msg
84 )