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

1import sys 1abcdefghijklmnopqrst

2import typing 1abcdefghijklmnopqrst

3from types import NoneType 1abcdefghijklmnopqrst

4 

5__all__ = ( 1abcdefghijklmnopqrst

6 "ExceptionGroup", 

7 "evaluate_forwardref", 

8) 

9 

10 

11if sys.version_info < (3, 11): 1abcdefghijklmnopqrst

12 from exceptiongroup import ExceptionGroup as ExceptionGroup 1abc

13else: 

14 ExceptionGroup = ExceptionGroup 1defghijklmnopqrst

15 

16 

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

26 

27 elif isinstance(value, str): 1abcdefghijklmnopqrst

28 value = typing.ForwardRef(value, is_argument=False, is_class=True) 1abcdefghijklmnopqrst

29 

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

35 

36 

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 ) 

54 

55 else: 

56 return typing._eval_type( # type: ignore 1abcdefghis

57 value, globalns, localns 

58 ) 

59 

60 except TypeError as e: 1abcdefghijklmnopqrst

61 if not (isinstance(value, typing.ForwardRef) and is_backport_fixable_error(e)): 1abcdefghijklmnopqrst

62 raise 1abcdefghijklmnopqrst

63 

64 try: 1abcdefghijklmnopqrst

65 from eval_type_backport import eval_type_backport as _eval_type_backport 1abcdefghijklmnopqrst

66 

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 

74 

75 else: 

76 return _eval_type_backport(value, globalns, localns, try_default=False) 1abcdefghijklmnopqrst

77 

78 

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 )