"""This module provides useful decorators for common use.""" import logging import time logger = logging.getLogger(__name__) def retry(max_attempts=4, initial_delay=1, delay_multiplier=2, retry_on_exception=Exception): """Retry call of decorated function in case of Exception. If called function raises exception when sleep for a delay and then retry. Delay increases by multiplier. Args: max_attempts (int): maximum number of attempts initial_delay (float): delay after first unsuccessful call delay_multiplier (float): delay multiplier for each following attempt retry_on_exception (Exception class): base exception to being caught for retry """ def decorator(func): def wrapper(*args, **kwargs): delay_between_attempts = initial_delay last_exception = None for try_attempt in range(1, max_attempts+1): try: return func(*args, **kwargs) except retry_on_exception as exception: last_exception = exception logger.warning(f'Try {try_attempt} of {max_attempts}. ' f'Got exception: {repr(exception)}') if try_attempt < max_attempts: time.sleep(delay_between_attempts) delay_between_attempts *= delay_multiplier else: raise last_exception return wrapper return decorator