Skip to content

Added log_traceback parameter to retry + improved logging by adding failed function reference #42

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion AUTHORS
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
Andrei Suiu <[email protected]>
Mateusz Warowny <[email protected]>
Richard O'Dwyer <[email protected]>
Rémy <[email protected]>
Rémy <[email protected]>
Rémy Greinhofer <[email protected]>
invl <[email protected]>
invlpg <[email protected]>
Richard O'Dwyer <[email protected]>
[email protected] <[email protected]>
williara <[email protected]>
52 changes: 42 additions & 10 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,23 +1,55 @@
CHANGES
=======

0.9.5
-----

* removed redundant dependencies

0.9.4
-----

* Updated version to 0.9.4 with tag
* Add on\_exception handler called with captured exception. (#1)
* Updates to construct PyPi retry2 wheel package

0.9.3
-----

* Added log\_traceback parameter to retry + improved logging by adding failed function reference
* Trim setup.py
* Move NullHandler to .compat
* Expose retry.retry\_call
* Relative import
* Move tests out of package
* Bump version
* Fix badges

0.9.2
-----

* Update ChangeLog
* Update AUTHORS
* Don't pin pytest
* tox: Add py35
* Bump version
* Updating requirements.txt to allow for any decorators >=3.4.2

0.9.1
-----

* Fix dependency issues with other packages caused by explicit dep verions in requirements
* Updates setup.cfg version info
* Updates authors and changelog
* Adds version ranges to requirements, widening compatibility with other packages and their deps

0.9.0
-----

* Fix typo in classifier
* Add AUTHORS and ChangeLog files
* Packaging the application using PBR
* Update documentation
* Add retry_call function
* Add retry\_call function
* Update tox.ini
* Update requirements
* Move the tests to the appropriate package
Expand All @@ -35,7 +67,7 @@ CHANGES
* v0.8.0
* dos2unix
* Add argument jitter for retry()
* Add argument max_delay for retry()
* Add argument max\_delay for retry()
* Refactor retry()

0.7.0
Expand All @@ -46,8 +78,8 @@ CHANGES
* retry(): Update docstring
* retry(): Change default tries to -1
* Move decorator() to .compat
* Add test_tries_minus1()
* Add test_tries_inf()
* Add test\_tries\_minus1()
* Add test\_tries\_inf()
* Mock time.sleep in test case
* Refactor retry()

Expand All @@ -57,7 +89,7 @@ CHANGES
* v0.6.0
* Fix inaccurate attempt counter
* logger is now optional
* Extract logging_logger
* Extract logging\_logger
* Make decorator module optional

0.5.0
Expand All @@ -74,22 +106,22 @@ CHANGES
* Add tox.ini
* Extract retry/api.py
* Require pytest
* Add test_retry.py
* Add test\_retry.py
* Added tag 0.4.2 for changeset 315f5f1229f6

0.4.2
-----

* Version 0.4.2
* python2.6 support
* (untested) python2.6 support
* README.rst: Add installation
* Add classifiers
* Add LICENSE
* Add requirements.txt
* Fix rST h1 h2 for README.rst
* Add url
* Add README.rst
* Ignore *.egg-info
* Ignore \*.egg-info
* Ignore .env
* Ignore .ropeproject
* Ignore .git
Expand All @@ -100,7 +132,7 @@ CHANGES

* Version 0.4.1
* Add license
* Add long_description
* Add long\_description
* Add docstring for retry()
* Added tag 0.4.0 for changeset e053cae4b105

Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright 2014 invl
Copyright 2021 [email protected]

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
32 changes: 20 additions & 12 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
retry
=====
retry2
======

.. image:: https://img.shields.io/pypi/dm/retry.svg?maxAge=2592000
:target: https://pypi.python.org/pypi/retry/
.. image:: https://img.shields.io/pypi/dm/retry2.svg?maxAge=2592000
:target: https://pypi.python.org/pypi/retry2/

.. image:: https://img.shields.io/pypi/v/retry.svg?maxAge=2592000
:target: https://pypi.python.org/pypi/retry/
.. image:: https://img.shields.io/pypi/v/retry2.svg?maxAge=2592000
:target: https://pypi.python.org/pypi/retry2/

.. image:: https://img.shields.io/pypi/l/retry.svg?maxAge=2592000
:target: https://pypi.python.org/pypi/retry/
.. image:: https://img.shields.io/pypi/l/retry2.svg?maxAge=2592000
:target: https://pypi.python.org/pypi/retry2/


Easy to use retry decorator.


[This is a fork of https://github.com/invl/retry which is not maintained anymore]

Features
--------

Expand All @@ -27,7 +29,7 @@ Installation

.. code-block:: bash

$ pip install retry
$ pip install retry2


API
Expand All @@ -38,7 +40,8 @@ retry decorator

.. code:: python

def retry(exceptions=Exception, tries=-1, delay=0, max_delay=None, backoff=1, jitter=0, logger=logging_logger):
def retry(exceptions=Exception, tries=-1, delay=0, max_delay=None, backoff=1, jitter=0, logger=logging_logger,
on_exception=None):
"""Return a retry decorator.

:param exceptions: an exception or a tuple of exceptions to catch. default: Exception.
Expand All @@ -50,6 +53,9 @@ retry decorator
fixed if a number, random if a range tuple (min, max)
:param logger: logger.warning(fmt, error, delay) will be called on failed attempts.
default: retry.logging_logger. if None, logging is disabled.
:param on_exception: handler called when exception occurs. will be passed the captured
exception as an argument. further retries are stopped when handler
returns True. default: None
"""

Various retrying logic can be achieved by combination of arguments.
Expand Down Expand Up @@ -107,8 +113,7 @@ retry_call
.. code:: python

def retry_call(f, fargs=None, fkwargs=None, exceptions=Exception, tries=-1, delay=0, max_delay=None, backoff=1,
jitter=0,
logger=logging_logger):
jitter=0, logger=logging_logger, on_exception=None):
"""
Calls a function and re-executes it if it failed.

Expand All @@ -124,6 +129,9 @@ retry_call
fixed if a number, random if a range tuple (min, max)
:param logger: logger.warning(fmt, error, delay) will be called on failed attempts.
default: retry.logging_logger. if None, logging is disabled.
:param on_exception: handler called when exception occurs. will be passed the captured
exception as an argument. further retries are stopped when handler
returns True. default: None
:returns: the result of the f function.
"""

Expand Down
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
decorator>=3.4.2
py>=1.4.26,<2.0.0
38 changes: 29 additions & 9 deletions retry/api.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import logging
import random
import time

import traceback
from functools import partial

from .compat import decorator


logging_logger = logging.getLogger(__name__)


def __retry_internal(f, exceptions=Exception, tries=-1, delay=0, max_delay=None, backoff=1, jitter=0,
logger=logging_logger):
logger=logging_logger, log_traceback=False, on_exception=None):
"""
Executes a function and retries it if it failed.

Expand All @@ -25,19 +24,33 @@ def __retry_internal(f, exceptions=Exception, tries=-1, delay=0, max_delay=None,
fixed if a number, random if a range tuple (min, max)
:param logger: logger.warning(fmt, error, delay) will be called on failed attempts.
default: retry.logging_logger. if None, logging is disabled.
:param on_exception: handler called when exception occurs. will be passed the captured
exception as an argument. further retries are stopped when handler
returns True. default: None
:returns: the result of the f function.
"""
_tries, _delay = tries, delay
while _tries:
try:
return f()
except exceptions as e:
if on_exception is not None:
if on_exception(e):
break

_tries -= 1
if not _tries:
raise

if logger is not None:
logger.warning('%s, retrying in %s seconds...', e, _delay)
try:
func_qualname = f.func.__qualname__
except AttributeError:
func_qualname = str(f.func)
logger.warning('{}: {} in {}.{}, retrying in {} seconds...'.format(e.__class__.__qualname__, e,
f.func.__module__, func_qualname, _delay))
if log_traceback:
logger.warning(traceback.format_exc())

time.sleep(_delay)
_delay *= backoff
Expand All @@ -51,7 +64,8 @@ def __retry_internal(f, exceptions=Exception, tries=-1, delay=0, max_delay=None,
_delay = min(_delay, max_delay)


def retry(exceptions=Exception, tries=-1, delay=0, max_delay=None, backoff=1, jitter=0, logger=logging_logger):
def retry(exceptions=Exception, tries=-1, delay=0, max_delay=None, backoff=1, jitter=0, logger=logging_logger,
log_traceback=False, on_exception=None):
"""Returns a retry decorator.

:param exceptions: an exception or a tuple of exceptions to catch. default: Exception.
Expand All @@ -63,6 +77,9 @@ def retry(exceptions=Exception, tries=-1, delay=0, max_delay=None, backoff=1, ji
fixed if a number, random if a range tuple (min, max)
:param logger: logger.warning(fmt, error, delay) will be called on failed attempts.
default: retry.logging_logger. if None, logging is disabled.
:param on_exception: handler called when exception occurs. will be passed the captured
exception as an argument. further retries are stopped when handler
returns True. default: None
:returns: a retry decorator.
"""

Expand All @@ -71,14 +88,13 @@ def retry_decorator(f, *fargs, **fkwargs):
args = fargs if fargs else list()
kwargs = fkwargs if fkwargs else dict()
return __retry_internal(partial(f, *args, **kwargs), exceptions, tries, delay, max_delay, backoff, jitter,
logger)
logger, log_traceback, on_exception)

return retry_decorator


def retry_call(f, fargs=None, fkwargs=None, exceptions=Exception, tries=-1, delay=0, max_delay=None, backoff=1,
jitter=0,
logger=logging_logger):
jitter=0, logger=logging_logger, log_traceback=False, on_exception=None):
"""
Calls a function and re-executes it if it failed.

Expand All @@ -94,8 +110,12 @@ def retry_call(f, fargs=None, fkwargs=None, exceptions=Exception, tries=-1, dela
fixed if a number, random if a range tuple (min, max)
:param logger: logger.warning(fmt, error, delay) will be called on failed attempts.
default: retry.logging_logger. if None, logging is disabled.
:param on_exception: handler called when exception occurs. will be passed the captured
exception as an argument. further retries are stopped when handler
returns True. default: None
:returns: the result of the f function.
"""
args = fargs if fargs else list()
kwargs = fkwargs if fkwargs else dict()
return __retry_internal(partial(f, *args, **kwargs), exceptions, tries, delay, max_delay, backoff, jitter, logger)
return __retry_internal(partial(f, *args, **kwargs), exceptions, tries, delay, max_delay, backoff, jitter, logger,
log_traceback, on_exception)
11 changes: 5 additions & 6 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
[metadata]
name = retry
version = 0.9.3
author = invl
author-email = invlpg@gmail.com
name = retry2
version = 0.9.5
author = Andrei Suiu | eSAMTrade
author-email = andrei.suiu@gmail.com
summary = Easy to use retry decorator.
license = Apache License 2.0
description-file = README.rst
home-page = https://github.com/invl/retry
home-page = https://github.com/eSAMTrade/retry
requires-python = >=2.6
classifier =
Development Status :: 4 - Beta
Expand All @@ -18,7 +18,6 @@ classifier =
Programming Language :: Python :: 2.6
Programming Language :: Python :: 2.7
Programming Language :: Python :: 3
Programming Language :: Python :: 3.4
Programming Language :: Python :: Implementation :: PyPy
Topic :: Software Development

Expand Down
2 changes: 1 addition & 1 deletion test-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
mock
-r requirements.txt
pbr
pytest
tox
Expand Down
Loading