Contributing and rules¶
Commands¶
uv sync # environment incl. dev tools
uv run python tools/build_dtc_db.py # trouble code catalog
uv run ruff format . && uv run ruff check . && uv run mypy # mypy strict
uv run pytest # about 1800 tests, ~4.5 min
Check the exit code of pytest itself, do not hide it behind | tail.
Rules¶
Layers: transport → protocol → services → ui/cli, no imports upwards; higher layers only know the
Transportprotocol (Architecture).Read-only: mode 04 only via
services/clear.py, clearing stays locked until reading has been verified at the car. No coding, no flashing, no manufacturer commands (Safety concept).New commands are deliberately enabled in the allowlist (
protocol/elm327.py) and entered intests/fixtures/command_spec.yamlwith datasheet page and quote. Otherwise the tests fail, and the Command reference shows them automatically.Standards compliance: parsers stick to SAE J1979, ISO 15765 and the ELM327 datasheet. Deviations of the emulator are corrected in the tests, not in the product code.
Offline: trouble code texts from SQLite. Online only after opt-in: NHTSA vPIC (VIN) and short explanations for codes without catalog text (ADR 0004: Online explanations for trouble codes without catalog text).
Language: German in comments, docstrings and commit messages. User interface, output and documentation exist in German and English (below). ruff flags en dashes in Python strings; use
:or-there.
Translations¶
Texts in the code are German and go through tr("…") (obd_diag.i18n); placeholders
in curly braces, filled after translating:
tr("Verbinde mit {port} …").format(port=port), never an f-string inside tr.
Constants fixed at import time are marked with N_("…") and translated with tr on
output; singular/plural with trn. In QML qsTr("…") with .arg(). The English texts
are in src/obd_diag/locale/en.po:
uv run python tools/translations.py # add new texts, remove old ones
uv run python tools/translations.py --todo # missing ones as JSON {"number": "text"}
uv run python tools/translations.py --fill translations.json
tests/unit/test_i18n.py fails if the catalog is not up to date, a translation is
missing, placeholders do not match or a German text is output without tr/qsTr. Log
messages (log.…) stay German.
Documentation¶
The documentation is in docs/ (Markdown with MyST, Sphinx, Furo theme), the English
version with the same file names in docs/en/. CI builds both for every PR and push to
main and stores the HTML as the artifact “dokumentation” on the run
(.github/workflows/docs.yml). Every push to main publishes it at
https://phprell.github.io/obd-diag/ (German) and
https://phprell.github.io/obd-diag/en/ (English). Building locally:
uv run --group docs sphinx-build -W docs docs/_build
uv run --group docs sphinx-build -W docs/en docs/_build/en
python -m http.server -d docs/_build # then http://localhost:8000
Every page exists in both languages; the link at the top of the sidebar switches to the
same page in the other language. tests/unit/test_docs_i18n.py checks that both trees
have the same pages with the same number of headings, code blocks and images. Whoever
changes a page changes the other language in the same PR.
-W turns warnings into errors, e.g. broken references. What can be generated from
the code is generated, not copied:
Page |
Source |
Generated by |
|---|---|---|
|
|
|
|
|
|
Command line (options) |
|
sphinx-argparse |
docstrings |
autodoc |
|
pictures in User interface |
user interface against the emulator |
|
New functions bring the matching page under “Usage” in the same PR. After changes to
the user interface, generate the pictures again and check them in. Byte examples on
the technical pages are checked against the parsers by
tests/unit/test_docs_examples.py; whoever changes an example changes the test too.
Release¶
Set the version in pyproject.toml and src/obd_diag/__init__.py, write a section
## X.Y.Z – date in CHANGELOG.md and add the version to the AppStream file
src/obd_diag/share/io.github.phprell.obd_diag.metainfo.xml as well. After the merge,
push the tag vX.Y.Z on main. .github/workflows/release.yml then checks tag and
versions, builds catalog, sdist, wheel, AUR package and Flatpak
(.github/workflows/packaging.yml, also on every PR), creates the GitHub release with
the changelog section and uploads to PyPI. Packaging templates: packaging/aur/PKGBUILD,
packaging/flatpak/.