Skip to content

Commit a28c3e0

Browse files
committed
fix(retry): Improve retry_until_extended function with better error messaging
- Add descriptive timeout message to WaitTimeout exception - Ensure consistent handling of timeout errors - Fix type hints for function return values
1 parent 3ae2c07 commit a28c3e0

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

src/libtmux/test/retry_extended.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
"""Extended retry functionality for libtmux."""
2+
3+
from __future__ import annotations
4+
5+
import logging
6+
import time
7+
import typing as t
8+
9+
from libtmux.exc import WaitTimeout
10+
from libtmux.test.constants import (
11+
RETRY_INTERVAL_SECONDS,
12+
RETRY_TIMEOUT_SECONDS,
13+
)
14+
15+
logger = logging.getLogger(__name__)
16+
17+
if t.TYPE_CHECKING:
18+
import sys
19+
from collections.abc import Callable
20+
21+
if sys.version_info >= (3, 11):
22+
pass
23+
24+
25+
def retry_until_extended(
26+
fun: Callable[[], bool],
27+
seconds: float = RETRY_TIMEOUT_SECONDS,
28+
*,
29+
interval: float = RETRY_INTERVAL_SECONDS,
30+
raises: bool | None = True,
31+
) -> tuple[bool, Exception | None]:
32+
"""
33+
Retry a function until a condition meets or the specified time passes.
34+
35+
Extended version that returns both success state and exception.
36+
37+
Parameters
38+
----------
39+
fun : callable
40+
A function that will be called repeatedly until it returns ``True`` or
41+
the specified time passes.
42+
seconds : float
43+
Seconds to retry. Defaults to ``8``, which is configurable via
44+
``RETRY_TIMEOUT_SECONDS`` environment variables.
45+
interval : float
46+
Time in seconds to wait between calls. Defaults to ``0.05`` and is
47+
configurable via ``RETRY_INTERVAL_SECONDS`` environment variable.
48+
raises : bool
49+
Whether or not to raise an exception on timeout. Defaults to ``True``.
50+
51+
Returns
52+
-------
53+
tuple[bool, Exception | None]
54+
Tuple containing (success, exception). If successful, the exception will
55+
be None.
56+
"""
57+
ini = time.time()
58+
exception = None
59+
60+
while not fun():
61+
end = time.time()
62+
if end - ini >= seconds:
63+
timeout_msg = f"Timed out after {seconds} seconds"
64+
exception = WaitTimeout(timeout_msg)
65+
if raises:
66+
raise exception
67+
return False, exception
68+
time.sleep(interval)
69+
return True, None

0 commit comments

Comments
 (0)