python-backoff 2.3.1__py3-none-any.whl → 3.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- backoff/__init__.py +11 -7
- backoff/_async.py +219 -110
- backoff/_common.py +183 -36
- backoff/_decorator.py +279 -64
- backoff/_sync.py +193 -97
- backoff/_typing.py +43 -28
- backoff/_wait_gen.py +58 -39
- backoff/types.py +2 -1
- {python_backoff-2.3.1.dist-info → python_backoff-3.0.0.dist-info}/METADATA +4 -7
- python_backoff-3.0.0.dist-info/RECORD +14 -0
- {python_backoff-2.3.1.dist-info → python_backoff-3.0.0.dist-info}/WHEEL +1 -1
- python_backoff-2.3.1.dist-info/RECORD +0 -14
- {python_backoff-2.3.1.dist-info → python_backoff-3.0.0.dist-info}/licenses/LICENSE +0 -0
backoff/_decorator.py
CHANGED
|
@@ -1,39 +1,51 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import inspect
|
|
2
4
|
import logging
|
|
3
5
|
import operator
|
|
4
|
-
from typing import
|
|
6
|
+
from typing import TYPE_CHECKING, Any, cast
|
|
5
7
|
|
|
8
|
+
from backoff import _async, _sync
|
|
6
9
|
from backoff._common import (
|
|
7
|
-
_prepare_logger,
|
|
8
10
|
_config_handlers,
|
|
9
11
|
_log_backoff,
|
|
12
|
+
_log_backoff_context,
|
|
10
13
|
_log_giveup,
|
|
14
|
+
_log_giveup_context,
|
|
15
|
+
_prepare_logger,
|
|
11
16
|
)
|
|
12
17
|
from backoff._jitter import full_jitter
|
|
13
|
-
from backoff import
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
from backoff._wait_gen import expo
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from collections.abc import AsyncGenerator, Callable, Generator, Iterable
|
|
22
|
+
|
|
23
|
+
from backoff._common import Attempt
|
|
24
|
+
from backoff._typing import (
|
|
25
|
+
_AnyLoggerOrName,
|
|
26
|
+
_CallableT,
|
|
27
|
+
_ContextHandler,
|
|
28
|
+
_Handler,
|
|
29
|
+
_Jitterer,
|
|
30
|
+
_MaybeCallable,
|
|
31
|
+
_MaybeTuple,
|
|
32
|
+
_Predicate,
|
|
33
|
+
_WaitGenerator,
|
|
34
|
+
)
|
|
24
35
|
|
|
25
36
|
|
|
26
37
|
def on_predicate(
|
|
27
38
|
wait_gen: _WaitGenerator,
|
|
28
39
|
predicate: _Predicate[Any] = operator.not_,
|
|
29
40
|
*,
|
|
30
|
-
max_tries:
|
|
31
|
-
max_time:
|
|
32
|
-
jitter:
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
41
|
+
max_tries: _MaybeCallable[int] | None = None,
|
|
42
|
+
max_time: _MaybeCallable[float] | None = None,
|
|
43
|
+
jitter: _Jitterer | None = full_jitter,
|
|
44
|
+
on_try: _Handler | Iterable[_Handler] | None = None,
|
|
45
|
+
on_success: _Handler | Iterable[_Handler] | None = None,
|
|
46
|
+
on_backoff: _Handler | Iterable[_Handler] | None = None,
|
|
47
|
+
on_giveup: _Handler | Iterable[_Handler] | None = None,
|
|
48
|
+
logger: _AnyLoggerOrName | None = "backoff",
|
|
37
49
|
backoff_log_level: int = logging.INFO,
|
|
38
50
|
giveup_log_level: int = logging.ERROR,
|
|
39
51
|
**wait_gen_kwargs: Any,
|
|
@@ -62,6 +74,9 @@ def on_predicate(
|
|
|
62
74
|
concurrent clients. Wait times are jittered by default
|
|
63
75
|
using the full_jitter function. Jittering may be disabled
|
|
64
76
|
altogether by passing jitter=None.
|
|
77
|
+
on_try: Callable (or iterable of callables) with a unary
|
|
78
|
+
signature to be called before each attempt. The parameter
|
|
79
|
+
is a dict containing details about the invocation.
|
|
65
80
|
on_success: Callable (or iterable of callables) with a unary
|
|
66
81
|
signature to be called in the event of success. The
|
|
67
82
|
parameter is a dict containing details about the invocation.
|
|
@@ -82,10 +97,11 @@ def on_predicate(
|
|
|
82
97
|
This is useful for runtime configuration.
|
|
83
98
|
"""
|
|
84
99
|
|
|
85
|
-
def decorate(target):
|
|
86
|
-
nonlocal logger, on_success, on_backoff, on_giveup
|
|
100
|
+
def decorate(target: _CallableT) -> _CallableT:
|
|
101
|
+
nonlocal logger, on_try, on_success, on_backoff, on_giveup
|
|
87
102
|
|
|
88
103
|
logger = _prepare_logger(logger)
|
|
104
|
+
on_try = _config_handlers(on_try)
|
|
89
105
|
on_success = _config_handlers(on_success)
|
|
90
106
|
on_backoff = _config_handlers(
|
|
91
107
|
on_backoff,
|
|
@@ -101,21 +117,38 @@ def on_predicate(
|
|
|
101
117
|
)
|
|
102
118
|
|
|
103
119
|
if inspect.iscoroutinefunction(target):
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
120
|
+
return cast(
|
|
121
|
+
"_CallableT",
|
|
122
|
+
_async.retry_predicate(
|
|
123
|
+
target,
|
|
124
|
+
wait_gen,
|
|
125
|
+
predicate,
|
|
126
|
+
max_tries=max_tries,
|
|
127
|
+
max_time=max_time,
|
|
128
|
+
jitter=jitter,
|
|
129
|
+
on_try=on_try,
|
|
130
|
+
on_success=on_success,
|
|
131
|
+
on_backoff=on_backoff,
|
|
132
|
+
on_giveup=on_giveup,
|
|
133
|
+
wait_gen_kwargs=wait_gen_kwargs,
|
|
134
|
+
),
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
return cast(
|
|
138
|
+
"_CallableT",
|
|
139
|
+
_sync.retry_predicate(
|
|
140
|
+
target,
|
|
141
|
+
wait_gen,
|
|
142
|
+
predicate,
|
|
143
|
+
max_tries=max_tries,
|
|
144
|
+
max_time=max_time,
|
|
145
|
+
jitter=jitter,
|
|
146
|
+
on_try=on_try,
|
|
147
|
+
on_success=on_success,
|
|
148
|
+
on_backoff=on_backoff,
|
|
149
|
+
on_giveup=on_giveup,
|
|
150
|
+
wait_gen_kwargs=wait_gen_kwargs,
|
|
151
|
+
),
|
|
119
152
|
)
|
|
120
153
|
|
|
121
154
|
# Return a function which decorates a target with a retry loop.
|
|
@@ -124,17 +157,18 @@ def on_predicate(
|
|
|
124
157
|
|
|
125
158
|
def on_exception(
|
|
126
159
|
wait_gen: _WaitGenerator,
|
|
127
|
-
exception:
|
|
160
|
+
exception: _MaybeTuple[type[Exception]],
|
|
128
161
|
*,
|
|
129
|
-
max_tries:
|
|
130
|
-
max_time:
|
|
131
|
-
jitter:
|
|
162
|
+
max_tries: _MaybeCallable[int] | None = None,
|
|
163
|
+
max_time: _MaybeCallable[float] | None = None,
|
|
164
|
+
jitter: _Jitterer | None = full_jitter,
|
|
132
165
|
giveup: _Predicate[Exception] = lambda e: False,
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
166
|
+
on_try: _Handler | Iterable[_Handler] | None = None,
|
|
167
|
+
on_success: _Handler | Iterable[_Handler] | None = None,
|
|
168
|
+
on_backoff: _Handler | Iterable[_Handler] | None = None,
|
|
169
|
+
on_giveup: _Handler | Iterable[_Handler] | None = None,
|
|
136
170
|
raise_on_giveup: bool = True,
|
|
137
|
-
logger:
|
|
171
|
+
logger: _AnyLoggerOrName | None = "backoff",
|
|
138
172
|
backoff_log_level: int = logging.INFO,
|
|
139
173
|
giveup_log_level: int = logging.ERROR,
|
|
140
174
|
**wait_gen_kwargs: Any,
|
|
@@ -164,6 +198,9 @@ def on_exception(
|
|
|
164
198
|
giveup: Function accepting an exception instance and
|
|
165
199
|
returning whether or not to give up. Optional. The default
|
|
166
200
|
is to always continue.
|
|
201
|
+
on_try: Callable (or iterable of callables) with a unary
|
|
202
|
+
signature to be called before each attempt. The parameter
|
|
203
|
+
is a dict containing details about the invocation.
|
|
167
204
|
on_success: Callable (or iterable of callables) with a unary
|
|
168
205
|
signature to be called in the event of success. The
|
|
169
206
|
parameter is a dict containing details about the invocation.
|
|
@@ -185,10 +222,11 @@ def on_exception(
|
|
|
185
222
|
This is useful for runtime configuration.
|
|
186
223
|
"""
|
|
187
224
|
|
|
188
|
-
def decorate(target):
|
|
189
|
-
nonlocal logger, on_success, on_backoff, on_giveup
|
|
225
|
+
def decorate(target: _CallableT) -> _CallableT:
|
|
226
|
+
nonlocal logger, on_try, on_success, on_backoff, on_giveup
|
|
190
227
|
|
|
191
228
|
logger = _prepare_logger(logger)
|
|
229
|
+
on_try = _config_handlers(on_try)
|
|
192
230
|
on_success = _config_handlers(on_success)
|
|
193
231
|
on_backoff = _config_handlers(
|
|
194
232
|
on_backoff,
|
|
@@ -204,24 +242,201 @@ def on_exception(
|
|
|
204
242
|
)
|
|
205
243
|
|
|
206
244
|
if inspect.iscoroutinefunction(target):
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
245
|
+
return cast(
|
|
246
|
+
"_CallableT",
|
|
247
|
+
_async.retry_exception(
|
|
248
|
+
target,
|
|
249
|
+
wait_gen,
|
|
250
|
+
exception,
|
|
251
|
+
max_tries=max_tries,
|
|
252
|
+
max_time=max_time,
|
|
253
|
+
jitter=jitter,
|
|
254
|
+
giveup=giveup,
|
|
255
|
+
on_try=on_try,
|
|
256
|
+
on_success=on_success,
|
|
257
|
+
on_backoff=on_backoff,
|
|
258
|
+
on_giveup=on_giveup,
|
|
259
|
+
raise_on_giveup=raise_on_giveup,
|
|
260
|
+
wait_gen_kwargs=wait_gen_kwargs,
|
|
261
|
+
),
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
return cast(
|
|
265
|
+
"_CallableT",
|
|
266
|
+
_sync.retry_exception(
|
|
267
|
+
target,
|
|
268
|
+
wait_gen,
|
|
269
|
+
exception,
|
|
270
|
+
max_tries=max_tries,
|
|
271
|
+
max_time=max_time,
|
|
272
|
+
jitter=jitter,
|
|
273
|
+
giveup=giveup,
|
|
274
|
+
on_try=on_try,
|
|
275
|
+
on_success=on_success,
|
|
276
|
+
on_backoff=on_backoff,
|
|
277
|
+
on_giveup=on_giveup,
|
|
278
|
+
raise_on_giveup=raise_on_giveup,
|
|
279
|
+
wait_gen_kwargs=wait_gen_kwargs,
|
|
280
|
+
),
|
|
224
281
|
)
|
|
225
282
|
|
|
226
283
|
# Return a function which decorates a target with a retry loop.
|
|
227
284
|
return decorate
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
def retry_context(
|
|
288
|
+
exception: _MaybeTuple[type[Exception]] = Exception,
|
|
289
|
+
wait_gen: _WaitGenerator = expo,
|
|
290
|
+
*,
|
|
291
|
+
max_tries: _MaybeCallable[int] | None = None,
|
|
292
|
+
max_time: _MaybeCallable[float] | None = None,
|
|
293
|
+
jitter: _Jitterer | None = full_jitter,
|
|
294
|
+
giveup: _Predicate[BaseException] = lambda e: False,
|
|
295
|
+
on_try: _ContextHandler | Iterable[_ContextHandler] | None = None,
|
|
296
|
+
on_success: _ContextHandler | Iterable[_ContextHandler] | None = None,
|
|
297
|
+
on_backoff: _ContextHandler | Iterable[_ContextHandler] | None = None,
|
|
298
|
+
on_giveup: _ContextHandler | Iterable[_ContextHandler] | None = None,
|
|
299
|
+
raise_on_giveup: bool = True,
|
|
300
|
+
logger: _AnyLoggerOrName | None = "backoff",
|
|
301
|
+
backoff_log_level: int = logging.INFO,
|
|
302
|
+
giveup_log_level: int = logging.ERROR,
|
|
303
|
+
**wait_gen_kwargs: Any,
|
|
304
|
+
) -> Generator[Attempt, None, None]:
|
|
305
|
+
"""Returns a generator of retry attempts, for direct use with a `for` loop.
|
|
306
|
+
|
|
307
|
+
Unlike `on_exception`, this doesn't wrap a whole function; it lets a
|
|
308
|
+
caller retry an arbitrary block of code:
|
|
309
|
+
|
|
310
|
+
for attempt in backoff.retry_context(ValueError, backoff.expo):
|
|
311
|
+
with attempt:
|
|
312
|
+
do_something()
|
|
313
|
+
|
|
314
|
+
Each `attempt` is a context manager: exceptions matching `exception`
|
|
315
|
+
are caught, and the loop either sleeps and retries or lets the
|
|
316
|
+
exception (or a different one) propagate once retries are exhausted.
|
|
317
|
+
Succeeding (no exception raised in the `with` block) ends the loop.
|
|
318
|
+
|
|
319
|
+
Args:
|
|
320
|
+
exception: An exception type (or tuple of types) which triggers
|
|
321
|
+
backoff.
|
|
322
|
+
wait_gen: A generator yielding successive wait times in seconds.
|
|
323
|
+
max_tries: The maximum number of attempts to make before giving
|
|
324
|
+
up. Once exhausted, the exception will be allowed to escape.
|
|
325
|
+
The default value of None means there is no limit to the
|
|
326
|
+
number of tries. If a callable is passed, it will be
|
|
327
|
+
evaluated at runtime and its return value used.
|
|
328
|
+
max_time: The maximum total amount of time to try for before
|
|
329
|
+
giving up. Once expired, the exception will be allowed to
|
|
330
|
+
escape. If a callable is passed, it will be evaluated at
|
|
331
|
+
runtime and its return value used.
|
|
332
|
+
jitter: A function of the value yielded by wait_gen returning
|
|
333
|
+
the actual time to wait. Jittered by default using
|
|
334
|
+
full_jitter; disable with jitter=None.
|
|
335
|
+
giveup: Function accepting an exception instance and returning
|
|
336
|
+
whether or not to give up. Optional. The default is to
|
|
337
|
+
always continue.
|
|
338
|
+
on_success: Callable (or iterable of callables) with a unary
|
|
339
|
+
signature called on success. The parameter is a dict with
|
|
340
|
+
`tries` and `elapsed`.
|
|
341
|
+
on_backoff: Callable (or iterable of callables) called on
|
|
342
|
+
backoff. The parameter dict additionally has `wait` and
|
|
343
|
+
`exception`.
|
|
344
|
+
on_giveup: Callable (or iterable of callables) called when
|
|
345
|
+
giving up. The parameter dict additionally has `exception`.
|
|
346
|
+
raise_on_giveup: Boolean indicating whether the registered
|
|
347
|
+
exception should be raised on giveup. Defaults to `True`.
|
|
348
|
+
logger: Name or Logger object to log to. Defaults to 'backoff'.
|
|
349
|
+
backoff_log_level: log level for the backoff event. Defaults to "INFO"
|
|
350
|
+
giveup_log_level: log level for the give up event. Defaults to "ERROR"
|
|
351
|
+
**wait_gen_kwargs: Any additional keyword args specified will be
|
|
352
|
+
passed to wait_gen when it is initialized.
|
|
353
|
+
"""
|
|
354
|
+
logger = _prepare_logger(logger)
|
|
355
|
+
on_try = _config_handlers(on_try)
|
|
356
|
+
on_success = _config_handlers(on_success)
|
|
357
|
+
on_backoff = _config_handlers(
|
|
358
|
+
on_backoff,
|
|
359
|
+
default_handler=_log_backoff_context,
|
|
360
|
+
logger=logger,
|
|
361
|
+
log_level=backoff_log_level,
|
|
362
|
+
)
|
|
363
|
+
on_giveup = _config_handlers(
|
|
364
|
+
on_giveup,
|
|
365
|
+
default_handler=_log_giveup_context,
|
|
366
|
+
logger=logger,
|
|
367
|
+
log_level=giveup_log_level,
|
|
368
|
+
)
|
|
369
|
+
|
|
370
|
+
return _sync.retry_context(
|
|
371
|
+
exception,
|
|
372
|
+
wait_gen,
|
|
373
|
+
max_tries=max_tries,
|
|
374
|
+
max_time=max_time,
|
|
375
|
+
jitter=jitter,
|
|
376
|
+
giveup=giveup,
|
|
377
|
+
on_try=on_try,
|
|
378
|
+
on_success=on_success,
|
|
379
|
+
on_backoff=on_backoff,
|
|
380
|
+
on_giveup=on_giveup,
|
|
381
|
+
raise_on_giveup=raise_on_giveup,
|
|
382
|
+
wait_gen_kwargs=wait_gen_kwargs,
|
|
383
|
+
)
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
def aretry_context(
|
|
387
|
+
exception: _MaybeTuple[type[Exception]] = Exception,
|
|
388
|
+
wait_gen: _WaitGenerator = expo,
|
|
389
|
+
*,
|
|
390
|
+
max_tries: _MaybeCallable[int] | None = None,
|
|
391
|
+
max_time: _MaybeCallable[float] | None = None,
|
|
392
|
+
jitter: _Jitterer | None = full_jitter,
|
|
393
|
+
giveup: _Predicate[BaseException] = lambda e: False,
|
|
394
|
+
on_try: _ContextHandler | Iterable[_ContextHandler] | None = None,
|
|
395
|
+
on_success: _ContextHandler | Iterable[_ContextHandler] | None = None,
|
|
396
|
+
on_backoff: _ContextHandler | Iterable[_ContextHandler] | None = None,
|
|
397
|
+
on_giveup: _ContextHandler | Iterable[_ContextHandler] | None = None,
|
|
398
|
+
raise_on_giveup: bool = True,
|
|
399
|
+
logger: _AnyLoggerOrName | None = "backoff",
|
|
400
|
+
backoff_log_level: int = logging.INFO,
|
|
401
|
+
giveup_log_level: int = logging.ERROR,
|
|
402
|
+
**wait_gen_kwargs: Any,
|
|
403
|
+
) -> AsyncGenerator[Attempt, None]:
|
|
404
|
+
"""Async counterpart to `retry_context`, for use with `async for`.
|
|
405
|
+
|
|
406
|
+
async for attempt in backoff.aretry_context(ValueError, backoff.expo):
|
|
407
|
+
with attempt:
|
|
408
|
+
await do_something()
|
|
409
|
+
|
|
410
|
+
`giveup` and the handlers may be sync or async callables. See
|
|
411
|
+
`retry_context` for the full argument reference.
|
|
412
|
+
"""
|
|
413
|
+
logger = _prepare_logger(logger)
|
|
414
|
+
on_try = _config_handlers(on_try)
|
|
415
|
+
on_success = _config_handlers(on_success)
|
|
416
|
+
on_backoff = _config_handlers(
|
|
417
|
+
on_backoff,
|
|
418
|
+
default_handler=_log_backoff_context,
|
|
419
|
+
logger=logger,
|
|
420
|
+
log_level=backoff_log_level,
|
|
421
|
+
)
|
|
422
|
+
on_giveup = _config_handlers(
|
|
423
|
+
on_giveup,
|
|
424
|
+
default_handler=_log_giveup_context,
|
|
425
|
+
logger=logger,
|
|
426
|
+
log_level=giveup_log_level,
|
|
427
|
+
)
|
|
428
|
+
|
|
429
|
+
return _async.aretry_context(
|
|
430
|
+
exception,
|
|
431
|
+
wait_gen,
|
|
432
|
+
max_tries=max_tries,
|
|
433
|
+
max_time=max_time,
|
|
434
|
+
jitter=jitter,
|
|
435
|
+
giveup=giveup,
|
|
436
|
+
on_try=on_try,
|
|
437
|
+
on_success=on_success,
|
|
438
|
+
on_backoff=on_backoff,
|
|
439
|
+
on_giveup=on_giveup,
|
|
440
|
+
raise_on_giveup=raise_on_giveup,
|
|
441
|
+
wait_gen_kwargs=wait_gen_kwargs,
|
|
442
|
+
)
|