Initial commit

This commit is contained in:
kdusek
2025-12-09 12:13:01 +01:00
commit 8e654ed209
13332 changed files with 2695056 additions and 0 deletions

View File

@@ -0,0 +1,137 @@
Metadata-Version: 2.4
Name: stamina
Version: 25.1.0
Summary: Production-grade retries made easy.
Project-URL: Documentation, https://stamina.hynek.me/
Project-URL: GitHub, https://github.com/hynek/stamina
Project-URL: Changelog, https://github.com/hynek/stamina/blob/main/CHANGELOG.md
Project-URL: Funding, https://github.com/sponsors/hynek
Project-URL: Mastodon, https://mastodon.social/@hynek
Project-URL: Bluesky, https://bsky.app/profile/hynek.me
Project-URL: Twitter, https://twitter.com/hynek
Author-email: Hynek Schlawack <hs@ox.cx>
License-Expression: MIT
License-File: LICENSE
Keywords: reliability,retries,retry
Classifier: Development Status :: 5 - Production/Stable
Classifier: Framework :: AsyncIO
Classifier: Framework :: Trio
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.8
Requires-Dist: tenacity
Requires-Dist: typing-extensions; python_version < '3.10'
Provides-Extra: dev
Requires-Dist: anyio; extra == 'dev'
Requires-Dist: dirty-equals; extra == 'dev'
Requires-Dist: mypy>=1.4; extra == 'dev'
Requires-Dist: nox>=2024.3.2; extra == 'dev'
Requires-Dist: prometheus-client; extra == 'dev'
Requires-Dist: pytest; extra == 'dev'
Requires-Dist: structlog; extra == 'dev'
Requires-Dist: tomli; (python_version < '3.11') and extra == 'dev'
Requires-Dist: trio; extra == 'dev'
Requires-Dist: uv; extra == 'dev'
Provides-Extra: docs
Requires-Dist: furo; extra == 'docs'
Requires-Dist: myst-parser; extra == 'docs'
Requires-Dist: prometheus-client; extra == 'docs'
Requires-Dist: sphinx-copybutton; extra == 'docs'
Requires-Dist: sphinx-notfound-page; extra == 'docs'
Requires-Dist: sphinx>=7.2.2; extra == 'docs'
Requires-Dist: structlog; extra == 'docs'
Provides-Extra: tests
Requires-Dist: anyio; extra == 'tests'
Requires-Dist: dirty-equals; extra == 'tests'
Requires-Dist: pytest; extra == 'tests'
Provides-Extra: typing
Requires-Dist: mypy>=1.4; extra == 'typing'
Description-Content-Type: text/markdown
# *stamina*: Production-grade Retries Made Easy
Transient failures are common in distributed systems.
To make your systems resilient, you need to **retry** failed operations.
But bad retries can make things *much worse*.
*stamina* is an opinionated wrapper around the great-but-unopinionated [Tenacity](https://tenacity.readthedocs.io/) package.
Our goal is to be as **ergonomic** as possible, while doing the **right thing by default**, and minimizing the potential for **misuse**.
It is the result of years of copy-pasting the same configuration over and over again:
- Retry only on certain exceptions or even a subset of them by introspecting them first using a predicate.
- Exponential **backoff** with **jitter** between retries.
- Limit the number of retries **and** total time.
- Automatic **async** support including [Trio](https://trio.readthedocs.io/).
- Preserve **type hints** of the decorated callable.
- Flexible **instrumentation** with [Prometheus](https://github.com/prometheus/client_python), [*structlog*](https://www.structlog.org/), and standard library's `logging` support out-of-the-box.
- Dedicated support for **testing** that allows to _globally_ deactivate retries, or to limit the number of retries and to remove backoffs.
For example:
```python
import httpx
import stamina
@stamina.retry(on=httpx.HTTPError, attempts=3)
def do_it(code: int) -> httpx.Response:
resp = httpx.get(f"https://httpbin.org/status/{code}")
resp.raise_for_status()
return resp
```
<!-- end docs index -->
**Async** callables work use the same API and it's possible to retry **arbitrary blocks**, too.
Check out our [tutorial](https://stamina.hynek.me/en/latest/tutorial.html) for more examples!
Or, if you prefer video, here's a brief introduction into retries and *stamina*:
[![Watch the video](https://img.youtube.com/vi/BxikFuvaT1Y/maxresdefault.jpg)](https://youtu.be/BxikFuvaT1Y)
## Release Information
### Added
- *cap* argument to `stamina.set_testing()`.
By default, the value passed as *attempts* is used strictly.
When `cap=True`, it is used as an upper cap; that means that if the original attempts number is lower, it's not changed.
[#80](https://github.com/hynek/stamina/pull/80)
- `stamina.set_testing()` can now be used as a context manager.
[#94](https://github.com/hynek/stamina/pull/94)
- Instrumentation hooks can now can return context managers.
If they do, they are entered when a retry is scheduled and exited right before the retry is attempted.
[#95](https://github.com/hynek/stamina/pull/95)
---
[Full Changelog →](https://github.com/hynek/stamina/blob/main/CHANGELOG.md)
## Credits
*stamina* is written by [Hynek Schlawack](https://hynek.me/) and distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.
The development is kindly supported by my employer [Variomedia AG](https://www.variomedia.de/) and all my amazing [GitHub Sponsors](https://github.com/sponsors/hynek).
This project would not be possible without the years of incredible work that went into [Tenacity](https://tenacity.readthedocs.io/).
## *stamina* for Enterprise
Available as part of the [Tidelift Subscription](https://tidelift.com/?utm_source=lifter&utm_medium=referral&utm_campaign=hynek).
The maintainers of *stamina* and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open-source packages you use to build your applications.
Save time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use.

View File

@@ -0,0 +1,26 @@
stamina-25.1.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
stamina-25.1.0.dist-info/METADATA,sha256=knYt3sC7fugfcPrhUitXnjI7H-cTc6co0SX0cLC39fA,5872
stamina-25.1.0.dist-info/RECORD,,
stamina-25.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
stamina-25.1.0.dist-info/licenses/LICENSE,sha256=vm_ejQmrgTxa8Gnxhp_JSxyja-9_2ZSXA4asa61kYho,1101
stamina/__init__.py,sha256=yYk1pBBuIzdCwEEzPpRWXrSqLHITIpegLpk8INWgBU4,859
stamina/__pycache__/__init__.cpython-310.pyc,,
stamina/__pycache__/_config.cpython-310.pyc,,
stamina/__pycache__/_core.cpython-310.pyc,,
stamina/__pycache__/typing.cpython-310.pyc,,
stamina/_config.py,sha256=7irZDv1S5au1LB_eSEZGWgxrcnKWWqBxaVzWbuotwk0,4808
stamina/_core.py,sha256=61RBSloGkqrb92zLUcwquxv6glzabAOWWTKvlRDF61k,21355
stamina/instrumentation/__init__.py,sha256=fLCjtKMed0UoNPJ0vDimVemWZ5OBByBG_rQHZH1DBBA,647
stamina/instrumentation/__pycache__/__init__.cpython-310.pyc,,
stamina/instrumentation/__pycache__/_data.cpython-310.pyc,,
stamina/instrumentation/__pycache__/_hooks.cpython-310.pyc,,
stamina/instrumentation/__pycache__/_logging.cpython-310.pyc,,
stamina/instrumentation/__pycache__/_prometheus.cpython-310.pyc,,
stamina/instrumentation/__pycache__/_structlog.cpython-310.pyc,,
stamina/instrumentation/_data.py,sha256=_Sl7jVJOW9mgbwndQ1z2psGiz8lP6ZeWfQ1M4blm_jo,2603
stamina/instrumentation/_hooks.py,sha256=or1CQwskgQA2VEku5e8dpoWQzYLJlglHqqtgq-YlhFI,2128
stamina/instrumentation/_logging.py,sha256=-CcnW2CVpw6GiOZxf4V249aMhQ-KZgEY-FMtp79ZlaA,1158
stamina/instrumentation/_prometheus.py,sha256=WFkKEiw-O3N-Xb00qh9rxxuhfIAFuk9Jsx40o3t1I3w,1632
stamina/instrumentation/_structlog.py,sha256=2m3TnDnf_-PZLFiLJ7sv6L-G7ZSbiXyxKdWsXGi3UUI,924
stamina/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
stamina/typing.py,sha256=x9nlmkeotN72RU2DmN54Y-bbOI_PEbIdBMPilOY2Luw,223

View File

@@ -0,0 +1,4 @@
Wheel-Version: 1.0
Generator: hatchling 1.27.0
Root-Is-Purelib: true
Tag: py3-none-any

View File

@@ -0,0 +1,20 @@
MIT License
Copyright (c) 2022 Hynek Schlawack and the stamina contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.