Skip to content

Commit

Permalink
Upgrade tenacity to 8.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
pfmoore committed Oct 10, 2022
1 parent f32627f commit 216cda7
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 16 deletions.
1 change: 1 addition & 0 deletions news/tenacity.vendor.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Upgrade tenacity to 8.1.0
2 changes: 2 additions & 0 deletions src/pip/_vendor/tenacity/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
from .retry import retry_any # noqa
from .retry import retry_if_exception # noqa
from .retry import retry_if_exception_type # noqa
from .retry import retry_if_exception_cause_type # noqa
from .retry import retry_if_not_exception_type # noqa
from .retry import retry_if_not_result # noqa
from .retry import retry_if_result # noqa
Expand Down Expand Up @@ -63,6 +64,7 @@
from .wait import wait_random # noqa
from .wait import wait_random_exponential # noqa
from .wait import wait_random_exponential as wait_full_jitter # noqa
from .wait import wait_exponential_jitter # noqa

# Import all built-in before strategies for easier usage.
from .before import before_log # noqa
Expand Down
27 changes: 27 additions & 0 deletions src/pip/_vendor/tenacity/retry.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,33 @@ def __call__(self, retry_state: "RetryCallState") -> bool:
return self.predicate(retry_state.outcome.exception())


class retry_if_exception_cause_type(retry_base):
"""Retries if any of the causes of the raised exception is of one or more types.
The check on the type of the cause of the exception is done recursively (until finding
an exception in the chain that has no `__cause__`)
"""

def __init__(
self,
exception_types: typing.Union[
typing.Type[BaseException],
typing.Tuple[typing.Type[BaseException], ...],
] = Exception,
) -> None:
self.exception_cause_types = exception_types

def __call__(self, retry_state: "RetryCallState") -> bool:
if retry_state.outcome.failed:
exc = retry_state.outcome.exception()
while exc is not None:
if isinstance(exc.__cause__, self.exception_cause_types):
return True
exc = exc.__cause__

return False


class retry_if_result(retry_base):
"""Retries if the result verifies a predicate."""

Expand Down
71 changes: 56 additions & 15 deletions src/pip/_vendor/tenacity/wait.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,19 @@
import abc
import random
import typing
from datetime import timedelta

from pip._vendor.tenacity import _utils

if typing.TYPE_CHECKING:
from pip._vendor.tenacity import RetryCallState

wait_unit_type = typing.Union[int, float, timedelta]


def to_seconds(wait_unit: wait_unit_type) -> float:
return float(wait_unit.total_seconds() if isinstance(wait_unit, timedelta) else wait_unit)


class wait_base(abc.ABC):
"""Abstract base class for wait strategies."""
Expand All @@ -44,8 +51,8 @@ def __radd__(self, other: "wait_base") -> typing.Union["wait_combine", "wait_bas
class wait_fixed(wait_base):
"""Wait strategy that waits a fixed amount of time between each retry."""

def __init__(self, wait: float) -> None:
self.wait_fixed = wait
def __init__(self, wait: wait_unit_type) -> None:
self.wait_fixed = to_seconds(wait)

def __call__(self, retry_state: "RetryCallState") -> float:
return self.wait_fixed
Expand All @@ -61,9 +68,9 @@ def __init__(self) -> None:
class wait_random(wait_base):
"""Wait strategy that waits a random amount of time between min/max."""

def __init__(self, min: typing.Union[int, float] = 0, max: typing.Union[int, float] = 1) -> None: # noqa
self.wait_random_min = min
self.wait_random_max = max
def __init__(self, min: wait_unit_type = 0, max: wait_unit_type = 1) -> None: # noqa
self.wait_random_min = to_seconds(min)
self.wait_random_max = 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))
Expand Down Expand Up @@ -113,13 +120,13 @@ class wait_incrementing(wait_base):

def __init__(
self,
start: typing.Union[int, float] = 0,
increment: typing.Union[int, float] = 100,
max: typing.Union[int, float] = _utils.MAX_WAIT, # noqa
start: wait_unit_type = 0,
increment: wait_unit_type = 100,
max: wait_unit_type = _utils.MAX_WAIT, # noqa
) -> None:
self.start = start
self.increment = increment
self.max = max
self.start = to_seconds(start)
self.increment = to_seconds(increment)
self.max = to_seconds(max)

def __call__(self, retry_state: "RetryCallState") -> float:
result = self.start + (self.increment * (retry_state.attempt_number - 1))
Expand All @@ -142,13 +149,13 @@ class wait_exponential(wait_base):
def __init__(
self,
multiplier: typing.Union[int, float] = 1,
max: typing.Union[int, float] = _utils.MAX_WAIT, # noqa
max: wait_unit_type = _utils.MAX_WAIT, # noqa
exp_base: typing.Union[int, float] = 2,
min: typing.Union[int, float] = 0, # noqa
min: wait_unit_type = 0, # noqa
) -> None:
self.multiplier = multiplier
self.min = min
self.max = max
self.min = to_seconds(min)
self.max = to_seconds(max)
self.exp_base = exp_base

def __call__(self, retry_state: "RetryCallState") -> float:
Expand Down Expand Up @@ -189,3 +196,37 @@ 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):
"""Wait strategy that applies exponential backoff and jitter.
It allows for a customized initial wait, maximum wait and jitter.
This implements the strategy described here:
https://cloud.google.com/storage/docs/retry-strategy
The wait time is min(initial * (2**n + random.uniform(0, jitter)), maximum)
where n is the retry count.
"""

def __init__(
self,
initial: float = 1,
max: float = _utils.MAX_WAIT, # noqa
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))
2 changes: 1 addition & 1 deletion src/pip/_vendor/vendor.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ rich==12.6.0
resolvelib==0.8.1
setuptools==44.0.0
six==1.16.0
tenacity==8.0.1
tenacity==8.1.0
tomli==2.0.1
webencodings==0.5.1

0 comments on commit 216cda7

Please sign in to comment.