🐍 PyEssential
A growing collection of Python utilities and decorators to simplify common development tasks.
✨ Features
PyEssential aims to be the go-to library for small, reusable tools that you often find yourself writing from scratch. It has no dependencies.
- Decorators:
@timeitfor benchmarking,@retrywith exponential backoff, and@deprecatedfor marking old code.@timeitand@retryalso work withasyncfunctions. - Generators: Secure random integers and secret keys.
- Logging: A
Loggerwith separate log files for input, output and errors. - Command line: Check your installed version with
pyessential --version. - Typing: Ships a
py.typedmarker so editors and type checkers can use its type hints. - Scalability: Structured for easy addition of new utility groups (e.g.,
networking,file_io,validation).
🚀 Installation
Requires Python 3.9+
pip install pyessential
To upgrade to the latest release:
pip install --upgrade pyessential
📖 Usage
@timeit
Prints how long a function took, even if it raises. Works with async def functions too.
from pyessential.decorators import timeit
@timeit
def slow_function():
sum(range(1_000_000))
slow_function()
# [slow_function] executed in 0.0123 seconds.
@retry
Retries a function when it raises, waiting longer between each attempt. After the last attempt, the original exception is re-raised.
from pyessential.decorators import retry
@retry(tries=4, delay=0.5, backoff=2, exceptions=(ConnectionError, TimeoutError))
def fetch_data():
...
This waits 0.5s, 1s, then 2s between attempts. Only the listed exceptions trigger a retry; anything else is raised immediately.
| Option | Meaning |
|---|---|
tries |
Total attempts, including the first (default 3) |
delay |
Seconds to wait after the first failure (default 1.0) |
backoff |
Multiplier applied to the wait after each failure (default 2.0; use 1 for a constant delay) |
max_delay |
Upper limit for any single wait |
jitter |
Up to this many extra random seconds added to each wait |
exceptions |
Exception class or tuple of classes that trigger a retry (default Exception) |
on_retry |
Callback on_retry(exc, attempt, wait), e.g. for logging |
@deprecated
Emits a DeprecationWarning when the function or class is used.
from pyessential.decorators import deprecated
@deprecated("use new_func instead", version="0.2.0")
def old_func():
...
Python hides DeprecationWarning by default outside of __main__ and test runs. Pass category=FutureWarning if you want end users to always see it.
Random generators
from pyessential import generate_random_int, generate_secret_key
generate_random_int(1, 10) # e.g. 7 (both ends are included)
generate_secret_key(16) # 32 hex characters (the length is in bytes)
Logger
from pyessential import Logger
with Logger(log_name="my_app", log_dir="logs", enable_console=True) as log:
log.info("Application started")
log.error("Something went wrong")
Command line
pyessential --version
python -m pyessential --version # also works
🛠️ Development
git clone https://github.com/Abhi39054/PyEssential.git
cd PyEssential
pip install -e .
pip install pytest
pytest
Releasing
- Move the entries under
[Unreleased]inCHANGELOG.mdto a new version heading with today's date. - Bump the version in
pyessential/_version.py, commit, and push tomain:
git commit -am "chore: bump version to X.Y.Z"
git push origin main
- Tag the release and push the tag:
git tag -a vX.Y.Z -m "Release X.Y.Z"
git push origin vX.Y.Z
- CI runs the tests, builds the package, publishes to TestPyPI, waits for approval, publishes to PyPI, and creates the GitHub Release.
The tag must match the version in _version.py (vX.Y.Z ↔ X.Y.Z), or the build fails.
📝 Changelog
See CHANGELOG.md for what changed in each release.
🤝 Contributing
Contributions are welcome. See CONTRIBUTING.md.
📄 License
Released under the MIT License.
Metadata
Release files for pyessential 0.1.6
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pyessential-0.1.6.tar.gz | 17.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pyessential-0.1.6-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 30.2 kB
Release files / pyessential-0.1.6.tar.gz
| Download URL | pyessential-0.1.6.tar.gz |
|---|---|
| Size | 17.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
66058f7f4c1cfd3e970055d705b070e3c68143a321b3229573a4083233aace41
|
|
BLAKE2b-256 checksum How to use checksums |
b1ba9ace0d08655e053fcfee5b65980c08979f3928f8341fa5da7c30da9ca0ca
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.
Transparency logRelease files / pyessential-0.1.6-py3-none-any.whl
| Download URL | pyessential-0.1.6-py3-none-any.whl |
|---|---|
| Size | 12.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
32d70987d2d27123860374c30e15d8ee6802e636d3c2ab12209166d69ba2a4e5
|
|
BLAKE2b-256 checksum How to use checksums |
219530ea575ce97219d48417db7838fec6f524b6a2f8bc13871752ffbd5971f3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.
Transparency log