11from __future__ import annotations
22
3+ import asyncio
4+ import inspect
35import shutil
46import time
57from functools import wraps
@@ -26,9 +28,7 @@ def clear_idom_web_modules_dir() -> None:
2628_RC = TypeVar ("_RC" , covariant = True )
2729
2830
29- class _UntilFunc (Protocol [_RC ]):
30- def __call__ (self , condition : Callable [[_RC ], bool ], timeout : float = ...) -> Any :
31- ...
31+ _DEFAULT_POLL_DELAY = 0.1
3232
3333
3434class poll (Generic [_R ]): # noqa: N801
@@ -40,64 +40,54 @@ def __init__(
4040 * args : _P .args ,
4141 ** kwargs : _P .kwargs ,
4242 ) -> None :
43- self .until : _UntilFunc [_R ]
44- """Check that the coroutines result meets a condition within the timeout"""
43+ coro : Callable [_P , Awaitable [_R ]]
44+ if not inspect .iscoroutinefunction (function ):
45+
46+ async def coro (* args : _P .args , ** kwargs : _P .kwargs ) -> _R :
47+ return cast (_R , function (* args , ** kwargs ))
4548
46- if iscoroutinefunction (function ):
47- coro_function = cast (Callable [_P , Awaitable [_R ]], function )
48-
49- async def coro_until (
50- condition : Callable [[_R ], bool ],
51- timeout : float = IDOM_TESTING_DEFAULT_TIMEOUT .current ,
52- ) -> None :
53- started_at = time .time ()
54- while True :
55- result = await coro_function (* args , ** kwargs )
56- if condition (result ):
57- break
58- elif (time .time () - started_at ) > timeout : # pragma: no cover
59- raise TimeoutError (
60- f"Condition not met within { timeout } "
61- f"seconds - last value was { result !r} "
62- )
63-
64- self .until = coro_until
6549 else :
66- sync_function = cast (Callable [_P , _R ], function )
67-
68- def sync_until (
69- condition : Callable [[_R ], bool ] | Any ,
70- timeout : float = IDOM_TESTING_DEFAULT_TIMEOUT .current ,
71- ) -> None :
72- started_at = time .time ()
73- while True :
74- result = sync_function (* args , ** kwargs )
75- if condition (result ):
76- break
77- elif (time .time () - started_at ) > timeout : # pragma: no cover
78- raise TimeoutError (
79- f"Condition not met within { timeout } "
80- f"seconds - last value was { result !r} "
81- )
82-
83- self .until = sync_until
84-
85- def until_is (
50+ coro = cast (Callable [_P , Awaitable [_R ]], function )
51+ self ._func = coro
52+ self ._args = args
53+ self ._kwargs = kwargs
54+
55+ async def until (
8656 self ,
87- right : Any ,
57+ condition : Callable [[ _R ], bool ] ,
8858 timeout : float = IDOM_TESTING_DEFAULT_TIMEOUT .current ,
89- ) -> Any :
59+ delay : float = _DEFAULT_POLL_DELAY ,
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 : # pragma: no cover
69+ raise TimeoutError (
70+ f"Condition not met within { timeout } "
71+ f"seconds - last value was { result !r} "
72+ )
73+
74+ async def until_is (
75+ self ,
76+ right : _R ,
77+ timeout : float = IDOM_TESTING_DEFAULT_TIMEOUT .current ,
78+ delay : float = _DEFAULT_POLL_DELAY ,
79+ ) -> None :
9080 """Wait until the result is identical to the given value"""
91- return self .until (lambda left : left is right , timeout )
81+ return await self .until (lambda left : left is right , timeout , delay )
9282
93- def until_equals (
83+ async def until_equals (
9484 self ,
95- right : Any ,
85+ right : _R ,
9686 timeout : float = IDOM_TESTING_DEFAULT_TIMEOUT .current ,
97- ) -> Any :
87+ delay : float = _DEFAULT_POLL_DELAY ,
88+ ) -> None :
9889 """Wait until the result is equal to the given value"""
99- # not really sure why I need a type ignore comment here
100- return self .until (lambda left : left == right , timeout ) # type: ignore
90+ return await self .until (lambda left : left == right , timeout , delay )
10191
10292
10393class HookCatcher :
0 commit comments