Hello community, here is the log from the commit of package python-tenacity for openSUSE:Factory checked in at 2018-01-13 21:47:36 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-tenacity (Old) and /work/SRC/openSUSE:Factory/.python-tenacity.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-tenacity" Sat Jan 13 21:47:36 2018 rev:4 rq:563549 version:4.8.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-tenacity/python-tenacity.changes 2017-11-11 14:20:46.828617522 +0100 +++ /work/SRC/openSUSE:Factory/.python-tenacity.new/python-tenacity.changes 2018-01-13 21:47:40.198011952 +0100 @@ -1,0 +2,23 @@ +Wed Jan 10 22:24:53 UTC 2018 - [email protected] + +- Remove repetition of license terms in description. + +------------------------------------------------------------------- +Wed Jan 10 20:48:41 UTC 2018 - [email protected] + +- update to 4.8.0 + * Allow waiters to introspect last result +- update to 4.7.1 + * Missed top level import of stop\_when\_event\_set + * Mention Tornado minimum version in README + * Fix unless\_exception test names and add no input test +- update to 4.7.0 + * Add Tornado support + * Fix pep8 +- update to 4.6.1 + * Simplify wrapping code +- update to 4.6.0 + * Implement \`retry\_with' on decorated functions +- Implement single-spec version + +------------------------------------------------------------------- Old: ---- tenacity-4.5.0.tar.gz New: ---- tenacity-4.8.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-tenacity.spec ++++++ --- /var/tmp/diff_new_pack.nfgl2p/_old 2018-01-13 21:47:40.785984540 +0100 +++ /var/tmp/diff_new_pack.nfgl2p/_new 2018-01-13 21:47:40.789984354 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-tenacity # -# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -16,29 +16,41 @@ # +%{?!python_module:%define python_module() python-%{**} python3-%{**}} +%bcond_without test Name: python-tenacity -Version: 4.5.0 +Version: 4.8.0 Release: 0 Summary: Retry code until it succeeeds License: Apache-2.0 Group: Development/Languages/Python Url: https://github.com/jd/tenacity -Source: https://pypi.io/packages/source/t/tenacity/tenacity-%{version}.tar.gz -BuildRequires: python-devel +Source: https://files.pythonhosted.org/packages/source/t/tenacity/tenacity-%{version}.tar.gz +BuildRequires: %{python_module devel} +BuildRequires: %{python_module monotonic >= 0.6} +BuildRequires: %{python_module pbr} +BuildRequires: %{python_module setuptools} +BuildRequires: %{python_module six >= 1.7.0} +BuildRequires: fdupes BuildRequires: python-futures >= 3.0 -BuildRequires: python-monotonic >= 0.6 -BuildRequires: python-pbr -BuildRequires: python-setuptools -BuildRequires: python-six >= 1.7.0 -Requires: python-futures >= 3.0 +BuildRequires: python-rpm-macros +%if %{with test} +BuildRequires: %{python_module nose} +BuildRequires: %{python_module tornado} +%endif Requires: python-monotonic >= 0.6 Requires: python-six >= 1.9.0 -BuildRoot: %{_tmppath}/%{name}-%{version}-build +Recommends: python-tornado +%ifpython2 +Requires: python-futures >= 3.0 +%endif BuildArch: noarch +%python_subpackages + %description -Tenacity is an Apache 2.0 licensed general-purpose retrying library, written in -Python, to simplify the task of adding retry behavior to just about anything. +Tenacity is a general-purpose retrying library, written in Python, to simplify +the task of adding retry behavior to just about anything. It originates from a fork of `Retrying`_ Features -------- @@ -52,15 +64,18 @@ %setup -q -n tenacity-%{version} %build -python setup.py build +%python_build %install -python setup.py install --prefix=%{_prefix} --root=%{buildroot} +%python_install +%python_expand %fdupes -s %{buildroot}%{$python_sitelib} +%if %{with test} %check -python setup.py test +%python_exec setup.py nosetests --ignore-files '.*async.py' +%endif -%files +%files %{python_files} %defattr(-,root,root,-) %doc AUTHORS ChangeLog LICENSE README.rst %{python_sitelib}/* ++++++ tenacity-4.5.0.tar.gz -> tenacity-4.8.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tenacity-4.5.0/AUTHORS new/tenacity-4.8.0/AUTHORS --- old/tenacity-4.5.0/AUTHORS 2017-10-24 10:41:17.000000000 +0200 +++ new/tenacity-4.8.0/AUTHORS 2017-12-14 09:53:45.000000000 +0100 @@ -1,8 +1,8 @@ Brian Williams <[email protected]> Brian-Williams <[email protected]> +Elisey Zanko <[email protected]> Joshua Harlow <[email protected]> Julien Danjou <[email protected]> -Mehdi Abaakouk <[email protected]> Michael Evans <[email protected]> Victor Yap <[email protected]> William Silversmith <[email protected]> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tenacity-4.5.0/ChangeLog new/tenacity-4.8.0/ChangeLog --- old/tenacity-4.5.0/ChangeLog 2017-10-24 10:41:17.000000000 +0200 +++ new/tenacity-4.8.0/ChangeLog 2017-12-14 09:53:45.000000000 +0100 @@ -1,6 +1,34 @@ CHANGES ======= +4.8.0 +----- + +* Allow waiters to introspect last result + +4.7.1 +----- + +* Missed top level import of stop\_when\_event\_set +* Mention Tornado minimum version in README +* Fix unless\_exception test names and add no input test + +4.7.0 +----- + +* Add Tornado support +* Fix pep8 + +4.6.1 +----- + +* Simplify wrapping code + +4.6.0 +----- + +* Implement \`retry\_with' on decorated functions + 4.5.0 ----- @@ -92,10 +120,3 @@ ----- * Deprecate wait\_jitter for wait\_random -* Align tox and travis settings -* Fix README typo -* Bump hacking to 0.12 -* Fix README.rst wrong description -* This is using floating point seconds (not milliseconds) -* Some small docstring updates -* Use py3.x compat print in README.rst diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tenacity-4.5.0/PKG-INFO new/tenacity-4.8.0/PKG-INFO --- old/tenacity-4.5.0/PKG-INFO 2017-10-24 10:41:17.000000000 +0200 +++ new/tenacity-4.8.0/PKG-INFO 2017-12-14 09:53:45.000000000 +0100 @@ -1,11 +1,12 @@ Metadata-Version: 1.1 Name: tenacity -Version: 4.5.0 +Version: 4.8.0 Summary: Retry code until it succeeeds Home-page: https://github.com/jd/tenacity Author: Julien Danjou Author-email: [email protected] License: UNKNOWN +Description-Content-Type: UNKNOWN Description: Tenacity ======== .. image:: https://img.shields.io/pypi/v/tenacity.svg @@ -283,8 +284,29 @@ ... - Finally, ``retry`` works also on asyncio coroutines. Sleeps are done - asynchronously too. + You can change the arguments of a retry decorator as needed when calling it by + using the `retry_with` function attached to the wrapped function: + + .. testcode:: + + @retry(stop=stop_after_attempt(3)) + def raise_my_exception(): + raise MyException("Fail") + + try: + raise_my_exception.retry_with(stop=stop_after_attempt(4))() + except Exception: + pass + + print(raise_my_exception.retry.statistics) + + .. testoutput:: + :hide: + + ... + + Finally, ``retry`` works also on asyncio and Tornado (>= 4.5) coroutines. + Sleeps are done asynchronously too. .. code-block:: python @@ -292,6 +314,13 @@ async def my_async_function(loop): await loop.getaddrinfo('8.8.8.8', 53) + .. code-block:: python + + @retry + @tornado.gen.coroutine + def my_async_function(http_client, url): + yield http_client.fetch(url) + Contribute ---------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tenacity-4.5.0/README.rst new/tenacity-4.8.0/README.rst --- old/tenacity-4.5.0/README.rst 2017-10-24 10:40:34.000000000 +0200 +++ new/tenacity-4.8.0/README.rst 2017-12-14 09:53:01.000000000 +0100 @@ -275,8 +275,29 @@ ... -Finally, ``retry`` works also on asyncio coroutines. Sleeps are done -asynchronously too. +You can change the arguments of a retry decorator as needed when calling it by +using the `retry_with` function attached to the wrapped function: + +.. testcode:: + + @retry(stop=stop_after_attempt(3)) + def raise_my_exception(): + raise MyException("Fail") + + try: + raise_my_exception.retry_with(stop=stop_after_attempt(4))() + except Exception: + pass + + print(raise_my_exception.retry.statistics) + +.. testoutput:: + :hide: + + ... + +Finally, ``retry`` works also on asyncio and Tornado (>= 4.5) coroutines. +Sleeps are done asynchronously too. .. code-block:: python @@ -284,6 +305,13 @@ async def my_async_function(loop): await loop.getaddrinfo('8.8.8.8', 53) +.. code-block:: python + + @retry + @tornado.gen.coroutine + def my_async_function(http_client, url): + yield http_client.fetch(url) + Contribute ---------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tenacity-4.5.0/doc/source/index.rst new/tenacity-4.8.0/doc/source/index.rst --- old/tenacity-4.5.0/doc/source/index.rst 2017-10-24 10:40:34.000000000 +0200 +++ new/tenacity-4.8.0/doc/source/index.rst 2017-12-14 09:53:01.000000000 +0100 @@ -275,8 +275,29 @@ ... -Finally, ``retry`` works also on asyncio coroutines. Sleeps are done -asynchronously too. +You can change the arguments of a retry decorator as needed when calling it by +using the `retry_with` function attached to the wrapped function: + +.. testcode:: + + @retry(stop=stop_after_attempt(3)) + def raise_my_exception(): + raise MyException("Fail") + + try: + raise_my_exception.retry_with(stop=stop_after_attempt(4))() + except Exception: + pass + + print(raise_my_exception.retry.statistics) + +.. testoutput:: + :hide: + + ... + +Finally, ``retry`` works also on asyncio and Tornado (>= 4.5) coroutines. +Sleeps are done asynchronously too. .. code-block:: python @@ -284,6 +305,13 @@ async def my_async_function(loop): await loop.getaddrinfo('8.8.8.8', 53) +.. code-block:: python + + @retry + @tornado.gen.coroutine + def my_async_function(http_client, url): + yield http_client.fetch(url) + Contribute ---------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tenacity-4.5.0/tenacity/__init__.py new/tenacity-4.8.0/tenacity/__init__.py --- old/tenacity-4.5.0/tenacity/__init__.py 2017-10-24 10:40:34.000000000 +0200 +++ new/tenacity-4.8.0/tenacity/__init__.py 2017-12-14 09:53:01.000000000 +0100 @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +# Copyright 2017 Elisey Zanko # Copyright 2016 Étienne Bersac # Copyright 2016 Julien Danjou # Copyright 2016 Joshua Harlow @@ -21,13 +22,23 @@ except ImportError: asyncio = None +try: + import tornado +except ImportError: + tornado = None + +import inspect import sys import threading - from concurrent import futures + from monotonic import monotonic as now + import six +from tenacity import _utils +from tenacity import wait as _wait + # Import all built-in retry strategies for easier usage. from .retry import retry_all # noqa from .retry import retry_always # noqa @@ -49,6 +60,7 @@ from .stop import stop_all # noqa from .stop import stop_any # noqa from .stop import stop_never # noqa +from .stop import stop_when_event_set # noqa # Import all built-in wait strategies for easier usage. from .wait import wait_chain # noqa @@ -69,8 +81,6 @@ from .after import after_log # noqa from .after import after_nothing # noqa -from tenacity import _utils - def retry(*dargs, **dkw): """Wrap a function with a new `Retrying` object. @@ -85,6 +95,8 @@ def wrap(f): if asyncio and asyncio.iscoroutinefunction(f): r = AsyncRetrying(*dargs, **dkw) + elif tornado and tornado.gen.is_coroutine_function(f): + r = TornadoRetrying(*dargs, **dkw) else: r = Retrying(*dargs, **dkw) @@ -108,6 +120,9 @@ pass +_unset = object() + + class BaseRetrying(object): def __init__(self, @@ -125,6 +140,32 @@ self.after = after self.reraise = reraise self._local = threading.local() + # This will allow for passing in the result and handling + # the older versions of these functions that do not take + # the prior result. + self._wait_takes_result = self._waiter_takes_last_result(wait) + + def copy(self, sleep=_unset, stop=_unset, wait=_unset, + retry=_unset, before=_unset, after=_unset, reraise=_unset): + """Copy this object with some parameters changed if needed.""" + return self.__class__( + sleep=self.sleep if sleep is _unset else sleep, + stop=self.stop if stop is _unset else stop, + wait=self.wait if wait is _unset else wait, + retry=self.retry if retry is _unset else retry, + before=self.before if before is _unset else before, + after=self.after if after is _unset else after, + reraise=self.reraise if after is _unset else reraise, + ) + + @staticmethod + def _waiter_takes_last_result(waiter): + if not six.callable(waiter): + return False + if isinstance(waiter, _wait.wait_base): + waiter = waiter.__call__ + waiter_spec = inspect.getargspec(waiter) + return 'last_result' in waiter_spec.args def __repr__(self): attrs = dict( @@ -171,7 +212,13 @@ @six.wraps(f) def wrapped_f(*args, **kw): return self.call(f, *args, **kw) + + def retry_with(*args, **kwargs): + return self.copy(*args, **kwargs).wraps(f) + wrapped_f.retry = self + wrapped_f.retry_with = retry_with + return wrapped_f def begin(self, fn): @@ -219,8 +266,12 @@ six.raise_from(RetryError(fut), fut.exception()) if self.wait: - sleep = self.wait(self.statistics['attempt_number'], - delay_since_first_attempt) + if self._wait_takes_result: + sleep = self.wait(self.statistics['attempt_number'], + delay_since_first_attempt, last_result=fut) + else: + sleep = self.wait(self.statistics['attempt_number'], + delay_since_first_attempt) else: sleep = 0 self.statistics['idle_for'] += sleep @@ -299,3 +350,6 @@ if asyncio: from tenacity.async import AsyncRetrying + +if tornado: + from tenacity.tornadoweb import TornadoRetrying diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tenacity-4.5.0/tenacity/tests/test_tenacity.py new/tenacity-4.8.0/tenacity/tests/test_tenacity.py --- old/tenacity-4.5.0/tenacity/tests/test_tenacity.py 2017-10-24 10:40:34.000000000 +0200 +++ new/tenacity-4.8.0/tenacity/tests/test_tenacity.py 2017-12-14 09:53:01.000000000 +0100 @@ -175,6 +175,24 @@ def test_legacy_explicit_wait_type(self): Retrying(wait="exponential_sleep") + def test_wait_func_result(self): + captures = [] + + def wait_capture(attempt, delay, last_result=None): + captures.append(last_result) + return 1 + + def dying(): + raise Exception("Broken") + + r_attempts = 10 + r = Retrying(wait=wait_capture, sleep=lambda secs: None, + stop=tenacity.stop_after_attempt(r_attempts), + reraise=True) + self.assertRaises(Exception, r.call, dying) + self.assertEqual(r_attempts - 1, len(captures)) + self.assertTrue(all([r.failed for r in captures])) + def test_wait_func(self): r = Retrying(wait=lambda attempt, delay: attempt * delay) self.assertEqual(r.wait(1, 5), 5) @@ -525,14 +543,19 @@ @retry(retry=tenacity.retry_unless_exception_type(NameError)) -def _retryable_test_with_not_exception_type_name(thing): +def _retryable_test_with_unless_exception_type_name(thing): return thing.go() @retry( stop=tenacity.stop_after_attempt(3), retry=tenacity.retry_unless_exception_type(NameError)) -def _retryable_test_with_not_exception_type_name_attempt_limit(thing): +def _retryable_test_with_unless_exception_type_name_attempt_limit(thing): + return thing.go() + + +@retry(retry=tenacity.retry_unless_exception_type()) +def _retryable_test_with_unless_exception_type_no_input(thing): return thing.go() @@ -567,6 +590,14 @@ self.assertGreaterEqual(t, 250) self.assertTrue(result) + def test_retry_with(self): + start = current_time_ms() + result = _retryable_test_with_wait.retry_with( + wait=tenacity.wait_fixed(0.1))(NoneReturnUntilAfterCount(5)) + t = current_time_ms() - start + self.assertGreaterEqual(t, 500) + self.assertTrue(result) + def test_with_stop_on_return_value(self): try: _retryable_test_with_stop(NoneReturnUntilAfterCount(5)) @@ -609,10 +640,26 @@ def test_retry_until_exception_of_type_attempt_number(self): try: - self.assertTrue(_retryable_test_with_not_exception_type_name( + self.assertTrue(_retryable_test_with_unless_exception_type_name( NameErrorUntilCount(5))) except NameError as e: - s = _retryable_test_with_not_exception_type_name.retry.statistics + s = _retryable_test_with_unless_exception_type_name.\ + retry.statistics + self.assertTrue(s['attempt_number'] == 6) + print(e) + else: + self.fail("Expected NameError") + + def test_retry_until_exception_of_type_no_type(self): + try: + # no input should catch all subclasses of Exception + self.assertTrue( + _retryable_test_with_unless_exception_type_no_input( + NameErrorUntilCount(5)) + ) + except NameError as e: + s = _retryable_test_with_unless_exception_type_no_input.\ + retry.statistics self.assertTrue(s['attempt_number'] == 6) print(e) else: @@ -621,7 +668,7 @@ def test_retry_until_exception_of_type_wrong_exception(self): try: # two iterations with IOError, one that returns True - _retryable_test_with_not_exception_type_name_attempt_limit( + _retryable_test_with_unless_exception_type_name_attempt_limit( IOErrorUntilCount(2)) self.fail("Expected RetryError") except RetryError as e: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tenacity-4.5.0/tenacity/tests/test_tornado.py new/tenacity-4.8.0/tenacity/tests/test_tornado.py --- old/tenacity-4.5.0/tenacity/tests/test_tornado.py 1970-01-01 01:00:00.000000000 +0100 +++ new/tenacity-4.8.0/tenacity/tests/test_tornado.py 2017-12-14 09:53:01.000000000 +0100 @@ -0,0 +1,46 @@ +# coding: utf-8 +# Copyright 2017 Elisey Zanko +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# 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 unittest + +from tenacity import retry +from tenacity import tornadoweb +from tenacity.tests.test_tenacity import NoIOErrorAfterCount + +from tornado import gen +from tornado import testing + + +@retry [email protected] +def _retryable_coroutine(thing): + yield gen.sleep(0.00001) + thing.go() + + +class TestTornado(testing.AsyncTestCase): + @testing.gen_test + def test_retry(self): + assert gen.is_coroutine_function(_retryable_coroutine) + thing = NoIOErrorAfterCount(5) + yield _retryable_coroutine(thing) + assert thing.counter == thing.count + + def test_repr(self): + repr(tornadoweb.TornadoRetrying()) + + +if __name__ == '__main__': + unittest.main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tenacity-4.5.0/tenacity/tornadoweb.py new/tenacity-4.8.0/tenacity/tornadoweb.py --- old/tenacity-4.5.0/tenacity/tornadoweb.py 1970-01-01 01:00:00.000000000 +0100 +++ new/tenacity-4.8.0/tenacity/tornadoweb.py 2017-12-14 09:53:01.000000000 +0100 @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Elisey Zanko +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# 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 sys + +from monotonic import monotonic as now + +from tenacity import BaseRetrying +from tenacity import DoAttempt +from tenacity import DoSleep +from tenacity import NO_RESULT + +from tornado import gen + + +class TornadoRetrying(BaseRetrying): + + def __init__(self, + sleep=gen.sleep, + **kwargs): + super(TornadoRetrying, self).__init__(**kwargs) + self.sleep = sleep + + @gen.coroutine + def call(self, fn, *args, **kwargs): + self.begin(fn) + + result = NO_RESULT + exc_info = None + start_time = now() + + while True: + do = self.iter(result=result, exc_info=exc_info, + start_time=start_time) + if isinstance(do, DoAttempt): + try: + result = yield fn(*args, **kwargs) + exc_info = None + continue + except Exception: + result = NO_RESULT + exc_info = sys.exc_info() + continue + elif isinstance(do, DoSleep): + result = NO_RESULT + exc_info = None + yield self.sleep(do) + else: + raise gen.Return(do) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tenacity-4.5.0/tenacity/wait.py new/tenacity-4.8.0/tenacity/wait.py --- old/tenacity-4.5.0/tenacity/wait.py 2017-10-24 10:40:34.000000000 +0200 +++ new/tenacity-4.8.0/tenacity/wait.py 2017-12-14 09:53:01.000000000 +0100 @@ -27,7 +27,8 @@ """Abstract base class for wait strategies.""" @abc.abstractmethod - def __call__(self, previous_attempt_number, delay_since_first_attempt): + def __call__(self, previous_attempt_number, delay_since_first_attempt, + last_result=None): pass def __add__(self, other): @@ -46,7 +47,8 @@ def __init__(self, wait): self.wait_fixed = wait - def __call__(self, previous_attempt_number, delay_since_first_attempt): + def __call__(self, previous_attempt_number, delay_since_first_attempt, + last_result=None): return self.wait_fixed @@ -64,7 +66,8 @@ self.wait_random_min = min self.wait_random_max = max - def __call__(self, previous_attempt_number, delay_since_first_attempt): + def __call__(self, previous_attempt_number, delay_since_first_attempt, + last_result=None): return (self.wait_random_min + (random.random() * (self.wait_random_max - self.wait_random_min))) @@ -76,7 +79,8 @@ def __init__(self, *strategies): self.wait_funcs = strategies - def __call__(self, previous_attempt_number, delay_since_first_attempt): + def __call__(self, previous_attempt_number, delay_since_first_attempt, + last_result=None): return sum(map( lambda x: x(previous_attempt_number, delay_since_first_attempt), self.wait_funcs)) @@ -101,7 +105,8 @@ def __init__(self, *strategies): self.strategies = list(strategies) - def __call__(self, previous_attempt_number, delay_since_first_attempt): + def __call__(self, previous_attempt_number, delay_since_first_attempt, + last_result=None): wait_func = self.strategies[0] if len(self.strategies) > 1: self.strategies.pop(0) @@ -120,7 +125,8 @@ self.increment = increment self.max = max - def __call__(self, previous_attempt_number, delay_since_first_attempt): + def __call__(self, previous_attempt_number, delay_since_first_attempt, + last_result=None): result = self.start + ( self.increment * (previous_attempt_number - 1) ) @@ -145,7 +151,8 @@ self.max = max self.exp_base = exp_base - def __call__(self, previous_attempt_number, delay_since_first_attempt): + def __call__(self, previous_attempt_number, delay_since_first_attempt, + last_result=None): try: exp = self.exp_base ** previous_attempt_number result = self.multiplier * exp @@ -179,7 +186,8 @@ wait_exponential strategy (which uses a fixed interval) may be preferable. """ - def __call__(self, previous_attempt_number, delay_since_first_attempt): + def __call__(self, previous_attempt_number, delay_since_first_attempt, + last_result=None): high = super(wait_random_exponential, self).__call__( previous_attempt_number, delay_since_first_attempt) return random.uniform(0, high) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tenacity-4.5.0/tenacity.egg-info/PKG-INFO new/tenacity-4.8.0/tenacity.egg-info/PKG-INFO --- old/tenacity-4.5.0/tenacity.egg-info/PKG-INFO 2017-10-24 10:41:17.000000000 +0200 +++ new/tenacity-4.8.0/tenacity.egg-info/PKG-INFO 2017-12-14 09:53:45.000000000 +0100 @@ -1,11 +1,12 @@ Metadata-Version: 1.1 Name: tenacity -Version: 4.5.0 +Version: 4.8.0 Summary: Retry code until it succeeeds Home-page: https://github.com/jd/tenacity Author: Julien Danjou Author-email: [email protected] License: UNKNOWN +Description-Content-Type: UNKNOWN Description: Tenacity ======== .. image:: https://img.shields.io/pypi/v/tenacity.svg @@ -283,8 +284,29 @@ ... - Finally, ``retry`` works also on asyncio coroutines. Sleeps are done - asynchronously too. + You can change the arguments of a retry decorator as needed when calling it by + using the `retry_with` function attached to the wrapped function: + + .. testcode:: + + @retry(stop=stop_after_attempt(3)) + def raise_my_exception(): + raise MyException("Fail") + + try: + raise_my_exception.retry_with(stop=stop_after_attempt(4))() + except Exception: + pass + + print(raise_my_exception.retry.statistics) + + .. testoutput:: + :hide: + + ... + + Finally, ``retry`` works also on asyncio and Tornado (>= 4.5) coroutines. + Sleeps are done asynchronously too. .. code-block:: python @@ -292,6 +314,13 @@ async def my_async_function(loop): await loop.getaddrinfo('8.8.8.8', 53) + .. code-block:: python + + @retry + @tornado.gen.coroutine + def my_async_function(http_client, url): + yield http_client.fetch(url) + Contribute ---------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tenacity-4.5.0/tenacity.egg-info/SOURCES.txt new/tenacity-4.8.0/tenacity.egg-info/SOURCES.txt --- old/tenacity-4.5.0/tenacity.egg-info/SOURCES.txt 2017-10-24 10:41:17.000000000 +0200 +++ new/tenacity-4.8.0/tenacity.egg-info/SOURCES.txt 2017-12-14 09:53:45.000000000 +0100 @@ -17,6 +17,7 @@ tenacity/nap.py tenacity/retry.py tenacity/stop.py +tenacity/tornadoweb.py tenacity/wait.py tenacity.egg-info/PKG-INFO tenacity.egg-info/SOURCES.txt @@ -27,4 +28,5 @@ tenacity.egg-info/top_level.txt tenacity/tests/__init__.py tenacity/tests/test_async.py -tenacity/tests/test_tenacity.py \ No newline at end of file +tenacity/tests/test_tenacity.py +tenacity/tests/test_tornado.py \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tenacity-4.5.0/tenacity.egg-info/pbr.json new/tenacity-4.8.0/tenacity.egg-info/pbr.json --- old/tenacity-4.5.0/tenacity.egg-info/pbr.json 2017-10-24 10:41:17.000000000 +0200 +++ new/tenacity-4.8.0/tenacity.egg-info/pbr.json 2017-12-14 09:53:45.000000000 +0100 @@ -1 +1 @@ -{"git_version": "a86237f", "is_release": true} \ No newline at end of file +{"git_version": "69cf4a7", "is_release": true} \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tenacity-4.5.0/tox.ini new/tenacity-4.8.0/tox.ini --- old/tenacity-4.5.0/tox.ini 2017-10-24 10:40:34.000000000 +0200 +++ new/tenacity-4.8.0/tox.ini 2017-12-14 09:53:01.000000000 +0100 @@ -13,6 +13,7 @@ deps = nose sphinx + tornado commands = py{27,py}: python setup.py nosetests --ignore-files '.*async.py' py3{5,6}: python setup.py nosetests
