11from __future__ import annotations
22
3- import time
43import warnings
5- from concurrent .futures import ThreadPoolExecutor
6- from threading import Event
74from typing import TYPE_CHECKING , Any , Callable , NamedTuple
85
9- from .._utils import batched , with_timeout
6+ from .._utils import batched , waiter
107from ..core import BoundModelBase , ClientEntityBase , Meta
118from .domain import Action , ActionFailedException , ActionTimeoutException
129
@@ -19,18 +16,24 @@ class BoundAction(BoundModelBase, Action):
1916
2017 model = Action
2118
22- def wait_until_finished (self , max_retries : int | None = None ) -> None :
19+ def wait_until_finished (
20+ self ,
21+ max_retries : int | None = None ,
22+ * ,
23+ timeout : float | None = None ,
24+ ) -> None :
2325 """Wait until the specific action has status=finished.
2426
2527 :param max_retries: int Specify how many retries will be performed before an ActionTimeoutException will be raised.
2628 :raises: ActionFailedException when action is finished with status==error
27- :raises: ActionTimeoutException when Action is still in status==running after max_retries is reached.
29+ :raises: ActionTimeoutException when Action is still in status==running after max_retries or timeout is reached.
2830 """
2931 if max_retries is None :
3032 # pylint: disable=protected-access
3133 max_retries = self ._client ._client ._poll_max_retries
3234
3335 retries = 0
36+ wait = waiter (timeout )
3437 while True :
3538 self .reload ()
3639 if self .status != Action .STATUS_RUNNING :
@@ -39,8 +42,8 @@ def wait_until_finished(self, max_retries: int | None = None) -> None:
3942 retries += 1
4043 if retries < max_retries :
4144 # pylint: disable=protected-access
42- time . sleep (self ._client ._client ._poll_interval_func (retries ))
43- continue
45+ if not wait (self ._client ._client ._poll_interval_func (retries )):
46+ continue
4447
4548 raise ActionTimeoutException (action = self )
4649
@@ -170,9 +173,10 @@ def _get_list_by_ids(self, ids: list[int]) -> list[BoundAction]:
170173
171174 def wait_for_function (
172175 self ,
173- stop : Event ,
174176 handle_update : Callable [[BoundAction ], None ],
175177 actions : list [Action | BoundAction ],
178+ * ,
179+ timeout : float | None = None ,
176180 ) -> list [BoundAction ]:
177181 """
178182 Waits until all Actions succeed by polling the API at the interval defined by
@@ -183,6 +187,7 @@ def wait_for_function(
183187
184188 :param handle_update: Function called every time an Action is updated.
185189 :param actions: List of Actions to wait for.
190+ :param timeout: Timeout in seconds.
186191 :raises: ActionFailedException when an Action failed.
187192 :return: List of succeeded Actions.
188193 """
@@ -191,10 +196,12 @@ def wait_for_function(
191196 completed : list [BoundAction ] = []
192197
193198 retries = 0
199+ wait = waiter (timeout )
194200 while len (running_ids ):
195201 # pylint: disable=protected-access
196- if stop .wait (self ._client ._poll_interval_func (retries )):
197- raise ActionTimeoutException ()
202+ if wait (self ._client ._poll_interval_func (retries )):
203+ # TODO: How to raise a timeout exception for many actiosn without exception group.
204+ raise ActionTimeoutException ("" )
198205
199206 retries += 1
200207
@@ -212,6 +219,7 @@ def wait_for_function(
212219 def wait_for (
213220 self ,
214221 actions : list [Action | BoundAction ],
222+ * ,
215223 timeout : float | None = None ,
216224 ) -> list [BoundAction ]:
217225 """
@@ -222,6 +230,7 @@ def wait_for(
222230 If a single Action fails, the function will stop waiting and raise ActionFailedException.
223231
224232 :param actions: List of Actions to wait for.
233+ :param timeout: Timeout in seconds.
225234 :raises: ActionFailedException when an Action failed.
226235 :raises: TimeoutError when the Actions did not succeed before timeout.
227236 :return: List of succeeded Actions.
@@ -231,10 +240,7 @@ def handle_update(update: BoundAction) -> None:
231240 if update .status == Action .STATUS_ERROR :
232241 raise ActionFailedException (action = update )
233242
234- def run () -> list [BoundAction ]:
235- return self .wait_for_function (handle_update , actions )
236-
237- return with_timeout (timeout )(run )()
243+ return self .wait_for_function (handle_update , actions , timeout = timeout )
238244
239245 def get_list (
240246 self ,
0 commit comments