Contributing
Development setup
git clone https://github.com/de-platform-ops/tollkeeper.git
cd tollkeeper
uv sync
Run the test suite:
uv run pytest tests/ -v
Run lint and format checks:
uv run ruff check src/ tests/
uv run ruff format --check src/ tests/
Type check:
uv run ty
All of the above must pass before you open a PR. uv run ruff format src/ tests/ && uv run ruff check src/ tests/ && uv run pytest tests/ -v runs everything except the type checker in one shot.
Use uv for everything. Do not use pip or venv directly.
Before submitting a PR
- Search open and closed PRs for the same problem. Don't duplicate an existing effort — comment on it instead.
- One problem per PR. Bundle unrelated changes and it gets closed.
- Target
develop, notmain. Branch names:feature/<name>for features,fix/<name>for bug fixes. - Tests and lint must pass locally before you push.
- Fill out every section of the PR template. Placeholder text gets the PR closed without review.
- Describe the problem you solved, not just what you changed.
What we won't accept
- Bulk or spray-and-pray PRs. Don't trawl the issue tracker and open PRs for multiple issues in one session. Pick one, understand it, submit it.
- Speculative fixes. "This could theoretically break" isn't a problem statement. If you can't point to a failing test or a reproducible bug, don't submit the PR.
- Restructuring without evidence. Changes to core abstractions (the
BackendABC,TollkeeperSessionstate machine,BaseCheckABC) need a concrete second use case or a bug report, not a taste preference. - New dependencies for what a few lines can do. This library has zero required dependencies by design. Optional backends (
polars,iceberg) are extras — don't add another.
Code style
- Ruff handles formatting and linting. Don't hand-format code that
ruff formatwould rewrite. - Python >=3.11 features are fine:
X | None,list[T],from __future__ import annotations. - Type hints on all functions.
- No comments unless the why is non-obvious. Don't narrate what the code already says.
Testing
- TDD is expected: write the failing test first.
- pytest, with in-memory fakes (e.g.
FakeBackend) over mocks. - Coverage must stay at 80% or above.
- Test behavior, not implementation. A test that breaks on a refactor with no behavior change is a bad test.