Development¶
How to build TOONS from source and work on it.
Prerequisites¶
Setup¶
git clone https://github.com/alesanfra/toons.git
cd toons
uv venv -p 3.14
uv sync --frozen
uv run maturin develop --uv
maturin develop compiles the Rust extension and installs it into the
virtual environment.
Use --no-sync after building
uv run re-syncs the project by default, which reinstalls toons from
the package index and replaces the module you just built. Run tests and
scripts as uv run --no-sync pytest.
Rebuild after every change to a .rs file:
Add --release for an optimized build. Debug builds compile faster but
encode and decode noticeably slower.
Project layout¶
toons/
├── src/
│ ├── lib.rs # PyO3 module: public API and argument validation
│ ├── serialization.rs # Encoder: Python object → TOON
│ └── deserialization.rs # Decoder: TOON → Python object
├── toons.pyi # Type stubs shipped in the wheel
├── tests/
│ ├── conftest.py
│ └── integration/
│ ├── fixtures/ # Official spec fixtures (JSON)
│ └── test_*.py
├── examples/ # Runnable scripts
├── docs/ # This documentation
├── Cargo.toml # Rust package and version number
└── pyproject.toml # Python package, dependency groups, tooling
All public functions live in src/lib.rs. There is no Python source code.
Tests¶
uv run --no-sync pytest
uv run --no-sync pytest -k tabular # subset by name
uv run --no-sync pytest --cov=toons # coverage
See the Testing Guide for conventions.
Code quality¶
Or run everything configured for the repository at once:
Install the hooks so they run on each commit:
Building wheels¶
CI builds wheels for Linux (glibc and musl), macOS, and Windows on both x86_64 and aarch64, including free-threaded Python 3.14 builds.
Documentation¶
uv sync --frozen --all-groups # installs the docs dependency group
uv run --no-sync mkdocs serve # http://127.0.0.1:8000
uv run --no-sync mkdocs build # static site in site/
Read the Docs runs uv sync with the docs group against pyproject.toml
and uv.lock, so adding a docs dependency needs nothing more than a lock
update. The build compiles the extension as well, which is why
.readthedocs.yaml also asks for a Rust toolchain.
Debugging¶
Print from Rust with eprintln! and rebuild:
Print from Python tests with pytest -s to keep stdout visible.
Release¶
- Bump the version in
Cargo.toml(pyproject.tomlreads it from there). - Add a
CHANGELOG.mdentry. - Tag the commit with the version number and push the tag.
The release job in .github/workflows/CI.yml builds every wheel, attests
the artifacts, and publishes to PyPI.