import abc
import random
import typing
from pip._vendor.tenacity import _utils
if typing.TYPE_CHECKING:
from pip._vendor.tenacity import RetryCallState
class wait_base(abc.ABC):
@abc.abstractmethod
def __call__(self, retry_state: "RetryCallState") -> float:
pass
def __add__(self, other: "wait_base") -> "wait_combine":
return wait_combine(self, other)
def __radd__(self, other: "wait_base") -> typing.Union["wait_combine", "wait_base"]:
if other == 0: return self
return self.__add__(other)
WaitBaseT = typing.Union[wait_base, typing.Callable[["RetryCallState"], typing.Union[float, int]]]
class wait_fixed(wait_base):
def __init__(self, wait: _utils.time_unit_type) -> None:
self.wait_fixed = _utils.to_seconds(wait)
def __call__(self, retry_state: "RetryCallState") -> float:
return self.wait_fixed
class wait_none(wait_fixed):
def __init__(self) -> None:
super().__init__(0)
class wait_random(wait_base):
def __init__(self, min: _utils.time_unit_type = 0, max: _utils.time_unit_type = 1) -> None: self.wait_random_min = _utils.to_seconds(min)
self.wait_random_max = _utils.to_seconds(max)
def __call__(self, retry_state: "RetryCallState") -> float:
return self.wait_random_min + (random.random() * (self.wait_random_max - self.wait_random_min))
class wait_combine(wait_base):
def __init__(self, *strategies: wait_base) -> None:
self.wait_funcs = strategies
def __call__(self, retry_state: "RetryCallState") -> float:
return sum(x(retry_state=retry_state) for x in self.wait_funcs)
class wait_chain(wait_base):
def __init__(self, *strategies: wait_base) -> None:
self.strategies = strategies
def __call__(self, retry_state: "RetryCallState") -> float:
wait_func_no = min(max(retry_state.attempt_number, 1), len(self.strategies))
wait_func = self.strategies[wait_func_no - 1]
return wait_func(retry_state=retry_state)
class wait_incrementing(wait_base):
def __init__(
self,
start: _utils.time_unit_type = 0,
increment: _utils.time_unit_type = 100,
max: _utils.time_unit_type = _utils.MAX_WAIT, ) -> None:
self.start = _utils.to_seconds(start)
self.increment = _utils.to_seconds(increment)
self.max = _utils.to_seconds(max)
def __call__(self, retry_state: "RetryCallState") -> float:
result = self.start + (self.increment * (retry_state.attempt_number - 1))
return max(0, min(result, self.max))
class wait_exponential(wait_base):
def __init__(
self,
multiplier: typing.Union[int, float] = 1,
max: _utils.time_unit_type = _utils.MAX_WAIT, exp_base: typing.Union[int, float] = 2,
min: _utils.time_unit_type = 0, ) -> None:
self.multiplier = multiplier
self.min = _utils.to_seconds(min)
self.max = _utils.to_seconds(max)
self.exp_base = exp_base
def __call__(self, retry_state: "RetryCallState") -> float:
try:
exp = self.exp_base ** (retry_state.attempt_number - 1)
result = self.multiplier * exp
except OverflowError:
return self.max
return max(max(0, self.min), min(result, self.max))
class wait_random_exponential(wait_exponential):
def __call__(self, retry_state: "RetryCallState") -> float:
high = super().__call__(retry_state=retry_state)
return random.uniform(0, high)
class wait_exponential_jitter(wait_base):
def __init__(
self,
initial: float = 1,
max: float = _utils.MAX_WAIT, exp_base: float = 2,
jitter: float = 1,
) -> None:
self.initial = initial
self.max = max
self.exp_base = exp_base
self.jitter = jitter
def __call__(self, retry_state: "RetryCallState") -> float:
jitter = random.uniform(0, self.jitter)
try:
exp = self.exp_base ** (retry_state.attempt_number - 1)
result = self.initial * exp + jitter
except OverflowError:
result = self.max
return max(0, min(result, self.max))