Skip to content
Merged
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
37 changes: 37 additions & 0 deletions .artifacts/20261021--py-buzz/hack-journal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# py-buzz documentation refresh

Focused documentation pass to make the package purpose, first use, and API examples easier to understand.


## Profile and tier

- Profile: documentation
- Tier: low-risk


## Changes

- Reworked the README and user-facing guides in a conversational, lightly playful voice.
- Added matching README and docs landing-page quickstarts covering typed validation and contextual exception handling.
- Clarified feature-guide positioning and corrected examples that did not match the current API or valid Python syntax.
- Quoted extras in shell commands so they work in zsh.
- Corrected `handle_errors()` callback behavior and clarified jittered retry delays.
- Split the feature guide into individual pages, kept `features/index.md`
as an overview, and updated navigation and links.
- Added standalone and derived-`Buzz` usage examples across the feature
guides, clarifying exceptions where a class method is not available.
- Added `Advanced use` sections with comprehensive code examples to complex
guides, covering meaningful options and standalone versus `Buzz` usage.
- Kept standalone examples on non-Buzz exceptions and placed each derived exception next to its Buzz-method example.
- Kept `raise_from` in its own guide while grouping retries and the other small utilities in `other_functions.md`.
- Migrated the docs build to Zensical with a dedicated docs environment and updated CI build triggers.
- Replaced the MkDocs YAML file with native `docs/zensical.toml` configuration.
- Enabled native fenced-code rendering, fixed Griffe warnings, and selected native `typing.TypeForm` on Python 3.15+.


## Verification

- `dt format markdown` completed for all edited Markdown.
- `make docs/build` succeeded with no issues or Griffe warnings.
- `make qa/full` passed: 96 tests, lint, type checks, and coverage threshold.
- `uv run --python 3.11 pytest` passed: 96 tests, confirming the backported `TypeForm` import.
4 changes: 3 additions & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ on:
- main
paths:
- 'docs/**'
- 'buzz/**'
- 'src/buzz/**'
- 'pyproject.toml'
- 'Makefile'

jobs:
build:
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).


## v9.0.1 - 2026-10-21

* Added PyPI keywords and classifiers to improve package discovery


## v9.0.0 - 2026-10-12

* Drop support for Python 3.9 and 3.10 and add support for 3.14 and 3.15
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ qa/mutate: ## Run mutation testing (slow, not part of qa/full)
docs: docs/serve ## Shortcut for docs/serve

docs/build: ## Build the documentation
@uv run mkdocs build --config-file=docs/mkdocs.yaml
@uv run --project docs zensical build --config-file=docs/zensical.toml

docs/serve: ## Build the docs and start a local dev server
@uv run mkdocs serve --config-file=docs/mkdocs.yaml --dev-addr=localhost:10000
@uv run --project docs zensical serve --config-file=docs/zensical.toml --dev-addr=localhost:10000


## ==== Demo ===========================================================================================================
Expand Down
93 changes: 67 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,81 @@
[![Latest
Version](https://img.shields.io/pypi/v/py-buzz?label=pypi-version&logo=python&style=plastic)](https://pypi.org/project/py-buzz/)
[![Python
Versions](https://img.shields.io/python/required-version-toml?tomlFilePath=https%3A%2F%2Fraw.githubusercontent.com%2Fdusktreader%2Fpy-buzz%2Fmain%2Fpyproject.toml&style=plastic&logo=python&label=python-versions)](https://www.python.org/)
[![Build
Status](https://github.com/dusktreader/py-buzz/actions/workflows/main.yml/badge.svg)](https://github.com/dusktreader/py-buzz/actions/workflows/main.yml)
[![Documentation
Status](https://github.com/dusktreader/py-buzz/actions/workflows/docs.yml/badge.svg)](https://dusktreader.github.io/py-buzz/)
[![PyPI version][pypi-badge]][pypi-project]
[![Python versions][python-badge]][python-versions]
[![Build status][build-badge]][build-workflow]
[![Documentation status][docs-badge]][docs-site]

![py-buzz-logo](https://github.com/dusktreader/py-buzz/blob/main/docs/source/images/buzz-logo-text.png)

**That's not flying, _it's falling with style_: Exceptions with extras**

![asciicast](https://github.com/dusktreader/py-buzz/blob/main/docs/source/images/py-buzz.gif)
![py-buzz-demo](https://github.com/dusktreader/py-buzz/blob/main/docs/source/images/py-buzz.gif)

py-buzz is fully equipped with a suite of exception tools that will save you
from writing the same code over and over again in your python projects. These
include:
Long ago, I found myself writing the same boilerplate for condition checks and exception wrappers over and over. So I
gathered some helpers together to cut down on repetitive error-handling code. When I switched projects later, I wanted
those helpers there, too! That's how `py-buzz` came to be.

* checking many conditions and reporting which ones failed (`check_expressions()`)
* catching exceptions wrapping them in clearer exception types with better error messages (`handle_errors()`)
* retrying operations with exponential backoff until they succeed (`retry()`)
* checking that values are defined and raising errors if not (`enforce_defined()`)
* checking that values are a certain type and raising errors if not (`ensure_type()`)
* checking conditions and raising errors on failure (`require_condition()`)
Now, I have a collection of really useful exception helpers that I can use in all my projects, and I'm sharing them with
you!

py-buzz also provides an exception class, Buzz, that can be used as a base class
for custom exceptions within a project.

## Getting started

## Super-quick Start
Python 3.11 or newer is required, and installation takes one line:

* Requires Python 3.11 or later
* Installed with pip (`$ pip install py-buzz`)
* Each feature demonstrated in an executable demo "extra"
```shell
uv add py-buzz
```

Here's a small example with a project-specific exception:

## Documentation
```python
from buzz import Buzz

The complete documentation can be found at the [py-buzz documentation page](https://dusktreader.github.io/py-buzz/)

class ConfigError(Buzz):
pass


def read_port(value: object) -> int:
port = ConfigError.ensure_type(value, int, "Port must be an integer")
ConfigError.require_condition(1 <= port <= 65535, "Port must be between 1 and 65535")
return port


def parse_port(value: str) -> int:
with ConfigError.handle_errors("Couldn't parse the configured port"):
port = int(value)
return read_port(port)
```

Here, `ensure_type()` checks the value at runtime and returns it with a narrowed type, while `require_condition()`
raises `ConfigError` if the port is out of range. `handle_errors()` gives parsing failures
a bit more context by wrapping the original `ValueError` in a `ConfigError`.


## What's in the box

- Checks for conditions, defined values, types, and `Literal` values, with useful errors.
- More context around handled exceptions, or a new exception raised from the original.
- Several failed checks gathered into one report.
- Synchronous and asynchronous retries with exponential backoff through `Buzz.retry()` and `Buzz.retry_async()`.
- A `Buzz` base class for project-specific exceptions, along with standalone helpers for existing exception types.


## Further reading

The [documentation](https://dusktreader.github.io/py-buzz/) has feature guides and the API reference.

A set of demos is also included if you want to see the features in action. You can run them with one line:

```shell
uvx --from='py-buzz[demo]' py-buzz-demo
```

[pypi-badge]: https://img.shields.io/pypi/v/py-buzz?label=pypi-version&logo=python&style=plastic
[pypi-project]: https://pypi.org/project/py-buzz/
[python-badge]: https://img.shields.io/python/required-version-toml?tomlFilePath=https%3A%2F%2Fraw.githubusercontent.com%2Fdusktreader%2Fpy-buzz%2Fmain%2Fpyproject.toml&style=plastic&logo=python&label=python-versions
[python-versions]: https://www.python.org/
[build-badge]: https://github.com/dusktreader/py-buzz/actions/workflows/main.yml/badge.svg
[build-workflow]: https://github.com/dusktreader/py-buzz/actions/workflows/main.yml
[docs-badge]: https://github.com/dusktreader/py-buzz/actions/workflows/docs.yml/badge.svg
[docs-site]: https://dusktreader.github.io/py-buzz/
49 changes: 0 additions & 49 deletions docs/mkdocs.yaml

This file was deleted.

17 changes: 17 additions & 0 deletions docs/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[project]
name = "py-buzz-docs"
version = "0.1.0"
description = "Documentation site for py-buzz"
requires-python = ">=3.11"
dependencies = [
"mkdocstrings-python>=2.0.1",
"py-buzz",
"pygments>=2.19.2",
"zensical~=0.0.33",
]

[tool.uv]
package = false

[tool.uv.sources]
py-buzz = { path = "..", editable = true }
39 changes: 18 additions & 21 deletions docs/source/demo.md
Original file line number Diff line number Diff line change
@@ -1,50 +1,47 @@
# Demo

The `py-buzz` package includes an "extra" that can be installed to show all its features.
Each demo focuses on a particular feature and runs an examples that demonstrates how
`py-buzz` interacts with exceptions, how it affects code flow, and any side-effects it
has.
The optional `demo` extra comes with executable examples of the `py-buzz` helpers.
Each one shows how a helper shapes exception handling and program flow.


## Installation

To install the `demo` with `py-buzz` you need to supply it as an "extra" when installing `py-buzz`.
The following command can be used:
The demo is an optional extra, so it joins `py-buzz` when the package is installed with:

```bash
pip install py-buzz[demo]
```shell
uv pip install 'py-buzz[demo]'
```


## Running the demo

An entrypoint for the demo is included when it is installed. Simply run:
Installing the extra also adds a demo entrypoint:

```bash
```shell
py-buzz-demo
```

If you provide no arguments, it will run all available demos. If you wish to only see the demos
for a particular feature, you can use the `--feature=<feature>` option to target one feature.
With no arguments, the entrypoint runs all available demos. To focus on one feature, the `--feature=<feature>` option
selects its demos.

To see all available options, run:
The full list of options is available with:

```bash
```shell
py-buzz-demo --help
```


## Running the demo in an isolated environment with uv

If you want to run the demo but not include its dependencies in your system python
or an activated virtual environment, you can execute the demo with uv:
The demo can run through `uv` without adding its dependencies to your system Python or an activated virtual environment:

```bash
uvx --from=py-buzz[demo] py-buzz-demo
```shell
uvx --from='py-buzz[demo]' py-buzz-demo
```


## Check out the source
## Demo source

You can also examine the demo source to examine how `py-buzz` is used.
The demo source offers a closer look at how `py-buzz` fits into the examples.

Check out the [source code on Github](https://github.com/dusktreader/py-buzz/tree/main/src/buzz_demo).
The [source code on Github](https://github.com/dusktreader/py-buzz/tree/main/src/buzz_demo) is available for browsing.
Loading
Loading