Spaces:
Sleeping
Sleeping
import functools | |
from time import perf_counter, sleep | |
from typing import Callable, TypeVar | |
from pip._vendor.typing_extensions import ParamSpec | |
T = TypeVar("T") | |
P = ParamSpec("P") | |
def retry( | |
wait: float, stop_after_delay: float | |
) -> Callable[[Callable[P, T]], Callable[P, T]]: | |
"""Decorator to automatically retry a function on error. | |
If the function raises, the function is recalled with the same arguments | |
until it returns or the time limit is reached. When the time limit is | |
surpassed, the last exception raised is reraised. | |
:param wait: The time to wait after an error before retrying, in seconds. | |
:param stop_after_delay: The time limit after which retries will cease, | |
in seconds. | |
""" | |
def wrapper(func: Callable[P, T]) -> Callable[P, T]: | |
def retry_wrapped(*args: P.args, **kwargs: P.kwargs) -> T: | |
# The performance counter is monotonic on all platforms we care | |
# about and has much better resolution than time.monotonic(). | |
start_time = perf_counter() | |
while True: | |
try: | |
return func(*args, **kwargs) | |
except Exception: | |
if perf_counter() - start_time > stop_after_delay: | |
raise | |
sleep(wait) | |
return retry_wrapped | |
return wrapper | |