1
1
from typing import (
2
+ AsyncIterator ,
2
3
Awaitable ,
3
4
TypeVar ,
4
5
)
5
6
6
7
from cancel_token import CancelToken
7
8
9
+ TReturn = TypeVar ('TReturn' )
10
+
8
11
9
12
class CancellableMixin :
10
13
cancel_token : CancelToken = None
11
14
12
- _TReturn = TypeVar ('_TReturn' )
13
-
14
15
async def wait (self ,
15
- awaitable : Awaitable [_TReturn ],
16
+ awaitable : Awaitable [TReturn ],
16
17
token : CancelToken = None ,
17
- timeout : float = None ) -> _TReturn :
18
+ timeout : float = None ) -> TReturn :
18
19
"""See wait_first()"""
19
20
return await self .wait_first (awaitable , token = token , timeout = timeout )
20
21
21
22
async def wait_first (self ,
22
- * awaitables : Awaitable [_TReturn ],
23
+ * awaitables : Awaitable [TReturn ],
23
24
token : CancelToken = None ,
24
- timeout : float = None ) -> _TReturn :
25
+ timeout : float = None ) -> TReturn :
25
26
"""
26
27
Wait for the first awaitable to complete, unless we timeout or the token chain is triggered.
27
28
@@ -39,3 +40,30 @@ async def wait_first(self,
39
40
else :
40
41
token_chain = token .chain (self .cancel_token )
41
42
return await token_chain .cancellable_wait (* awaitables , timeout = timeout )
43
+
44
+ async def wait_iter (
45
+ self ,
46
+ aiterable : AsyncIterator [TReturn ],
47
+ token : CancelToken = None ,
48
+ timeout : float = None ) -> AsyncIterator [TReturn ]:
49
+ """
50
+ Iterate through an async iterator, raising the OperationCancelled exception if the token is
51
+ triggered. For example:
52
+
53
+ ::
54
+
55
+ async for val in self.wait_iter(my_async_iterator()):
56
+ do_stuff(val)
57
+
58
+ See :meth:`CancellableMixin.wait_first` for using arguments ``token`` and ``timeout``
59
+ """
60
+ aiter = aiterable .__aiter__ ()
61
+ while True :
62
+ try :
63
+ yield await self .wait (
64
+ aiter .__anext__ (),
65
+ token = token ,
66
+ timeout = timeout ,
67
+ )
68
+ except StopAsyncIteration :
69
+ break
0 commit comments