tenacity 8.2.3__tar.gz → 8.4.0__tar.gz
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.
- tenacity-8.4.0/.github/dependabot.yml +10 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/.github/workflows/ci.yaml +7 -8
- {tenacity-8.2.3 → tenacity-8.4.0}/.github/workflows/deploy.yaml +7 -6
- tenacity-8.4.0/.mergify.yml +41 -0
- {tenacity-8.2.3/tenacity.egg-info → tenacity-8.4.0}/PKG-INFO +4 -3
- {tenacity-8.2.3 → tenacity-8.4.0}/README.rst +30 -50
- {tenacity-8.2.3 → tenacity-8.4.0}/doc/source/api.rst +3 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/doc/source/index.rst +30 -50
- {tenacity-8.2.3 → tenacity-8.4.0}/pyproject.toml +5 -5
- tenacity-8.4.0/releasenotes/notes/add-async-actions-b249c527d99723bb.yaml +5 -0
- tenacity-8.4.0/releasenotes/notes/add-stop-before-delay-a775f88ac872c923.yaml +7 -0
- tenacity-8.4.0/releasenotes/notes/add-test-extra-55e869261b03e56d.yaml +3 -0
- tenacity-8.4.0/releasenotes/notes/dependabot-for-github-actions-4d2464f3c0928463.yaml +5 -0
- tenacity-8.4.0/releasenotes/notes/some-slug-for-preserve-defaults-86682846dfa18005.yaml +4 -0
- tenacity-8.4.0/releasenotes/notes/trio-support-retry-22bd544800cd1f36.yaml +6 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/setup.cfg +5 -2
- {tenacity-8.2.3 → tenacity-8.4.0}/tenacity/__init__.py +155 -47
- {tenacity-8.2.3 → tenacity-8.4.0}/tenacity/_utils.py +27 -2
- tenacity-8.4.0/tenacity/asyncio/__init__.py +201 -0
- tenacity-8.4.0/tenacity/asyncio/retry.py +125 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/tenacity/before.py +3 -1
- {tenacity-8.2.3 → tenacity-8.4.0}/tenacity/before_sleep.py +2 -1
- {tenacity-8.2.3 → tenacity-8.4.0}/tenacity/retry.py +14 -4
- {tenacity-8.2.3 → tenacity-8.4.0}/tenacity/stop.py +28 -1
- {tenacity-8.2.3 → tenacity-8.4.0}/tenacity/tornadoweb.py +5 -1
- {tenacity-8.2.3 → tenacity-8.4.0}/tenacity/wait.py +9 -3
- {tenacity-8.2.3 → tenacity-8.4.0/tenacity.egg-info}/PKG-INFO +4 -3
- {tenacity-8.2.3 → tenacity-8.4.0}/tenacity.egg-info/SOURCES.txt +11 -2
- {tenacity-8.2.3 → tenacity-8.4.0}/tenacity.egg-info/requires.txt +4 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/tests/test_after.py +29 -6
- tenacity-8.4.0/tests/test_asyncio.py +409 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/tests/test_tenacity.py +197 -49
- {tenacity-8.2.3 → tenacity-8.4.0}/tests/test_tornado.py +2 -2
- tenacity-8.4.0/tests/test_utils.py +41 -0
- tenacity-8.4.0/tox.ini +35 -0
- tenacity-8.2.3/.mergify.yml +0 -64
- tenacity-8.2.3/tenacity/_asyncio.py +0 -94
- tenacity-8.2.3/tests/test_asyncio.py +0 -184
- tenacity-8.2.3/tox.ini +0 -57
- {tenacity-8.2.3 → tenacity-8.4.0}/.editorconfig +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/.gitignore +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/.readthedocs.yml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/LICENSE +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/doc/source/changelog.rst +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/doc/source/conf.py +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/Fix-tests-for-typeguard-3.x-6eebfea546b6207e.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/Use--for-formatting-and-validate-using-black-39ec9d57d4691778.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/add-reno-d1ab5710f272650a.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/add-retry_except_exception_type-31b31da1924d55f4.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/add_omitted_modules_to_import_all-2ab282f20a2c22f7.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/add_retry_if_exception_cause_type-d16b918ace4ae0ad.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/added_a_link_to_documentation-eefaf8f074b539f8.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/after_log-50f4d73b24ce9203.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/allow-mocking-of-nap-sleep-6679c50e702446f1.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/annotate_code-197b93130df14042.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/before_sleep_log-improvements-d8149274dfb37d7c.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/clarify-reraise-option-6829667eacf4f599.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/do_not_package_tests-fe5ac61940b0a5ed.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/drop-deprecated-python-versions-69a05cb2e0f1034c.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/drop_deprecated-7ea90b212509b082.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/export-convenience-symbols-981d9611c8b754f3.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/fix-async-loop-with-result-f68e913ccb425aca.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/fix-wait-typing-b26eecdb6cc0a1de.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/fix_async-52b6594c8e75c4bc.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/make-logger-more-compatible-5da1ddf1bab77047.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/no-async-iter-6132a42e52348a75.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/pr320-py3-only-wheel-tag.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/py36_plus-c425fb3aa17c6682.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/remove-py36-876c0416cf279d15.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/retrycallstate-repr-94947f7b00ee15e1.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/sphinx_define_error-642c9cd5c165d39a.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/support-timedelta-wait-unit-type-5ba1e9fc0fe45523.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/timedelta-for-stop-ef6bf71b88ce9988.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/releasenotes/notes/wait_exponential_jitter-6ffc81dddcbaa6d3.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/reno.yaml +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/setup.py +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/tenacity/after.py +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/tenacity/nap.py +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/tenacity/py.typed +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/tenacity.egg-info/dependency_links.txt +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/tenacity.egg-info/top_level.txt +0 -0
- {tenacity-8.2.3 → tenacity-8.4.0}/tests/__init__.py +0 -0
|
@@ -18,8 +18,6 @@ jobs:
|
|
|
18
18
|
strategy:
|
|
19
19
|
matrix:
|
|
20
20
|
include:
|
|
21
|
-
- python: "3.7"
|
|
22
|
-
tox: py37
|
|
23
21
|
- python: "3.8"
|
|
24
22
|
tox: py38
|
|
25
23
|
- python: "3.9"
|
|
@@ -28,22 +26,23 @@ jobs:
|
|
|
28
26
|
tox: py310
|
|
29
27
|
- python: "3.11"
|
|
30
28
|
tox: py311
|
|
31
|
-
- python: "3.
|
|
29
|
+
- python: "3.12"
|
|
30
|
+
tox: py312,py312-trio
|
|
31
|
+
- python: "3.12"
|
|
32
32
|
tox: pep8
|
|
33
|
-
- python: "3.11"
|
|
34
|
-
tox: black-ci
|
|
35
33
|
- python: "3.11"
|
|
36
34
|
tox: mypy
|
|
37
35
|
steps:
|
|
38
36
|
- name: Checkout 🛎️
|
|
39
|
-
uses: actions/checkout@
|
|
37
|
+
uses: actions/checkout@v4.1.6
|
|
40
38
|
with:
|
|
41
39
|
fetch-depth: 0
|
|
42
40
|
|
|
43
41
|
- name: Setup Python 🔧
|
|
44
|
-
uses: actions/setup-python@
|
|
42
|
+
uses: actions/setup-python@v5.1.0
|
|
45
43
|
with:
|
|
46
|
-
python-version: ${{
|
|
44
|
+
python-version: ${{ matrix.python }}
|
|
45
|
+
allow-prereleases: true
|
|
47
46
|
|
|
48
47
|
- name: Build 🔧 & Test 🔍
|
|
49
48
|
run: |
|
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
name: Release deploy
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
release:
|
|
5
|
+
types:
|
|
6
|
+
- published
|
|
6
7
|
|
|
7
8
|
jobs:
|
|
8
|
-
|
|
9
|
+
publish:
|
|
9
10
|
timeout-minutes: 20
|
|
10
|
-
runs-on: ubuntu-
|
|
11
|
+
runs-on: ubuntu-latest
|
|
11
12
|
steps:
|
|
12
13
|
- name: Checkout 🛎️
|
|
13
|
-
uses: actions/checkout@
|
|
14
|
+
uses: actions/checkout@v4.1.6
|
|
14
15
|
with:
|
|
15
16
|
fetch-depth: 0
|
|
16
17
|
|
|
17
18
|
- name: Setup Python 🔧
|
|
18
|
-
uses: actions/setup-python@
|
|
19
|
+
uses: actions/setup-python@v5.1.0
|
|
19
20
|
with:
|
|
20
21
|
python-version: 3.11
|
|
21
22
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
queue_rules:
|
|
2
|
+
- name: default
|
|
3
|
+
merge_method: squash
|
|
4
|
+
queue_conditions:
|
|
5
|
+
- or:
|
|
6
|
+
- author = jd
|
|
7
|
+
- "#approved-reviews-by >= 1"
|
|
8
|
+
- author = dependabot[bot]
|
|
9
|
+
- or:
|
|
10
|
+
- files ~= ^releasenotes/notes/
|
|
11
|
+
- label = no-changelog
|
|
12
|
+
- author = dependabot[bot]
|
|
13
|
+
- "check-success=test (3.8, py38)"
|
|
14
|
+
- "check-success=test (3.9, py39)"
|
|
15
|
+
- "check-success=test (3.10, py310)"
|
|
16
|
+
- "check-success=test (3.11, py311)"
|
|
17
|
+
- "check-success=test (3.12, py312,py312-trio)"
|
|
18
|
+
- "check-success=test (3.12, pep8)"
|
|
19
|
+
|
|
20
|
+
pull_request_rules:
|
|
21
|
+
- name: warn on no changelog
|
|
22
|
+
conditions:
|
|
23
|
+
- -files~=^releasenotes/notes/
|
|
24
|
+
- label!=no-changelog
|
|
25
|
+
- -closed
|
|
26
|
+
actions:
|
|
27
|
+
comment:
|
|
28
|
+
message: >
|
|
29
|
+
⚠️ No release notes detected. Please make sure to use
|
|
30
|
+
[reno](https://docs.openstack.org/reno/latest/user/usage.html) to add
|
|
31
|
+
a changelog entry.
|
|
32
|
+
|
|
33
|
+
- name: automatic queue
|
|
34
|
+
conditions: []
|
|
35
|
+
actions:
|
|
36
|
+
queue:
|
|
37
|
+
|
|
38
|
+
- name: dismiss reviews
|
|
39
|
+
conditions: []
|
|
40
|
+
actions:
|
|
41
|
+
dismiss_reviews: {}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: tenacity
|
|
3
|
-
Version: 8.
|
|
3
|
+
Version: 8.4.0
|
|
4
4
|
Summary: Retry code until it succeeds
|
|
5
5
|
Home-page: https://github.com/jd/tenacity
|
|
6
6
|
Author: Julien Danjou
|
|
@@ -11,14 +11,15 @@ Classifier: License :: OSI Approved :: Apache Software License
|
|
|
11
11
|
Classifier: Programming Language :: Python
|
|
12
12
|
Classifier: Programming Language :: Python :: 3
|
|
13
13
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.8
|
|
16
15
|
Classifier: Programming Language :: Python :: 3.9
|
|
17
16
|
Classifier: Programming Language :: Python :: 3.10
|
|
18
17
|
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
19
|
Classifier: Topic :: Utilities
|
|
20
|
-
Requires-Python: >=3.
|
|
20
|
+
Requires-Python: >=3.8
|
|
21
21
|
Provides-Extra: doc
|
|
22
|
+
Provides-Extra: test
|
|
22
23
|
License-File: LICENSE
|
|
23
24
|
|
|
24
25
|
Tenacity is a general-purpose retrying library to simplify the task of adding retry behavior to just about anything.
|
|
@@ -79,7 +79,7 @@ Examples
|
|
|
79
79
|
Basic Retry
|
|
80
80
|
~~~~~~~~~~~
|
|
81
81
|
|
|
82
|
-
.. testsetup::
|
|
82
|
+
.. testsetup::
|
|
83
83
|
|
|
84
84
|
import logging
|
|
85
85
|
#
|
|
@@ -124,6 +124,16 @@ retrying stuff.
|
|
|
124
124
|
print("Stopping after 10 seconds")
|
|
125
125
|
raise Exception
|
|
126
126
|
|
|
127
|
+
If you're on a tight deadline, and exceeding your delay time isn't ok,
|
|
128
|
+
then you can give up on retries one attempt before you would exceed the delay.
|
|
129
|
+
|
|
130
|
+
.. testcode::
|
|
131
|
+
|
|
132
|
+
@retry(stop=stop_before_delay(10))
|
|
133
|
+
def stop_before_10_s():
|
|
134
|
+
print("Stopping 1 attempt before 10 seconds")
|
|
135
|
+
raise Exception
|
|
136
|
+
|
|
127
137
|
You can combine several stop conditions by using the `|` operator:
|
|
128
138
|
|
|
129
139
|
.. testcode::
|
|
@@ -402,43 +412,7 @@ without raising an exception (or you can re-raise or do anything really)
|
|
|
402
412
|
RetryCallState
|
|
403
413
|
~~~~~~~~~~~~~~
|
|
404
414
|
|
|
405
|
-
``retry_state`` argument is an object of
|
|
406
|
-
|
|
407
|
-
.. autoclass:: tenacity.RetryCallState
|
|
408
|
-
|
|
409
|
-
Constant attributes:
|
|
410
|
-
|
|
411
|
-
.. autoattribute:: start_time(float)
|
|
412
|
-
:annotation:
|
|
413
|
-
|
|
414
|
-
.. autoattribute:: retry_object(BaseRetrying)
|
|
415
|
-
:annotation:
|
|
416
|
-
|
|
417
|
-
.. autoattribute:: fn(callable)
|
|
418
|
-
:annotation:
|
|
419
|
-
|
|
420
|
-
.. autoattribute:: args(tuple)
|
|
421
|
-
:annotation:
|
|
422
|
-
|
|
423
|
-
.. autoattribute:: kwargs(dict)
|
|
424
|
-
:annotation:
|
|
425
|
-
|
|
426
|
-
Variable attributes:
|
|
427
|
-
|
|
428
|
-
.. autoattribute:: attempt_number(int)
|
|
429
|
-
:annotation:
|
|
430
|
-
|
|
431
|
-
.. autoattribute:: outcome(tenacity.Future or None)
|
|
432
|
-
:annotation:
|
|
433
|
-
|
|
434
|
-
.. autoattribute:: outcome_timestamp(float or None)
|
|
435
|
-
:annotation:
|
|
436
|
-
|
|
437
|
-
.. autoattribute:: idle_for(float)
|
|
438
|
-
:annotation:
|
|
439
|
-
|
|
440
|
-
.. autoattribute:: next_action(tenacity.RetryAction or None)
|
|
441
|
-
:annotation:
|
|
415
|
+
``retry_state`` argument is an object of :class:`~tenacity.RetryCallState` class.
|
|
442
416
|
|
|
443
417
|
Other Custom Callbacks
|
|
444
418
|
~~~~~~~~~~~~~~~~~~~~~~
|
|
@@ -447,33 +421,33 @@ It's also possible to define custom callbacks for other keyword arguments.
|
|
|
447
421
|
|
|
448
422
|
.. function:: my_stop(retry_state)
|
|
449
423
|
|
|
450
|
-
:param
|
|
424
|
+
:param RetryCallState retry_state: info about current retry invocation
|
|
451
425
|
:return: whether or not retrying should stop
|
|
452
426
|
:rtype: bool
|
|
453
427
|
|
|
454
428
|
.. function:: my_wait(retry_state)
|
|
455
429
|
|
|
456
|
-
:param
|
|
430
|
+
:param RetryCallState retry_state: info about current retry invocation
|
|
457
431
|
:return: number of seconds to wait before next retry
|
|
458
432
|
:rtype: float
|
|
459
433
|
|
|
460
434
|
.. function:: my_retry(retry_state)
|
|
461
435
|
|
|
462
|
-
:param
|
|
436
|
+
:param RetryCallState retry_state: info about current retry invocation
|
|
463
437
|
:return: whether or not retrying should continue
|
|
464
438
|
:rtype: bool
|
|
465
439
|
|
|
466
440
|
.. function:: my_before(retry_state)
|
|
467
441
|
|
|
468
|
-
:param
|
|
442
|
+
:param RetryCallState retry_state: info about current retry invocation
|
|
469
443
|
|
|
470
444
|
.. function:: my_after(retry_state)
|
|
471
445
|
|
|
472
|
-
:param
|
|
446
|
+
:param RetryCallState retry_state: info about current retry invocation
|
|
473
447
|
|
|
474
448
|
.. function:: my_before_sleep(retry_state)
|
|
475
449
|
|
|
476
|
-
:param
|
|
450
|
+
:param RetryCallState retry_state: info about current retry invocation
|
|
477
451
|
|
|
478
452
|
Here's an example with a custom ``before_sleep`` function:
|
|
479
453
|
|
|
@@ -594,28 +568,34 @@ in retry strategies like ``retry_if_result``. This can be done accessing the
|
|
|
594
568
|
Async and retry
|
|
595
569
|
~~~~~~~~~~~~~~~
|
|
596
570
|
|
|
597
|
-
Finally, ``retry`` works also on asyncio and Tornado (>= 4.5) coroutines.
|
|
571
|
+
Finally, ``retry`` works also on asyncio, Trio, and Tornado (>= 4.5) coroutines.
|
|
598
572
|
Sleeps are done asynchronously too.
|
|
599
573
|
|
|
600
574
|
.. code-block:: python
|
|
601
575
|
|
|
602
576
|
@retry
|
|
603
|
-
async def
|
|
577
|
+
async def my_asyncio_function(loop):
|
|
604
578
|
await loop.getaddrinfo('8.8.8.8', 53)
|
|
605
579
|
|
|
580
|
+
.. code-block:: python
|
|
581
|
+
|
|
582
|
+
@retry
|
|
583
|
+
async def my_async_trio_function():
|
|
584
|
+
await trio.socket.getaddrinfo('8.8.8.8', 53)
|
|
585
|
+
|
|
606
586
|
.. code-block:: python
|
|
607
587
|
|
|
608
588
|
@retry
|
|
609
589
|
@tornado.gen.coroutine
|
|
610
|
-
def
|
|
590
|
+
def my_async_tornado_function(http_client, url):
|
|
611
591
|
yield http_client.fetch(url)
|
|
612
592
|
|
|
613
|
-
You can even use alternative event loops such as `curio`
|
|
593
|
+
You can even use alternative event loops such as `curio` by passing the correct sleep function:
|
|
614
594
|
|
|
615
595
|
.. code-block:: python
|
|
616
596
|
|
|
617
|
-
@retry(sleep=
|
|
618
|
-
async def
|
|
597
|
+
@retry(sleep=curio.sleep)
|
|
598
|
+
async def my_async_curio_function():
|
|
619
599
|
await asks.get('https://example.org')
|
|
620
600
|
|
|
621
601
|
Contribute
|
|
@@ -79,7 +79,7 @@ Examples
|
|
|
79
79
|
Basic Retry
|
|
80
80
|
~~~~~~~~~~~
|
|
81
81
|
|
|
82
|
-
.. testsetup::
|
|
82
|
+
.. testsetup::
|
|
83
83
|
|
|
84
84
|
import logging
|
|
85
85
|
#
|
|
@@ -124,6 +124,16 @@ retrying stuff.
|
|
|
124
124
|
print("Stopping after 10 seconds")
|
|
125
125
|
raise Exception
|
|
126
126
|
|
|
127
|
+
If you're on a tight deadline, and exceeding your delay time isn't ok,
|
|
128
|
+
then you can give up on retries one attempt before you would exceed the delay.
|
|
129
|
+
|
|
130
|
+
.. testcode::
|
|
131
|
+
|
|
132
|
+
@retry(stop=stop_before_delay(10))
|
|
133
|
+
def stop_before_10_s():
|
|
134
|
+
print("Stopping 1 attempt before 10 seconds")
|
|
135
|
+
raise Exception
|
|
136
|
+
|
|
127
137
|
You can combine several stop conditions by using the `|` operator:
|
|
128
138
|
|
|
129
139
|
.. testcode::
|
|
@@ -402,43 +412,7 @@ without raising an exception (or you can re-raise or do anything really)
|
|
|
402
412
|
RetryCallState
|
|
403
413
|
~~~~~~~~~~~~~~
|
|
404
414
|
|
|
405
|
-
``retry_state`` argument is an object of
|
|
406
|
-
|
|
407
|
-
.. autoclass:: tenacity.RetryCallState
|
|
408
|
-
|
|
409
|
-
Constant attributes:
|
|
410
|
-
|
|
411
|
-
.. autoattribute:: start_time(float)
|
|
412
|
-
:annotation:
|
|
413
|
-
|
|
414
|
-
.. autoattribute:: retry_object(BaseRetrying)
|
|
415
|
-
:annotation:
|
|
416
|
-
|
|
417
|
-
.. autoattribute:: fn(callable)
|
|
418
|
-
:annotation:
|
|
419
|
-
|
|
420
|
-
.. autoattribute:: args(tuple)
|
|
421
|
-
:annotation:
|
|
422
|
-
|
|
423
|
-
.. autoattribute:: kwargs(dict)
|
|
424
|
-
:annotation:
|
|
425
|
-
|
|
426
|
-
Variable attributes:
|
|
427
|
-
|
|
428
|
-
.. autoattribute:: attempt_number(int)
|
|
429
|
-
:annotation:
|
|
430
|
-
|
|
431
|
-
.. autoattribute:: outcome(tenacity.Future or None)
|
|
432
|
-
:annotation:
|
|
433
|
-
|
|
434
|
-
.. autoattribute:: outcome_timestamp(float or None)
|
|
435
|
-
:annotation:
|
|
436
|
-
|
|
437
|
-
.. autoattribute:: idle_for(float)
|
|
438
|
-
:annotation:
|
|
439
|
-
|
|
440
|
-
.. autoattribute:: next_action(tenacity.RetryAction or None)
|
|
441
|
-
:annotation:
|
|
415
|
+
``retry_state`` argument is an object of :class:`~tenacity.RetryCallState` class.
|
|
442
416
|
|
|
443
417
|
Other Custom Callbacks
|
|
444
418
|
~~~~~~~~~~~~~~~~~~~~~~
|
|
@@ -447,33 +421,33 @@ It's also possible to define custom callbacks for other keyword arguments.
|
|
|
447
421
|
|
|
448
422
|
.. function:: my_stop(retry_state)
|
|
449
423
|
|
|
450
|
-
:param
|
|
424
|
+
:param RetryCallState retry_state: info about current retry invocation
|
|
451
425
|
:return: whether or not retrying should stop
|
|
452
426
|
:rtype: bool
|
|
453
427
|
|
|
454
428
|
.. function:: my_wait(retry_state)
|
|
455
429
|
|
|
456
|
-
:param
|
|
430
|
+
:param RetryCallState retry_state: info about current retry invocation
|
|
457
431
|
:return: number of seconds to wait before next retry
|
|
458
432
|
:rtype: float
|
|
459
433
|
|
|
460
434
|
.. function:: my_retry(retry_state)
|
|
461
435
|
|
|
462
|
-
:param
|
|
436
|
+
:param RetryCallState retry_state: info about current retry invocation
|
|
463
437
|
:return: whether or not retrying should continue
|
|
464
438
|
:rtype: bool
|
|
465
439
|
|
|
466
440
|
.. function:: my_before(retry_state)
|
|
467
441
|
|
|
468
|
-
:param
|
|
442
|
+
:param RetryCallState retry_state: info about current retry invocation
|
|
469
443
|
|
|
470
444
|
.. function:: my_after(retry_state)
|
|
471
445
|
|
|
472
|
-
:param
|
|
446
|
+
:param RetryCallState retry_state: info about current retry invocation
|
|
473
447
|
|
|
474
448
|
.. function:: my_before_sleep(retry_state)
|
|
475
449
|
|
|
476
|
-
:param
|
|
450
|
+
:param RetryCallState retry_state: info about current retry invocation
|
|
477
451
|
|
|
478
452
|
Here's an example with a custom ``before_sleep`` function:
|
|
479
453
|
|
|
@@ -594,28 +568,34 @@ in retry strategies like ``retry_if_result``. This can be done accessing the
|
|
|
594
568
|
Async and retry
|
|
595
569
|
~~~~~~~~~~~~~~~
|
|
596
570
|
|
|
597
|
-
Finally, ``retry`` works also on asyncio and Tornado (>= 4.5) coroutines.
|
|
571
|
+
Finally, ``retry`` works also on asyncio, Trio, and Tornado (>= 4.5) coroutines.
|
|
598
572
|
Sleeps are done asynchronously too.
|
|
599
573
|
|
|
600
574
|
.. code-block:: python
|
|
601
575
|
|
|
602
576
|
@retry
|
|
603
|
-
async def
|
|
577
|
+
async def my_asyncio_function(loop):
|
|
604
578
|
await loop.getaddrinfo('8.8.8.8', 53)
|
|
605
579
|
|
|
580
|
+
.. code-block:: python
|
|
581
|
+
|
|
582
|
+
@retry
|
|
583
|
+
async def my_async_trio_function():
|
|
584
|
+
await trio.socket.getaddrinfo('8.8.8.8', 53)
|
|
585
|
+
|
|
606
586
|
.. code-block:: python
|
|
607
587
|
|
|
608
588
|
@retry
|
|
609
589
|
@tornado.gen.coroutine
|
|
610
|
-
def
|
|
590
|
+
def my_async_tornado_function(http_client, url):
|
|
611
591
|
yield http_client.fetch(url)
|
|
612
592
|
|
|
613
|
-
You can even use alternative event loops such as `curio`
|
|
593
|
+
You can even use alternative event loops such as `curio` by passing the correct sleep function:
|
|
614
594
|
|
|
615
595
|
.. code-block:: python
|
|
616
596
|
|
|
617
|
-
@retry(sleep=
|
|
618
|
-
async def
|
|
597
|
+
@retry(sleep=curio.sleep)
|
|
598
|
+
async def my_async_curio_function():
|
|
619
599
|
await asks.get('https://example.org')
|
|
620
600
|
|
|
621
601
|
Contribute
|
|
@@ -8,14 +8,14 @@ requires = [
|
|
|
8
8
|
]
|
|
9
9
|
build-backend="setuptools.build_meta"
|
|
10
10
|
|
|
11
|
-
[tool.
|
|
12
|
-
line-length =
|
|
13
|
-
|
|
14
|
-
target-version =
|
|
11
|
+
[tool.ruff]
|
|
12
|
+
line-length = 88
|
|
13
|
+
indent-width = 4
|
|
14
|
+
target-version = "py38"
|
|
15
15
|
|
|
16
16
|
[tool.mypy]
|
|
17
17
|
strict = true
|
|
18
|
-
files = ["tenacity"]
|
|
18
|
+
files = ["tenacity", "tests"]
|
|
19
19
|
show_error_codes = true
|
|
20
20
|
|
|
21
21
|
[[tool.mypy.overrides]]
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
features:
|
|
3
|
+
- |
|
|
4
|
+
Added a new stop function: stop_before_delay, which will stop execution
|
|
5
|
+
if the next sleep time would cause overall delay to exceed the specified delay.
|
|
6
|
+
Useful for use cases where you have some upper bound on retry times that you must
|
|
7
|
+
not exceed, so returning before that timeout is preferable than returning after that timeout.
|
|
@@ -13,16 +13,16 @@ classifier =
|
|
|
13
13
|
Programming Language :: Python
|
|
14
14
|
Programming Language :: Python :: 3
|
|
15
15
|
Programming Language :: Python :: 3 :: Only
|
|
16
|
-
Programming Language :: Python :: 3.7
|
|
17
16
|
Programming Language :: Python :: 3.8
|
|
18
17
|
Programming Language :: Python :: 3.9
|
|
19
18
|
Programming Language :: Python :: 3.10
|
|
20
19
|
Programming Language :: Python :: 3.11
|
|
20
|
+
Programming Language :: Python :: 3.12
|
|
21
21
|
Topic :: Utilities
|
|
22
22
|
|
|
23
23
|
[options]
|
|
24
24
|
install_requires =
|
|
25
|
-
python_requires = >=3.
|
|
25
|
+
python_requires = >=3.8
|
|
26
26
|
packages = tenacity
|
|
27
27
|
|
|
28
28
|
[options.packages.find]
|
|
@@ -35,7 +35,10 @@ tenacity = py.typed
|
|
|
35
35
|
doc =
|
|
36
36
|
reno
|
|
37
37
|
sphinx
|
|
38
|
+
test =
|
|
39
|
+
pytest
|
|
38
40
|
tornado>=4.5
|
|
41
|
+
typeguard
|
|
39
42
|
|
|
40
43
|
[tool:pytest]
|
|
41
44
|
filterwarnings =
|