Contributing to iiisight¶
Thanks for your interest in iiisight. This guide covers the development setup and
the conventions CI enforces. For the architecture and deeper design rationale,
see CLAUDE.md and PLAN.md.
Development setup¶
Requires Python 3.10+.
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]" # installs iiisight + the test/lint/build toolchain
The version is derived from the git tag by setuptools-scm; there is no
hand-maintained version string.
Everyday commands¶
pytest # run the suite + coverage gate
pytest tests/test_normalize_v3.py # a single file
pytest tests/test_image.py::test_tile_grid_scale_factor_8 # a single test
ruff check . # lint
ruff format . # auto-format
ruff format --check . # verify formatting (as CI does)
CI (.gitlab-ci.yml) runs ruff check, ruff format --check, and pytest
across Python 3.10–3.13. All three must pass.
Conventions¶
Coverage gate: 90% (
--cov-fail-under=90inpyproject.toml). New behavior needs tests; if a line is genuinely defensive/unreachable, mark it# pragma: no coverwith a reason rather than lowering the gate.Tolerance is a core invariant.
normalize()must never raise on spec-imperfect input — it repairs and records aDiagnostic. Every normalization path should have a malformed-input test asserting “does not raise, emits the expected diagnostic, yields a usable model.”The model is pure and I/O-free. All network access is explicit on the client (
fetch,expand,load_info, …); never fetch behind attribute access.Style:
rufffor lint + format (line length 100, double quotes). Precise type hints on public functions; Google-style docstrings; f-strings. Prefer nativeX | None/list[str]overtyping/from __future__ import.Public API is a contract once released. Keep import paths and the normalized model’s attribute names stable; a break is a MAJOR-version,
CHANGELOG-documented event.
Changelog¶
Every user-affecting change gets an entry under ## [Unreleased] in
CHANGELOG.md (Keep a Changelog format), in the same commit as the change.
Internal-only churn (refactors, test/CI/formatting) does not need an entry.
Real-world check (optional)¶
scripts/validate_realworld.py runs iiisight against live IIIF servers (not part
of CI — it needs network). Run it when touching normalization, the upgrade, or the
tile math:
python scripts/validate_realworld.py
Documentation¶
The user documentation is a Sphinx site under docs/ (MyST Markdown, Furo theme),
published on Read the Docs. Build it locally with:
pip install -e ".[docs]"
python -m sphinx -b html --keep-going docs docs/_build/html
open docs/_build/html/index.html
The build must complete with zero warnings (broken cross-references show up as
warnings). When you change the public API or behavior, update the relevant guide
page under docs/guide/, keep every public symbol’s docstring current (the API
reference is generated from them), and show both async and sync styles for any
example that does I/O. See the “Keeping docs in sync” section of CLAUDE.md for
the full policy.
Releases¶
Releases are automated via GitLab CI and OIDC trusted publishing — see the
Build & release section of CLAUDE.md. In short: push a vX.Y tag to publish
to PyPI (or a vX.Yrc1 tag to rehearse on TestPyPI); do not twine upload from a
workstation.