Contributing¶
Working on nab itself, rather than installing it as a tool, starts from the workspace check-out.
Development install¶
nab uses hatch as its environment manager; clone the repository and let hatch do the editable installs:
git clone https://github.com/notatallshaw/nab.git
cd nab
hatch shell
nab --version
hatch shell enters a virtual environment (.venv by default) with
all four workspace members installed editable, plus the test, lint,
docs, and types groups available via hatch run.
Running the tests¶
The default suite is fast (under a minute) and covers every module
under nab_resolver, nab_python, nab_index, and nab:
.venv/bin/python -m pytest # default selection (no markers)
Branch coverage runs through the coverage CLI. Each process writes its
own data file, so combine before reporting:
.venv/bin/python -m coverage erase
.venv/bin/python -m coverage run -m pytest
.venv/bin/python -m coverage combine
.venv/bin/python -m coverage report # fails below 100 percent
CI gates each workspace’s coverage on its own tests through nox (see
noxfile.py). With nox installed (pip install nox), reproduce a single
workspace, or all of them, with:
nox -s tests # every workspace, each gated
nox -s "tests(workspace='python')" # just one workspace
Property-based tests are opt-in via marker:
.venv/bin/python -m pytest -m property # Hypothesis-only suites
Lint and format with ruff; type-check with pyright:
.venv/bin/python -m ruff check .
.venv/bin/python -m ruff format .
.venv/bin/python -m pyright
CI checks the same trees with five checkers rather than one, so a change
pyright accepts can still fail the matrix. Reproduce a single cell with
nox -s "types(checker='mypy')"; the trees are TYPED_TREES in
noxfile.py.
Building the docs¶
hatch run docs:build # sphinx-build -W, warnings are errors
hatch run docs:serve # live-reloading preview
The docs dependency-group in pyproject.toml is the one place the doc
tooling is declared. nab locks it into
.github/requirements/pylock.docs.toml (tasks/refresh-locks.sh), and both
CI and Read the Docs install from that lock, so a published build resolves
nothing. After changing the group, re-run the refresh script and commit the
lock.
Unlike the other groups, that lock is a single resolution for Python 3.13, the one version Read the Docs and the CI docs job build with. nab runs on 3.10 and newer, but the docs build is only supported on 3.13: locking the toolchain across the whole range would hold it to whatever still supports the floor.
Coverage policy¶
The pyproject.toml [tool.coverage.report] fail_under = 100
setting requires 100 percent branch coverage on every workspace
package: nab_resolver, nab_python, nab_index, and nab. The
full local suite under coverage run -m pytest checks all four
together; nox splits them per workspace in CI so each workspace’s
tests cover only its own package, with nab_index gated alongside
nab_python, whose tests exercise it. When code is genuinely
unreachable from the default suite, prefer:
# pragma: no coverfor a platform-specific or defensively unreachable line.raise RuntimeError("Bug: unreachable")style guards:coverageexcludes those automatically via theraise RuntimeError.*unreachablepattern in[tool.coverage.report].exclude_also.
Code under _build/env.py and the CLI typically mocks subprocesses,
network calls, and venv creation rather than skipping the gate.