[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