Contributing
Bug reports, documentation fixes, examples and code are all welcome. This page summarises CONTRIBUTING.md, which has the full conventions and the release process. Please also read the Code of Conduct.
Development setup
Section titled “Development setup”mapcv is a Python package with a Rust extension built by maturin. You need Python 3.10+, Rust and uv.
-
Fork and clone the repository, then install the development dependencies and build the extension:
Terminal window uv sync --all-extrasuv run maturin developRe-run
uv run maturin developafter every change to Rust code (src/*.rs).--all-extrasinstalls every optional dependency, so the Sentinel-2, GeoParquet, export and MCP tests run too (thezarrextra installs nothing on Python 3.14).rust-toolchain.tomlpins the Rust version CI uses; rustup installs it on first use. -
Install the pre-commit hooks (
cargo fmt,clippy,ruff,mypyandpytestrun before each commit):Terminal window pip install pre-commitpre-commit install
Tests and linters
Section titled “Tests and linters”uv run pytest # testsuv run ruff format . && uv run ruff check .uv run mypy src tests # strict, configured in pyproject.tomlcargo fmt && cargo clippy --all-targets -- -D warnings && cargo testThe GeoTIFF, KML and tile parsers also have fuzz targets (fuzz/): fuzz/run.sh geotiff_open 60 runs one for a minute (needs the nightly toolchain and cargo install cargo-fuzz). CI runs them on pull requests that touch a parser and every night; a crash is fixed in the parser and pinned with a regression test.
The live Sentinel-2 test is opt-in: set MAPCV_EOPF_URL to a public product and run uv run pytest -m eopf_live.
Conventions in brief
Section titled “Conventions in brief”- Python: sources in
src/mapcv/, tests intests/test_<module>.py; every file starts with a one-line docstring andfrom __future__ import annotations; full type annotations with built-in generics andX | None(dict[str, int],list[Path]); plain-prose docstrings; comments explain why;ruff(line length 100) andmypy --strictmust pass. - Rust: one module per file with a
//!header;///docs on public items with# Errors/# Panicssections; public functions returnResult<T, String>; nounwrap()/expect()in public functions; named constants instead of magic numbers. - Commits: Conventional Commits (
feat:,fix:,perf:,refactor:,docs:,ci:,chore:,test:). They drive the changelog. PRs are squash-merged.
Submitting a change
Section titled “Submitting a change”- For anything substantial, open an issue first to discuss it.
- Create a branch (
git checkout -b feat/your-feature-name), commit with the pre-commit checks passing. - Open a pull request against
mainthat explains the problem and the solution and links related issues.
Working on these docs
Section titled “Working on these docs”The site is Astro Starlight in website/, deployed to GitHub Pages from main.
cd websitenpm cinpm run dev # http://localhost:4321/mapcv/npm run build # also fails on broken internal links- Pages are MDX files in
website/src/content/docs/, organised as Get started, Tutorials, How-to guides (guides/), Reference, Concepts and Project. The sidebar is defined inwebsite/astro.config.mjs. - The CLI reference embeds
--helpsnapshots fromwebsite/src/cli-help/. After changing the CLI, refresh them withwebsite/scripts/update-cli-help.sh(setMAPCV="uv run mapcv"to use the development build). - The Changelog page renders
CHANGELOG.mddirectly; the Migration and Providers pages mirrorMIGRATION.mdandPROVIDERS.md, so update both places together. - Terminal output on the site is real output, trimmed. When behaviour changes, re-run the commands and paste the new output rather than editing it by hand.