Skip to content

Uu#1

Open
Rwadxvv wants to merge 183 commits intoBATS:masterfrom
jd:main
Open

Uu#1
Rwadxvv wants to merge 183 commits intoBATS:masterfrom
jd:main

Conversation

@Rwadxvv
Copy link

@Rwadxvv Rwadxvv commented Nov 15, 2022

Y

asqui and others added 30 commits October 26, 2020 09:06
* start_time == outcome_timestamp is possible
* logging.Formatter uses explicitly hard-coded `\n` newlines
  (as opposed to using the platform-specific os.linesep)
...rather than sometimes allowing a default return of `None`

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: Slava Skvortsov <kondor1995@mail.ru>
* Fix iscoroutinefunction check (inspect & asyncio)

* Add real async wrap & preserve retry attributes

* Adjust to pep8

* Add test to ensure retryable_coroutine attributes

* Fix `blank line contains whitespace` pep8 error
* chore: add missing noqa statements

* docs: fix autoinstanceattribute
chore: add support for Python 3.9
* Copy whole internal state when retry_with (#233)

Both `retry_error_cls` and `retry_error_callback` were missing from
the copy, resulting in a copy that presents a different behavior
than the original function.

* Apply review feedback

- define `_first_set` only once
- get away with unittest
- use pytest.raises
* Warn when calling retry() on retry_base (#269)

* Wrap warning message string to 79 columns (PEP 8)
This should make sure we don't forget to put a release note before merging a
PR.

Related to #284
ci(mergify): force release notes to be present
* Make logger more compatible

* Add release note

* Fix black formatting

* Ignore D402 error in flake8

* Update PR

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
* Add retry_except_exception_type

Fixes #256

* Apply suggestions from code review

Co-authored-by: Julien Danjou <julien@danjou.info>

* rename 'except' to 'if not'

* fix test

* rename again

Co-authored-by: Julien Danjou <julien@danjou.info>
* Removed all transitional requirements (including `six`)
* Most type annotations fixed.
* Python 3.10 tested.
* Most part of code is type annotated.

Co-authored-by: Julien Danjou <julien@danjou.info>

Co-authored-by: Julien Danjou <julien@danjou.info>
- Use `black` for code formatting and validate using `black --check`. Code compatibility: py26-py39.
- Enforce maximal line length to 120 symbols
Use black instead of "flake8-black" on CI.
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
jd and others added 30 commits February 18, 2026 16:26
- Pin runner to ubuntu-24.04 for reproducibility (matches CI)
- Drop contents:write permission (only id-token:write needed
  for PyPI trusted publishing)

Change-Id: I62d46b341d351e3576d3a1e37bc203949c368c1d
On Python 3.11+, Self is available in the standard typing module.
Only fall back to typing_extensions for Python 3.10 (under
TYPE_CHECKING only, so no runtime dependency added).


Change-Id: I3e39dfbf6ab99b6005026315ff7f070b0910a9dc

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Tornado 4.x and 5.x are long EOL. Tornado 6.0 was released in
March 2019 and is the minimum version that supports Python 3.10+
(our minimum). This aligns the declared floor with reality since
older versions cannot install on supported Python versions anyway.


Change-Id: I821043167849e8df30ef6f7d37409dfc707a7cd3

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Remove the sys.path hack (unnecessary — tenacity is installed as a
package when running via uv). Remove doctest_path (sphinx.ext.doctest
finds tenacity through the installed package). Remove commented-out
sphinx options that were never configured. Remove unused os/sys imports.


Change-Id: I9ab61b9422939b1b396fdc4ad66f25f834e74315

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
The __all__ list already declares public exports, making the F401
noqa comments on re-export imports unnecessary. Also remove bare
noqa on iter/begin_iter (was suppressing UP007) and fix the Union
type annotation to use X | Y syntax.


Change-Id: I7327e94a653fb97a3497fcddf0566b542746744a

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Enable C4, FURB, PERF, PIE, RET, RUF, SIM, TCH rule sets.

Key changes:
- Remove all stale noqa comments across the codebase (RUF100)
- Sort __all__ alphabetically (RUF022)
- Remove superfluous else after return/raise (RET505/RET506)
- Replace try/except/pass with contextlib.suppress (SIM105)
- Move type-only imports into TYPE_CHECKING blocks (TC001/TC003)
- Quote type expressions in typing.cast() calls (TC006)
- Use list comprehension instead of loop-append (PERF401)
- Fix Cyrillic character in docstring (RUF002)
- Remove unnecessary int() wrapping round() (RUF046)
- Replace dict() call with literal (C408)

Ignored rules:
- RUF003: ambiguous unicode in comments (copyright holder names)
- RUF005: iterable unpacking vs concatenation (less readable)
- RUF012: mutable class defaults (false positive on test fixtures)
- SIM108: ternary expressions (less readable in context)


Change-Id: I88ea78e2254b8a9fee00743464e44e6d33400f47

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Remove blanket mypy disable comments from test_tenacity.py,
test_asyncio.py, test_tornado.py, and test_after.py. Add type
annotations to all test methods, helper functions, and inner
functions so they pass mypy strict without suppressions.

Targeted type: ignore comments are used only for intentional
type mismatches in tests (e.g. passing None where BaseRetrying
is expected) and dynamically-added attributes on decorated
functions (.statistics, .retry, .retry_with).


Change-Id: I872c723b28364cf30c546c767ad665336ef62df4

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Remove the positional-only marker (/) from LoggerProtocol.log().
logging.Logger.log() defines msg as a regular parameter, so the
positional-only constraint caused mypy to reject logging.Logger
as incompatible with the protocol.

Closes #554


Change-Id: Icc8ffaff0d828c5103c13e97dd2ca7701089713f

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This field was declared and reset but never read or written anywhere
in the codebase. The actual delay tracking uses
statistics["delay_since_first_attempt"] instead.


Change-Id: If82d3ab8694516b21cae6d33147694e19b7cdc45

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
reraise() is typed as NoReturn and always raises internally.
The outer `raise` keyword was dead code that could never execute,
and was misleading since it suggested reraise() returns an exception
rather than raising one directly.


Change-Id: I8ef31ce3d62db7d56adb0053855a1131b54f1fa5

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
typing.Pattern has been deprecated since Python 3.9 in favor of
re.Pattern. Since we require Python >=3.10, use the standard form.


Change-Id: Ic4a74dff54b2877ff64112220c6805f17c1ffefc

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- "there existence" → "their existence"
- "there own view" → "their own view"
- "some what" → "somewhat"
- "to wraps for" → "to wrap for"


Change-Id: Ie9509ff1d7de851708793c9023f3fd728681a868

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
`RetryCallState.seconds_since_start` returns None when
`outcome_timestamp` is not set. The `%` format operator in `after_log`
would crash with a TypeError in this case. Fall back to "?" when the
value is None.


Change-Id: Ib18f8aced63c084204b2d4719579fae4b8e557f5

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
When using `Retrying` or `AsyncRetrying` as a context manager, log
callbacks showed '<unknown>' as the function name since no `fn` is
set. A new `name` parameter allows users to provide a meaningful
identifier:

    for attempt in Retrying(name='ws_listener', before_sleep=before_sleep_log(...)):
        with attempt:
            ...

`RetryCallState.get_fn_name()` is introduced as the single source of
truth for resolving the display name: it returns the decorated
function's qualified name when used as a decorator, falls back to
`str(retry_object)` in context manager mode. `BaseRetrying.__str__`
returns `name` if set, else '<unknown>'. The three log helpers
(before_log, after_log, before_sleep_log) all use `get_fn_name()`
instead of the repeated `fn is None` boilerplate.

Closes #273, closes #333


Change-Id: I717d4d3977028b499612cecb567d0ebc49b5f539

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
#599)

Add an attribute reference for RetryCallState in the docs, listing
attempt_number, outcome, seconds_since_start, idle_for, and start_time.
Includes a short example showing how to log total elapsed time via the
after callback — directly addressing the common confusion between
seconds_since_start (wall-clock elapsed) and idle_for (sleep time only).

Closes #303


Change-Id: I1dbaa9072c2f47822e05f859514a42dcf83ae6d3

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Add _RetryDecorated Protocol that combines the original callable
signature (via ParamSpec) with the retry control attributes. Update
all retry() overloads, _AsyncRetryDecorator, and wraps() methods to
return _RetryDecorated[P, R] instead of bare WrappedFn.

This lets mypy see .retry, .statistics, and .retry_with on decorated
functions without # type: ignore, fixing a long-standing typing gap.

Removes ~30 now-unnecessary type: ignore comments from tests.

Closes #346


Change-Id: I8c2bc7b49a0cb51175a8e0bf33d9742f10bc49a0

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Add examples for two frequently asked usage patterns:
- Running setup code between retries (before_sleep for reconnection)
- Accessing the attempt number inside the function (iterator API)

These address recurring questions from issues #298, #316, #344, #361.


Change-Id: Ic4cea9f63db72a6f9cb47287597a8dacffdc8533

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
)

Closes #421


Change-Id: I104d68d8dbfe41282632b8183c267aa88d682be3

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…606)

The delegation to __ror__/__rand__ introduced for async retry support
broke composing retry_base instances with plain callables. Add an
isinstance guard so delegation only happens for retry_base subclasses,
while plain callables fall through to direct retry_all/retry_any wrapping.

Also widen type annotations on retry_any/retry_all and the operator
methods to accept RetryBaseT (the union of retry_base and plain
callables), matching the runtime behavior.

Fixes #481


Change-Id: I24e081b67dfa7e184266621f73cec4de5177ea25

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
AttemptManager now supports `async with` in addition to `with`,
allowing cleaner usage inside `async for` loops.

Closes #469


Change-Id: If6d24d58fbb4a0eaba5b62b20f6821d2ccd073a9

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
When enabled=False, the decorated function is called directly without
any retry logic. This is useful during development or testing.

Closes #467


Change-Id: I2ae833504b87df74ac94503c0c7059a3587730b9

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
When composing multiple retry conditions like `a | b | c`, the
operators now flatten into `retry_any(a, b, c)` instead of nesting
`retry_any(retry_any(a, b), c)`. This reduces call stack depth
when debugging complex retry conditions.

Flattening is done in __ror__/__rand__ (where containers are created)
and in retry_any.__ror__/retry_all.__rand__ (to extend existing
containers). Async versions get the same treatment.

Fixes #476


Change-Id: I3a58c9dfeed2309427e65a1c79cb9ac252db0c2a

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Fixes #64
Fixes #66
Fixes #138

Document that @Retry does not support generator functions, and that
generators passed as arguments to retried functions will be exhausted
after the first attempt. Include a workaround using factory functions.


Change-Id: I4fe3ba2d82d1204a7f583b054064999dc1720a03

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…#615)

Add __getstate__/__setstate__ to BaseRetrying to exclude the unpicklable
threading.local object during serialization. Replace lambdas in retry
strategy classes with bound methods so they can be pickled with standard
pickle.

Fixes #147


Change-Id: Ia3cb014c783078a08492014bb7088f10f95e4ae9

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Fixes #613

func.retry.statistics was always empty because func.retry points to
the original Retrying object, but begin() (which populates statistics)
is only called on the per-invocation copy. Fix by pointing the
original's _local.statistics to the copy's statistics dict so they
share the same object.


Change-Id: I0299c76659ae6fc0c6354efae22b17946dca223c

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Replace t.Optional, t.Union, and typing.Union with X | None / X | Y
union syntax (PEP 604).


Change-Id: I569081564348eac6cdfd934c8abcc92b144d35c6

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Change-Id: If2ab751202beaf911d9c8127982c4692ec686acc

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
The contextmanager helper was defined but never called. Also removes
the now-unused warnings, contextmanager, and copy imports.


Change-Id: I9cbcd372905800951e853543ae3d878f76370c7a

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- Add PGH (pygrep-hooks): enforces specific `# type: ignore[code]`
- Add PYI (flake8-pyi): catches redundant numeric unions, stub issues
- Rename deprecated TCH prefix to TC
- Suppress PYI036 (false positive on string-quoted __exit__ annotations)
- Fix PYI041: simplify `int | float` to `float` in wait_exponential


Change-Id: If3863e7940c5f32e5a39d7719984f32684799bf9

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Enable 11 new zero-violation guardrail rules (ASYNC, DTZ, EXE, FLY,
ICN, ISC, LOG, PTH, SLF, SLOT, T10) and RSE (8 auto-fixed
unnecessary parentheses on raises).

Suppress ASYNC105 on the intentional unawaited trio.sleep return in
_portable_async_sleep.


Change-Id: I0c9ce63d66f43757ed2292d6151c031a4a21362d

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.