Skip to content

Commit 07c86c7

Browse files
committed
Upgrade tenacity to 8.1.0
1 parent b922e0f commit 07c86c7

File tree

5 files changed

+87
-16
lines changed

5 files changed

+87
-16
lines changed

news/tenacity.vendor.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Upgrade tenacity to 8.1.0

src/pip/_vendor/tenacity/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
from .retry import retry_any # noqa
3434
from .retry import retry_if_exception # noqa
3535
from .retry import retry_if_exception_type # noqa
36+
from .retry import retry_if_exception_cause_type # noqa
3637
from .retry import retry_if_not_exception_type # noqa
3738
from .retry import retry_if_not_result # noqa
3839
from .retry import retry_if_result # noqa
@@ -63,6 +64,7 @@
6364
from .wait import wait_random # noqa
6465
from .wait import wait_random_exponential # noqa
6566
from .wait import wait_random_exponential as wait_full_jitter # noqa
67+
from .wait import wait_exponential_jitter # noqa
6668

6769
# Import all built-in before strategies for easier usage.
6870
from .before import before_log # noqa

src/pip/_vendor/tenacity/retry.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,33 @@ def __call__(self, retry_state: "RetryCallState") -> bool:
117117
return self.predicate(retry_state.outcome.exception())
118118

119119

120+
class retry_if_exception_cause_type(retry_base):
121+
"""Retries if any of the causes of the raised exception is of one or more types.
122+
123+
The check on the type of the cause of the exception is done recursively (until finding
124+
an exception in the chain that has no `__cause__`)
125+
"""
126+
127+
def __init__(
128+
self,
129+
exception_types: typing.Union[
130+
typing.Type[BaseException],
131+
typing.Tuple[typing.Type[BaseException], ...],
132+
] = Exception,
133+
) -> None:
134+
self.exception_cause_types = exception_types
135+
136+
def __call__(self, retry_state: "RetryCallState") -> bool:
137+
if retry_state.outcome.failed:
138+
exc = retry_state.outcome.exception()
139+
while exc is not None:
140+
if isinstance(exc.__cause__, self.exception_cause_types):
141+
return True
142+
exc = exc.__cause__
143+
144+
return False
145+
146+
120147
class retry_if_result(retry_base):
121148
"""Retries if the result verifies a predicate."""
122149

src/pip/_vendor/tenacity/wait.py

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,19 @@
1717
import abc
1818
import random
1919
import typing
20+
from datetime import timedelta
2021

2122
from pip._vendor.tenacity import _utils
2223

2324
if typing.TYPE_CHECKING:
2425
from pip._vendor.tenacity import RetryCallState
2526

27+
wait_unit_type = typing.Union[int, float, timedelta]
28+
29+
30+
def to_seconds(wait_unit: wait_unit_type) -> float:
31+
return float(wait_unit.total_seconds() if isinstance(wait_unit, timedelta) else wait_unit)
32+
2633

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

47-
def __init__(self, wait: float) -> None:
48-
self.wait_fixed = wait
54+
def __init__(self, wait: wait_unit_type) -> None:
55+
self.wait_fixed = to_seconds(wait)
4956

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

64-
def __init__(self, min: typing.Union[int, float] = 0, max: typing.Union[int, float] = 1) -> None: # noqa
65-
self.wait_random_min = min
66-
self.wait_random_max = max
71+
def __init__(self, min: wait_unit_type = 0, max: wait_unit_type = 1) -> None: # noqa
72+
self.wait_random_min = to_seconds(min)
73+
self.wait_random_max = to_seconds(max)
6774

6875
def __call__(self, retry_state: "RetryCallState") -> float:
6976
return self.wait_random_min + (random.random() * (self.wait_random_max - self.wait_random_min))
@@ -113,13 +120,13 @@ class wait_incrementing(wait_base):
113120

114121
def __init__(
115122
self,
116-
start: typing.Union[int, float] = 0,
117-
increment: typing.Union[int, float] = 100,
118-
max: typing.Union[int, float] = _utils.MAX_WAIT, # noqa
123+
start: wait_unit_type = 0,
124+
increment: wait_unit_type = 100,
125+
max: wait_unit_type = _utils.MAX_WAIT, # noqa
119126
) -> None:
120-
self.start = start
121-
self.increment = increment
122-
self.max = max
127+
self.start = to_seconds(start)
128+
self.increment = to_seconds(increment)
129+
self.max = to_seconds(max)
123130

124131
def __call__(self, retry_state: "RetryCallState") -> float:
125132
result = self.start + (self.increment * (retry_state.attempt_number - 1))
@@ -142,13 +149,13 @@ class wait_exponential(wait_base):
142149
def __init__(
143150
self,
144151
multiplier: typing.Union[int, float] = 1,
145-
max: typing.Union[int, float] = _utils.MAX_WAIT, # noqa
152+
max: wait_unit_type = _utils.MAX_WAIT, # noqa
146153
exp_base: typing.Union[int, float] = 2,
147-
min: typing.Union[int, float] = 0, # noqa
154+
min: wait_unit_type = 0, # noqa
148155
) -> None:
149156
self.multiplier = multiplier
150-
self.min = min
151-
self.max = max
157+
self.min = to_seconds(min)
158+
self.max = to_seconds(max)
152159
self.exp_base = exp_base
153160

154161
def __call__(self, retry_state: "RetryCallState") -> float:
@@ -189,3 +196,37 @@ class wait_random_exponential(wait_exponential):
189196
def __call__(self, retry_state: "RetryCallState") -> float:
190197
high = super().__call__(retry_state=retry_state)
191198
return random.uniform(0, high)
199+
200+
201+
class wait_exponential_jitter(wait_base):
202+
"""Wait strategy that applies exponential backoff and jitter.
203+
204+
It allows for a customized initial wait, maximum wait and jitter.
205+
206+
This implements the strategy described here:
207+
https://cloud.google.com/storage/docs/retry-strategy
208+
209+
The wait time is min(initial * (2**n + random.uniform(0, jitter)), maximum)
210+
where n is the retry count.
211+
"""
212+
213+
def __init__(
214+
self,
215+
initial: float = 1,
216+
max: float = _utils.MAX_WAIT, # noqa
217+
exp_base: float = 2,
218+
jitter: float = 1,
219+
) -> None:
220+
self.initial = initial
221+
self.max = max
222+
self.exp_base = exp_base
223+
self.jitter = jitter
224+
225+
def __call__(self, retry_state: "RetryCallState") -> float:
226+
jitter = random.uniform(0, self.jitter)
227+
try:
228+
exp = self.exp_base ** (retry_state.attempt_number - 1)
229+
result = self.initial * exp + jitter
230+
except OverflowError:
231+
result = self.max
232+
return max(0, min(result, self.max))

src/pip/_vendor/vendor.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ rich==12.5.1
1818
resolvelib==0.8.1
1919
setuptools==44.0.0
2020
six==1.16.0
21-
tenacity==8.0.1
21+
tenacity==8.1.0
2222
tomli==2.0.1
2323
webencodings==0.5.1

0 commit comments

Comments
 (0)