Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-tenacity for openSUSE:Factory
checked in at 2022-11-12 17:41:15
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-tenacity (Old)
and /work/SRC/openSUSE:Factory/.python-tenacity.new.1597 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-tenacity"
Sat Nov 12 17:41:15 2022 rev:16 rq:1035302 version:8.1.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-tenacity/python-tenacity.changes
2022-11-01 13:43:11.828096823 +0100
+++
/work/SRC/openSUSE:Factory/.python-tenacity.new.1597/python-tenacity.changes
2022-11-12 17:41:38.114334474 +0100
@@ -1,0 +2,59 @@
+Fri Nov 11 13:21:11 UTC 2022 - [email protected]
+
+- silent rpmlint
+
+-------------------------------------------------------------------
+Fri Nov 11 11:38:22 UTC 2022 - [email protected]
+
+- python-six is not required
+
+-------------------------------------------------------------------
+Wed Nov 9 19:19:10 UTC 2022 - Yogalakshmi Arunachalam <[email protected]>
+
+- Update to version 8.1.0 (included changes also from 8.0.1, 8.0.0, 7.0.0)
+ * feat: Add retry_if_exception_cause_type (#362)
+ * Support `datetime.timedelta` as a valid wait unit type (#342)
+ * Show All Exception Predicates in Docs (#332)
+ * Implement a wait.wait_exponential_jitter per Google's storage guide (#351)
+ * Define a ClientError to fix Sphinx build errors (#352)
+ * Merge pull request #340 from jd/fix-mergify
+ * ci: fix Mergify config
+ * Merge pull request #337 from william-silversmith/master
+ * docs: show how to use retry_if_not_exception_type
+ * Rickroll a function name in one of the examples (#331)
+ * Fix after_log logger format (#317)
+ * Drop `py2` tag from the wheel name (#320)
+ * Add a __repr__ method to RetryCallState objects (#302)
+ * Add type annotations to cover all code. (#315)
+ * Fix #307 : Drop deprecated APIs (#314)
+ * Fix DeprecationWarnings in tests (#313)
+ * Do not package tests with tenacity (#308)
+ * Fix issue #288 : __name__ and other attributes for async functions (#312)
+ * Use f-strings instead of `str.format` as faster and easier to read (#311)
+ * Replace abc.ABCMeta with abc.ABC (#310)
+ * Remove encoding declarations (#309)
+ * Merge pull request #306 from penguinolog/black_full_ci
+ * Use black instead of "flake8-black" on CI.
+ * Fix #291: drop python < 3.6 (#304)
+ * Merge pull request #293 from and-semakin/drop_deprecated_pythons
+ * Drop support for deprecated Python versions (2.7 and 3.5)
+ * Add retry_if_not_exception_type() (#300)
+ * Make logger more compatible (#294)
+ * ci: fix pep8 error (#297)
+ * Merge pull request #286 from jd/reno-mergify
+ * Add Python 3.8 in tox.ini
+ * Fix upload job
+ * Merge pull request #202 from jd/release-auto
+ * Release via CircleCI
+ * Merge pull request #191 from bersace/context-manager
+ * Merge branch 'master' into context-manager
+ * Merge pull request #201 from bersace/async
+ * Ensure coroutine passes asyncio.iscoroutinefunction
+ * Test async keyword
+ * Retry code block with context manager
+ * Merge pull request #200 from Dectinc/master
+ * Fix setup.cfg typo
+ * Merge pull request #198 from BATS/py2-compatability-for-_asyncio-module
+ * Ensure that the _asyncio.py module can be compiled, even on Python 2
+
+-------------------------------------------------------------------
@@ -4 +63 @@
-- Update to version 8.1.0
+- Update to version 8.0.1
Old:
----
tenacity-8.0.1.tar.gz
New:
----
tenacity-8.1.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-tenacity.spec ++++++
--- /var/tmp/diff_new_pack.y40xvu/_old 2022-11-12 17:41:38.594337332 +0100
+++ /var/tmp/diff_new_pack.y40xvu/_new 2022-11-12 17:41:38.594337332 +0100
@@ -17,7 +17,7 @@
Name: python-tenacity
-Version: 8.0.1
+Version: 8.1.0
Release: 0
Summary: Python module for retrying code until it succeeeds
License: Apache-2.0
@@ -27,13 +27,11 @@
BuildRequires: %{python_module pytest}
BuildRequires: %{python_module setuptools_scm}
BuildRequires: %{python_module setuptools}
-BuildRequires: %{python_module six >= 1.9.0}
BuildRequires: %{python_module tornado}
BuildRequires: %{python_module typeguard}
BuildRequires: %{python_module typing-extensions}
BuildRequires: fdupes
BuildRequires: python-rpm-macros
-Requires: python-six >= 1.9.0
Recommends: python-tornado
BuildArch: noarch
%python_subpackages
@@ -66,6 +64,7 @@
%files %{python_files}
%license LICENSE
%doc README.rst
-%{python_sitelib}/*
+%{python_sitelib}/tenacity
+%{python_sitelib}/tenacity-*egg-info
%changelog
++++++ tenacity-8.0.1.tar.gz -> tenacity-8.1.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/tenacity-8.0.1/.mergify.yml
new/tenacity-8.1.0/.mergify.yml
--- old/tenacity-8.0.1/.mergify.yml 2021-06-30 14:37:02.000000000 +0200
+++ new/tenacity-8.1.0/.mergify.yml 2022-09-21 14:23:59.000000000 +0200
@@ -1,3 +1,13 @@
+queue_rules:
+ - name: default
+ conditions:
+ - "status-success=ci/circleci: pep8"
+ - "status-success=ci/circleci: black"
+ - "status-success=ci/circleci: py36"
+ - "status-success=ci/circleci: py37"
+ - "status-success=ci/circleci: py38"
+ - "status-success=ci/circleci: py39"
+
pull_request_rules:
- name: warn on no changelog
conditions:
@@ -21,8 +31,8 @@
- "#approved-reviews-by>=1"
- label=no-changelog
actions:
- merge:
- strict: "smart"
+ queue:
+ name: default
method: squash
- name: automatic merge with changelog
conditions:
@@ -35,8 +45,8 @@
- "#approved-reviews-by>=1"
- files~=^releasenotes/notes/
actions:
- merge:
- strict: "smart"
+ queue:
+ name: default
method: squash
- name: automatic merge for jd without changelog
conditions:
@@ -49,8 +59,8 @@
- "status-success=ci/circleci: py39"
- label=no-changelog
actions:
- merge:
- strict: "smart"
+ queue:
+ name: default
method: squash
- name: automatic merge for jd with changelog
conditions:
@@ -63,8 +73,8 @@
- "status-success=ci/circleci: py39"
- files~=^releasenotes/notes/
actions:
- merge:
- strict: "smart"
+ queue:
+ name: default
method: squash
- name: dismiss reviews
conditions: []
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/tenacity-8.0.1/AUTHORS new/tenacity-8.1.0/AUTHORS
--- old/tenacity-8.0.1/AUTHORS 2019-08-16 10:42:50.000000000 +0200
+++ new/tenacity-8.1.0/AUTHORS 1970-01-01 01:00:00.000000000 +0100
@@ -1,46 +0,0 @@
-Alex Kuang <[email protected]>
-Alexey <[email protected]>
-Boden R <[email protected]>
-Brian Pandola <[email protected]>
-Brian Williams <[email protected]>
-Brian Williams <[email protected]>
-Brian-Williams <[email protected]>
-Cyrus Durgin <[email protected]>
-Daniel Bennett <[email protected]>
-Daniel Nephin <[email protected]>
-Dave Hirschfeld <[email protected]>
-Derek Wilson <[email protected]>
-Elisey Zanko <[email protected]>
-Gevorg Davoian <[email protected]>
-Hamish Downer <[email protected]>
-Hannes Gräuler <[email protected]>
-Haïkel Guémar <[email protected]>
-Hugo <[email protected]>
-Jaye Doepke <[email protected]>
-Jonathan Herriott <[email protected]>
-Joshua Harlow <[email protected]>
-Joshua Harlow <[email protected]>
-Joshua Harlow <[email protected]>
-Julien Danjou <[email protected]>
-Martin Larralde <[email protected]>
-Mehdi Abaakouk <[email protected]>
-Michael Elsdörfer <[email protected]>
-Michael Evans <[email protected]>
-MikeWooster <[email protected]>
-Monty Taylor <[email protected]>
-Ray Holder <[email protected]>
-Ray Holder <[email protected]>
-Ryan Peck <[email protected]>
-Sam Park <[email protected]>
-Saul Shanabrook <[email protected]>
-Simeon Visser <[email protected]>
-Simon Dollé <[email protected]>
-Tim Burke <[email protected]>
-Victor Yap <[email protected]>
-William Silversmith <[email protected]>
-Zane Bitter <[email protected]>
-cyrus durgin <[email protected]>
-immerrr <[email protected]>
-mergify-bot <[email protected]>
-mergify[bot] <mergify[bot]@users.noreply.github.com>
-Ãtienne BERSAC (bersace) <[email protected]>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/tenacity-8.0.1/PKG-INFO new/tenacity-8.1.0/PKG-INFO
--- old/tenacity-8.0.1/PKG-INFO 2021-07-12 11:36:06.397020600 +0200
+++ new/tenacity-8.1.0/PKG-INFO 2022-09-21 14:24:11.075567200 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: tenacity
-Version: 8.0.1
+Version: 8.1.0
Summary: Retry code until it succeeds
Home-page: https://github.com/jd/tenacity
Author: Julien Danjou
@@ -21,7 +21,6 @@
Requires-Python: >=3.6
Provides-Extra: doc
License-File: LICENSE
-License-File: AUTHORS
Tenacity is a general-purpose retrying library to simplify the task of adding
retry behavior to just about anything.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/tenacity-8.0.1/README.rst
new/tenacity-8.1.0/README.rst
--- old/tenacity-8.0.1/README.rst 2021-01-29 16:26:35.000000000 +0100
+++ new/tenacity-8.1.0/README.rst 2022-09-21 14:23:59.000000000 +0200
@@ -95,7 +95,7 @@
.. testcode::
@retry
- def never_give_up_never_surrender():
+ def never_gonna_give_you_up():
print("Retry forever ignoring Exceptions, don't wait between retries")
raise Exception
@@ -205,11 +205,19 @@
.. testcode::
+ class ClientError(Exception):
+ """Some type of client error."""
+
@retry(retry=retry_if_exception_type(IOError))
def might_io_error():
print("Retry forever with no wait if an IOError occurs, raise any
other errors")
raise Exception
+ @retry(retry=retry_if_not_exception_type(ClientError))
+ def might_client_error():
+ print("Retry forever with no wait if any error other than ClientError
occurs. Immediately raise ClientError.")
+ raise Exception
+
We can also use the result of the function to alter the behavior of retrying.
.. testcode::
@@ -222,6 +230,21 @@
def might_return_none():
print("Retry with no wait if return value is None")
+See also these methods:
+
+.. testcode::
+
+ retry_if_exception
+ retry_if_exception_type
+ retry_if_not_exception_type
+ retry_unless_exception_type
+ retry_if_result
+ retry_if_not_result
+ retry_if_exception_message
+ retry_if_not_exception_message
+ retry_any
+ retry_all
+
We can also combine several conditions:
.. testcode::
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/tenacity-8.0.1/doc/source/index.rst
new/tenacity-8.1.0/doc/source/index.rst
--- old/tenacity-8.0.1/doc/source/index.rst 2021-01-29 16:26:35.000000000
+0100
+++ new/tenacity-8.1.0/doc/source/index.rst 2022-09-21 14:23:59.000000000
+0200
@@ -95,7 +95,7 @@
.. testcode::
@retry
- def never_give_up_never_surrender():
+ def never_gonna_give_you_up():
print("Retry forever ignoring Exceptions, don't wait between retries")
raise Exception
@@ -205,11 +205,19 @@
.. testcode::
+ class ClientError(Exception):
+ """Some type of client error."""
+
@retry(retry=retry_if_exception_type(IOError))
def might_io_error():
print("Retry forever with no wait if an IOError occurs, raise any
other errors")
raise Exception
+ @retry(retry=retry_if_not_exception_type(ClientError))
+ def might_client_error():
+ print("Retry forever with no wait if any error other than ClientError
occurs. Immediately raise ClientError.")
+ raise Exception
+
We can also use the result of the function to alter the behavior of retrying.
.. testcode::
@@ -222,6 +230,21 @@
def might_return_none():
print("Retry with no wait if return value is None")
+See also these methods:
+
+.. testcode::
+
+ retry_if_exception
+ retry_if_exception_type
+ retry_if_not_exception_type
+ retry_unless_exception_type
+ retry_if_result
+ retry_if_not_result
+ retry_if_exception_message
+ retry_if_not_exception_message
+ retry_any
+ retry_all
+
We can also combine several conditions:
.. testcode::
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/tenacity-8.0.1/releasenotes/notes/add_retry_if_exception_cause_type-d16b918ace4ae0ad.yaml
new/tenacity-8.1.0/releasenotes/notes/add_retry_if_exception_cause_type-d16b918ace4ae0ad.yaml
---
old/tenacity-8.0.1/releasenotes/notes/add_retry_if_exception_cause_type-d16b918ace4ae0ad.yaml
1970-01-01 01:00:00.000000000 +0100
+++
new/tenacity-8.1.0/releasenotes/notes/add_retry_if_exception_cause_type-d16b918ace4ae0ad.yaml
2022-09-21 14:23:59.000000000 +0200
@@ -0,0 +1,5 @@
+---
+features:
+ - |
+ Add a new `retry_base` class called `retry_if_exception_cause_type` that
+ checks, recursively, if any of the causes of the raised exception is of a
certain type.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/tenacity-8.0.1/releasenotes/notes/sphinx_define_error-642c9cd5c165d39a.yaml
new/tenacity-8.1.0/releasenotes/notes/sphinx_define_error-642c9cd5c165d39a.yaml
---
old/tenacity-8.0.1/releasenotes/notes/sphinx_define_error-642c9cd5c165d39a.yaml
1970-01-01 01:00:00.000000000 +0100
+++
new/tenacity-8.1.0/releasenotes/notes/sphinx_define_error-642c9cd5c165d39a.yaml
2022-09-21 14:23:59.000000000 +0200
@@ -0,0 +1,2 @@
+---
+fixes: Sphinx build error where Sphinx complains about an undefined class.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/tenacity-8.0.1/releasenotes/notes/support-timedelta-wait-unit-type-5ba1e9fc0fe45523.yaml
new/tenacity-8.1.0/releasenotes/notes/support-timedelta-wait-unit-type-5ba1e9fc0fe45523.yaml
---
old/tenacity-8.0.1/releasenotes/notes/support-timedelta-wait-unit-type-5ba1e9fc0fe45523.yaml
1970-01-01 01:00:00.000000000 +0100
+++
new/tenacity-8.1.0/releasenotes/notes/support-timedelta-wait-unit-type-5ba1e9fc0fe45523.yaml
2022-09-21 14:23:59.000000000 +0200
@@ -0,0 +1,3 @@
+---
+features:
+ - Add ``datetime.timedelta`` as accepted wait unit type.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/tenacity-8.0.1/releasenotes/notes/wait_exponential_jitter-6ffc81dddcbaa6d3.yaml
new/tenacity-8.1.0/releasenotes/notes/wait_exponential_jitter-6ffc81dddcbaa6d3.yaml
---
old/tenacity-8.0.1/releasenotes/notes/wait_exponential_jitter-6ffc81dddcbaa6d3.yaml
1970-01-01 01:00:00.000000000 +0100
+++
new/tenacity-8.1.0/releasenotes/notes/wait_exponential_jitter-6ffc81dddcbaa6d3.yaml
2022-09-21 14:23:59.000000000 +0200
@@ -0,0 +1,5 @@
+---
+features:
+ - |
+ Implement a wait.wait_exponential_jitter per Google's storage retry guide.
+ See https://cloud.google.com/storage/docs/retry-strategy
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/tenacity-8.0.1/tenacity/__init__.py
new/tenacity-8.1.0/tenacity/__init__.py
--- old/tenacity-8.0.1/tenacity/__init__.py 2021-07-08 09:31:14.000000000
+0200
+++ new/tenacity-8.1.0/tenacity/__init__.py 2022-09-21 14:23:59.000000000
+0200
@@ -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
@@ -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
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/tenacity-8.0.1/tenacity/retry.py
new/tenacity-8.1.0/tenacity/retry.py
--- old/tenacity-8.0.1/tenacity/retry.py 2021-06-30 14:37:02.000000000
+0200
+++ new/tenacity-8.1.0/tenacity/retry.py 2022-09-21 14:23:59.000000000
+0200
@@ -117,6 +117,33 @@
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."""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/tenacity-8.0.1/tenacity/wait.py
new/tenacity-8.1.0/tenacity/wait.py
--- old/tenacity-8.0.1/tenacity/wait.py 2021-07-08 09:31:14.000000000 +0200
+++ new/tenacity-8.1.0/tenacity/wait.py 2022-09-21 14:23:59.000000000 +0200
@@ -17,12 +17,19 @@
import abc
import random
import typing
+from datetime import timedelta
from tenacity import _utils
if typing.TYPE_CHECKING:
from 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."""
@@ -44,8 +51,8 @@
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
@@ -61,9 +68,9 @@
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))
@@ -113,13 +120,13 @@
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))
@@ -142,13 +149,13 @@
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:
@@ -189,3 +196,37 @@
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))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/tenacity-8.0.1/tenacity.egg-info/PKG-INFO
new/tenacity-8.1.0/tenacity.egg-info/PKG-INFO
--- old/tenacity-8.0.1/tenacity.egg-info/PKG-INFO 2021-07-12
11:36:06.000000000 +0200
+++ new/tenacity-8.1.0/tenacity.egg-info/PKG-INFO 2022-09-21
14:24:11.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: tenacity
-Version: 8.0.1
+Version: 8.1.0
Summary: Retry code until it succeeds
Home-page: https://github.com/jd/tenacity
Author: Julien Danjou
@@ -21,7 +21,6 @@
Requires-Python: >=3.6
Provides-Extra: doc
License-File: LICENSE
-License-File: AUTHORS
Tenacity is a general-purpose retrying library to simplify the task of adding
retry behavior to just about anything.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/tenacity-8.0.1/tenacity.egg-info/SOURCES.txt
new/tenacity-8.1.0/tenacity.egg-info/SOURCES.txt
--- old/tenacity-8.0.1/tenacity.egg-info/SOURCES.txt 2021-07-12
11:36:06.000000000 +0200
+++ new/tenacity-8.1.0/tenacity.egg-info/SOURCES.txt 2022-09-21
14:24:11.000000000 +0200
@@ -2,7 +2,6 @@
.gitignore
.mergify.yml
.readthedocs.yml
-AUTHORS
LICENSE
README.rst
pyproject.toml
@@ -18,6 +17,7 @@
releasenotes/notes/Use--for-formatting-and-validate-using-black-39ec9d57d4691778.yaml
releasenotes/notes/add-reno-d1ab5710f272650a.yaml
releasenotes/notes/add-retry_except_exception_type-31b31da1924d55f4.yaml
+releasenotes/notes/add_retry_if_exception_cause_type-d16b918ace4ae0ad.yaml
releasenotes/notes/after_log-50f4d73b24ce9203.yaml
releasenotes/notes/allow-mocking-of-nap-sleep-6679c50e702446f1.yaml
releasenotes/notes/annotate_code-197b93130df14042.yaml
@@ -30,6 +30,9 @@
releasenotes/notes/pr320-py3-only-wheel-tag.yaml
releasenotes/notes/py36_plus-c425fb3aa17c6682.yaml
releasenotes/notes/retrycallstate-repr-94947f7b00ee15e1.yaml
+releasenotes/notes/sphinx_define_error-642c9cd5c165d39a.yaml
+releasenotes/notes/support-timedelta-wait-unit-type-5ba1e9fc0fe45523.yaml
+releasenotes/notes/wait_exponential_jitter-6ffc81dddcbaa6d3.yaml
tenacity/__init__.py
tenacity/_asyncio.py
tenacity/_utils.py
@@ -45,7 +48,6 @@
tenacity.egg-info/PKG-INFO
tenacity.egg-info/SOURCES.txt
tenacity.egg-info/dependency_links.txt
-tenacity.egg-info/pbr.json
tenacity.egg-info/requires.txt
tenacity.egg-info/top_level.txt
tests/__init__.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/tenacity-8.0.1/tenacity.egg-info/pbr.json
new/tenacity-8.1.0/tenacity.egg-info/pbr.json
--- old/tenacity-8.0.1/tenacity.egg-info/pbr.json 2019-08-16
10:42:49.000000000 +0200
+++ new/tenacity-8.1.0/tenacity.egg-info/pbr.json 1970-01-01
01:00:00.000000000 +0100
@@ -1 +0,0 @@
-{"git_version": "58495e5", "is_release": false}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/tenacity-8.0.1/tests/test_tenacity.py
new/tenacity-8.1.0/tests/test_tenacity.py
--- old/tenacity-8.0.1/tests/test_tenacity.py 2021-07-08 09:31:14.000000000
+0200
+++ new/tenacity-8.1.0/tests/test_tenacity.py 2022-09-21 14:23:59.000000000
+0200
@@ -13,6 +13,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+import datetime
import logging
import re
import sys
@@ -29,7 +30,6 @@
import tenacity
from tenacity import RetryCallState, RetryError, Retrying, retry
-
_unset = object()
@@ -180,28 +180,34 @@
self.assertEqual(0, r.wait(make_retry_state(18, 9879)))
def test_fixed_sleep(self):
- r = Retrying(wait=tenacity.wait_fixed(1))
- self.assertEqual(1, r.wait(make_retry_state(12, 6546)))
+ for wait in (1, datetime.timedelta(seconds=1)):
+ with self.subTest():
+ r = Retrying(wait=tenacity.wait_fixed(wait))
+ self.assertEqual(1, r.wait(make_retry_state(12, 6546)))
def test_incrementing_sleep(self):
- r = Retrying(wait=tenacity.wait_incrementing(start=500, increment=100))
- self.assertEqual(500, r.wait(make_retry_state(1, 6546)))
- self.assertEqual(600, r.wait(make_retry_state(2, 6546)))
- self.assertEqual(700, r.wait(make_retry_state(3, 6546)))
+ for start, increment in ((500, 100), (datetime.timedelta(seconds=500),
datetime.timedelta(seconds=100))):
+ with self.subTest():
+ r = Retrying(wait=tenacity.wait_incrementing(start=start,
increment=increment))
+ self.assertEqual(500, r.wait(make_retry_state(1, 6546)))
+ self.assertEqual(600, r.wait(make_retry_state(2, 6546)))
+ self.assertEqual(700, r.wait(make_retry_state(3, 6546)))
def test_random_sleep(self):
- r = Retrying(wait=tenacity.wait_random(min=1, max=20))
- times = set()
- for x in range(1000):
- times.add(r.wait(make_retry_state(1, 6546)))
-
- # this is kind of non-deterministic...
- self.assertTrue(len(times) > 1)
- for t in times:
- self.assertTrue(t >= 1)
- self.assertTrue(t < 20)
+ for min_, max_ in ((1, 20), (datetime.timedelta(seconds=1),
datetime.timedelta(seconds=20))):
+ with self.subTest():
+ r = Retrying(wait=tenacity.wait_random(min=min_, max=max_))
+ times = set()
+ for _ in range(1000):
+ times.add(r.wait(make_retry_state(1, 6546)))
+
+ # this is kind of non-deterministic...
+ self.assertTrue(len(times) > 1)
+ for t in times:
+ self.assertTrue(t >= 1)
+ self.assertTrue(t < 20)
- def test_random_sleep_without_min(self):
+ def test_random_sleep_withoutmin_(self):
r = Retrying(wait=tenacity.wait_random(max=2))
times = set()
times.add(r.wait(make_retry_state(1, 6546)))
@@ -274,18 +280,20 @@
self.assertEqual(r.wait(make_retry_state(8, 0)), 256)
self.assertEqual(r.wait(make_retry_state(20, 0)), 1048576)
- def test_exponential_with_min_wait_and_max_wait(self):
- r = Retrying(wait=tenacity.wait_exponential(min=10, max=100))
- self.assertEqual(r.wait(make_retry_state(1, 0)), 10)
- self.assertEqual(r.wait(make_retry_state(2, 0)), 10)
- self.assertEqual(r.wait(make_retry_state(3, 0)), 10)
- self.assertEqual(r.wait(make_retry_state(4, 0)), 10)
- self.assertEqual(r.wait(make_retry_state(5, 0)), 16)
- self.assertEqual(r.wait(make_retry_state(6, 0)), 32)
- self.assertEqual(r.wait(make_retry_state(7, 0)), 64)
- self.assertEqual(r.wait(make_retry_state(8, 0)), 100)
- self.assertEqual(r.wait(make_retry_state(9, 0)), 100)
- self.assertEqual(r.wait(make_retry_state(20, 0)), 100)
+ def test_exponential_with_min_wait_andmax__wait(self):
+ for min_, max_ in ((10, 100), (datetime.timedelta(seconds=10),
datetime.timedelta(seconds=100))):
+ with self.subTest():
+ r = Retrying(wait=tenacity.wait_exponential(min=min_,
max=max_))
+ self.assertEqual(r.wait(make_retry_state(1, 0)), 10)
+ self.assertEqual(r.wait(make_retry_state(2, 0)), 10)
+ self.assertEqual(r.wait(make_retry_state(3, 0)), 10)
+ self.assertEqual(r.wait(make_retry_state(4, 0)), 10)
+ self.assertEqual(r.wait(make_retry_state(5, 0)), 16)
+ self.assertEqual(r.wait(make_retry_state(6, 0)), 32)
+ self.assertEqual(r.wait(make_retry_state(7, 0)), 64)
+ self.assertEqual(r.wait(make_retry_state(8, 0)), 100)
+ self.assertEqual(r.wait(make_retry_state(9, 0)), 100)
+ self.assertEqual(r.wait(make_retry_state(20, 0)), 100)
def test_legacy_explicit_wait_type(self):
Retrying(wait="exponential_sleep")
@@ -335,7 +343,7 @@
)
)
# Test it a few time since it's random
- for i in range(1000):
+ for _ in range(1000):
w = r.wait(make_retry_state(1, 5))
self.assertLess(w, 9)
self.assertGreaterEqual(w, 6)
@@ -435,6 +443,28 @@
self._assert_inclusive_epsilon(mean(attempt[8]), 30, 2.56)
self._assert_inclusive_epsilon(mean(attempt[9]), 30, 2.56)
+ def test_wait_exponential_jitter(self):
+ fn = tenacity.wait_exponential_jitter(max=60)
+
+ for _ in range(1000):
+ self._assert_inclusive_range(fn(make_retry_state(1, 0)), 1, 2)
+ self._assert_inclusive_range(fn(make_retry_state(2, 0)), 2, 3)
+ self._assert_inclusive_range(fn(make_retry_state(3, 0)), 4, 5)
+ self._assert_inclusive_range(fn(make_retry_state(4, 0)), 8, 9)
+ self._assert_inclusive_range(fn(make_retry_state(5, 0)), 16, 17)
+ self._assert_inclusive_range(fn(make_retry_state(6, 0)), 32, 33)
+ self.assertEqual(fn(make_retry_state(7, 0)), 60)
+ self.assertEqual(fn(make_retry_state(8, 0)), 60)
+ self.assertEqual(fn(make_retry_state(9, 0)), 60)
+
+ fn = tenacity.wait_exponential_jitter(10, 5)
+ for _ in range(1000):
+ self.assertEqual(fn(make_retry_state(1, 0)), 5)
+
+ # Default arguments exist
+ fn = tenacity.wait_exponential_jitter()
+ fn(make_retry_state(0, 0))
+
def test_wait_retry_state_attributes(self):
class ExtractCallState(Exception):
pass
@@ -646,6 +676,56 @@
return True
+class NoNameErrorCauseAfterCount:
+ """Holds counter state for invoking a method several times in a row."""
+
+ def __init__(self, count):
+ self.counter = 0
+ self.count = count
+
+ def go2(self):
+ raise NameError("Hi there, I'm a NameError")
+
+ def go(self):
+ """Raise an IOError with a NameError as cause until after count
threshold has been crossed.
+
+ Then return True.
+ """
+ if self.counter < self.count:
+ self.counter += 1
+ try:
+ self.go2()
+ except NameError as e:
+ raise IOError() from e
+
+ return True
+
+
+class NoIOErrorCauseAfterCount:
+ """Holds counter state for invoking a method several times in a row."""
+
+ def __init__(self, count):
+ self.counter = 0
+ self.count = count
+
+ def go2(self):
+ raise IOError("Hi there, I'm an IOError")
+
+ def go(self):
+ """Raise a NameError with an IOError as cause until after count
threshold has been crossed.
+
+ Then return True.
+ """
+ if self.counter < self.count:
+ self.counter += 1
+ try:
+ self.go2()
+ except IOError as e:
+ raise NameError() from e
+
+ return True
+
+
class NameErrorUntilCount:
"""Holds counter state for invoking a method several times in a row."""
@@ -753,6 +833,11 @@
return thing.go()
+@retry(retry=tenacity.retry_if_exception_cause_type(NameError))
+def _retryable_test_with_exception_cause_type(thing):
+ return thing.go()
+
+
@retry(retry=tenacity.retry_if_exception_type(IOError))
def _retryable_test_with_exception_type_io(thing):
return thing.go()
@@ -957,6 +1042,15 @@
s =
_retryable_test_if_not_exception_message_message.retry.statistics
self.assertTrue(s["attempt_number"] == 1)
+ def test_retry_if_exception_cause_type(self):
+
self.assertTrue(_retryable_test_with_exception_cause_type(NoNameErrorCauseAfterCount(5)))
+
+ try:
+
_retryable_test_with_exception_cause_type(NoIOErrorCauseAfterCount(5))
+ self.fail("Expected exception without NameError as cause")
+ except NameError:
+ pass
+
def test_defaults(self):
self.assertTrue(_retryable_default(NoNameErrorAfterCount(5)))
self.assertTrue(_retryable_default_f(NoNameErrorAfterCount(5)))