import functools import time from typing import Callable, Tuple def retry(count: int, retry_delay: int, excepted: Tuple[Exception], exc_handler: Callable = None) -> Callable: """ Retry decorator. :param count: number of attempts to retry. :param retry_delay: delay between sequential retries. :param excepted: tuple of exceptions to catch and retry for, another exceptions will be raised. :param exc_handler: optional callable handler to handle cough exception between retry, should take parameters: exception, retry number, *args, **kwargs. """ def wrapper(f) -> Callable: @functools.wraps(f) def wrapped(*args, **kwargs): counter = 1 while True: try: return f(*args, **kwargs) except excepted as exc: if counter > count: raise if exc_handler is not None: exc_handler(exc, counter, *args, **kwargs) counter += 1 time.sleep(retry_delay) return wrapped return wrapper