Notes for working on rut itself. For user documentation see README.md.
uv sync --dev./run_tests.sh # all tests
./run_tests.sh --cov # with coverage reportThe suite is plain unittest run through unittest discover — not through rut
itself, to avoid the runner being unable to report its own breakage.
ruff checkpyproject.toml declares [tool.uv.sources], which makes uv resolve some
dependencies from local checkouts instead of PyPI:
[tool.uv.sources]
rut = { path = ".", editable = true }Additionally, uv_unreleased.toml (not tracked in git) can override sources to point
at sibling checkouts of unreleased dependencies. To enable it, symlink it as uv.toml
so uv picks it up automatically:
ln -s uv_unreleased.toml uv.tomlThis is how you develop against an unreleased import-deps. Remove the symlink to go
back to PyPI versions.
CI sets UV_NO_SOURCES: true so it ignores all of the above and installs from
PyPI. That is deliberate: it verifies the package works with the dependency versions
users will actually get. If a build passes locally but fails in CI, an unreleased local
dependency is the first thing to check:
UV_NO_SOURCES=true uv sync --dev && ./run_tests.shThe version is stored in two places that must stay in sync:
pyproject.toml→versionsrc/rutlib/__init__.py→__version__
Steps (using X.Y.Z as the new version):
-
Verify the release resolves against PyPI, not local checkouts:
UV_NO_SOURCES=true uv sync --dev ./run_tests.sh ruff check
Make sure every dependency version required in
pyproject.tomlis actually published. Confirm CI is green onmainfor all supported Python versions. -
In
CHANGES, replace theX.Y.Z (unreleased)header with the release date:X.Y.Z (YYYY-MM-DD). -
Bump
versioninpyproject.tomland__version__insrc/rutlib/__init__.pyfromX.Y.Z.devNtoX.Y.Z. -
uv syncto refreshuv.lockwith the new version. -
Commit as
release X.Y.Zand tag:git commit -am "release X.Y.Z" git tag X.Y.Z -
Build. Clear
dist/first — it is gitignored and keeps artifacts from previous releases, whichtwine upload dist/*would otherwise try to re-upload:rm -rf dist/ uv run python -m build uv run twine check dist/* -
Upload:
uv run twine upload dist/* -
Push the commit and the tag:
git push && git push --tags -
Open the next development cycle: bump both version strings to the next
X.Y+1.0.dev0, add aX.Y+1.0 (unreleased)section at the top ofCHANGES, and commit asstart dev X.Y+1.
The site is published to GitHub Pages from docs/, but docs/ is generated output —
never edit it directly. The source lives in marketing/gh-pages/ (a separate git
repo, gitignored here).
cd marketing
./serve.sh # preview at http://localhost:4000/rut/
./publish.sh # copy gh-pages/* into ../docs/After publish.sh, commit the docs/ changes in this repo to deploy.