Contributing¶
Setting up¶
Clone the repository and install zabgrab in a virtual environment, in editable mode with the development tools:
git clone https://github.com/SeanDS/zabgrab.git
cd zabgrab
python -m venv .venv
.venv/bin/pip install -e ".[dev,plot,docs]"
.venv/bin/pre-commit install
The pre-commit hooks check formatting and linting on each commit.
Checks¶
Run these before pushing; CI runs the same checks on Linux (Python 3.11 to 3.14), macOS and Windows:
.venv/bin/ruff check .
.venv/bin/ruff format --check .
.venv/bin/mypy
.venv/bin/pytest --cov=zabgrab
The tests need 100% coverage (branches included) to pass. Use # pragma: no cover
only for lines that genuinely can’t be tested.
CI’s last job, CI passed, passes only if every other job did; it’s the one check
main’s branch rules require.
The tests run in UK time, which their expected local times are written in. On Linux
and macOS they set it themselves; Windows can’t change a running process’s time
zone, so there the system time zone must be UK time (tzutil /s "GMT Standard
Time").
Building the documentation¶
.venv/bin/sphinx-build -b html docs docs/_build/html
Then open docs/_build/html/index.html. CI builds the documentation too, and fails
on any warning (add --fail-on-warning to see the same). Each CI run keeps the
built documentation as an artifact named docs, and once changes reach main
they’re published as the development documentation (see Making a release).
Code layout¶
The code is split into layers, and dependencies only point inwards:
zabgrab.modelData classes only: config, item specs, Zabbix objects, queries and fetched data.
zabgrab.servicesThe logic: resolving settings, choosing servers, logging in, finding items, downloading, naming files, updating and merging. Services get everything they need (the Zabbix client, the UI, the clock, …) as arguments, through the protocols in
zabgrab.services.ports, and never print or prompt directly.zabgrab.adaptersThe outside world: the Zabbix API, config files, file formats and the keyring.
zabgrab.uiTerminal output (rich) and plots (matplotlib).
zabgrab.cliThe click commands, which only wire the rest together.
Data goes to stdout; messages, warnings, questions and progress go to stderr. Every
question carries a fix: how to give the answer without being asked, shown when
zabgrab can’t ask (see Scripts and scheduled jobs).
Conventions¶
Comment code wherever it isn’t trivial, explaining why rather than restating what.
Every module, class, function and method has a NumPy-style docstring, which this documentation’s API reference is built from. ruff’s docstring rules check the basics, and examples in docstrings run as tests.
Add tests covering every branch of new code. Tests use an in-memory fake Zabbix server (
tests/fakezabbix.py) and fake UI, clock and keyring (tests/fakes.py); command line tests usetests/cli_support.py.Record design decisions in
PLAN.md, and user-visible changes inCHANGELOG.rstunder the next version’s heading ((unreleased)).
MATLAB files¶
The layout of .mat and .h5 files is pinned by files verified in MATLAB, in
tests/matlab/reference/. If a change breaks the tests comparing against them, the
new layout must be checked in MATLAB before the reference files are replaced:
tests/test_matlab.py runs tests/matlab/check_files.m in MATLAB when it’s
installed (or listed in $ZABGRAB_MATLAB), and is skipped otherwise.
Every group records the version of the layout it was written with
(FORMAT_VERSION in zabgrab.model.series, and supported_format in
matlab/zabgrab_load.m). Readers refuse newer versions, so increase both whenever
the layout changes in a way an older zabgrab or zabgrab_load would misread:
removing, renaming or changing the meaning of a group, dataset, attribute or
metadata key. Purely additive changes that older readers safely ignore don’t need a
new version. Readers must keep reading every older version.