[Python-modules-commits] [python-tenacity] 01/05: Import python-tenacity_4.4.0.orig.tar.gz
Ondrej Koblizek
kobla-guest at moszumanska.debian.org
Sun Aug 6 02:45:43 UTC 2017
This is an automated email from the git hooks/post-receive script.
kobla-guest pushed a commit to branch master
in repository python-tenacity.
commit 09a438ca11c118b53dbc5c91a722b41710471fdb
Author: Ondřej Kobližek <ondrej.koblizek at firma.seznam.cz>
Date: Sat Aug 5 20:00:07 2017 -0400
Import python-tenacity_4.4.0.orig.tar.gz
---
.gitignore | 9 -
.travis.yml | 7 +-
AUTHORS | 27 +++
ChangeLog | 261 ++++++++++++++++++++++++++++
MANIFEST.in | 1 -
NOTICE | 13 --
PKG-INFO | 301 +++++++++++++++++++++++++++++++++
README.rst | 283 ++++++++++++++++++++++++++++++-
doc/source/index.rst | 133 +++++++++++----
requirements.txt | 2 +-
setup.cfg | 31 ++--
tenacity.egg-info/PKG-INFO | 301 +++++++++++++++++++++++++++++++++
tenacity.egg-info/SOURCES.txt | 30 ++++
tenacity.egg-info/dependency_links.txt | 1 +
tenacity.egg-info/not-zip-safe | 1 +
tenacity.egg-info/pbr.json | 1 +
tenacity.egg-info/requires.txt | 3 +
tenacity.egg-info/top_level.txt | 1 +
tenacity/__init__.py | 221 ++++++++++++++++--------
tenacity/after.py | 8 +-
tenacity/async.py | 56 ++++++
tenacity/{after.py => nap.py} | 26 +--
tenacity/retry.py | 79 ++++++++-
tenacity/stop.py | 65 ++++++-
tenacity/tests/test_async.py | 53 ++++++
tenacity/tests/test_tenacity.py | 281 +++++++++++++++++++++++++++++-
tenacity/wait.py | 78 +++++++--
tox.ini | 16 +-
28 files changed, 2092 insertions(+), 197 deletions(-)
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 151b766..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,9 +0,0 @@
-.idea
-dist
-*.pyc
-*.egg-info
-build
-.tox/
-AUTHORS
-ChangeLog
-.eggs/
diff --git a/.travis.yml b/.travis.yml
index 6af8e93..7ddeb0f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,10 +4,9 @@ python:
- 2.7
- 3.4
- 3.5
+ - 3.6
- pypy
-install: pip install tox nose
+install: pip install tox tox-travis nose
-script:
- - tox -e pep8
- - python setup.py nosetests
+script: tox
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..9596023
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,27 @@
+Alex Kuang <akuang at bizo.com>
+Boden R <bodenvmw at gmail.com>
+Brian Williams <brian.williams at actifio.com>
+Brian-Williams <Brian-Williams at users.noreply.github.com>
+Cyrus Durgin <cyrus at statelessnetworks.com>
+Daniel Nephin <dnephin at yelp.com>
+Derek Wilson <dwilson at domaintools.com>
+Gevorg Davoian <gdavoian at mirantis.com>
+Haïkel Guémar <hguemar at fedoraproject.org>
+Jonathan Herriott <jherriott at bitcasa.com>
+Joshua Harlow <harlowja at gmail.com>
+Joshua Harlow <harlowja at yahoo-inc.com>
+Joshua Harlow <jxharlow at godaddy.com>
+Julien Danjou <julien at danjou.info>
+Mehdi Abaakouk <sileht at sileht.net>
+Michael Evans <michael.evans at mwrinfosecurity.com>
+Monty Taylor <mordred at inaugust.com>
+Ray Holder <ray.holder+github at gmail.com>
+Ray Holder <ray at blacklocus.com>
+Ryan Peck <ryan at rypeck.com>
+Saul Shanabrook <s.shanabrook at gmail.com>
+Simeon Visser <svisser at users.noreply.github.com>
+Simon Dollé <simon.dolle at gmail.com>
+William Silversmith <william.silversmith at gmail.com>
+Zane Bitter <zbitter at redhat.com>
+cyrus durgin <cyrusd at gmail.com>
+Étienne BERSAC (bersace) <etienne.bersac at people-doc.com>
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..67b9151
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,261 @@
+CHANGES
+=======
+
+4.4.0
+-----
+
+* Document wait\_random\_exponential strategy
+* Rename wait\_full\_jitter to wait\_random\_exponential
+
+4.3.0
+-----
+
+* Add retry\_unless\_exception\_type
+* Add missing ')' to README.rst
+* Do not duplicate statistics fields in instance
+* Do not start trial\_start\_time as an attribute
+* Add an example on how to combine stop conditions
+
+4.2.0
+-----
+
+* Put a link to the GitHub issue of retrying about the fork
+* feat: added wait\_full\_jitter
+* Add new event based sleep and stop
+* Add \`wraps' method directly on Retrying object
+
+4.1.0
+-----
+
+* wait: handle OverflowError
+* doc: raise Exception in example so they actually work
+* Remove weird example with retry\_if\_io\_error
+* Bump version for new feature
+* Add Python 3.6 support
+* Add retry\_if\_not\_result class to compliment the existing retry\_if\_result class
+
+4.0.1
+-----
+
+* Fix six minimum version
+* doc: rewrite the before explanation
+
+4.0.0
+-----
+
+* Add \_\_call\_\_ on BaseRetrying class
+* Document before and after keywords
+* Remove useless MANIFEST
+* Remove non-working PyPI download image
+* Bump hacking to 0.13
+* Use Python 3 for pep8 tox target
+* Remove deprecated wait\_jitter
+
+3.7.1
+-----
+
+* Fix pep8 errors
+
+3.7.0
+-----
+
+* Correctly set the exception if we TryAgain for ever
+
+3.6.0
+-----
+
+* Retry on coroutines
+* Run flake8 only with latest python
+* Deduplicate retry decorator logic
+* Extract controller IOs in subclass
+
+3.5.0
+-----
+
+* Allow to combine stop conditions
+* Add SayThanks
+* retry: implement bitwise operators on retry strategies
+* retry: add retry\_all
+
+3.4.0
+-----
+
+* 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
+* Fix typo in retry\_if\_exception example
+
+3.3.0
+-----
+
+* Implement '+' operator for wait strategies
+
+3.2.1
+-----
+
+* Initialize statistics at runtime
+
+3.2.0
+-----
+
+* Rename \`\_retrying\` attribute to \`retry\` and document it
+* Store retrying object as an attribute of retried function
+* Make sure statistics are thread locals
+* Remove NOTICE file
+
+3.1.1
+-----
+
+* Fix reraise when no exception
+
+3.1.0
+-----
+
+* Add support for reraise
+* doc: fix text legend for retry\_if\_result
+* Add a useful \_\_repr\_\_
+
+3.0.0
+-----
+
+* wait: fix wait\_random to return floating point numbers
+* Remove milliseconds usage in modules
+* Stop using millisecond values for callbacks
+* Add pbr generated files to ignore list
+
+2.0.0
+-----
+
+* Use seconds everywhere instead of miliseconds
+* Fix retry\_if\_exception\_type usage in doc
+* Add and use a nice ordinal func when logging before/after
+* Add before/after strategies
+* Add wait\_chain()
+* Add basic stats
+* Fix comment stating rejection
+* Rename reject to retry
+* Enable pep8 checks on Travis
+* Remove Python 2.6 support
+* Fix pep8 errors
+* Move to a folder structure
+* Remove dead versions of py 3.x
+* Allow to raise TryAgain to force a retry at any time
+* Use monotonic time
+* Fix doc with retry\_if\_exception\_type
+* Add retry\_if\_exception(predicate)
+* Rename retry\_if\_exceptino to retry\_if\_exception\_type
+* Remove dead code
+* Use futures
+* Add docstring on wait\_jitter
+* Allow to specify exp\_base
+* Simplify wait min/max computing
+* test: add test for RetryError.\_\_str\_\_
+* Always wrap exceptions
+* Add project name in doc
+* Add .tox to .gitignore
+* Add doc
+* Remove retry select strategy, use a functional composition approach
+* test: replace assertTrue by assertGreaterEqual
+* Make stop have a default value
+* Make README doc8 compliant
+* Allow to specify sleep function
+* Implement wait strategy combination to replace jitter argument
+* Fix typo in README
+* Simplify wait strategy picking by forcing a func in kwargs
+* Fix stop examples in README
+* Simplify stop strategy picking by always requiring a function
+* Add some copyrights
+* Depends on nose in tox
+* Move some methods to staticmethods
+* Fix tox command
+* Fix pep8 errors
+* Add tox.ini
+* Switch to pbr
+* Rename to tenacity
+* Update README
+* Remove AUTHORS
+* Remove HISTORY.rst
+* Declutter \_\_init\_\_ by using strategy selection
+* Dynamically compute MAX\_WAIT
+* Add Python 3.5
+* updated
+* Adds two additional parameters to the Retrying() constructor:
+* Add a upper bound on incrementing wait
+* Allow providing exception tuple for 'retry\_on\_exception' argument
+* bump version up to 1.3.4-dev, align badges in README.rst with a service that still works
+* Declare a few methods static
+* prepare for 1.3.3 release
+* update history for 1.3.3 release
+* add a few more contributors
+* Adding in minimum version since anything lower doesn't work
+* prepare for 1.3.2 release
+* remove six license boilerplate since we're not embedding it anymore
+* update HISTORY.rst for 1.3.2
+* adding Maxym Shalenyi to AUTHORS.rst
+* fix up some some pep8 stuff
+* bump version up to 1.3.2-dev
+* Allow a jitter value to be passed in
+* Ensure we wrap the decorated functions
+* Add requirements.txt to MANFEST.in
+* prepare for 1.3.0 release
+* update AUTHORS.rst to add contributors
+* Replaced bundled code with using six
+* update AUTHORS.rst
+* bump version up to 1.2.4-dev
+* Ensure file handles are closed using with statement
+* prepare for 1.2.3 release
+* add Daniel Nephin to AUTHORS.rst
+* Support custom wait and stop functions
+* bump version to 1.2.3-dev, add 3.3/3.4 classifiers
+* add Saul Shanabrook to AUTHORS.rst
+* Add python 3.3 and 3.4 support
+* prepare for 1.2.2 release
+* update HISTORY.rst for 1.2.2 release
+* add comments from rdooley, add comment around stop behavior
+* Update AUTHORS.rst
+* If possible, raise the last exception when stopping
+* Test exception type on failure
+* bump version up to 1.2.2-dev
+* update HISTORY.rst, bump version up to 1.2.1 for release
+* Fix AttributeError when explicitly specifying wait type, and add appropriate regression tests. (fixes #4)
+* update HISTORY.rst for 1.2.0 release
+* prepare for 1.2.0 release
+* add a crude check for a custom exception message in the test suite
+* remove need for specification of stop/wait type
+* prepare for 1.1.0 release
+* Update HISTORY.rst
+* add even moar Python 3.x compatibility hacks from the six project, update license
+* let's see if Python 3.2.x is happy now..
+* Fix up Python 2.6 and Python 3.2 compatibility
+* propagate complete tracebacks such that they show up in nested stack frames, adjust api and tests #1
+* adding version and download badges
+* clean up the classifiers so they appear correctly on pypi, add license metadata, prep for release
+* add note about Python 2.x/3.x compatibility and patch up test suite to run under Python 3
+* fixed a bug where classes not extending from the Python exception hierarchy could slip through, preparing for 1.0.1 release
+* add missing files..
+* typo... um... yeah..
+* clean up RST for PyPI, add some better annotations to examples
+* Python 3.2 compatibility fix, since we don't have sys.maxint anymore..
+* sanitize setup.py one more time before release
+* add a few more tests for some edge cases
+* add configurable support for wrapping any raised Exception in a RetryError instead of just raising it directly, add a few more comments
+* stop committing nonsense examples..
+* add a bunch of examples since they're more succinct than a full api description
+* adding AUTHORS.rst
+* flushing out the README.rst a bit more
+* default to retry on any exception, handle @retry and @retry() behavior
+* update history
+* add test suite, clean up packaging
+* ignore packaging and pyc's
+* add Travis CI support
+* drop in an \_\_init\_\_.py
+* adding HISTORY.rst
+* clean up some TODO's and comments
+* adding first stable implementation, reasonable passing test coverage
+* add minimal readme
+* add license and other project boilerplate
diff --git a/MANIFEST.in b/MANIFEST.in
deleted file mode 100644
index 5602966..0000000
--- a/MANIFEST.in
+++ /dev/null
@@ -1 +0,0 @@
-include README.rst HISTORY.rst AUTHORS.rst LICENSE NOTICE requirements.txt
diff --git a/NOTICE b/NOTICE
deleted file mode 100644
index 18434bc..0000000
--- a/NOTICE
+++ /dev/null
@@ -1,13 +0,0 @@
-Copyright 2013 Ray Holder
-
-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.
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..0aa8f2c
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,301 @@
+Metadata-Version: 1.1
+Name: tenacity
+Version: 4.4.0
+Summary: Retry code until it succeeeds
+Home-page: https://github.com/jd/tenacity
+Author: Julien Danjou
+Author-email: julien at danjou.info
+License: UNKNOWN
+Description: Tenacity
+ ========
+ .. image:: https://img.shields.io/pypi/v/tenacity.svg
+ :target: https://pypi.python.org/pypi/tenacity
+
+ .. image:: https://img.shields.io/travis/jd/tenacity.svg
+ :target: https://travis-ci.org/jd/tenacity
+
+ .. image:: https://img.shields.io/badge/SayThanks.io-%E2%98%BC-1EAEDB.svg
+ :target: https://saythanks.io/to/jd
+
+ 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.
+ It originates from `a fork of retrying
+ <https://github.com/rholder/retrying/issues/65>`_.
+
+ The simplest use case is retrying a flaky function whenever an `Exception`
+ occurs until a value is returned.
+
+ .. code-block:: python
+
+ import random
+ from tenacity import retry
+
+ @retry
+ def do_something_unreliable():
+ if random.randint(0, 10) > 1:
+ raise IOError("Broken sauce, everything is hosed!!!111one")
+ else:
+ return "Awesome sauce!"
+
+ print(do_something_unreliable())
+
+
+ Features
+ --------
+
+ - Generic Decorator API
+ - Specify stop condition (i.e. limit by number of attempts)
+ - Specify wait condition (i.e. exponential backoff sleeping between attempts)
+ - Customize retrying on Exceptions
+ - Customize retrying on expected returned result
+ - Retry on coroutines
+
+
+ Installation
+ ------------
+
+ To install *tenacity*, simply:
+
+ .. code-block:: bash
+
+ $ pip install tenacity
+
+
+ Examples
+ ----------
+
+ As you saw above, the default behavior is to retry forever without waiting when
+ an exception is raised.
+
+ .. code-block:: python
+
+ @retry
+ def never_give_up_never_surrender():
+ print("Retry forever ignoring Exceptions, don't wait between retries")
+ raise Exception
+
+ Let's be a little less persistent and set some boundaries, such as the number
+ of attempts before giving up.
+
+ .. code-block:: python
+
+ @retry(stop=stop_after_attempt(7))
+ def stop_after_7_attempts():
+ print("Stopping after 7 attempts")
+ raise Exception
+
+ We don't have all day, so let's set a boundary for how long we should be
+ retrying stuff.
+
+ .. code-block:: python
+
+ @retry(stop=stop_after_delay(10))
+ def stop_after_10_s():
+ print("Stopping after 10 seconds")
+ raise Exception
+
+ You can combine several stop conditions by using the `|` operator:
+
+ .. code-block:: python
+
+ @retry(stop=(stop_after_delay(10) | stop_after_attempt(5)))
+ def stop_after_10_s_or_5_retries():
+ print("Stopping after 10 seconds or 5 retries")
+ raise Exception
+
+ Most things don't like to be polled as fast as possible, so let's just wait 2
+ seconds between retries.
+
+ .. code-block:: python
+
+ @retry(wait=wait_fixed(2))
+ def wait_2_s():
+ print("Wait 2 second between retries")
+ raise Exception
+
+ Some things perform best with a bit of randomness injected.
+
+ .. code-block:: python
+
+ @retry(wait=wait_random(min=1, max=2))
+ def wait_random_1_to_2_s():
+ print("Randomly wait 1 to 2 seconds between retries")
+ raise Exception
+
+ Then again, it's hard to beat exponential backoff when retrying distributed
+ services and other remote endpoints.
+
+ .. code-block:: python
+
+ @retry(wait=wait_exponential(multiplier=1, max=10))
+ def wait_exponential_1():
+ print("Wait 2^x * 1 second between each retry, up to 10 seconds, then 10 seconds afterwards")
+ raise Exception
+
+
+ Then again, it's also hard to beat combining fixed waits and jitter (to
+ help avoid thundering herds) when retrying distributed services and other
+ remote endpoints.
+
+ .. code-block:: python
+
+ @retry(wait=wait_fixed(3) + wait_random(0, 2))
+ def wait_fixed_jitter():
+ print("Wait at least 3 seconds, and add up to 2 seconds of random delay")
+ raise Exception
+
+ When multiple processes are in contention for a shared resource, exponentially
+ increasing jitter helps minimise collisions.
+
+ .. code-block:: python
+
+ @retry(wait=wait_random_exponential(multiplier=1, max=60))
+ def wait_exponential_jitter():
+ print("Randomly wait up to 2^x * 1 seconds between each retry until the range reaches 60 seconds, then randomly up to 60 seconds afterwards")
+ raise Exception
+
+
+ Sometimes it's necessary to build a chain of backoffs.
+
+ .. code-block:: python
+
+ @retry(wait=wait_chain(*[wait_fixed(3) for i in range(3)] +
+ [wait_fixed(7) for i in range(2)] +
+ [wait_fixed(9)]))
+ def wait_fixed_chained():
+ print("Wait 3s for 3 attempts, 7s for the next 2 attempts and 9s for all attempts thereafter")
+ raise Exception
+
+ We have a few options for dealing with retries that raise specific or general
+ exceptions, as in the cases here.
+
+ .. code-block:: python
+
+ @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")
+ retry Exception
+
+ We can also use the result of the function to alter the behavior of retrying.
+
+ .. code-block:: python
+
+ def is_none_p(value):
+ """Return True if value is None"""
+ return value is None
+
+ @retry(retry=retry_if_result(is_none_p))
+ def might_return_none():
+ print("Retry with no wait if return value is None")
+
+ We can also combine several conditions:
+
+ .. code-block:: python
+
+ def is_none_p(value):
+ """Return True if value is None"""
+ return value is None
+
+ @retry(retry=(retry_if_result(is_none_p) | retry_if_exception_type()))
+ def might_return_none():
+ print("Retry forever ignoring Exceptions with no wait if return value is None")
+
+ Any combination of stop, wait, etc. is also supported to give you the freedom
+ to mix and match.
+
+ It's also possible to retry explicitly at any time by raising the `TryAgain`
+ exception:
+
+ .. code-block:: python
+
+ @retry
+ def do_something():
+ result = something_else()
+ if result == 23:
+ raise TryAgain
+
+ While callables that "timeout" retrying raise a `RetryError` by default,
+ we can reraise the last attempt's exception if needed:
+
+ .. code-block:: python
+
+ @retry(reraise=True, stop=stop_after_attempt(3))
+ def raise_my_exception():
+ raise MyException("Fail")
+
+ try:
+ raise_my_exception()
+ except MyException:
+ # timed out retrying
+
+ It's possible to execute an action before any attempt of calling the function
+ by using the before callback function:
+
+ .. code-block:: python
+
+ logger = logging.getLogger(__name__)
+
+ @retry(stop=stop_after_attempt(3), before=before_log(logger, logging.DEBUG))
+ def raise_my_exception():
+ raise MyException("Fail")
+
+ In the same spirit, It's possible to execute after a call that failed:
+
+ .. code-block:: python
+
+ logger = logging.getLogger(__name__)
+
+ @retry(stop=stop_after_attempt(3), after=after_log(logger, logging.DEBUG))
+ def raise_my_exception():
+ raise MyException("Fail")
+
+ You can access the statistics about the retry made over a function by using the
+ `retry` attribute attached to the function and its `statistics` attribute:
+
+ .. code-block:: python
+
+ @retry(stop=stop_after_attempt(3))
+ def raise_my_exception():
+ raise MyException("Fail")
+
+ try:
+ raise_my_exception()
+ except Exception:
+ pass
+
+ print(raise_my_exception.retry.statistics)
+
+
+ Finally, ``retry`` works also on asyncio coroutines. Sleeps are done
+ asynchronously too.
+
+ .. code-block:: python
+
+ @retry
+ async def my_async_function(loop):
+ await loop.getaddrinfo('8.8.8.8', 53)
+
+
+ Contribute
+ ----------
+
+ #. Check for open issues or open a fresh issue to start a discussion around a
+ feature idea or a bug.
+ #. Fork `the repository`_ on GitHub to start making your changes to the
+ **master** branch (or branch off of it).
+ #. Write a test which shows that the bug was fixed or that the feature works as
+ expected.
+ #. Make the docs better (or more detailed, or more easier to read, or ...)
+
+ .. _`the repository`: https://github.com/jd/tenacity
+
+
+Platform: UNKNOWN
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: Apache Software License
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Topic :: Utilities
diff --git a/README.rst b/README.rst
deleted file mode 120000
index c560c78..0000000
--- a/README.rst
+++ /dev/null
@@ -1 +0,0 @@
-doc/source/index.rst
\ No newline at end of file
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..497c577
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,282 @@
+Tenacity
+========
+.. image:: https://img.shields.io/pypi/v/tenacity.svg
+ :target: https://pypi.python.org/pypi/tenacity
+
+.. image:: https://img.shields.io/travis/jd/tenacity.svg
+ :target: https://travis-ci.org/jd/tenacity
+
+.. image:: https://img.shields.io/badge/SayThanks.io-%E2%98%BC-1EAEDB.svg
+ :target: https://saythanks.io/to/jd
+
+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.
+It originates from `a fork of retrying
+<https://github.com/rholder/retrying/issues/65>`_.
+
+The simplest use case is retrying a flaky function whenever an `Exception`
+occurs until a value is returned.
+
+.. code-block:: python
+
+ import random
+ from tenacity import retry
+
+ @retry
+ def do_something_unreliable():
+ if random.randint(0, 10) > 1:
+ raise IOError("Broken sauce, everything is hosed!!!111one")
+ else:
+ return "Awesome sauce!"
+
+ print(do_something_unreliable())
+
+
+Features
+--------
+
+- Generic Decorator API
+- Specify stop condition (i.e. limit by number of attempts)
+- Specify wait condition (i.e. exponential backoff sleeping between attempts)
+- Customize retrying on Exceptions
+- Customize retrying on expected returned result
+- Retry on coroutines
+
+
+Installation
+------------
+
+To install *tenacity*, simply:
+
+.. code-block:: bash
+
+ $ pip install tenacity
+
+
+Examples
+----------
+
+As you saw above, the default behavior is to retry forever without waiting when
+an exception is raised.
+
+.. code-block:: python
+
+ @retry
+ def never_give_up_never_surrender():
+ print("Retry forever ignoring Exceptions, don't wait between retries")
+ raise Exception
+
+Let's be a little less persistent and set some boundaries, such as the number
+of attempts before giving up.
+
+.. code-block:: python
+
+ @retry(stop=stop_after_attempt(7))
+ def stop_after_7_attempts():
+ print("Stopping after 7 attempts")
+ raise Exception
+
+We don't have all day, so let's set a boundary for how long we should be
+retrying stuff.
+
+.. code-block:: python
+
+ @retry(stop=stop_after_delay(10))
+ def stop_after_10_s():
+ print("Stopping after 10 seconds")
+ raise Exception
+
+You can combine several stop conditions by using the `|` operator:
+
+.. code-block:: python
+
+ @retry(stop=(stop_after_delay(10) | stop_after_attempt(5)))
+ def stop_after_10_s_or_5_retries():
+ print("Stopping after 10 seconds or 5 retries")
+ raise Exception
+
+Most things don't like to be polled as fast as possible, so let's just wait 2
+seconds between retries.
+
+.. code-block:: python
+
+ @retry(wait=wait_fixed(2))
+ def wait_2_s():
+ print("Wait 2 second between retries")
+ raise Exception
+
+Some things perform best with a bit of randomness injected.
+
+.. code-block:: python
+
+ @retry(wait=wait_random(min=1, max=2))
+ def wait_random_1_to_2_s():
+ print("Randomly wait 1 to 2 seconds between retries")
+ raise Exception
+
+Then again, it's hard to beat exponential backoff when retrying distributed
+services and other remote endpoints.
+
+.. code-block:: python
+
+ @retry(wait=wait_exponential(multiplier=1, max=10))
+ def wait_exponential_1():
+ print("Wait 2^x * 1 second between each retry, up to 10 seconds, then 10 seconds afterwards")
+ raise Exception
+
+
+Then again, it's also hard to beat combining fixed waits and jitter (to
+help avoid thundering herds) when retrying distributed services and other
+remote endpoints.
+
+.. code-block:: python
+
+ @retry(wait=wait_fixed(3) + wait_random(0, 2))
+ def wait_fixed_jitter():
+ print("Wait at least 3 seconds, and add up to 2 seconds of random delay")
+ raise Exception
+
+When multiple processes are in contention for a shared resource, exponentially
+increasing jitter helps minimise collisions.
+
+.. code-block:: python
+
+ @retry(wait=wait_random_exponential(multiplier=1, max=60))
+ def wait_exponential_jitter():
+ print("Randomly wait up to 2^x * 1 seconds between each retry until the range reaches 60 seconds, then randomly up to 60 seconds afterwards")
+ raise Exception
+
+
+Sometimes it's necessary to build a chain of backoffs.
+
+.. code-block:: python
+
+ @retry(wait=wait_chain(*[wait_fixed(3) for i in range(3)] +
+ [wait_fixed(7) for i in range(2)] +
+ [wait_fixed(9)]))
+ def wait_fixed_chained():
+ print("Wait 3s for 3 attempts, 7s for the next 2 attempts and 9s for all attempts thereafter")
+ raise Exception
+
+We have a few options for dealing with retries that raise specific or general
+exceptions, as in the cases here.
+
+.. code-block:: python
+
+ @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")
+ retry Exception
+
+We can also use the result of the function to alter the behavior of retrying.
+
+.. code-block:: python
+
+ def is_none_p(value):
+ """Return True if value is None"""
+ return value is None
+
+ @retry(retry=retry_if_result(is_none_p))
+ def might_return_none():
+ print("Retry with no wait if return value is None")
+
+We can also combine several conditions:
+
+.. code-block:: python
+
+ def is_none_p(value):
+ """Return True if value is None"""
+ return value is None
+
+ @retry(retry=(retry_if_result(is_none_p) | retry_if_exception_type()))
+ def might_return_none():
+ print("Retry forever ignoring Exceptions with no wait if return value is None")
+
+Any combination of stop, wait, etc. is also supported to give you the freedom
+to mix and match.
+
+It's also possible to retry explicitly at any time by raising the `TryAgain`
+exception:
+
+.. code-block:: python
+
+ @retry
+ def do_something():
+ result = something_else()
+ if result == 23:
+ raise TryAgain
+
+While callables that "timeout" retrying raise a `RetryError` by default,
+we can reraise the last attempt's exception if needed:
+
+.. code-block:: python
+
+ @retry(reraise=True, stop=stop_after_attempt(3))
+ def raise_my_exception():
+ raise MyException("Fail")
+
+ try:
+ raise_my_exception()
+ except MyException:
+ # timed out retrying
+
+It's possible to execute an action before any attempt of calling the function
+by using the before callback function:
+
+.. code-block:: python
+
+ logger = logging.getLogger(__name__)
+
+ @retry(stop=stop_after_attempt(3), before=before_log(logger, logging.DEBUG))
+ def raise_my_exception():
+ raise MyException("Fail")
+
+In the same spirit, It's possible to execute after a call that failed:
+
+.. code-block:: python
+
+ logger = logging.getLogger(__name__)
+
+ @retry(stop=stop_after_attempt(3), after=after_log(logger, logging.DEBUG))
+ def raise_my_exception():
+ raise MyException("Fail")
+
+You can access the statistics about the retry made over a function by using the
+`retry` attribute attached to the function and its `statistics` attribute:
+
+.. code-block:: python
+
+ @retry(stop=stop_after_attempt(3))
+ def raise_my_exception():
+ raise MyException("Fail")
+
+ try:
+ raise_my_exception()
+ except Exception:
+ pass
+
+ print(raise_my_exception.retry.statistics)
+
+
+Finally, ``retry`` works also on asyncio coroutines. Sleeps are done
+asynchronously too.
+
+.. code-block:: python
+
+ @retry
+ async def my_async_function(loop):
+ await loop.getaddrinfo('8.8.8.8', 53)
+
+
+Contribute
+----------
+
+#. Check for open issues or open a fresh issue to start a discussion around a
+ feature idea or a bug.
+#. Fork `the repository`_ on GitHub to start making your changes to the
+ **master** branch (or branch off of it).
+#. Write a test which shows that the bug was fixed or that the feature works as
+ expected.
+#. Make the docs better (or more detailed, or more easier to read, or ...)
+
+.. _`the repository`: https://github.com/jd/tenacity
diff --git a/doc/source/index.rst b/doc/source/index.rst
index 0da12ba..497c577 100644
... 1987 lines suppressed ...
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-tenacity.git
More information about the Python-modules-commits
mailing list