Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/anyio/_core/_compat.py: 57%
82 statements
« prev ^ index » next coverage.py v7.2.2, created at 2023-03-26 06:12 +0000
« prev ^ index » next coverage.py v7.2.2, created at 2023-03-26 06:12 +0000
1from abc import ABCMeta, abstractmethod
2from contextlib import AbstractContextManager
3from types import TracebackType
4from typing import (
5 TYPE_CHECKING,
6 Any,
7 AsyncContextManager,
8 Callable,
9 ContextManager,
10 Generator,
11 Generic,
12 Iterable,
13 List,
14 Optional,
15 Tuple,
16 Type,
17 TypeVar,
18 Union,
19 overload,
20)
21from warnings import warn
23if TYPE_CHECKING:
24 from ._testing import TaskInfo
25else:
26 TaskInfo = object
28T = TypeVar("T")
29AnyDeprecatedAwaitable = Union[
30 "DeprecatedAwaitable",
31 "DeprecatedAwaitableFloat",
32 "DeprecatedAwaitableList[T]",
33 TaskInfo,
34]
37@overload
38async def maybe_async(__obj: TaskInfo) -> TaskInfo:
39 ...
42@overload
43async def maybe_async(__obj: "DeprecatedAwaitableFloat") -> float:
44 ...
47@overload
48async def maybe_async(__obj: "DeprecatedAwaitableList[T]") -> List[T]:
49 ...
52@overload
53async def maybe_async(__obj: "DeprecatedAwaitable") -> None:
54 ...
57async def maybe_async(
58 __obj: "AnyDeprecatedAwaitable[T]",
59) -> Union[TaskInfo, float, List[T], None]:
60 """
61 Await on the given object if necessary.
63 This function is intended to bridge the gap between AnyIO 2.x and 3.x where some functions and
64 methods were converted from coroutine functions into regular functions.
66 Do **not** try to use this for any other purpose!
68 :return: the result of awaiting on the object if coroutine, or the object itself otherwise
70 .. versionadded:: 2.2
72 """
73 return __obj._unwrap()
76class _ContextManagerWrapper:
77 def __init__(self, cm: ContextManager[T]):
78 self._cm = cm
80 async def __aenter__(self) -> T:
81 return self._cm.__enter__()
83 async def __aexit__(
84 self,
85 exc_type: Optional[Type[BaseException]],
86 exc_val: Optional[BaseException],
87 exc_tb: Optional[TracebackType],
88 ) -> Optional[bool]:
89 return self._cm.__exit__(exc_type, exc_val, exc_tb)
92def maybe_async_cm(
93 cm: Union[ContextManager[T], AsyncContextManager[T]]
94) -> AsyncContextManager[T]:
95 """
96 Wrap a regular context manager as an async one if necessary.
98 This function is intended to bridge the gap between AnyIO 2.x and 3.x where some functions and
99 methods were changed to return regular context managers instead of async ones.
101 :param cm: a regular or async context manager
102 :return: an async context manager
104 .. versionadded:: 2.2
106 """
107 if not isinstance(cm, AbstractContextManager):
108 raise TypeError("Given object is not an context manager")
110 return _ContextManagerWrapper(cm)
113def _warn_deprecation(
114 awaitable: "AnyDeprecatedAwaitable[Any]", stacklevel: int = 1
115) -> None:
116 warn(
117 f'Awaiting on {awaitable._name}() is deprecated. Use "await '
118 f"anyio.maybe_async({awaitable._name}(...)) if you have to support both AnyIO 2.x "
119 f'and 3.x, or just remove the "await" if you are completely migrating to AnyIO 3+.',
120 DeprecationWarning,
121 stacklevel=stacklevel + 1,
122 )
125class DeprecatedAwaitable:
126 def __init__(self, func: Callable[..., "DeprecatedAwaitable"]):
127 self._name = f"{func.__module__}.{func.__qualname__}"
129 def __await__(self) -> Generator[None, None, None]:
130 _warn_deprecation(self)
131 if False:
132 yield
134 def __reduce__(self) -> Tuple[Type[None], Tuple[()]]:
135 return type(None), ()
137 def _unwrap(self) -> None:
138 return None
141class DeprecatedAwaitableFloat(float):
142 def __new__(
143 cls, x: float, func: Callable[..., "DeprecatedAwaitableFloat"]
144 ) -> "DeprecatedAwaitableFloat":
145 return super().__new__(cls, x)
147 def __init__(self, x: float, func: Callable[..., "DeprecatedAwaitableFloat"]):
148 self._name = f"{func.__module__}.{func.__qualname__}"
150 def __await__(self) -> Generator[None, None, float]:
151 _warn_deprecation(self)
152 if False:
153 yield
155 return float(self)
157 def __reduce__(self) -> Tuple[Type[float], Tuple[float]]:
158 return float, (float(self),)
160 def _unwrap(self) -> float:
161 return float(self)
164class DeprecatedAwaitableList(List[T]):
165 def __init__(
166 self,
167 iterable: Iterable[T] = (),
168 *,
169 func: Callable[..., "DeprecatedAwaitableList[T]"],
170 ):
171 super().__init__(iterable)
172 self._name = f"{func.__module__}.{func.__qualname__}"
174 def __await__(self) -> Generator[None, None, List[T]]:
175 _warn_deprecation(self)
176 if False:
177 yield
179 return list(self)
181 def __reduce__(self) -> Tuple[Type[List[T]], Tuple[List[T]]]:
182 return list, (list(self),)
184 def _unwrap(self) -> List[T]:
185 return list(self)
188class DeprecatedAsyncContextManager(Generic[T], metaclass=ABCMeta):
189 @abstractmethod
190 def __enter__(self) -> T:
191 pass
193 @abstractmethod
194 def __exit__(
195 self,
196 exc_type: Optional[Type[BaseException]],
197 exc_val: Optional[BaseException],
198 exc_tb: Optional[TracebackType],
199 ) -> Optional[bool]:
200 pass
202 async def __aenter__(self) -> T:
203 warn(
204 f"Using {self.__class__.__name__} as an async context manager has been deprecated. "
205 f'Use "async with anyio.maybe_async_cm(yourcontextmanager) as foo:" if you have to '
206 f'support both AnyIO 2.x and 3.x, or just remove the "async" from "async with" if '
207 f"you are completely migrating to AnyIO 3+.",
208 DeprecationWarning,
209 )
210 return self.__enter__()
212 async def __aexit__(
213 self,
214 exc_type: Optional[Type[BaseException]],
215 exc_val: Optional[BaseException],
216 exc_tb: Optional[TracebackType],
217 ) -> Optional[bool]:
218 return self.__exit__(exc_type, exc_val, exc_tb)