Contributing¶
Contributions of all kinds are welcome — bug reports, feature implementations, documentation improvements, and feedback.
Ways to Contribute¶
-
Report Bugs
Open an issue at github.com/nfb2021/canvodpy/issues. Include your OS, Python version, and steps to reproduce.
-
Fix Bugs
Issues labelled "bug" and "help wanted" are open for PRs. Comment on the issue first so nobody duplicates work.
-
Implement Features
Issues labelled "enhancement" and "help wanted" are open. Keep scope narrow — one feature per PR.
-
Improve Documentation
Improvements to docs, docstrings, or external articles are always appreciated. See the Development Guide.
Required Tools¶
Two tools must be installed before uv sync (not managed by it):
brew install uv just
# uv
curl -LsSf https://astral.sh/uv/install.sh | sh
# just
curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh \
| bash -s -- --to ~/.local/bin
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
winget install Casey.Just
Verify both are available:
just check-dev-tools
Contribution Workflow¶
# 1. Fork on GitHub, then clone your fork
git clone git@github.com:YOUR_USERNAME/canvodpy.git
cd canvodpy
# 2. Install dependencies + hooks
git submodule update --init --recursive
uv sync
just hooks
# 3. Create a feature branch
git checkout -b feature/my-feature
# 4. Make changes
# packages/<pkg>/src/canvod/<pkg>/ ← implementation
# packages/<pkg>/tests/ ← tests
# 5. Verify
just test && just check
# 6. Commit with Conventional Commits
git add packages/<pkg>/src/... packages/<pkg>/tests/...
git commit -m "feat(readers): add RINEX 4.0 support"
# 7. Push + open PR
git push origin feature/my-feature
Commit Message Format¶
<type>(<scope>): <subject>
Types: feat · fix · docs · refactor · test · chore · perf · ci
Scopes: readers · aux · grids · vod · store · viz · utils · docs · ci · deps
git commit -m "feat(vod): add tau-omega calculator"
git commit -m "fix(readers): handle empty RINEX files"
git commit -m "docs: update installation instructions"
git commit -m "feat(viz)!: redesign 3D plotting API" # ! = breaking change
See Conventional Commits for the full specification.
Pre-Commit Hooks¶
When you run just hooks, Git hooks are installed that execute automatically on every git commit. These hooks enforce code quality and commit message standards. If a hook fails, the commit is rejected — your files stay staged, but no commit object is created.
Hooks and what they check¶
| Hook | Stage | What it does |
|---|---|---|
| ruff check --fix | Before commit | Lints Python; auto-fixes where possible (unused imports, style) |
| ruff format | Before commit | Formats Python code (indentation, line length, quotes) |
| uv-lock | Before commit | Verifies uv.lock matches all pyproject.toml files |
| trailing-whitespace | Before commit | Strips trailing whitespace |
| check-added-large-files | Before commit | Blocks files above the size threshold |
| detect-private-key | Before commit | Prevents accidental commit of SSH/PGP keys |
| end-of-file-fixer | Before commit | Ensures files end with exactly one newline |
| commitizen | After writing message | Validates type(scope): subject format |
Fixing a rejected commit¶
ruff modifies files in place when it can. After rejection, stage the fixes and retry:
git add -u
git commit -m "feat(readers): your original message"
Your message must follow type(scope): subject. Example:
# Wrong:
git commit -m "updated the reader"
# Correct:
git commit -m "fix(readers): handle empty observation epochs"
uv sync
git add uv.lock
git commit -m "feat(readers): your message"
Continuous Integration and Coverage¶
Every push and pull request triggers automated CI on GitHub Actions:
- Code Quality — ruff linting, formatting, ty type-checking, lockfile consistency
- Test with Coverage — pytest with coverage measurement, results uploaded to Coveralls and posted as a PR comment
- Platform Tests — test suite across multiple OS and Python versions
The CI runs the same checks as the pre-commit hooks, so fixing hook failures locally means your PR will pass CI.
Pull Request Guidelines¶
Before opening a PR
just test && just checkmust pass with no errors.- Include tests for all new functionality.
- New code must not reduce test coverage. Aim to increase it.
- Update the Zensical documentation in
docs/if adding or changing public API, behaviour, or configuration. - Target Python 3.14+.
- Add yourself to
CONTRIBUTORS.mdif this is your first contribution.
Test coverage requirement¶
Every pull request that adds new functionality must include tests. The CI pipeline measures line coverage and posts a report on the PR. While there is no hard minimum percentage, reviewers will check that:
- All new public functions and methods have at least one test
- Edge cases and error paths are covered (empty inputs, invalid parameters)
- Coverage does not decrease compared to the base branch
Run just test-coverage locally to inspect which lines are covered before pushing.
Licensing¶
canVODpy is licensed under the Apache License 2.0.
By submitting a pull request, you agree that your contribution is licensed under
the same terms. The LICENSE and NOTICE files at the repository root apply to
all source files. Per-file license headers are not required.
Code Quality¶
just check # lint + format + type-check (run before committing)
| Tool | Role |
|---|---|
| ruff | Linting + formatting |
| ty | Type checking |
| pytest | Testing with coverage |
| pre-commit | Automatic checks on git commit |
Deploying (Maintainers)¶
just bump minor # bump version in all pyproject.toml files
git push
git push --tags # triggers GitHub Actions → publish to PyPI