From fd7842774cc10d41e68e6bc64afe7d9f83221aa0 Mon Sep 17 00:00:00 2001 From: Julien Danjou Date: Fri, 29 Jan 2021 16:42:15 +0100 Subject: [PATCH] ci: enable black (#277) --- doc/source/conf.py | 10 +- setup.py | 2 +- tenacity/__init__.py | 94 ++++--- tenacity/_asyncio.py | 8 +- tenacity/_utils.py | 15 +- tenacity/after.py | 17 +- tenacity/before.py | 11 +- tenacity/before_sleep.py | 21 +- tenacity/retry.py | 22 +- tenacity/tests/test_asyncio.py | 7 +- tenacity/tests/test_tenacity.py | 479 ++++++++++++++++++-------------- tenacity/tests/test_tornado.py | 3 +- tenacity/tornadoweb.py | 8 +- tenacity/wait.py | 16 +- tox.ini | 3 +- 15 files changed, 411 insertions(+), 305 deletions(-) diff --git a/doc/source/conf.py b/doc/source/conf.py index 23856bc5..8bb88192 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -19,16 +19,16 @@ import os import sys -master_doc = 'index' +master_doc = "index" project = "Tenacity" # Add tenacity to the path, so sphinx can find the functions for autodoc. -sys.path.insert(0, os.path.abspath('../..')) +sys.path.insert(0, os.path.abspath("../..")) extensions = [ - 'sphinx.ext.doctest', - 'sphinx.ext.autodoc', - 'reno.sphinxext', + "sphinx.ext.doctest", + "sphinx.ext.autodoc", + "reno.sphinxext", ] # -- Options for sphinx.ext.doctest ----------------------------------------- diff --git a/setup.py b/setup.py index 66163685..ec7ac861 100644 --- a/setup.py +++ b/setup.py @@ -16,6 +16,6 @@ import setuptools setuptools.setup( - setup_requires=['setuptools_scm'], + setup_requires=["setuptools_scm"], use_scm_version=True, ) diff --git a/tenacity/__init__.py b/tenacity/__init__.py index f17472ca..74205127 100644 --- a/tenacity/__init__.py +++ b/tenacity/__init__.py @@ -115,11 +115,15 @@ def retry(*dargs, **dkw): # noqa if len(dargs) == 1 and callable(dargs[0]): return retry()(dargs[0]) else: + def wrap(f): if iscoroutinefunction is not None and iscoroutinefunction(f): r = AsyncRetrying(*dargs, **dkw) - elif tornado and hasattr(tornado.gen, 'is_coroutine_function') \ - and tornado.gen.is_coroutine_function(f): + elif ( + tornado + and hasattr(tornado.gen, "is_coroutine_function") + and tornado.gen.is_coroutine_function(f) + ): r = TornadoRetrying(*dargs, **dkw) else: r = Retrying(*dargs, **dkw) @@ -157,17 +161,18 @@ class BaseAction(object): NAME = None def __repr__(self): - state_str = ', '.join('%s=%r' % (field, getattr(self, field)) - for field in self.REPR_FIELDS) - return '%s(%s)' % (type(self).__name__, state_str) + state_str = ", ".join( + "%s=%r" % (field, getattr(self, field)) for field in self.REPR_FIELDS + ) + return "%s(%s)" % (type(self).__name__, state_str) def __str__(self): return repr(self) class RetryAction(BaseAction): - REPR_FIELDS = ('sleep',) - NAME = 'retry' + REPR_FIELDS = ("sleep",) + NAME = "retry" def __init__(self, sleep): self.sleep = float(sleep) @@ -213,16 +218,19 @@ def __exit__(self, exc_type, exc_value, traceback): class BaseRetrying(object): __metaclass__ = ABCMeta - def __init__(self, - sleep=sleep, - stop=stop_never, wait=wait_none(), - retry=retry_if_exception_type(), - before=before_nothing, - after=after_nothing, - before_sleep=None, - reraise=False, - retry_error_cls=RetryError, - retry_error_callback=None): + def __init__( + self, + sleep=sleep, + stop=stop_never, + wait=wait_none(), + retry=retry_if_exception_type(), + before=before_nothing, + after=after_nothing, + before_sleep=None, + reraise=False, + retry_error_cls=RetryError, + retry_error_callback=None, + ): self.sleep = sleep self.stop = stop self.wait = wait @@ -239,9 +247,17 @@ def __init__(self, # Retrying objects but kept for backward compatibility. self.fn = None - def copy(self, sleep=_unset, stop=_unset, wait=_unset, - retry=_unset, before=_unset, after=_unset, before_sleep=_unset, - reraise=_unset): + def copy( + self, + sleep=_unset, + stop=_unset, + wait=_unset, + retry=_unset, + before=_unset, + after=_unset, + before_sleep=_unset, + reraise=_unset, + ): """Copy this object with some parameters changed if needed.""" if before_sleep is _unset: before_sleep = self.before_sleep @@ -258,12 +274,14 @@ def copy(self, sleep=_unset, stop=_unset, wait=_unset, def __repr__(self): attrs = dict( - _utils.visible_attrs(self, attrs={'me': id(self)}), + _utils.visible_attrs(self, attrs={"me": id(self)}), __class__=self.__class__.__name__, ) - return ("<%(__class__)s object at 0x%(me)x (stop=%(stop)s, " - "wait=%(wait)s, sleep=%(sleep)s, retry=%(retry)s, " - "before=%(before)s, after=%(after)s)>") % (attrs) + return ( + "<%(__class__)s object at 0x%(me)x (stop=%(stop)s, " + "wait=%(wait)s, sleep=%(sleep)s, retry=%(retry)s, " + "before=%(before)s, after=%(after)s)>" + ) % (attrs) @property def statistics(self): @@ -298,6 +316,7 @@ def wraps(self, f): :param f: A function to wraps for retrying. """ + @_utils.wraps(f) def wrapped_f(*args, **kw): return self(f, *args, **kw) @@ -312,9 +331,9 @@ def retry_with(*args, **kwargs): def begin(self, fn): self.statistics.clear() - self.statistics['start_time'] = _utils.now() - self.statistics['attempt_number'] = 1 - self.statistics['idle_for'] = 0 + self.statistics["start_time"] = _utils.now() + self.statistics["attempt_number"] = 1 + self.statistics["idle_for"] = 0 self.fn = fn def iter(self, retry_state): # noqa @@ -324,16 +343,16 @@ def iter(self, retry_state): # noqa self.before(retry_state) return DoAttempt() - is_explicit_retry = retry_state.outcome.failed \ - and isinstance(retry_state.outcome.exception(), TryAgain) + is_explicit_retry = retry_state.outcome.failed and isinstance( + retry_state.outcome.exception(), TryAgain + ) if not (is_explicit_retry or self.retry(retry_state=retry_state)): return fut.result() if self.after is not None: self.after(retry_state=retry_state) - self.statistics['delay_since_first_attempt'] = \ - retry_state.seconds_since_start + self.statistics["delay_since_first_attempt"] = retry_state.seconds_since_start if self.stop(retry_state=retry_state): if self.retry_error_callback: return self.retry_error_callback(retry_state=retry_state) @@ -348,8 +367,8 @@ def iter(self, retry_state): # noqa sleep = 0.0 retry_state.next_action = RetryAction(sleep) retry_state.idle_for += sleep - self.statistics['idle_for'] += sleep - self.statistics['attempt_number'] += 1 + self.statistics["idle_for"] += sleep + self.statistics["attempt_number"] += 1 if self.before_sleep is not None: self.before_sleep(retry_state=retry_state) @@ -376,8 +395,10 @@ def __call__(self, *args, **kwargs): def call(self, *args, **kwargs): """Use ``__call__`` instead because this method is deprecated.""" - warnings.warn("'call()' method is deprecated. " + - "Use '__call__()' instead", DeprecationWarning) + warnings.warn( + "'call()' method is deprecated. " + "Use '__call__()' instead", + DeprecationWarning, + ) return self.__call__(*args, **kwargs) @@ -387,8 +408,7 @@ class Retrying(BaseRetrying): def __call__(self, fn, *args, **kwargs): self.begin(fn) - retry_state = RetryCallState( - retry_object=self, fn=fn, args=args, kwargs=kwargs) + retry_state = RetryCallState(retry_object=self, fn=fn, args=args, kwargs=kwargs) while True: do = self.iter(retry_state=retry_state) if isinstance(do, DoAttempt): diff --git a/tenacity/_asyncio.py b/tenacity/_asyncio.py index de0f5fc2..979b6544 100644 --- a/tenacity/_asyncio.py +++ b/tenacity/_asyncio.py @@ -26,18 +26,14 @@ class AsyncRetrying(BaseRetrying): - - def __init__(self, - sleep=sleep, - **kwargs): + def __init__(self, sleep=sleep, **kwargs): super(AsyncRetrying, self).__init__(**kwargs) self.sleep = sleep async def __call__(self, fn, *args, **kwargs): self.begin(fn) - retry_state = RetryCallState( - retry_object=self, fn=fn, args=args, kwargs=kwargs) + retry_state = RetryCallState(retry_object=self, fn=fn, args=args, kwargs=kwargs) while True: do = self.iter(retry_state=retry_state) if isinstance(do, DoAttempt): diff --git a/tenacity/_utils.py b/tenacity/_utils.py index 6703bd9c..625d5901 100644 --- a/tenacity/_utils.py +++ b/tenacity/_utils.py @@ -40,12 +40,15 @@ def wraps(fn): Also, see https://github.com/benjaminp/six/issues/250. """ + def filter_hasattr(obj, attrs): return tuple(a for a in attrs if hasattr(obj, a)) + return six.wraps( fn, assigned=filter_hasattr(fn, WRAPPER_ASSIGNMENTS), - updated=filter_hasattr(fn, WRAPPER_UPDATES)) + updated=filter_hasattr(fn, WRAPPER_UPDATES), + ) def capture(fut, tb): # TODO(harlowja): delete this in future, since its @@ -55,6 +58,8 @@ def capture(fut, tb): def getargspec(func): # This was deprecated in Python 3. return inspect.getargspec(func) + + else: from functools import wraps # noqa @@ -80,13 +85,13 @@ def find_ordinal(pos_num): if pos_num == 0: return "th" elif pos_num == 1: - return 'st' + return "st" elif pos_num == 2: - return 'nd' + return "nd" elif pos_num == 3: - return 'rd' + return "rd" elif pos_num >= 4 and pos_num <= 20: - return 'th' + return "th" else: return find_ordinal(pos_num % 10) diff --git a/tenacity/after.py b/tenacity/after.py index 55522c99..c577d7c7 100644 --- a/tenacity/after.py +++ b/tenacity/after.py @@ -23,13 +23,18 @@ def after_nothing(retry_state): def after_log(logger, log_level, sec_format="%0.3f"): """After call strategy that logs to some logger the finished attempt.""" - log_tpl = ("Finished call to '%s' after " + str(sec_format) + "(s), " - "this was the %s time calling it.") + log_tpl = ( + "Finished call to '%s' after " + str(sec_format) + "(s), " + "this was the %s time calling it." + ) def log_it(retry_state): - logger.log(log_level, log_tpl, - _utils.get_callback_name(retry_state.fn), - retry_state.seconds_since_start, - _utils.to_ordinal(retry_state.attempt_number)) + logger.log( + log_level, + log_tpl, + _utils.get_callback_name(retry_state.fn), + retry_state.seconds_since_start, + _utils.to_ordinal(retry_state.attempt_number), + ) return log_it diff --git a/tenacity/before.py b/tenacity/before.py index 54259ddd..68a2ae61 100644 --- a/tenacity/before.py +++ b/tenacity/before.py @@ -23,10 +23,13 @@ def before_nothing(retry_state): def before_log(logger, log_level): """Before call strategy that logs to some logger the attempt.""" + def log_it(retry_state): - logger.log(log_level, - "Starting call to '%s', this is the %s time calling it.", - _utils.get_callback_name(retry_state.fn), - _utils.to_ordinal(retry_state.attempt_number)) + logger.log( + log_level, + "Starting call to '%s', this is the %s time calling it.", + _utils.get_callback_name(retry_state.fn), + _utils.to_ordinal(retry_state.attempt_number), + ) return log_it diff --git a/tenacity/before_sleep.py b/tenacity/before_sleep.py index c8b3d33c..d797a246 100644 --- a/tenacity/before_sleep.py +++ b/tenacity/before_sleep.py @@ -24,23 +24,28 @@ def before_sleep_nothing(retry_state): def before_sleep_log(logger, log_level, exc_info=False): """Before call strategy that logs to some logger the attempt.""" + def log_it(retry_state): if retry_state.outcome.failed: ex = retry_state.outcome.exception() - verb, value = 'raised', '%s: %s' % (type(ex).__name__, ex) + verb, value = "raised", "%s: %s" % (type(ex).__name__, ex) if exc_info: local_exc_info = get_exc_info_from_future(retry_state.outcome) else: local_exc_info = False else: - verb, value = 'returned', retry_state.outcome.result() + verb, value = "returned", retry_state.outcome.result() local_exc_info = False # exc_info does not apply when no exception - logger.log(log_level, - "Retrying %s in %s seconds as it %s %s.", - _utils.get_callback_name(retry_state.fn), - getattr(retry_state.next_action, 'sleep'), - verb, value, - exc_info=local_exc_info) + logger.log( + log_level, + "Retrying %s in %s seconds as it %s %s.", + _utils.get_callback_name(retry_state.fn), + getattr(retry_state.next_action, "sleep"), + verb, + value, + exc_info=local_exc_info, + ) + return log_it diff --git a/tenacity/retry.py b/tenacity/retry.py index 55e59510..ebf26df5 100644 --- a/tenacity/retry.py +++ b/tenacity/retry.py @@ -76,7 +76,8 @@ class retry_if_exception_type(retry_if_exception): def __init__(self, exception_types=Exception): self.exception_types = exception_types super(retry_if_exception_type, self).__init__( - lambda e: isinstance(e, exception_types)) + lambda e: isinstance(e, exception_types) + ) class retry_unless_exception_type(retry_if_exception): @@ -85,7 +86,8 @@ class retry_unless_exception_type(retry_if_exception): def __init__(self, exception_types=Exception): self.exception_types = exception_types super(retry_unless_exception_type, self).__init__( - lambda e: not isinstance(e, exception_types)) + lambda e: not isinstance(e, exception_types) + ) def __call__(self, retry_state): # always retry if no exception was raised @@ -127,23 +129,30 @@ def __init__(self, message=None, match=None): if message and match: raise TypeError( "{}() takes either 'message' or 'match', not both".format( - self.__class__.__name__)) + self.__class__.__name__ + ) + ) # set predicate if message: + def message_fnc(exception): return message == str(exception) + predicate = message_fnc elif match: prog = re.compile(match) def match_fnc(exception): return prog.match(str(exception)) + predicate = match_fnc else: raise TypeError( - "{}() missing 1 required argument 'message' or 'match'". - format(self.__class__.__name__)) + "{}() missing 1 required argument 'message' or 'match'".format( + self.__class__.__name__ + ) + ) super(retry_if_exception_message, self).__init__(predicate) @@ -155,8 +164,7 @@ def __init__(self, *args, **kwargs): super(retry_if_not_exception_message, self).__init__(*args, **kwargs) # invert predicate if_predicate = self.predicate - self.predicate = lambda *args_, **kwargs_: not if_predicate( - *args_, **kwargs_) + self.predicate = lambda *args_, **kwargs_: not if_predicate(*args_, **kwargs_) def __call__(self, retry_state): if not retry_state.outcome.failed: diff --git a/tenacity/tests/test_asyncio.py b/tenacity/tests/test_asyncio.py index cfd664cc..2057fd2d 100644 --- a/tenacity/tests/test_asyncio.py +++ b/tenacity/tests/test_asyncio.py @@ -93,8 +93,8 @@ def test_repr(self): repr(tasyncio.AsyncRetrying()) def test_retry_attributes(self): - assert hasattr(_retryable_coroutine, 'retry') - assert hasattr(_retryable_coroutine, 'retry_with') + assert hasattr(_retryable_coroutine, "retry") + assert hasattr(_retryable_coroutine, "retry_with") @asynctest async def test_attempt_number_is_correct_for_interleaved_coroutines(self): @@ -109,7 +109,8 @@ def after(retry_state): await asyncio.gather( _retryable_coroutine.retry_with(after=after)(thing1), - _retryable_coroutine.retry_with(after=after)(thing2)) + _retryable_coroutine.retry_with(after=after)(thing2), + ) # There's no waiting on retry, only a wait in the coroutine, so the # executions should be interleaved. diff --git a/tenacity/tests/test_tenacity.py b/tenacity/tests/test_tenacity.py index b800a3e3..0ffd26b4 100644 --- a/tenacity/tests/test_tenacity.py +++ b/tenacity/tests/test_tenacity.py @@ -42,31 +42,34 @@ def _make_unset_exception(func_name, **kwargs): for k, v in six.iteritems(kwargs): if v is _unset: missing.append(k) - missing_str = ', '.join(repr(s) for s in missing) - return TypeError(func_name + ' func missing parameters: ' + missing_str) + missing_str = ", ".join(repr(s) for s in missing) + return TypeError(func_name + " func missing parameters: " + missing_str) def _set_delay_since_start(retry_state, delay): # Ensure outcome_timestamp - start_time is *exactly* equal to the delay to # avoid complexity in test code. retry_state.start_time = Fraction(retry_state.start_time) - retry_state.outcome_timestamp = (retry_state.start_time + Fraction(delay)) + retry_state.outcome_timestamp = retry_state.start_time + Fraction(delay) assert retry_state.seconds_since_start == delay -def make_retry_state(previous_attempt_number, delay_since_first_attempt, - last_result=None): +def make_retry_state( + previous_attempt_number, delay_since_first_attempt, last_result=None +): """Construct RetryCallState for given attempt number & delay. Only used in testing and thus is extra careful about timestamp arithmetics. """ - required_parameter_unset = (previous_attempt_number is _unset or - delay_since_first_attempt is _unset) + required_parameter_unset = ( + previous_attempt_number is _unset or delay_since_first_attempt is _unset + ) if required_parameter_unset: raise _make_unset_exception( - 'wait/stop', + "wait/stop", previous_attempt_number=previous_attempt_number, - delay_since_first_attempt=delay_since_first_attempt) + delay_since_first_attempt=delay_since_first_attempt, + ) retry_state = RetryCallState(None, None, (), {}) retry_state.attempt_number = previous_attempt_number @@ -79,7 +82,6 @@ def make_retry_state(previous_attempt_number, delay_since_first_attempt, class TestBase(unittest.TestCase): - def test_repr(self): class ConcreteRetrying(tenacity.BaseRetrying): def __call__(self): @@ -89,18 +91,18 @@ def __call__(self): class TestStopConditions(unittest.TestCase): - def test_never_stop(self): r = Retrying() self.assertFalse(r.stop(make_retry_state(3, 6546))) def test_stop_any(self): stop = tenacity.stop_any( - tenacity.stop_after_delay(1), - tenacity.stop_after_attempt(4)) + tenacity.stop_after_delay(1), tenacity.stop_after_attempt(4) + ) def s(*args): return stop(make_retry_state(*args)) + self.assertFalse(s(1, 0.1)) self.assertFalse(s(2, 0.2)) self.assertFalse(s(2, 0.8)) @@ -110,11 +112,12 @@ def s(*args): def test_stop_all(self): stop = tenacity.stop_all( - tenacity.stop_after_delay(1), - tenacity.stop_after_attempt(4)) + tenacity.stop_after_delay(1), tenacity.stop_after_attempt(4) + ) def s(*args): return stop(make_retry_state(*args)) + self.assertFalse(s(1, 0.1)) self.assertFalse(s(2, 0.2)) self.assertFalse(s(2, 0.8)) @@ -127,6 +130,7 @@ def test_stop_or(self): def s(*args): return stop(make_retry_state(*args)) + self.assertFalse(s(1, 0.1)) self.assertFalse(s(2, 0.2)) self.assertFalse(s(2, 0.8)) @@ -139,6 +143,7 @@ def test_stop_and(self): def s(*args): return stop(make_retry_state(*args)) + self.assertFalse(s(1, 0.1)) self.assertFalse(s(2, 0.2)) self.assertFalse(s(2, 0.8)) @@ -173,7 +178,6 @@ def stop_func(retry_state): class TestWaitConditions(unittest.TestCase): - def test_no_sleep(self): r = Retrying() self.assertEqual(0, r.wait(make_retry_state(18, 9879))) @@ -183,8 +187,7 @@ def test_fixed_sleep(self): self.assertEqual(1, r.wait(make_retry_state(12, 6546))) def test_incrementing_sleep(self): - r = Retrying(wait=tenacity.wait_incrementing( - start=500, increment=100)) + r = Retrying(wait=tenacity.wait_incrementing(start=500, increment=100)) self.assertEqual(500, r.wait(make_retry_state(1, 6546))) self.assertEqual(600, r.wait(make_retry_state(2, 6546))) self.assertEqual(700, r.wait(make_retry_state(3, 6546))) @@ -251,8 +254,7 @@ def test_exponential_with_min_wait(self): self.assertEqual(r.wait(make_retry_state(20, 0)), 524288) def test_exponential_with_max_wait_and_multiplier(self): - r = Retrying(wait=tenacity.wait_exponential( - max=50, multiplier=1)) + r = Retrying(wait=tenacity.wait_exponential(max=50, multiplier=1)) self.assertEqual(r.wait(make_retry_state(1, 0)), 1) self.assertEqual(r.wait(make_retry_state(2, 0)), 2) self.assertEqual(r.wait(make_retry_state(3, 0)), 4) @@ -264,8 +266,7 @@ def test_exponential_with_max_wait_and_multiplier(self): self.assertEqual(r.wait(make_retry_state(50, 0)), 50) def test_exponential_with_min_wait_and_multiplier(self): - r = Retrying(wait=tenacity.wait_exponential( - min=20, multiplier=2)) + r = Retrying(wait=tenacity.wait_exponential(min=20, multiplier=2)) self.assertEqual(r.wait(make_retry_state(1, 0)), 20) self.assertEqual(r.wait(make_retry_state(2, 0)), 20) self.assertEqual(r.wait(make_retry_state(3, 0)), 20) @@ -295,14 +296,18 @@ def test_legacy_explicit_wait_type(self): def test_wait_func(self): def wait_func(retry_state): return retry_state.attempt_number * retry_state.seconds_since_start + r = Retrying(wait=wait_func) self.assertEqual(r.wait(make_retry_state(1, 5)), 5) self.assertEqual(r.wait(make_retry_state(2, 11)), 22) self.assertEqual(r.wait(make_retry_state(10, 100)), 1000) def test_wait_combine(self): - r = Retrying(wait=tenacity.wait_combine(tenacity.wait_random(0, 3), - tenacity.wait_fixed(5))) + r = Retrying( + wait=tenacity.wait_combine( + tenacity.wait_random(0, 3), tenacity.wait_fixed(5) + ) + ) # Test it a few time since it's random for i in six.moves.range(1000): w = r.wait(make_retry_state(1, 5)) @@ -318,8 +323,11 @@ def test_wait_double_sum(self): self.assertGreaterEqual(w, 5) def test_wait_triple_sum(self): - r = Retrying(wait=tenacity.wait_fixed(1) + tenacity.wait_random(0, 3) + - tenacity.wait_fixed(5)) + r = Retrying( + wait=tenacity.wait_fixed(1) + + tenacity.wait_random(0, 3) + + tenacity.wait_fixed(5) + ) # Test it a few time since it's random for i in six.moves.range(1000): w = r.wait(make_retry_state(1, 5)) @@ -327,10 +335,16 @@ def test_wait_triple_sum(self): self.assertGreaterEqual(w, 6) def test_wait_arbitrary_sum(self): - r = Retrying(wait=sum([tenacity.wait_fixed(1), - tenacity.wait_random(0, 3), - tenacity.wait_fixed(5), - tenacity.wait_none()])) + r = Retrying( + wait=sum( + [ + tenacity.wait_fixed(1), + tenacity.wait_random(0, 3), + tenacity.wait_fixed(5), + tenacity.wait_none(), + ] + ) + ) # Test it a few time since it's random for i in six.moves.range(1000): w = r.wait(make_retry_state(1, 5)) @@ -350,10 +364,13 @@ def _assert_inclusive_epsilon(self, wait, target, epsilon): self.assertGreaterEqual(wait, target - epsilon) def test_wait_chain(self): - r = Retrying(wait=tenacity.wait_chain( - *[tenacity.wait_fixed(1) for i in six.moves.range(2)] + - [tenacity.wait_fixed(4) for i in six.moves.range(2)] + - [tenacity.wait_fixed(8) for i in six.moves.range(1)])) + r = Retrying( + wait=tenacity.wait_chain( + *[tenacity.wait_fixed(1) for i in six.moves.range(2)] + + [tenacity.wait_fixed(4) for i in six.moves.range(2)] + + [tenacity.wait_fixed(8) for i in six.moves.range(1)] + ) + ) for i in six.moves.range(10): w = r.wait(make_retry_state(i + 1, 1)) @@ -368,9 +385,9 @@ def test_wait_chain_multiple_invocations(self): sleep_intervals = [] r = Retrying( sleep=sleep_intervals.append, - wait=tenacity.wait_chain(*[ - tenacity.wait_fixed(i + 1) for i in six.moves.range(3) - ]), + wait=tenacity.wait_chain( + *[tenacity.wait_fixed(i + 1) for i in six.moves.range(3)] + ), stop=tenacity.stop_after_attempt(5), retry=tenacity.retry_if_result(lambda x: x == 1), ) @@ -404,9 +421,7 @@ def test_wait_random_exponential(self): fn = tenacity.wait_random_exponential(10, 5) for _ in six.moves.range(1000): - self._assert_inclusive_range( - fn(make_retry_state(1, 0)), 0.00, 5.00 - ) + self._assert_inclusive_range(fn(make_retry_state(1, 0)), 0.00, 5.00) # Default arguments exist fn = tenacity.wait_random_exponential() @@ -417,9 +432,7 @@ def test_wait_random_exponential_statistically(self): attempt = [] for i in six.moves.range(10): - attempt.append( - [fn(make_retry_state(i, 0)) for _ in six.moves.range(4000)] - ) + attempt.append([fn(make_retry_state(i, 0)) for _ in six.moves.range(4000)]) def mean(lst): return float(sum(lst)) / float(len(lst)) @@ -436,7 +449,6 @@ def mean(lst): self._assert_inclusive_epsilon(mean(attempt[9]), 30, 2.56) def test_wait_retry_state_attributes(self): - class ExtractCallState(Exception): pass @@ -447,11 +459,15 @@ def waitfunc(retry_state): retrying = Retrying( wait=waitfunc, - retry=(tenacity.retry_if_exception_type() | - tenacity.retry_if_result(lambda result: result == 123))) + retry=( + tenacity.retry_if_exception_type() + | tenacity.retry_if_result(lambda result: result == 123) + ), + ) def returnval(): return 123 + try: retrying(returnval) except ExtractCallState as err: @@ -461,11 +477,11 @@ def returnval(): self.assertEqual(retry_state.kwargs, {}) self.assertEqual(retry_state.outcome.result(), 123) self.assertEqual(retry_state.attempt_number, 1) - self.assertGreaterEqual(retry_state.outcome_timestamp, - retry_state.start_time) + self.assertGreaterEqual(retry_state.outcome_timestamp, retry_state.start_time) def dying(): raise Exception("Broken") + try: retrying(dying) except ExtractCallState as err: @@ -473,40 +489,42 @@ def dying(): self.assertIs(retry_state.fn, dying) self.assertEqual(retry_state.args, ()) self.assertEqual(retry_state.kwargs, {}) - self.assertEqual(str(retry_state.outcome.exception()), 'Broken') + self.assertEqual(str(retry_state.outcome.exception()), "Broken") self.assertEqual(retry_state.attempt_number, 1) - self.assertGreaterEqual(retry_state.outcome_timestamp, - retry_state.start_time) + self.assertGreaterEqual(retry_state.outcome_timestamp, retry_state.start_time) class TestRetryConditions(unittest.TestCase): - def test_retry_if_result(self): - retry = (tenacity.retry_if_result(lambda x: x == 1)) + retry = tenacity.retry_if_result(lambda x: x == 1) def r(fut): retry_state = make_retry_state(1, 1.0, last_result=fut) return retry(retry_state) + self.assertTrue(r(tenacity.Future.construct(1, 1, False))) self.assertFalse(r(tenacity.Future.construct(1, 2, False))) def test_retry_if_not_result(self): - retry = (tenacity.retry_if_not_result(lambda x: x == 1)) + retry = tenacity.retry_if_not_result(lambda x: x == 1) def r(fut): retry_state = make_retry_state(1, 1.0, last_result=fut) return retry(retry_state) + self.assertTrue(r(tenacity.Future.construct(1, 2, False))) self.assertFalse(r(tenacity.Future.construct(1, 1, False))) def test_retry_any(self): retry = tenacity.retry_any( tenacity.retry_if_result(lambda x: x == 1), - tenacity.retry_if_result(lambda x: x == 2)) + tenacity.retry_if_result(lambda x: x == 2), + ) def r(fut): retry_state = make_retry_state(1, 1.0, last_result=fut) return retry(retry_state) + self.assertTrue(r(tenacity.Future.construct(1, 1, False))) self.assertTrue(r(tenacity.Future.construct(1, 2, False))) self.assertFalse(r(tenacity.Future.construct(1, 3, False))) @@ -515,35 +533,41 @@ def r(fut): def test_retry_all(self): retry = tenacity.retry_all( tenacity.retry_if_result(lambda x: x == 1), - tenacity.retry_if_result(lambda x: isinstance(x, int))) + tenacity.retry_if_result(lambda x: isinstance(x, int)), + ) def r(fut): retry_state = make_retry_state(1, 1.0, last_result=fut) return retry(retry_state) + self.assertTrue(r(tenacity.Future.construct(1, 1, False))) self.assertFalse(r(tenacity.Future.construct(1, 2, False))) self.assertFalse(r(tenacity.Future.construct(1, 3, False))) self.assertFalse(r(tenacity.Future.construct(1, 1, True))) def test_retry_and(self): - retry = (tenacity.retry_if_result(lambda x: x == 1) & - tenacity.retry_if_result(lambda x: isinstance(x, int))) + retry = tenacity.retry_if_result(lambda x: x == 1) & tenacity.retry_if_result( + lambda x: isinstance(x, int) + ) def r(fut): retry_state = make_retry_state(1, 1.0, last_result=fut) return retry(retry_state) + self.assertTrue(r(tenacity.Future.construct(1, 1, False))) self.assertFalse(r(tenacity.Future.construct(1, 2, False))) self.assertFalse(r(tenacity.Future.construct(1, 3, False))) self.assertFalse(r(tenacity.Future.construct(1, 1, True))) def test_retry_or(self): - retry = (tenacity.retry_if_result(lambda x: x == "foo") | - tenacity.retry_if_result(lambda x: isinstance(x, int))) + retry = tenacity.retry_if_result( + lambda x: x == "foo" + ) | tenacity.retry_if_result(lambda x: isinstance(x, int)) def r(fut): retry_state = make_retry_state(1, 1.0, last_result=fut) return retry(retry_state) + self.assertTrue(r(tenacity.Future.construct(1, "foo", False))) self.assertFalse(r(tenacity.Future.construct(1, "foobar", False))) self.assertFalse(r(tenacity.Future.construct(1, 2.2, False))) @@ -556,32 +580,30 @@ def _raise_try_again(self): def test_retry_try_again(self): self._attempts = 0 - Retrying(stop=tenacity.stop_after_attempt(5), - retry=tenacity.retry_never)(self._raise_try_again) + Retrying(stop=tenacity.stop_after_attempt(5), retry=tenacity.retry_never)( + self._raise_try_again + ) self.assertEqual(3, self._attempts) def test_retry_try_again_forever(self): def _r(): raise tenacity.TryAgain - r = Retrying(stop=tenacity.stop_after_attempt(5), - retry=tenacity.retry_never) - self.assertRaises(tenacity.RetryError, - r, - _r) - self.assertEqual(5, r.statistics['attempt_number']) + r = Retrying(stop=tenacity.stop_after_attempt(5), retry=tenacity.retry_never) + self.assertRaises(tenacity.RetryError, r, _r) + self.assertEqual(5, r.statistics["attempt_number"]) def test_retry_try_again_forever_reraise(self): def _r(): raise tenacity.TryAgain - r = Retrying(stop=tenacity.stop_after_attempt(5), - retry=tenacity.retry_never, - reraise=True) - self.assertRaises(tenacity.TryAgain, - r, - _r) - self.assertEqual(5, r.statistics['attempt_number']) + r = Retrying( + stop=tenacity.stop_after_attempt(5), + retry=tenacity.retry_never, + reraise=True, + ) + self.assertRaises(tenacity.TryAgain, r, _r) + self.assertEqual(5, r.statistics["attempt_number"]) def test_retry_if_exception_message_negative_no_inputs(self): with self.assertRaises(TypeError): @@ -589,8 +611,7 @@ def test_retry_if_exception_message_negative_no_inputs(self): def test_retry_if_exception_message_negative_too_many_inputs(self): with self.assertRaises(TypeError): - tenacity.retry_if_exception_message( - message="negative", match="negative") + tenacity.retry_if_exception_message(message="negative", match="negative") class NoneReturnUntilAfterCount(object): @@ -738,14 +759,18 @@ def current_time_ms(): return int(round(time.time() * 1000)) -@retry(wait=tenacity.wait_fixed(0.05), - retry=tenacity.retry_if_result(lambda result: result is None)) +@retry( + wait=tenacity.wait_fixed(0.05), + retry=tenacity.retry_if_result(lambda result: result is None), +) def _retryable_test_with_wait(thing): return thing.go() -@retry(stop=tenacity.stop_after_attempt(3), - retry=tenacity.retry_if_result(lambda result: result is None)) +@retry( + stop=tenacity.stop_after_attempt(3), + retry=tenacity.retry_if_result(lambda result: result is None), +) def _retryable_test_with_stop(thing): return thing.go() @@ -756,8 +781,8 @@ def _retryable_test_with_exception_type_io(thing): @retry( - stop=tenacity.stop_after_attempt(3), - retry=tenacity.retry_if_exception_type(IOError)) + stop=tenacity.stop_after_attempt(3), retry=tenacity.retry_if_exception_type(IOError) +) def _retryable_test_with_exception_type_io_attempt_limit(thing): return thing.go() @@ -769,7 +794,8 @@ def _retryable_test_with_unless_exception_type_name(thing): @retry( stop=tenacity.stop_after_attempt(3), - retry=tenacity.retry_unless_exception_type(NameError)) + retry=tenacity.retry_unless_exception_type(NameError), +) def _retryable_test_with_unless_exception_type_name_attempt_limit(thing): return thing.go() @@ -782,31 +808,45 @@ def _retryable_test_with_unless_exception_type_no_input(thing): @retry( stop=tenacity.stop_after_attempt(5), retry=tenacity.retry_if_exception_message( - message=NoCustomErrorAfterCount.derived_message)) + message=NoCustomErrorAfterCount.derived_message + ), +) def _retryable_test_if_exception_message_message(thing): return thing.go() -@retry(retry=tenacity.retry_if_not_exception_message( - message=NoCustomErrorAfterCount.derived_message)) +@retry( + retry=tenacity.retry_if_not_exception_message( + message=NoCustomErrorAfterCount.derived_message + ) +) def _retryable_test_if_not_exception_message_message(thing): return thing.go() -@retry(retry=tenacity.retry_if_exception_message( - match=NoCustomErrorAfterCount.derived_message[:3] + ".*")) +@retry( + retry=tenacity.retry_if_exception_message( + match=NoCustomErrorAfterCount.derived_message[:3] + ".*" + ) +) def _retryable_test_if_exception_message_match(thing): return thing.go() -@retry(retry=tenacity.retry_if_not_exception_message( - match=NoCustomErrorAfterCount.derived_message[:3] + ".*")) +@retry( + retry=tenacity.retry_if_not_exception_message( + match=NoCustomErrorAfterCount.derived_message[:3] + ".*" + ) +) def _retryable_test_if_not_exception_message_match(thing): return thing.go() -@retry(retry=tenacity.retry_if_not_exception_message( - message=NameErrorUntilCount.derived_message)) +@retry( + retry=tenacity.retry_if_not_exception_message( + message=NameErrorUntilCount.derived_message + ) +) def _retryable_test_not_exception_message_delay(thing): return thing.go() @@ -828,13 +868,13 @@ def _retryable_test_with_exception_type_custom(thing): @retry( stop=tenacity.stop_after_attempt(3), - retry=tenacity.retry_if_exception_type(CustomError)) + retry=tenacity.retry_if_exception_type(CustomError), +) def _retryable_test_with_exception_type_custom_attempt_limit(thing): return thing.go() class TestDecoratorWrapper(unittest.TestCase): - def test_with_wait(self): start = current_time_ms() result = _retryable_test_with_wait(NoneReturnUntilAfterCount(5)) @@ -844,8 +884,9 @@ def test_with_wait(self): def test_retry_with(self): start = current_time_ms() - result = _retryable_test_with_wait.retry_with( - wait=tenacity.wait_fixed(0.1))(NoneReturnUntilAfterCount(5)) + 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) @@ -869,8 +910,7 @@ def test_with_stop_on_exception(self): print(re) def test_retry_if_exception_of_type(self): - self.assertTrue(_retryable_test_with_exception_type_io( - NoIOErrorAfterCount(5))) + self.assertTrue(_retryable_test_with_exception_type_io(NoIOErrorAfterCount(5))) try: _retryable_test_with_exception_type_io(NoNameErrorAfterCount(5)) @@ -879,12 +919,12 @@ def test_retry_if_exception_of_type(self): self.assertTrue(isinstance(n, NameError)) print(n) - self.assertTrue(_retryable_test_with_exception_type_custom( - NoCustomErrorAfterCount(5))) + self.assertTrue( + _retryable_test_with_exception_type_custom(NoCustomErrorAfterCount(5)) + ) try: - _retryable_test_with_exception_type_custom( - NoNameErrorAfterCount(5)) + _retryable_test_with_exception_type_custom(NoNameErrorAfterCount(5)) self.fail("Expected NameError") except NameError as n: self.assertTrue(isinstance(n, NameError)) @@ -892,12 +932,12 @@ def test_retry_if_exception_of_type(self): def test_retry_until_exception_of_type_attempt_number(self): try: - self.assertTrue(_retryable_test_with_unless_exception_type_name( - NameErrorUntilCount(5))) + self.assertTrue( + _retryable_test_with_unless_exception_type_name(NameErrorUntilCount(5)) + ) except NameError as e: - s = _retryable_test_with_unless_exception_type_name.\ - retry.statistics - self.assertTrue(s['attempt_number'] == 6) + s = _retryable_test_with_unless_exception_type_name.retry.statistics + self.assertTrue(s["attempt_number"] == 6) print(e) else: self.fail("Expected NameError") @@ -907,12 +947,12 @@ def test_retry_until_exception_of_type_no_type(self): # no input should catch all subclasses of Exception self.assertTrue( _retryable_test_with_unless_exception_type_no_input( - NameErrorUntilCount(5)) + NameErrorUntilCount(5) + ) ) except NameError as e: - s = _retryable_test_with_unless_exception_type_no_input.\ - retry.statistics - self.assertTrue(s['attempt_number'] == 6) + s = _retryable_test_with_unless_exception_type_no_input.retry.statistics + self.assertTrue(s["attempt_number"] == 6) print(e) else: self.fail("Expected NameError") @@ -921,7 +961,8 @@ def test_retry_until_exception_of_type_wrong_exception(self): try: # two iterations with IOError, one that returns True _retryable_test_with_unless_exception_type_name_attempt_limit( - IOErrorUntilCount(2)) + IOErrorUntilCount(2) + ) self.fail("Expected RetryError") except RetryError as e: self.assertTrue(isinstance(e, RetryError)) @@ -929,46 +970,52 @@ def test_retry_until_exception_of_type_wrong_exception(self): def test_retry_if_exception_message(self): try: - self.assertTrue(_retryable_test_if_exception_message_message( - NoCustomErrorAfterCount(3))) + self.assertTrue( + _retryable_test_if_exception_message_message(NoCustomErrorAfterCount(3)) + ) except CustomError: - print(_retryable_test_if_exception_message_message.retry. - statistics) + print(_retryable_test_if_exception_message_message.retry.statistics) self.fail("CustomError should've been retried from errormessage") def test_retry_if_not_exception_message(self): try: - self.assertTrue(_retryable_test_if_not_exception_message_message( - NoCustomErrorAfterCount(2))) + self.assertTrue( + _retryable_test_if_not_exception_message_message( + NoCustomErrorAfterCount(2) + ) + ) except CustomError: - s = _retryable_test_if_not_exception_message_message.retry.\ - statistics - self.assertTrue(s['attempt_number'] == 1) + s = _retryable_test_if_not_exception_message_message.retry.statistics + self.assertTrue(s["attempt_number"] == 1) def test_retry_if_not_exception_message_delay(self): try: - self.assertTrue(_retryable_test_not_exception_message_delay( - NameErrorUntilCount(3))) + self.assertTrue( + _retryable_test_not_exception_message_delay(NameErrorUntilCount(3)) + ) except NameError: s = _retryable_test_not_exception_message_delay.retry.statistics - print(s['attempt_number']) - self.assertTrue(s['attempt_number'] == 4) + print(s["attempt_number"]) + self.assertTrue(s["attempt_number"] == 4) def test_retry_if_exception_message_match(self): try: - self.assertTrue(_retryable_test_if_exception_message_match( - NoCustomErrorAfterCount(3))) + self.assertTrue( + _retryable_test_if_exception_message_match(NoCustomErrorAfterCount(3)) + ) except CustomError: self.fail("CustomError should've been retried from errormessage") def test_retry_if_not_exception_message_match(self): try: - self.assertTrue(_retryable_test_if_not_exception_message_message( - NoCustomErrorAfterCount(2))) + self.assertTrue( + _retryable_test_if_not_exception_message_message( + NoCustomErrorAfterCount(2) + ) + ) except CustomError: - s = _retryable_test_if_not_exception_message_message.retry.\ - statistics - self.assertTrue(s['attempt_number'] == 1) + s = _retryable_test_if_not_exception_message_message.retry.statistics + self.assertTrue(s["attempt_number"] == 1) def test_defaults(self): self.assertTrue(_retryable_default(NoNameErrorAfterCount(5))) @@ -982,11 +1029,14 @@ def test_retry_function_object(self): It raises an error upon trying to wrap it in Py2, because __name__ attribute is missing. It's fixed in Py3 but was never backported. """ + class Hello(object): def __call__(self): return "Hello" - retrying = Retrying(wait=tenacity.wait_fixed(0.01), - stop=tenacity.stop_after_attempt(3)) + + retrying = Retrying( + wait=tenacity.wait_fixed(0.01), stop=tenacity.stop_after_attempt(3) + ) h = retrying.wraps(Hello()) self.assertEqual(h(), "Hello") @@ -998,12 +1048,13 @@ def test_before_attempts(self): TestBeforeAfterAttempts._attempt_number = 0 def _before(retry_state): - TestBeforeAfterAttempts._attempt_number = \ - retry_state.attempt_number + TestBeforeAfterAttempts._attempt_number = retry_state.attempt_number - @retry(wait=tenacity.wait_fixed(1), - stop=tenacity.stop_after_attempt(1), - before=_before) + @retry( + wait=tenacity.wait_fixed(1), + stop=tenacity.stop_after_attempt(1), + before=_before, + ) def _test_before(): pass @@ -1015,12 +1066,13 @@ def test_after_attempts(self): TestBeforeAfterAttempts._attempt_number = 0 def _after(retry_state): - TestBeforeAfterAttempts._attempt_number = \ - retry_state.attempt_number + TestBeforeAfterAttempts._attempt_number = retry_state.attempt_number - @retry(wait=tenacity.wait_fixed(0.1), - stop=tenacity.stop_after_attempt(3), - after=_after) + @retry( + wait=tenacity.wait_fixed(0.1), + stop=tenacity.stop_after_attempt(3), + after=_after, + ) def _test_after(): if TestBeforeAfterAttempts._attempt_number < 2: raise Exception("testing after_attempts handler") @@ -1036,9 +1088,11 @@ def _before_sleep(retry_state): self.assertGreater(retry_state.next_action.sleep, 0) _before_sleep.attempt_number = retry_state.attempt_number - @retry(wait=tenacity.wait_fixed(0.01), - stop=tenacity.stop_after_attempt(3), - before_sleep=_before_sleep) + @retry( + wait=tenacity.wait_fixed(0.01), + stop=tenacity.stop_after_attempt(3), + before_sleep=_before_sleep, + ) def _test_before_sleep(): if _before_sleep.attempt_number < 2: raise Exception("testing before_sleep_attempts handler") @@ -1055,15 +1109,19 @@ def _before_sleep_log_raises(self, get_call_fn): logger.addHandler(handler) try: _before_sleep = tenacity.before_sleep_log(logger, logging.INFO) - retrying = Retrying(wait=tenacity.wait_fixed(0.01), - stop=tenacity.stop_after_attempt(3), - before_sleep=_before_sleep) + retrying = Retrying( + wait=tenacity.wait_fixed(0.01), + stop=tenacity.stop_after_attempt(3), + before_sleep=_before_sleep, + ) get_call_fn(retrying)(thing.go) finally: logger.removeHandler(handler) - etalon_re = (r"^Retrying .* in 0\.01 seconds as it raised " - r"(IO|OS)Error: Hi there, I'm an IOError\.$") + etalon_re = ( + r"^Retrying .* in 0\.01 seconds as it raised " + r"(IO|OS)Error: Hi there, I'm an IOError\.$" + ) self.assertEqual(len(handler.records), 2) fmt = logging.Formatter().format self.assertRegexpMatches(fmt(handler.records[0]), etalon_re) @@ -1083,21 +1141,25 @@ def test_before_sleep_log_raises_with_exc_info(self): handler = CapturingHandler() logger.addHandler(handler) try: - _before_sleep = tenacity.before_sleep_log(logger, - logging.INFO, - exc_info=True) - retrying = Retrying(wait=tenacity.wait_fixed(0.01), - stop=tenacity.stop_after_attempt(3), - before_sleep=_before_sleep) + _before_sleep = tenacity.before_sleep_log( + logger, logging.INFO, exc_info=True + ) + retrying = Retrying( + wait=tenacity.wait_fixed(0.01), + stop=tenacity.stop_after_attempt(3), + before_sleep=_before_sleep, + ) retrying(thing.go) finally: logger.removeHandler(handler) - etalon_re = re.compile(r"^Retrying .* in 0\.01 seconds as it raised " - r"(IO|OS)Error: Hi there, I'm an IOError\.{0}" - r"Traceback \(most recent call last\):{0}" - r".*$".format('\n'), - flags=re.MULTILINE) + etalon_re = re.compile( + r"^Retrying .* in 0\.01 seconds as it raised " + r"(IO|OS)Error: Hi there, I'm an IOError\.{0}" + r"Traceback \(most recent call last\):{0}" + r".*$".format("\n"), + flags=re.MULTILINE, + ) self.assertEqual(len(handler.records), 2) fmt = logging.Formatter().format self.assertRegexpMatches(fmt(handler.records[0]), etalon_re) @@ -1111,18 +1173,21 @@ def test_before_sleep_log_returns(self, exc_info=False): handler = CapturingHandler() logger.addHandler(handler) try: - _before_sleep = tenacity.before_sleep_log(logger, - logging.INFO, - exc_info=exc_info) + _before_sleep = tenacity.before_sleep_log( + logger, logging.INFO, exc_info=exc_info + ) _retry = tenacity.retry_if_result(lambda result: result is None) - retrying = Retrying(wait=tenacity.wait_fixed(0.01), - stop=tenacity.stop_after_attempt(3), - retry=_retry, before_sleep=_before_sleep) + retrying = Retrying( + wait=tenacity.wait_fixed(0.01), + stop=tenacity.stop_after_attempt(3), + retry=_retry, + before_sleep=_before_sleep, + ) retrying(thing.go) finally: logger.removeHandler(handler) - etalon_re = r'^Retrying .* in 0\.01 seconds as it returned None\.$' + etalon_re = r"^Retrying .* in 0\.01 seconds as it returned None\.$" self.assertEqual(len(handler.records), 2) fmt = logging.Formatter().format self.assertRegexpMatches(fmt(handler.records[0]), etalon_re) @@ -1133,15 +1198,16 @@ def test_before_sleep_log_returns_with_exc_info(self): class TestReraiseExceptions(unittest.TestCase): - def test_reraise_by_default(self): calls = [] - @retry(wait=tenacity.wait_fixed(0.1), - stop=tenacity.stop_after_attempt(2), - reraise=True) + @retry( + wait=tenacity.wait_fixed(0.1), + stop=tenacity.stop_after_attempt(2), + reraise=True, + ) def _reraised_by_default(): - calls.append('x') + calls.append("x") raise KeyError("Bad key") self.assertRaises(KeyError, _reraised_by_default) @@ -1150,10 +1216,9 @@ def _reraised_by_default(): def test_reraise_from_retry_error(self): calls = [] - @retry(wait=tenacity.wait_fixed(0.1), - stop=tenacity.stop_after_attempt(2)) + @retry(wait=tenacity.wait_fixed(0.1), stop=tenacity.stop_after_attempt(2)) def _raise_key_error(): - calls.append('x') + calls.append("x") raise KeyError("Bad key") def _reraised_key_error(): @@ -1168,11 +1233,13 @@ def _reraised_key_error(): def test_reraise_timeout_from_retry_error(self): calls = [] - @retry(wait=tenacity.wait_fixed(0.1), - stop=tenacity.stop_after_attempt(2), - retry=lambda retry_state: True) + @retry( + wait=tenacity.wait_fixed(0.1), + stop=tenacity.stop_after_attempt(2), + retry=lambda retry_state: True, + ) def _mock_fn(): - calls.append('x') + calls.append("x") def _reraised_mock_fn(): try: @@ -1186,19 +1253,20 @@ def _reraised_mock_fn(): def test_reraise_no_exception(self): calls = [] - @retry(wait=tenacity.wait_fixed(0.1), - stop=tenacity.stop_after_attempt(2), - retry=lambda retry_state: True, - reraise=True) + @retry( + wait=tenacity.wait_fixed(0.1), + stop=tenacity.stop_after_attempt(2), + retry=lambda retry_state: True, + reraise=True, + ) def _mock_fn(): - calls.append('x') + calls.append("x") self.assertRaises(tenacity.RetryError, _mock_fn) self.assertEqual(2, len(calls)) class TestStatistics(unittest.TestCase): - def test_stats(self): @retry() def _foobar(): @@ -1206,7 +1274,7 @@ def _foobar(): self.assertEqual({}, _foobar.retry.statistics) _foobar() - self.assertEqual(1, _foobar.retry.statistics['attempt_number']) + self.assertEqual(1, _foobar.retry.statistics["attempt_number"]) def test_stats_failing(self): @retry(stop=tenacity.stop_after_attempt(2)) @@ -1216,13 +1284,12 @@ def _foobar(): self.assertEqual({}, _foobar.retry.statistics) try: _foobar() - except Exception: # noqa: B902 + except Exception: # noqa: B902 pass - self.assertEqual(2, _foobar.retry.statistics['attempt_number']) + self.assertEqual(2, _foobar.retry.statistics["attempt_number"]) class TestRetryErrorCallback(unittest.TestCase): - def setUp(self): self._attempt_number = 0 self._callback_called = False @@ -1240,8 +1307,10 @@ def retry_error_callback(retry_state): retry_error_callback.called_times = 0 - @retry(stop=tenacity.stop_after_attempt(num_attempts), - retry_error_callback=retry_error_callback) + @retry( + stop=tenacity.stop_after_attempt(num_attempts), + retry_error_callback=retry_error_callback, + ) def _foobar(): self._attempt_number += 1 raise Exception("This exception should not be raised") @@ -1326,6 +1395,7 @@ def f(): if len(f.calls) <= 1: raise Exception("Retry it!") return 42 + f.calls = [] retry = Retrying() @@ -1341,6 +1411,7 @@ def f(): if len(f.calls) <= 1: raise CustomError("Don't retry!") return 42 + f.calls = [] retry = Retrying(retry=tenacity.retry_if_exception_type(IOError)) @@ -1352,6 +1423,7 @@ def test_retry_error(self): def f(): f.calls.append(len(f.calls) + 1) raise Exception("Retry it!") + f.calls = [] retry = Retrying(stop=tenacity.stop_after_attempt(2)) @@ -1366,6 +1438,7 @@ class CustomError(Exception): def f(): f.calls.append(len(f.calls) + 1) raise CustomError("Retry it!") + f.calls = [] retry = Retrying(reraise=True, stop=tenacity.stop_after_attempt(2)) @@ -1384,9 +1457,9 @@ def invoke(retry, f): class TestRetryException(unittest.TestCase): - def test_retry_error_is_pickleable(self): import pickle + expected = RetryError(last_attempt=123) pickled = pickle.dumps(expected) actual = pickle.loads(pickled) @@ -1394,10 +1467,8 @@ def test_retry_error_is_pickleable(self): class TestRetryTyping(unittest.TestCase): - @pytest.mark.skipif( - sys.version_info < (3, 0), - reason="typeguard not supported for python 2" + sys.version_info < (3, 0), reason="typeguard not supported for python 2" ) def test_retry_type_annotations(self): """The decorator should maintain types of decorated functions.""" @@ -1423,9 +1494,7 @@ def num_to_str(number): # These raise TypeError exceptions if they fail check_type("with_raw", with_raw, typing.Callable[[int], str]) check_type("with_raw_result", with_raw_result, str) - check_type( - "with_constructor", with_constructor, typing.Callable[[int], str] - ) + check_type("with_constructor", with_constructor, typing.Callable[[int], str]) check_type("with_constructor_result", with_constructor_result, str) @@ -1433,7 +1502,7 @@ def num_to_str(number): def reports_deprecation_warning(): __tracebackhide__ = True oldfilters = copy(warnings.filters) - warnings.simplefilter('always') + warnings.simplefilter("always") try: with pytest.warns(DeprecationWarning): yield @@ -1441,7 +1510,7 @@ def reports_deprecation_warning(): warnings.filters = oldfilters -class TestMockingSleep(): +class TestMockingSleep: RETRY_ARGS = dict( wait=tenacity.wait_fixed(0.1), stop=tenacity.stop_after_attempt(5), @@ -1486,5 +1555,5 @@ def test_decorated_retry_with(self, mock_sleep): assert mock_sleep.call_count == 1 -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tenacity/tests/test_tornado.py b/tenacity/tests/test_tornado.py index 23380170..1f72148c 100644 --- a/tenacity/tests/test_tornado.py +++ b/tenacity/tests/test_tornado.py @@ -67,9 +67,10 @@ def test_old_tornado(self): @retry def retryable(thing): pass + finally: gen.is_coroutine_function = old_attr -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tenacity/tornadoweb.py b/tenacity/tornadoweb.py index bf734477..243cf5de 100644 --- a/tenacity/tornadoweb.py +++ b/tenacity/tornadoweb.py @@ -24,10 +24,7 @@ class TornadoRetrying(BaseRetrying): - - def __init__(self, - sleep=gen.sleep, - **kwargs): + def __init__(self, sleep=gen.sleep, **kwargs): super(TornadoRetrying, self).__init__(**kwargs) self.sleep = sleep @@ -35,8 +32,7 @@ def __init__(self, def __call__(self, fn, *args, **kwargs): self.begin(fn) - retry_state = RetryCallState( - retry_object=self, fn=fn, args=args, kwargs=kwargs) + retry_state = RetryCallState(retry_object=self, fn=fn, args=args, kwargs=kwargs) while True: do = self.iter(retry_state=retry_state) if isinstance(do, DoAttempt): diff --git a/tenacity/wait.py b/tenacity/wait.py index 235a24bd..2f981c89 100644 --- a/tenacity/wait.py +++ b/tenacity/wait.py @@ -67,9 +67,9 @@ def __init__(self, min=0, max=1): # noqa self.wait_random_max = max def __call__(self, retry_state): - return (self.wait_random_min + - (random.random() * - (self.wait_random_max - self.wait_random_min))) + return self.wait_random_min + ( + random.random() * (self.wait_random_max - self.wait_random_min) + ) class wait_combine(wait_base): @@ -102,8 +102,7 @@ def __init__(self, *strategies): self.strategies = strategies def __call__(self, retry_state): - wait_func_no = min(max(retry_state.attempt_number, 1), - len(self.strategies)) + wait_func_no = min(max(retry_state.attempt_number, 1), len(self.strategies)) wait_func = self.strategies[wait_func_no - 1] return wait_func(retry_state=retry_state) @@ -121,9 +120,7 @@ def __init__(self, start=0, increment=100, max=_utils.MAX_WAIT): # noqa self.max = max def __call__(self, retry_state): - result = self.start + ( - self.increment * (retry_state.attempt_number - 1) - ) + result = self.start + (self.increment * (retry_state.attempt_number - 1)) return max(0, min(result, self.max)) @@ -182,6 +179,5 @@ class wait_random_exponential(wait_exponential): """ def __call__(self, retry_state): - high = super(wait_random_exponential, self).__call__( - retry_state=retry_state) + high = super(wait_random_exponential, self).__call__(retry_state=retry_state) return random.uniform(0, high) diff --git a/tox.ini b/tox.ini index d9a7528c..20f3b12a 100644 --- a/tox.ini +++ b/tox.ini @@ -23,6 +23,7 @@ deps = flake8 flake8-docstrings flake8-rst-docstrings flake8-logging-format + flake8-black commands = flake8 [testenv:reno] @@ -33,5 +34,5 @@ commands = reno {posargs} [flake8] exclude = .tox,.eggs show-source = true -ignore = D100,D101,D102,D103,D104,D105,D107,G200,G201,W503,W504 +ignore = D100,D101,D102,D103,D104,D105,D107,G200,G201,W503,W504,E501 enable-extensions=G