Wait until the result of an sync or async function meets some condition
| 31 | |
| 32 | |
| 33 | class poll(Generic[_R]): # noqa: N801 |
| 34 | """Wait until the result of an sync or async function meets some condition""" |
| 35 | |
| 36 | def __init__( |
| 37 | self, |
| 38 | function: Callable[_P, Awaitable[_R] | _R], |
| 39 | *args: _P.args, |
| 40 | **kwargs: _P.kwargs, |
| 41 | ) -> None: |
| 42 | coro: Callable[_P, Awaitable[_R]] |
| 43 | if not inspect.iscoroutinefunction(function): |
| 44 | |
| 45 | async def coro(*args: _P.args, **kwargs: _P.kwargs) -> _R: |
| 46 | return cast(_R, function(*args, **kwargs)) |
| 47 | |
| 48 | else: |
| 49 | coro = cast(Callable[_P, Awaitable[_R]], function) |
| 50 | self._func = coro |
| 51 | self._args = args |
| 52 | self._kwargs = kwargs |
| 53 | |
| 54 | async def until( |
| 55 | self, |
| 56 | condition: Callable[[_R], bool], |
| 57 | timeout: float = REACTPY_TESTING_DEFAULT_TIMEOUT.current, |
| 58 | delay: float = _DEFAULT_POLL_DELAY, |
| 59 | description: str = "condition to be true", |
| 60 | ) -> None: |
| 61 | """Check that the coroutines result meets a condition within the timeout""" |
| 62 | started_at = time.time() |
| 63 | while True: |
| 64 | await asyncio.sleep(delay) |
| 65 | result = await self._func(*self._args, **self._kwargs) |
| 66 | if condition(result): |
| 67 | break |
| 68 | elif (time.time() - started_at) > timeout: # nocov |
| 69 | msg = f"Expected {description} after {timeout} seconds - last value was {result!r}" |
| 70 | raise asyncio.TimeoutError(msg) |
| 71 | |
| 72 | async def until_is( |
| 73 | self, |
| 74 | right: _R, |
| 75 | timeout: float = REACTPY_TESTING_DEFAULT_TIMEOUT.current, |
| 76 | delay: float = _DEFAULT_POLL_DELAY, |
| 77 | ) -> None: |
| 78 | """Wait until the result is identical to the given value""" |
| 79 | return await self.until( |
| 80 | lambda left: left is right, |
| 81 | timeout, |
| 82 | delay, |
| 83 | f"value to be identical to {right!r}", |
| 84 | ) |
| 85 | |
| 86 | async def until_equals( |
| 87 | self, |
| 88 | right: _R, |
| 89 | timeout: float = REACTPY_TESTING_DEFAULT_TIMEOUT.current, |
| 90 | delay: float = _DEFAULT_POLL_DELAY, |
no outgoing calls