Repository navigation
Contributing and Development
rAPIdtools is developed in the open under the BSD-3-Clause license; this page covers setting up a development environment, the style and type gates, how the offline test suite works, what CI runs, and how releases are cut.
Repository: RAPID-Facility/rAPIdtools. Package layout is summarised in Core Concepts.
The package requires Python 3.11 or newer. Clone the repository and install it editable with the development extras:
git clone https://github.com/RAPID-Facility/rAPIdtools.git
cd rAPIdtools
make install # python -m pip install -e ".[dev]"pyproject.toml defines three extras:
| Extra | Contents |
|---|---|
test |
pytest, pytest-cov, requests-mock
|
docs |
sphinx>=8, sphinx-book-theme, sphinx-design, sphinx-copybutton
|
dev |
test and docs plus ruff, black, mypy
|
PYTHON can be overridden for any target, for example make test PYTHON=python3.12. On a machine without a GPU, install CPU-only PyTorch first so the install stays small, and install torch and torchvision from the same index (mixing indexes breaks every model module; see Troubleshooting and FAQ):
pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu| Target | What it does |
|---|---|
make install |
Editable install with the test and docs extras. |
make lint |
ruff check and ruff format --check on rapidtools and tests. |
make format |
Apply Ruff fixes and formatting. |
make typecheck |
mypy rapidtools. |
make test |
pytest with the options from pyproject.toml. |
make coverage |
Test suite plus an HTML coverage report in htmlcov/. |
make check |
lint, typecheck and test: what a pull request must pass. |
make docs |
Build the Sphinx site into docs/build/html. |
make docs-serve |
Build the docs and serve them at http://localhost:8000. |
make clean |
Remove build, cache and coverage artifacts. |
Ruff is the style gate, for linting and formatting alike. Its configuration in pyproject.toml ([tool.ruff]) sets a line length of 88, target py311, single quotes ([tool.ruff.lint.flake8-quotes] and [tool.ruff.format]), and the rule sets E, W, F, I, UP, B and Q. Run make format before committing; make lint must pass cleanly.
mypy runs over the package with the [tool.mypy] settings (python_version = "3.11", ignore_missing_imports = true, untyped definitions allowed). The package ships a py.typed marker, so keep public signatures annotated. The whole package type-checks clean; new code should too.
Source files carry the BSD-3-Clause header, a Contributors: list and a Last updated: date (see any module, or tests/conftest.py). Keep that convention in new files.
make test # or: python -m pytest[tool.pytest.ini_options] adds -ra -q --cov=rapidtools --cov-report=term-missing, so every run ends with a coverage table that lists the uncovered lines of each module. The suite is 44 modules and about 1,200 tests; coverage sits at 99% of the package's statements, and the badge in the README is updated from the Ubuntu / Python 3.11 cell of the CI matrix.
Most modules test one component and are named after it (test_image_analyzers.py, test_gui_server.py, test_mapillary_client.py, ...). A few cut across components:
| Module | What it holds |
|---|---|
test_edge_cases.py |
Error branches and fallbacks of the street-level modules: the duplicate resolver's unreadable crops, failed model calls and cancellation; the verifier's odd confidence and range values; the re-identification loader for both the CLIP and the DINOv2 branches; localisation and tracking helpers fed parallel rays, sightings without a ground position, rays that meet beyond the range limit, wandering and phantom tracks, singular merge gates. |
test_coverage_gaps.py |
Small fallbacks of otherwise well-covered modules: outline parsing, GUI server helpers, workflow model listing, prompt builder helpers, image asset parsing, provider rejections in the analyzer. |
test_api_harmonization.py |
Public names, lazy imports and deprecation shims of rapidtools. |
test_cancellation.py |
Every long-running component honours its cancel_event. |
Put a new test next to the component it exercises; use the cross-cutting modules only for a branch that needs a fixture the component's own module does not have.
The suite is offline and never downloads model weights:
-
tests/conftest.pyhas an autouse fixture,_no_huggingface_login, that replacesrapidtools.auth.get_tokenwith a stub returning a test token andrapidtools.models.local_base.ensure_huggingface_loginwithlambda: True. Because a token is always "cached", the realensure_huggingface_login(which the re-identification embedder imports fromrapidtools.auth) also returnsTruewithout contacting the Hugging Face Hub or the token registry. - Local model tests (
tests/test_models_local.py) monkeypatch the processor and model loaders with fakes (FakeProcessor.from_pretrainedand friends), sotransformersnever loads a checkpoint.tests/test_street_objects.pypasses aFakeSAM3that returns fixed masks. The re-identification test intests/test_edge_cases.pygoes one step further and injects faketorchandtransformersmodules intosys.modulesthat expose only what the loader touches (AutoConfig,AutoModel,CLIPVisionModelWithProjection,AutoImageProcessor,inference_mode), so the loader runs end to end in milliseconds. - HTTP calls to providers and tile servers are answered by
requests-mockfixtures, or by small fake clients such as theFakeClientintests/test_street_objects.py, which serves canned images, detections and pixels for a synthetic survey. - Vision-language models are stand-ins with a
run_inferencemethod that answer from the image file name or a script; ajudgecallable does the same for the duplicate resolver. - A second autouse fixture,
_restore_package_logger, undoes anyconfigure_logging()call a test or the GUI CLI performed, so logger state does not leak between tests. - Rasters, GeoJSON, shapefiles and crops are built in
tmp_path; the only committed fixtures are the small files undertests/mapillary_images.
Follow the same pattern for new tests: patch the network boundary, never call out to a real service, and keep fixtures deterministic. Do not let a change lower the coverage total; when a branch is hard to reach through the public API, test the helper directly rather than leaving it uncovered. make coverage writes an HTML report to htmlcov/ for finding what a change left out. The documentation's Development and testing page has the same material.
Three workflows live in .github/workflows/:
-
ci.yml(Tests) runs on pushes and pull requests tomain. Alintjob on Python 3.11 installs CPU-only PyTorch and runsruff check,ruff format --checkandmypy rapidtools. Atestjob runspytest --cov=rapidtoolson a matrix ofubuntu-latest,windows-latestandmacos-latestwith Python 3.11, 3.12 and 3.13 (fail-fast: false), and the Ubuntu / 3.11 cell updates the coverage badge. -
docs.yml(Docs) builds the Sphinx site on every push tomainand deploys it to GitHub Pages at https://rapid-facility.github.io/rAPIdtools/. -
release.yml(Release) runs when av*tag is pushed. It checks that the tag matchesproject.versioninpyproject.toml, extracts that version's section fromCHANGELOG.mdand creates the GitHub Release from it. Zenodo watches GitHub Releases to mint a DOI.
A fourth workflow, container.yml, builds the GUI server image from deploy/Dockerfile on the same tags and publishes it to the GitHub Container Registry in a CUDA and a -cpu variant (see Deployment). It lands with the release after 0.2.0.
- Branch from
mainand open a pull request against it. CI must be green; locally that meansmake checkpasses. - Commit subjects in this repository follow the pattern
bc - <Sentence describing the change>, for examplebc - Making the ego-vehicle filter linear in the sequence length. - Add a line to the
Unreleasedsection ofCHANGELOG.mdunderAdded,Changed,Deprecated,RemovedorFixed. The file follows Keep a Changelog and the project uses Semantic Versioning with the usual 0.x caveat that minor releases may change public APIs. - When renaming a constructor parameter, keep the old name working with a
DeprecationWarning, as the harmonised names in 0.2.0 did. - Public classes and functions carry Google-style docstrings with an
Example:block; the API reference is generated from them.
The docs are Sphinx with the Book theme; docs/source/ holds the getting_started, user_guide, examples and api sections. Build them with make docs (or cd docs && make html) and open docs/build/html/index.html. Autodoc imports the package, so the docs extra plus a CPU build of PyTorch is enough. Longer worked examples belong in examples/ and are referenced from Examples.
- Move the
Unreleasedentries inCHANGELOG.mdunder a new## [x.y.z] - YYYY-MM-DDheading. - Set
versioninpyproject.toml, andversionanddate-releasedinCITATION.cff, to the same value. - Commit, tag
vx.y.zand push the tag.release.ymlcreates the GitHub Release andcontainer.ymlpublishes the images; both refuse a tag that does not matchpyproject.toml.
rAPIdtools is released under the BSD-3-Clause license (LICENSE, copyright The University of Washington). CITATION.cff holds the citation metadata GitHub shows under Cite this repository and Zenodo reads when archiving a release; keep it in step with the version.
rAPIdtools is developed by the NHERI RAPID Facility and released under the BSD-3-Clause license. Found a problem on this page? Open an issue or edit the page directly. Missing a capability? Request a feature. No GitHub account? Email us.
Getting started
Workflows
- Aerial Imagery Workflows
- Street-Level Imagery Workflows
- Vision-Language Models
- Data Formats and Export
Using the app
Help
Reference