tenacity 9.1.2__tar.gz → 9.1.3__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-9.1.2 → tenacity-9.1.3}/.github/workflows/ci.yaml +8 -8
- {tenacity-9.1.2 → tenacity-9.1.3}/.github/workflows/release.yml +3 -3
- tenacity-9.1.3/.mergify.yml +21 -0
- {tenacity-9.1.2/tenacity.egg-info → tenacity-9.1.3}/PKG-INFO +3 -3
- {tenacity-9.1.2 → tenacity-9.1.3}/README.rst +0 -14
- {tenacity-9.1.2 → tenacity-9.1.3}/doc/source/index.rst +0 -14
- {tenacity-9.1.2 → tenacity-9.1.3}/pyproject.toml +1 -1
- tenacity-9.1.3/releasenotes/notes/async-sleep-retrying-32de5866f5d041.yaml +7 -0
- tenacity-9.1.3/releasenotes/notes/drop-python-3.9-ecfa2d7db9773e96.yaml +5 -0
- tenacity-9.1.3/releasenotes/notes/logging-protocol-a4cf0f786f21e4ee.yaml +5 -0
- tenacity-9.1.3/releasenotes/notes/support-py3.14-14928188cab53b99.yaml +3 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/setup.cfg +2 -2
- {tenacity-9.1.2 → tenacity-9.1.3}/tenacity/__init__.py +35 -23
- {tenacity-9.1.2 → tenacity-9.1.3}/tenacity/_utils.py +12 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/tenacity/after.py +2 -4
- {tenacity-9.1.2 → tenacity-9.1.3}/tenacity/asyncio/__init__.py +5 -1
- {tenacity-9.1.2 → tenacity-9.1.3}/tenacity/before.py +1 -3
- {tenacity-9.1.2 → tenacity-9.1.3}/tenacity/before_sleep.py +3 -4
- {tenacity-9.1.2 → tenacity-9.1.3}/tenacity/tornadoweb.py +1 -1
- {tenacity-9.1.2 → tenacity-9.1.3}/tenacity/wait.py +42 -3
- {tenacity-9.1.2 → tenacity-9.1.3/tenacity.egg-info}/PKG-INFO +3 -3
- {tenacity-9.1.2 → tenacity-9.1.3}/tenacity.egg-info/SOURCES.txt +4 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/tests/test_after.py +1 -1
- {tenacity-9.1.2 → tenacity-9.1.3}/tests/test_asyncio.py +27 -3
- {tenacity-9.1.2 → tenacity-9.1.3}/tests/test_issue_478.py +1 -2
- {tenacity-9.1.2 → tenacity-9.1.3}/tests/test_tenacity.py +19 -10
- {tenacity-9.1.2 → tenacity-9.1.3}/tox.ini +4 -4
- tenacity-9.1.2/.mergify.yml +0 -41
- {tenacity-9.1.2 → tenacity-9.1.3}/.editorconfig +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/.github/dependabot.yml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/.gitignore +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/.readthedocs.yml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/LICENSE +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/doc/source/api.rst +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/doc/source/changelog.rst +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/doc/source/conf.py +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/Fix-tests-for-typeguard-3.x-6eebfea546b6207e.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/Use--for-formatting-and-validate-using-black-39ec9d57d4691778.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/add-async-actions-b249c527d99723bb.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/add-re-pattern-to-match-types-6a4c1d9e64e2a5e1.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/add-reno-d1ab5710f272650a.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/add-retry_except_exception_type-31b31da1924d55f4.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/add-stop-before-delay-a775f88ac872c923.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/add-test-extra-55e869261b03e56d.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/add_omitted_modules_to_import_all-2ab282f20a2c22f7.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/add_retry_if_exception_cause_type-d16b918ace4ae0ad.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/added_a_link_to_documentation-eefaf8f074b539f8.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/after_log-50f4d73b24ce9203.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/allow-mocking-of-nap-sleep-6679c50e702446f1.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/annotate_code-197b93130df14042.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/before_sleep_log-improvements-d8149274dfb37d7c.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/clarify-reraise-option-6829667eacf4f599.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/dependabot-for-github-actions-4d2464f3c0928463.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/do_not_package_tests-fe5ac61940b0a5ed.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/drop-deprecated-python-versions-69a05cb2e0f1034c.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/drop_deprecated-7ea90b212509b082.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/export-convenience-symbols-981d9611c8b754f3.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/fix-async-loop-with-result-f68e913ccb425aca.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/fix-local-context-overwrite-94190ba06a481631.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/fix-retry-wrapper-attributes-f7a3a45b8e90f257.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/fix-setuptools-config-3af71aa3592b6948.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/fix-wait-typing-b26eecdb6cc0a1de.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/fix_async-52b6594c8e75c4bc.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/make-logger-more-compatible-5da1ddf1bab77047.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/no-async-iter-6132a42e52348a75.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/pr320-py3-only-wheel-tag.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/py36_plus-c425fb3aa17c6682.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/remove-py36-876c0416cf279d15.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/retrycallstate-repr-94947f7b00ee15e1.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/some-slug-for-preserve-defaults-86682846dfa18005.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/sphinx_define_error-642c9cd5c165d39a.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/support-timedelta-wait-unit-type-5ba1e9fc0fe45523.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/timedelta-for-stop-ef6bf71b88ce9988.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/trio-support-retry-22bd544800cd1f36.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/wait-random-exponential-min-2a4b7eed9f002436.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/wait_exponential_jitter-6ffc81dddcbaa6d3.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/reno.yaml +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/setup.py +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/tenacity/asyncio/retry.py +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/tenacity/nap.py +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/tenacity/py.typed +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/tenacity/retry.py +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/tenacity/stop.py +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/tenacity.egg-info/dependency_links.txt +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/tenacity.egg-info/requires.txt +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/tenacity.egg-info/top_level.txt +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/tests/__init__.py +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/tests/test_tornado.py +0 -0
- {tenacity-9.1.2 → tenacity-9.1.3}/tests/test_utils.py +0 -0
|
@@ -18,28 +18,28 @@ jobs:
|
|
|
18
18
|
strategy:
|
|
19
19
|
matrix:
|
|
20
20
|
include:
|
|
21
|
-
- python: "3.9"
|
|
22
|
-
tox: py39
|
|
23
21
|
- python: "3.10"
|
|
24
22
|
tox: py310
|
|
25
23
|
- python: "3.11"
|
|
26
24
|
tox: py311
|
|
27
25
|
- python: "3.12"
|
|
28
26
|
tox: py312
|
|
29
|
-
- python: "3.12"
|
|
30
|
-
tox: pep8
|
|
31
27
|
- python: "3.13"
|
|
32
|
-
tox: py313
|
|
33
|
-
- python: "3.
|
|
28
|
+
tox: py313
|
|
29
|
+
- python: "3.14"
|
|
30
|
+
tox: py314,py314-trio
|
|
31
|
+
- python: "3.14"
|
|
32
|
+
tox: pep8
|
|
33
|
+
- python: "3.14"
|
|
34
34
|
tox: mypy
|
|
35
35
|
steps:
|
|
36
36
|
- name: Checkout 🛎️
|
|
37
|
-
uses: actions/checkout@
|
|
37
|
+
uses: actions/checkout@v6.0.2
|
|
38
38
|
with:
|
|
39
39
|
fetch-depth: 0
|
|
40
40
|
|
|
41
41
|
- name: Setup Python 🔧
|
|
42
|
-
uses: actions/setup-python@
|
|
42
|
+
uses: actions/setup-python@v6.2.0
|
|
43
43
|
with:
|
|
44
44
|
python-version: ${{ matrix.python }}
|
|
45
45
|
allow-prereleases: true
|
|
@@ -13,14 +13,14 @@ jobs:
|
|
|
13
13
|
id-token: write
|
|
14
14
|
contents: write
|
|
15
15
|
steps:
|
|
16
|
-
- uses: actions/checkout@
|
|
16
|
+
- uses: actions/checkout@v6.0.2
|
|
17
17
|
with:
|
|
18
18
|
fetch-depth: 0
|
|
19
19
|
fetch-tags: true
|
|
20
20
|
|
|
21
|
-
- uses: actions/setup-python@
|
|
21
|
+
- uses: actions/setup-python@v6.2.0
|
|
22
22
|
with:
|
|
23
|
-
python-version: 3.
|
|
23
|
+
python-version: 3.14
|
|
24
24
|
|
|
25
25
|
- name: Install build
|
|
26
26
|
run: |
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
queue_rules:
|
|
2
|
+
- name: default
|
|
3
|
+
merge_method: squash
|
|
4
|
+
autoqueue: true
|
|
5
|
+
queue_conditions:
|
|
6
|
+
- or:
|
|
7
|
+
- author = jd
|
|
8
|
+
- "#approved-reviews-by >= 1"
|
|
9
|
+
- author = dependabot[bot]
|
|
10
|
+
- "check-success=test (3.10, py310)"
|
|
11
|
+
- "check-success=test (3.11, py311)"
|
|
12
|
+
- "check-success=test (3.12, py312)"
|
|
13
|
+
- "check-success=test (3.13, py313)"
|
|
14
|
+
- "check-success=test (3.14, py314,py314-trio)"
|
|
15
|
+
- "check-success=test (3.14, pep8)"
|
|
16
|
+
|
|
17
|
+
pull_request_rules:
|
|
18
|
+
- name: dismiss reviews
|
|
19
|
+
conditions: []
|
|
20
|
+
actions:
|
|
21
|
+
dismiss_reviews: {}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tenacity
|
|
3
|
-
Version: 9.1.
|
|
3
|
+
Version: 9.1.3
|
|
4
4
|
Summary: Retry code until it succeeds
|
|
5
5
|
Home-page: https://github.com/jd/tenacity
|
|
6
6
|
Author: Julien Danjou
|
|
@@ -11,13 +11,13 @@ 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.9
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.10
|
|
16
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
18
17
|
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
19
|
Classifier: Topic :: Utilities
|
|
20
|
-
Requires-Python: >=3.
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
21
|
License-File: LICENSE
|
|
22
22
|
Provides-Extra: doc
|
|
23
23
|
Requires-Dist: reno; extra == "doc"
|
|
@@ -637,17 +637,3 @@ Contribute
|
|
|
637
637
|
#. Make the docs better (or more detailed, or more easier to read, or ...)
|
|
638
638
|
|
|
639
639
|
.. _`the repository`: https://github.com/jd/tenacity
|
|
640
|
-
|
|
641
|
-
Changelogs
|
|
642
|
-
~~~~~~~~~~
|
|
643
|
-
|
|
644
|
-
`reno`_ is used for managing changelogs. Take a look at their usage docs.
|
|
645
|
-
|
|
646
|
-
The doc generation will automatically compile the changelogs. You just need to add them.
|
|
647
|
-
|
|
648
|
-
.. code-block:: sh
|
|
649
|
-
|
|
650
|
-
# Opens a template file in an editor
|
|
651
|
-
tox -e reno -- new some-slug-for-my-change --edit
|
|
652
|
-
|
|
653
|
-
.. _`reno`: https://docs.openstack.org/reno/latest/user/usage.html
|
|
@@ -637,17 +637,3 @@ Contribute
|
|
|
637
637
|
#. Make the docs better (or more detailed, or more easier to read, or ...)
|
|
638
638
|
|
|
639
639
|
.. _`the repository`: https://github.com/jd/tenacity
|
|
640
|
-
|
|
641
|
-
Changelogs
|
|
642
|
-
~~~~~~~~~~
|
|
643
|
-
|
|
644
|
-
`reno`_ is used for managing changelogs. Take a look at their usage docs.
|
|
645
|
-
|
|
646
|
-
The doc generation will automatically compile the changelogs. You just need to add them.
|
|
647
|
-
|
|
648
|
-
.. code-block:: sh
|
|
649
|
-
|
|
650
|
-
# Opens a template file in an editor
|
|
651
|
-
tox -e reno -- new some-slug-for-my-change --edit
|
|
652
|
-
|
|
653
|
-
.. _`reno`: https://docs.openstack.org/reno/latest/user/usage.html
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
fixes:
|
|
3
|
+
- |
|
|
4
|
+
Passing an async ``sleep`` callable (e.g. ``trio.sleep``) to ``@retry``
|
|
5
|
+
now correctly uses ``AsyncRetrying``, even when the decorated function is
|
|
6
|
+
synchronous. Previously, the async sleep would silently not be awaited,
|
|
7
|
+
resulting in no delay between retries.
|
|
@@ -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.9
|
|
17
16
|
Programming Language :: Python :: 3.10
|
|
18
17
|
Programming Language :: Python :: 3.11
|
|
19
18
|
Programming Language :: Python :: 3.12
|
|
20
19
|
Programming Language :: Python :: 3.13
|
|
20
|
+
Programming Language :: Python :: 3.14
|
|
21
21
|
Topic :: Utilities
|
|
22
22
|
|
|
23
23
|
[options]
|
|
24
24
|
install_requires =
|
|
25
|
-
python_requires = >=3.
|
|
25
|
+
python_requires = >=3.10
|
|
26
26
|
packages = find:
|
|
27
27
|
|
|
28
28
|
[options.packages.find]
|
|
@@ -59,6 +59,7 @@ from .stop import stop_when_event_set # noqa
|
|
|
59
59
|
# Import all built-in wait strategies for easier usage.
|
|
60
60
|
from .wait import wait_chain # noqa
|
|
61
61
|
from .wait import wait_combine # noqa
|
|
62
|
+
from .wait import wait_exception # noqa
|
|
62
63
|
from .wait import wait_exponential # noqa
|
|
63
64
|
from .wait import wait_fixed # noqa
|
|
64
65
|
from .wait import wait_incrementing # noqa
|
|
@@ -98,14 +99,11 @@ if t.TYPE_CHECKING:
|
|
|
98
99
|
|
|
99
100
|
WrappedFnReturnT = t.TypeVar("WrappedFnReturnT")
|
|
100
101
|
WrappedFn = t.TypeVar("WrappedFn", bound=t.Callable[..., t.Any])
|
|
102
|
+
P = t.ParamSpec("P")
|
|
103
|
+
R = t.TypeVar("R")
|
|
101
104
|
|
|
102
105
|
|
|
103
|
-
|
|
104
|
-
if sys.version_info >= (3, 10):
|
|
105
|
-
dataclass_kwargs.update({"slots": True})
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
@dataclasses.dataclass(**dataclass_kwargs)
|
|
106
|
+
@dataclasses.dataclass(slots=True)
|
|
109
107
|
class IterState:
|
|
110
108
|
actions: t.List[t.Callable[["RetryCallState"], t.Any]] = dataclasses.field(
|
|
111
109
|
default_factory=list
|
|
@@ -307,19 +305,15 @@ class BaseRetrying(ABC):
|
|
|
307
305
|
future we may provide a way to aggregate the various
|
|
308
306
|
statistics from each thread).
|
|
309
307
|
"""
|
|
310
|
-
|
|
311
|
-
return self._local.statistics # type: ignore[no-any-return]
|
|
312
|
-
except AttributeError:
|
|
308
|
+
if not hasattr(self._local, "statistics"):
|
|
313
309
|
self._local.statistics = t.cast(t.Dict[str, t.Any], {})
|
|
314
|
-
|
|
310
|
+
return self._local.statistics # type: ignore[no-any-return]
|
|
315
311
|
|
|
316
312
|
@property
|
|
317
313
|
def iter_state(self) -> IterState:
|
|
318
|
-
|
|
319
|
-
return self._local.iter_state # type: ignore[no-any-return]
|
|
320
|
-
except AttributeError:
|
|
314
|
+
if not hasattr(self._local, "iter_state"):
|
|
321
315
|
self._local.iter_state = IterState()
|
|
322
|
-
|
|
316
|
+
return self._local.iter_state # type: ignore[no-any-return]
|
|
323
317
|
|
|
324
318
|
def wraps(self, f: WrappedFn) -> WrappedFn:
|
|
325
319
|
"""Wrap a function for retrying.
|
|
@@ -489,13 +483,7 @@ class Retrying(BaseRetrying):
|
|
|
489
483
|
return do # type: ignore[no-any-return]
|
|
490
484
|
|
|
491
485
|
|
|
492
|
-
|
|
493
|
-
FutureGenericT = futures.Future[t.Any]
|
|
494
|
-
else:
|
|
495
|
-
FutureGenericT = futures.Future
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
class Future(FutureGenericT):
|
|
486
|
+
class Future(futures.Future[t.Any]):
|
|
499
487
|
"""Encapsulates a (future or past) attempted call to a target function."""
|
|
500
488
|
|
|
501
489
|
def __init__(self, attempt_number: int) -> None:
|
|
@@ -603,7 +591,27 @@ def retry(func: WrappedFn) -> WrappedFn: ...
|
|
|
603
591
|
|
|
604
592
|
@t.overload
|
|
605
593
|
def retry(
|
|
606
|
-
|
|
594
|
+
*,
|
|
595
|
+
sleep: t.Callable[[t.Union[int, float]], t.Awaitable[None]],
|
|
596
|
+
stop: "StopBaseT" = ...,
|
|
597
|
+
wait: "WaitBaseT" = ...,
|
|
598
|
+
retry: "t.Union[RetryBaseT, tasyncio.retry.RetryBaseT]" = ...,
|
|
599
|
+
before: t.Callable[["RetryCallState"], t.Union[None, t.Awaitable[None]]] = ...,
|
|
600
|
+
after: t.Callable[["RetryCallState"], t.Union[None, t.Awaitable[None]]] = ...,
|
|
601
|
+
before_sleep: t.Optional[
|
|
602
|
+
t.Callable[["RetryCallState"], t.Union[None, t.Awaitable[None]]]
|
|
603
|
+
] = ...,
|
|
604
|
+
reraise: bool = ...,
|
|
605
|
+
retry_error_cls: t.Type["RetryError"] = ...,
|
|
606
|
+
retry_error_callback: t.Optional[
|
|
607
|
+
t.Callable[["RetryCallState"], t.Union[t.Any, t.Awaitable[t.Any]]]
|
|
608
|
+
] = ...,
|
|
609
|
+
) -> t.Callable[[t.Callable[P, R | t.Awaitable[R]]], t.Callable[P, t.Awaitable[R]]]: ...
|
|
610
|
+
|
|
611
|
+
|
|
612
|
+
@t.overload
|
|
613
|
+
def retry(
|
|
614
|
+
sleep: t.Callable[[t.Union[int, float]], None] = sleep,
|
|
607
615
|
stop: "StopBaseT" = stop_never,
|
|
608
616
|
wait: "WaitBaseT" = wait_none(),
|
|
609
617
|
retry: "t.Union[RetryBaseT, tasyncio.retry.RetryBaseT]" = retry_if_exception_type(),
|
|
@@ -642,7 +650,10 @@ def retry(*dargs: t.Any, **dkw: t.Any) -> t.Any:
|
|
|
642
650
|
f"this will probably hang indefinitely (did you mean retry={f.__class__.__name__}(...)?)"
|
|
643
651
|
)
|
|
644
652
|
r: "BaseRetrying"
|
|
645
|
-
|
|
653
|
+
sleep = dkw.get("sleep")
|
|
654
|
+
if _utils.is_coroutine_callable(f) or (
|
|
655
|
+
sleep is not None and _utils.is_coroutine_callable(sleep)
|
|
656
|
+
):
|
|
646
657
|
r = AsyncRetrying(*dargs, **dkw)
|
|
647
658
|
elif (
|
|
648
659
|
tornado
|
|
@@ -690,6 +701,7 @@ __all__ = [
|
|
|
690
701
|
"stop_when_event_set",
|
|
691
702
|
"wait_chain",
|
|
692
703
|
"wait_combine",
|
|
704
|
+
"wait_exception",
|
|
693
705
|
"wait_exponential",
|
|
694
706
|
"wait_fixed",
|
|
695
707
|
"wait_incrementing",
|
|
@@ -25,6 +25,18 @@ from datetime import timedelta
|
|
|
25
25
|
MAX_WAIT = sys.maxsize / 2
|
|
26
26
|
|
|
27
27
|
|
|
28
|
+
class LoggerProtocol(typing.Protocol):
|
|
29
|
+
"""
|
|
30
|
+
Protocol used by utils expecting a logger (eg: before_log).
|
|
31
|
+
|
|
32
|
+
Compatible with logging, structlog, loguru, etc...
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
def log(
|
|
36
|
+
self, level: int, msg: str, /, *args: typing.Any, **kwargs: typing.Any
|
|
37
|
+
) -> typing.Any: ...
|
|
38
|
+
|
|
39
|
+
|
|
28
40
|
def find_ordinal(pos_num: int) -> str:
|
|
29
41
|
# See: https://en.wikipedia.org/wiki/English_numerals#Ordinal_numbers
|
|
30
42
|
if pos_num == 0:
|
|
@@ -19,8 +19,6 @@ import typing
|
|
|
19
19
|
from tenacity import _utils
|
|
20
20
|
|
|
21
21
|
if typing.TYPE_CHECKING:
|
|
22
|
-
import logging
|
|
23
|
-
|
|
24
22
|
from tenacity import RetryCallState
|
|
25
23
|
|
|
26
24
|
|
|
@@ -29,9 +27,9 @@ def after_nothing(retry_state: "RetryCallState") -> None:
|
|
|
29
27
|
|
|
30
28
|
|
|
31
29
|
def after_log(
|
|
32
|
-
logger:
|
|
30
|
+
logger: _utils.LoggerProtocol,
|
|
33
31
|
log_level: int,
|
|
34
|
-
sec_format: str = "
|
|
32
|
+
sec_format: str = "%.3g",
|
|
35
33
|
) -> typing.Callable[["RetryCallState"], None]:
|
|
36
34
|
"""After call strategy that logs to some logger the finished attempt."""
|
|
37
35
|
|
|
@@ -107,11 +107,15 @@ class AsyncRetrying(BaseRetrying):
|
|
|
107
107
|
self.begin()
|
|
108
108
|
|
|
109
109
|
retry_state = RetryCallState(retry_object=self, fn=fn, args=args, kwargs=kwargs)
|
|
110
|
+
is_async = _utils.is_coroutine_callable(fn)
|
|
110
111
|
while True:
|
|
111
112
|
do = await self.iter(retry_state=retry_state)
|
|
112
113
|
if isinstance(do, DoAttempt):
|
|
113
114
|
try:
|
|
114
|
-
|
|
115
|
+
if is_async:
|
|
116
|
+
result = await fn(*args, **kwargs)
|
|
117
|
+
else:
|
|
118
|
+
result = fn(*args, **kwargs)
|
|
115
119
|
except BaseException: # noqa: B902
|
|
116
120
|
retry_state.set_exception(sys.exc_info()) # type: ignore[arg-type]
|
|
117
121
|
else:
|
|
@@ -19,8 +19,6 @@ import typing
|
|
|
19
19
|
from tenacity import _utils
|
|
20
20
|
|
|
21
21
|
if typing.TYPE_CHECKING:
|
|
22
|
-
import logging
|
|
23
|
-
|
|
24
22
|
from tenacity import RetryCallState
|
|
25
23
|
|
|
26
24
|
|
|
@@ -29,7 +27,7 @@ def before_nothing(retry_state: "RetryCallState") -> None:
|
|
|
29
27
|
|
|
30
28
|
|
|
31
29
|
def before_log(
|
|
32
|
-
logger:
|
|
30
|
+
logger: _utils.LoggerProtocol, log_level: int
|
|
33
31
|
) -> typing.Callable[["RetryCallState"], None]:
|
|
34
32
|
"""Before call strategy that logs to some logger the attempt."""
|
|
35
33
|
|
|
@@ -19,8 +19,6 @@ import typing
|
|
|
19
19
|
from tenacity import _utils
|
|
20
20
|
|
|
21
21
|
if typing.TYPE_CHECKING:
|
|
22
|
-
import logging
|
|
23
|
-
|
|
24
22
|
from tenacity import RetryCallState
|
|
25
23
|
|
|
26
24
|
|
|
@@ -29,9 +27,10 @@ def before_sleep_nothing(retry_state: "RetryCallState") -> None:
|
|
|
29
27
|
|
|
30
28
|
|
|
31
29
|
def before_sleep_log(
|
|
32
|
-
logger:
|
|
30
|
+
logger: _utils.LoggerProtocol,
|
|
33
31
|
log_level: int,
|
|
34
32
|
exc_info: bool = False,
|
|
33
|
+
sec_format: str = "%.3g",
|
|
35
34
|
) -> typing.Callable[["RetryCallState"], None]:
|
|
36
35
|
"""Before sleep strategy that logs to some logger the attempt."""
|
|
37
36
|
|
|
@@ -65,7 +64,7 @@ def before_sleep_log(
|
|
|
65
64
|
logger.log(
|
|
66
65
|
log_level,
|
|
67
66
|
f"Retrying {fn_name} "
|
|
68
|
-
f"in {retry_state.next_action.sleep} seconds as it {verb} {value}.",
|
|
67
|
+
f"in {sec_format % retry_state.next_action.sleep} seconds as it {verb} {value}.",
|
|
69
68
|
exc_info=local_exc_info,
|
|
70
69
|
)
|
|
71
70
|
|
|
@@ -37,7 +37,7 @@ class TornadoRetrying(BaseRetrying):
|
|
|
37
37
|
super().__init__(**kwargs)
|
|
38
38
|
self.sleep = sleep
|
|
39
39
|
|
|
40
|
-
@gen.coroutine # type: ignore[
|
|
40
|
+
@gen.coroutine # type: ignore[untyped-decorator]
|
|
41
41
|
def __call__(
|
|
42
42
|
self,
|
|
43
43
|
fn: "typing.Callable[..., typing.Union[typing.Generator[typing.Any, typing.Any, _RetValT], Future[_RetValT]]]",
|
|
@@ -98,10 +98,10 @@ class wait_chain(wait_base):
|
|
|
98
98
|
|
|
99
99
|
@retry(wait=wait_chain(*[wait_fixed(1) for i in range(3)] +
|
|
100
100
|
[wait_fixed(2) for j in range(5)] +
|
|
101
|
-
[wait_fixed(5) for k in range(4)))
|
|
101
|
+
[wait_fixed(5) for k in range(4)]))
|
|
102
102
|
def wait_chained():
|
|
103
|
-
print("Wait 1s for 3 attempts, 2s for 5 attempts and 5s
|
|
104
|
-
|
|
103
|
+
print("Wait 1s for 3 attempts, 2s for 5 attempts and 5s "
|
|
104
|
+
"thereafter.")
|
|
105
105
|
"""
|
|
106
106
|
|
|
107
107
|
def __init__(self, *strategies: wait_base) -> None:
|
|
@@ -113,6 +113,45 @@ class wait_chain(wait_base):
|
|
|
113
113
|
return wait_func(retry_state=retry_state)
|
|
114
114
|
|
|
115
115
|
|
|
116
|
+
class wait_exception(wait_base):
|
|
117
|
+
"""Wait strategy that waits the amount of time returned by the predicate.
|
|
118
|
+
|
|
119
|
+
The predicate is passed the exception object. Based on the exception, the
|
|
120
|
+
user can decide how much time to wait before retrying.
|
|
121
|
+
|
|
122
|
+
For example::
|
|
123
|
+
|
|
124
|
+
def http_error(exception: BaseException) -> float:
|
|
125
|
+
if (
|
|
126
|
+
isinstance(exception, requests.HTTPError)
|
|
127
|
+
and exception.response.status_code == requests.codes.too_many_requests
|
|
128
|
+
):
|
|
129
|
+
return float(exception.response.headers.get("Retry-After", "1"))
|
|
130
|
+
return 60.0
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
@retry(
|
|
134
|
+
stop=stop_after_attempt(3),
|
|
135
|
+
wait=wait_exception(http_error),
|
|
136
|
+
)
|
|
137
|
+
def http_get_request(url: str) -> None:
|
|
138
|
+
response = requests.get(url)
|
|
139
|
+
response.raise_for_status()
|
|
140
|
+
"""
|
|
141
|
+
|
|
142
|
+
def __init__(self, predicate: typing.Callable[[BaseException], float]) -> None:
|
|
143
|
+
self.predicate = predicate
|
|
144
|
+
|
|
145
|
+
def __call__(self, retry_state: "RetryCallState") -> float:
|
|
146
|
+
if retry_state.outcome is None:
|
|
147
|
+
raise RuntimeError("__call__() called before outcome was set")
|
|
148
|
+
|
|
149
|
+
exception = retry_state.outcome.exception()
|
|
150
|
+
if exception is None:
|
|
151
|
+
raise RuntimeError("outcome failed but the exception is None")
|
|
152
|
+
return self.predicate(exception)
|
|
153
|
+
|
|
154
|
+
|
|
116
155
|
class wait_incrementing(wait_base):
|
|
117
156
|
"""Wait an incremental amount of time after each attempt.
|
|
118
157
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tenacity
|
|
3
|
-
Version: 9.1.
|
|
3
|
+
Version: 9.1.3
|
|
4
4
|
Summary: Retry code until it succeeds
|
|
5
5
|
Home-page: https://github.com/jd/tenacity
|
|
6
6
|
Author: Julien Danjou
|
|
@@ -11,13 +11,13 @@ 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.9
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.10
|
|
16
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
18
17
|
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
19
|
Classifier: Topic :: Utilities
|
|
20
|
-
Requires-Python: >=3.
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
21
|
License-File: LICENSE
|
|
22
22
|
Provides-Extra: doc
|
|
23
23
|
Requires-Dist: reno; extra == "doc"
|
|
@@ -30,11 +30,13 @@ releasenotes/notes/added_a_link_to_documentation-eefaf8f074b539f8.yaml
|
|
|
30
30
|
releasenotes/notes/after_log-50f4d73b24ce9203.yaml
|
|
31
31
|
releasenotes/notes/allow-mocking-of-nap-sleep-6679c50e702446f1.yaml
|
|
32
32
|
releasenotes/notes/annotate_code-197b93130df14042.yaml
|
|
33
|
+
releasenotes/notes/async-sleep-retrying-32de5866f5d041.yaml
|
|
33
34
|
releasenotes/notes/before_sleep_log-improvements-d8149274dfb37d7c.yaml
|
|
34
35
|
releasenotes/notes/clarify-reraise-option-6829667eacf4f599.yaml
|
|
35
36
|
releasenotes/notes/dependabot-for-github-actions-4d2464f3c0928463.yaml
|
|
36
37
|
releasenotes/notes/do_not_package_tests-fe5ac61940b0a5ed.yaml
|
|
37
38
|
releasenotes/notes/drop-deprecated-python-versions-69a05cb2e0f1034c.yaml
|
|
39
|
+
releasenotes/notes/drop-python-3.9-ecfa2d7db9773e96.yaml
|
|
38
40
|
releasenotes/notes/drop_deprecated-7ea90b212509b082.yaml
|
|
39
41
|
releasenotes/notes/export-convenience-symbols-981d9611c8b754f3.yaml
|
|
40
42
|
releasenotes/notes/fix-async-loop-with-result-f68e913ccb425aca.yaml
|
|
@@ -43,6 +45,7 @@ releasenotes/notes/fix-retry-wrapper-attributes-f7a3a45b8e90f257.yaml
|
|
|
43
45
|
releasenotes/notes/fix-setuptools-config-3af71aa3592b6948.yaml
|
|
44
46
|
releasenotes/notes/fix-wait-typing-b26eecdb6cc0a1de.yaml
|
|
45
47
|
releasenotes/notes/fix_async-52b6594c8e75c4bc.yaml
|
|
48
|
+
releasenotes/notes/logging-protocol-a4cf0f786f21e4ee.yaml
|
|
46
49
|
releasenotes/notes/make-logger-more-compatible-5da1ddf1bab77047.yaml
|
|
47
50
|
releasenotes/notes/no-async-iter-6132a42e52348a75.yaml
|
|
48
51
|
releasenotes/notes/pr320-py3-only-wheel-tag.yaml
|
|
@@ -51,6 +54,7 @@ releasenotes/notes/remove-py36-876c0416cf279d15.yaml
|
|
|
51
54
|
releasenotes/notes/retrycallstate-repr-94947f7b00ee15e1.yaml
|
|
52
55
|
releasenotes/notes/some-slug-for-preserve-defaults-86682846dfa18005.yaml
|
|
53
56
|
releasenotes/notes/sphinx_define_error-642c9cd5c165d39a.yaml
|
|
57
|
+
releasenotes/notes/support-py3.14-14928188cab53b99.yaml
|
|
54
58
|
releasenotes/notes/support-timedelta-wait-unit-type-5ba1e9fc0fe45523.yaml
|
|
55
59
|
releasenotes/notes/timedelta-for-stop-ef6bf71b88ce9988.yaml
|
|
56
60
|
releasenotes/notes/trio-support-retry-22bd544800cd1f36.yaml
|
|
@@ -27,7 +27,7 @@ class TestAfterLogFormat(unittest.TestCase):
|
|
|
27
27
|
log = unittest.mock.MagicMock(spec="logging.Logger.log")
|
|
28
28
|
logger = unittest.mock.MagicMock(spec="logging.Logger", log=log)
|
|
29
29
|
|
|
30
|
-
sec_format = "
|
|
30
|
+
sec_format = "%.3g"
|
|
31
31
|
delay_since_first_attempt = 0.1
|
|
32
32
|
|
|
33
33
|
retry_state = test_tenacity.make_retry_state(
|
|
@@ -34,14 +34,17 @@ from tenacity import asyncio as tasyncio
|
|
|
34
34
|
from tenacity import retry, retry_if_exception, retry_if_result, stop_after_attempt
|
|
35
35
|
from tenacity.wait import wait_fixed
|
|
36
36
|
|
|
37
|
-
from .test_tenacity import
|
|
37
|
+
from .test_tenacity import (
|
|
38
|
+
NoIOErrorAfterCount,
|
|
39
|
+
NoneReturnUntilAfterCount,
|
|
40
|
+
current_time_ms,
|
|
41
|
+
)
|
|
38
42
|
|
|
39
43
|
|
|
40
44
|
def asynctest(callable_):
|
|
41
45
|
@wraps(callable_)
|
|
42
46
|
def wrapper(*a, **kw):
|
|
43
|
-
|
|
44
|
-
return loop.run_until_complete(callable_(*a, **kw))
|
|
47
|
+
return asyncio.run(callable_(*a, **kw))
|
|
45
48
|
|
|
46
49
|
return wrapper
|
|
47
50
|
|
|
@@ -464,5 +467,26 @@ async def foo():
|
|
|
464
467
|
pass
|
|
465
468
|
|
|
466
469
|
|
|
470
|
+
class TestSyncFunctionWithAsyncSleep(unittest.TestCase):
|
|
471
|
+
@asynctest
|
|
472
|
+
async def test_sync_function_with_async_sleep(self):
|
|
473
|
+
"""A sync function with an async sleep callable uses AsyncRetrying."""
|
|
474
|
+
mock_sleep = mock.AsyncMock()
|
|
475
|
+
|
|
476
|
+
thing = NoneReturnUntilAfterCount(2)
|
|
477
|
+
|
|
478
|
+
@retry(
|
|
479
|
+
sleep=mock_sleep,
|
|
480
|
+
wait=wait_fixed(1),
|
|
481
|
+
retry=retry_if_result(lambda x: x is None),
|
|
482
|
+
)
|
|
483
|
+
def sync_function():
|
|
484
|
+
return thing.go()
|
|
485
|
+
|
|
486
|
+
result = await sync_function()
|
|
487
|
+
assert result is True
|
|
488
|
+
assert mock_sleep.await_count == 2
|
|
489
|
+
|
|
490
|
+
|
|
467
491
|
if __name__ == "__main__":
|
|
468
492
|
unittest.main()
|
|
@@ -12,8 +12,7 @@ def asynctest(
|
|
|
12
12
|
) -> typing.Callable[..., typing.Any]:
|
|
13
13
|
@wraps(callable_)
|
|
14
14
|
def wrapper(*a: typing.Any, **kw: typing.Any) -> typing.Any:
|
|
15
|
-
|
|
16
|
-
return loop.run_until_complete(callable_(*a, **kw))
|
|
15
|
+
return asyncio.run(callable_(*a, **kw))
|
|
17
16
|
|
|
18
17
|
return wrapper
|
|
19
18
|
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
import datetime
|
|
18
18
|
import logging
|
|
19
19
|
import re
|
|
20
|
-
import sys
|
|
21
20
|
import time
|
|
22
21
|
import typing
|
|
23
22
|
import unittest
|
|
@@ -28,6 +27,7 @@ from fractions import Fraction
|
|
|
28
27
|
from unittest import mock
|
|
29
28
|
|
|
30
29
|
import pytest
|
|
30
|
+
from typeguard import check_type
|
|
31
31
|
|
|
32
32
|
import tenacity
|
|
33
33
|
from tenacity import RetryCallState, RetryError, Retrying, retry
|
|
@@ -369,6 +369,24 @@ class TestWaitConditions(unittest.TestCase):
|
|
|
369
369
|
self.assertLess(w, 8)
|
|
370
370
|
self.assertGreaterEqual(w, 5)
|
|
371
371
|
|
|
372
|
+
def test_wait_exception(self):
|
|
373
|
+
def predicate(exc):
|
|
374
|
+
if isinstance(exc, ValueError):
|
|
375
|
+
return 3.5
|
|
376
|
+
return 10.0
|
|
377
|
+
|
|
378
|
+
r = Retrying(wait=tenacity.wait_exception(predicate))
|
|
379
|
+
|
|
380
|
+
fut1 = tenacity.Future.construct(1, ValueError(), True)
|
|
381
|
+
self.assertEqual(r.wait(make_retry_state(1, 0, last_result=fut1)), 3.5)
|
|
382
|
+
|
|
383
|
+
fut2 = tenacity.Future.construct(1, KeyError(), True)
|
|
384
|
+
self.assertEqual(r.wait(make_retry_state(1, 0, last_result=fut2)), 10.0)
|
|
385
|
+
|
|
386
|
+
fut3 = tenacity.Future.construct(1, None, False)
|
|
387
|
+
with self.assertRaises(RuntimeError):
|
|
388
|
+
r.wait(make_retry_state(1, 0, last_result=fut3))
|
|
389
|
+
|
|
372
390
|
def test_wait_double_sum(self):
|
|
373
391
|
r = Retrying(wait=tenacity.wait_random(0, 3) + tenacity.wait_fixed(5))
|
|
374
392
|
# Test it a few time since it's random
|
|
@@ -1711,17 +1729,8 @@ class TestRetryException(unittest.TestCase):
|
|
|
1711
1729
|
|
|
1712
1730
|
|
|
1713
1731
|
class TestRetryTyping(unittest.TestCase):
|
|
1714
|
-
@pytest.mark.skipif(
|
|
1715
|
-
sys.version_info < (3, 0), reason="typeguard not supported for python 2"
|
|
1716
|
-
)
|
|
1717
1732
|
def test_retry_type_annotations(self):
|
|
1718
1733
|
"""The decorator should maintain types of decorated functions."""
|
|
1719
|
-
# Just in case this is run with unit-test, return early for py2
|
|
1720
|
-
if sys.version_info < (3, 0):
|
|
1721
|
-
return
|
|
1722
|
-
|
|
1723
|
-
# Function-level import because we can't install this for python 2.
|
|
1724
|
-
from typeguard import check_type
|
|
1725
1734
|
|
|
1726
1735
|
def num_to_str(number):
|
|
1727
1736
|
# type: (int) -> str
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tox]
|
|
2
2
|
# we only test trio on latest python version
|
|
3
|
-
envlist = py3{
|
|
3
|
+
envlist = py3{10,11,12,13,14,14-trio}, pep8, pypy3
|
|
4
4
|
skip_missing_interpreters = True
|
|
5
5
|
|
|
6
6
|
[testenv]
|
|
@@ -11,9 +11,9 @@ deps =
|
|
|
11
11
|
.[doc]
|
|
12
12
|
trio: trio
|
|
13
13
|
commands =
|
|
14
|
-
py3{
|
|
15
|
-
py3{
|
|
16
|
-
py3{
|
|
14
|
+
py3{10,11,12,13,14},pypy3: pytest {posargs}
|
|
15
|
+
py3{10,11,12,13,14},pypy3: sphinx-build -a -E -W -b doctest doc/source doc/build
|
|
16
|
+
py3{10,11,12,13,14},pypy3: sphinx-build -a -E -W -b html doc/source doc/build
|
|
17
17
|
|
|
18
18
|
[testenv:pep8]
|
|
19
19
|
basepython = python3
|
tenacity-9.1.2/.mergify.yml
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
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.9, py39)"
|
|
14
|
-
- "check-success=test (3.10, py310)"
|
|
15
|
-
- "check-success=test (3.11, py311)"
|
|
16
|
-
- "check-success=test (3.12, py312)"
|
|
17
|
-
- "check-success=test (3.13, py313,py313-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: {}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/add-async-actions-b249c527d99723bb.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/add-stop-before-delay-a775f88ac872c923.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/clarify-reraise-option-6829667eacf4f599.yaml
RENAMED
|
File without changes
|
|
File without changes
|
{tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/do_not_package_tests-fe5ac61940b0a5ed.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/fix-setuptools-config-3af71aa3592b6948.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/retrycallstate-repr-94947f7b00ee15e1.yaml
RENAMED
|
File without changes
|
|
File without changes
|
{tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/sphinx_define_error-642c9cd5c165d39a.yaml
RENAMED
|
File without changes
|
|
File without changes
|
{tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/timedelta-for-stop-ef6bf71b88ce9988.yaml
RENAMED
|
File without changes
|
{tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/trio-support-retry-22bd544800cd1f36.yaml
RENAMED
|
File without changes
|
|
File without changes
|
{tenacity-9.1.2 → tenacity-9.1.3}/releasenotes/notes/wait_exponential_jitter-6ffc81dddcbaa6d3.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|