<s> import random <EOL> import six <EOL> import sys <EOL> import time <EOL> import traceback <EOL> MAX_WAIT = <NUM_LIT> <EOL> def retry ( * dargs , ** dkw ) : <EOL> """<STR_LIT>""" <EOL> if len ( dargs ) == <NUM_LIT:1> and callable ( dargs [ <NUM_LIT:0> ] ) : <EOL> def wrap_simple ( f ) : <EOL> @ six . wraps ( f ) <EOL> def wrapped_f ( * args , ** kw ) : <EOL> return Retrying ( ) . call ( f , * args , ** kw ) <EOL> return wrapped_f <EOL> return wrap_simple ( dargs [ <NUM_LIT:0> ] ) <EOL> else : <EOL> def wrap ( f ) : <EOL> @ six . wraps ( f ) <EOL> def wrapped_f ( * args , ** kw ) : <EOL> return Retrying ( * dargs , ** dkw ) . call ( f , * args , ** kw ) <EOL> return wrapped_f <EOL> return wrap <EOL> class Retrying ( object ) : <EOL> def __init__ ( self , <EOL> stop = None , wait = None , <EOL> stop_max_attempt_number = None , <EOL> stop_max_delay = None , <EOL> wait_fixed = None , <EOL> wait_random_min = None , wait_random_max = None , <EOL> wait_incrementing_start = None , wait_incrementing_increment = None , <EOL> wait_exponential_multiplier = None , wait_exponential_max = None , <EOL> retry_on_exception = None , <EOL> retry_on_result = None , <EOL> wrap_exception = False , <EOL> stop_func = None , <EOL> wait_func = None , <EOL> wait_jitter_max = None ) : <EOL> self . _stop_max_attempt_number = <NUM_LIT:5> if stop_max_attempt_number is None else stop_max_attempt_number <EOL> self . _stop_max_delay = <NUM_LIT:100> if stop_max_delay is None else stop_max_delay <EOL> self . _wait_fixed = <NUM_LIT:1000> if wait_fixed is None else wait_fixed <EOL> self . _wait_random_min = <NUM_LIT:0> if wait_random_min is None else wait_random_min <EOL> self . _wait_random_max = <NUM_LIT:1000> if wait_random_max is None else wait_random_max <EOL> self . _wait_incrementing_start = <NUM_LIT:0> if wait_incrementing_start is None else wait_incrementing_start <EOL> self . _wait_incrementing_increment = <NUM_LIT:100> if wait_incrementing_increment is None else wait_incrementing_increment <EOL> self . _wait_exponential_multiplier = <NUM_LIT:1> if wait_exponential_multiplier is None else wait_exponential_multiplier <EOL> self . _wait_exponential_max = MAX_WAIT if wait_exponential_max is None else wait_exponential_max <EOL> self . _wait_jitter_max = <NUM_LIT:0> if wait_jitter_max is None else wait_jitter_max <EOL> stop_funcs = [ ] <EOL> if stop_max_attempt_number is not None : <EOL> stop_funcs . append ( self . stop_after_attempt ) <EOL> if stop_max_delay is not None : <EOL> stop_funcs . append ( self . stop_after_delay ) <EOL> if stop_func is not None : <EOL> self . stop = stop_func <EOL> elif stop is None : <EOL> self . stop = lambda attempts , delay : any ( f ( attempts , delay ) for f in stop_funcs ) <EOL> else : <EOL> self . stop = getattr ( self , stop ) <EOL> wait_funcs = [ lambda * args , ** kwargs : <NUM_LIT:0> ] <EOL> if wait_fixed is not None : <EOL> wait_funcs . append ( self . fixed_sleep ) <EOL> if wait_random_min is not None or wait_random_max is not None : <EOL> wait_funcs . append ( self . random_sleep ) <EOL> if wait_incrementing_start is not None or wait_incrementing_increment is not None : <EOL> wait_funcs . append ( self . incrementing_sleep ) <EOL> if wait_exponential_multiplier is not None or wait_exponential_max is not None : <EOL> wait_funcs . append ( self . exponential_sleep ) <EOL> if wait_func is not None : <EOL> self . wait = wait_func <EOL> elif wait is None : <EOL> self . wait = lambda attempts , delay : max ( f ( attempts , delay ) for f in wait_funcs ) <EOL> else : <EOL> self . wait = getattr ( self , wait ) <EOL> if retry_on_exception is None : <EOL> self . _retry_on_exception = self . always_reject <EOL> else : <EOL> self . _retry_on_exception = retry_on_exception <EOL> if retry_on_result is None : <EOL> self . _retry_on_result = self . never_reject <EOL> else : <EOL> self . _retry_on_result = retry_on_result <EOL> self . _wrap_exception = wrap_exception <EOL> def stop_after_attempt ( self , previous_attempt_number , delay_since_first_attempt_ms ) : <EOL> """<STR_LIT>""" <EOL> return previous_attempt_number >= self . _stop_max_attempt_number <EOL> def stop_after_delay ( self , previous_attempt_number , delay_since_first_attempt_ms ) : <EOL> """<STR_LIT>""" <EOL> return delay_since_first_attempt_ms >= self . _stop_max_delay <EOL> def no_sleep ( self , previous_attempt_number , delay_since_first_attempt_ms ) : <EOL> """<STR_LIT>""" <EOL> return <NUM_LIT:0> <EOL> def fixed_sleep ( self , previous_attempt_number , delay_since_first_attempt_ms ) : <EOL> """<STR_LIT>""" <EOL> return self . _wait_fixed <EOL> def random_sleep ( self , previous_attempt_number , delay_since_first_attempt_ms ) : <EOL> """<STR_LIT>""" <EOL> return random . randint ( self . _wait_random_min , self . _wait_random_max ) <EOL> def incrementing_sleep ( self , previous_attempt_number , delay_since_first_attempt_ms ) : <EOL> """<STR_LIT>""" <EOL> result = self . _wait_incrementing_start + ( self . _wait_incrementing_increment * ( previous_attempt_number - <NUM_LIT:1> ) ) <EOL> if result < <NUM_LIT:0> : <EOL> result = <NUM_LIT:0> <EOL> return result <EOL> def exponential_sleep ( self , previous_attempt_number , delay_since_first_attempt_ms ) : <EOL> exp = <NUM_LIT:2> ** previous_attempt_number <EOL> result = self . _wait_exponential_multiplier * exp <EOL> if result > self . _wait_exponential_max : <EOL> result = self . _wait_exponential_max <EOL> if result < <NUM_LIT:0> : <EOL> result = <NUM_LIT:0> <EOL> return result <EOL> def never_reject ( self , result ) : <EOL> return False <EOL> def always_reject ( self , result ) : <EOL> return True <EOL> def should_reject ( self , attempt ) : <EOL> reject = False <EOL> if attempt . has_exception : <EOL> reject |= self . _retry_on_exception ( attempt . value [ <NUM_LIT:1> ] ) <EOL> else : <EOL> reject |= self . _retry_on_result ( attempt . value ) <EOL> return reject <EOL> def call ( self , fn , * args , ** kwargs ) : <EOL> start_time = int ( round ( time . time ( ) * <NUM_LIT:1000> ) ) <EOL> attempt_number = <NUM_LIT:1> <EOL> while True : <EOL> try : <EOL> attempt = Attempt ( fn ( * args , ** kwargs ) , attempt_number , False ) <EOL> except : <EOL> tb = sys . exc_info ( ) <EOL> attempt = Attempt ( tb , attempt_number , True ) <EOL> if not self . should_reject ( attempt ) : <EOL> return attempt . get ( self . _wrap_exception ) <EOL> delay_since_first_attempt_ms = int ( round ( time . time ( ) * <NUM_LIT:1000> ) ) - start_time <EOL> if self . stop ( attempt_number , delay_since_first_attempt_ms ) : <EOL> if not self . _wrap_exception and attempt . has_exception : <EOL> raise attempt . get ( ) <EOL> else : <EOL> raise RetryError ( attempt ) <EOL> else : <EOL> sleep = self . wait ( attempt_number , delay_since_first_attempt_ms ) <EOL> if self . _wait_jitter_max : <EOL> jitter = random . random ( ) * self . _wait_jitter_max <EOL> sleep = sleep + max ( <NUM_LIT:0> , jitter ) <EOL> time . sleep ( sleep / <NUM_LIT> ) <EOL> attempt_number += <NUM_LIT:1> <EOL> class Attempt ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , value , attempt_number , has_exception ) : <EOL> self . value = value <EOL> self . attempt_number = attempt_number <EOL> self . has_exception = has_exception <EOL> def get ( self , wrap_exception = False ) : <EOL> """<STR_LIT>""" <EOL> if self . has_exception : <EOL> if wrap_exception : <EOL> raise RetryError ( self ) <EOL> else : <EOL> six . reraise ( self . value [ <NUM_LIT:0> ] , self . value [ <NUM_LIT:1> ] , self . value [ <NUM_LIT:2> ] ) <EOL> else : <EOL> return self . value <EOL> def __repr__ ( self ) : <EOL> if self . has_exception : <EOL> return "<STR_LIT>" . format ( self . attempt_number , "<STR_LIT>" . join ( traceback . format_tb ( self . value [ <NUM_LIT:2> ] ) ) ) <EOL> else : <EOL> return "<STR_LIT>" . format ( self . attempt_number , self . value ) <EOL> class RetryError ( Exception ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , last_attempt ) : <EOL> self . last_attempt = last_attempt <EOL> def __str__ ( self ) : <EOL> return "<STR_LIT>" . format ( self . last_attempt ) </s>
