Development#
The single entry point for working on pain001: toolchain, how to
reproduce every CI gate locally, where tests live, and how a release
happens. CONTRIBUTING.md covers the etiquette (DCO,
commit format, review); this file covers the mechanics.
Toolchain#
Tool |
Version |
Where it is pinned |
|---|---|---|
Python |
3.12 for development; 3.10 is the floor |
|
Poetry |
2.x |
|
Node |
any current LTS |
only for |
Docker |
any |
only for the image smoke test |
git clone https://github.com/sebastienrousseau/pain001
cd pain001
mise install # picks up Python from .mise.toml (optional)
poetry install --all-extras --with dev,docs
poetry run pre-commit install # optional: runs ruff, codespell, hygiene hooks on commit
A devcontainer does the same in a
Codespace or VS Code container and boots to a working make.
Reproducing every CI gate#
Each workflow maps onto a make target so a red CI job can be
reproduced without reading YAML.
Gate |
Local command |
CI workflow |
|---|---|---|
Lint (ruff, ruff format, interrogate 100 %, pydoclint) |
|
|
Types (mypy |
|
|
Tests with the 100 % line + branch coverage floor |
|
|
Security (bandit, pip-audit) |
|
|
Docs lint (codespell, markdownlint) |
|
|
Docs build |
|
|
Tollgates (dependency, XSD, idempotency, env parity) |
|
|
Benchmarks (kept compiling, not asserted) |
|
|
Fuzzing (Atheris harness in |
|
|
Suite conformance (this repo against the family rules) |
|
|
Suite consistency (published versions across the family) |
|
|
Everything blocking |
|
— |
The coverage floor is 100 % and deliberately so: the rationale is in
CONTRIBUTING.md.
# pragma: no cover is reserved for entry-point guards and defensive
barriers that cannot be reached by a test.
Test layout#
tests/
test_<module>.py unit tests, one file per module or concern
test_golden_files.py byte-exact rendering of the first two rows of every template.csv
golden/ the golden XML, regenerate with scripts/generate_golden_files.py
test_suite_conformance.py the family-wide rules; a vendored, byte-identical copy — do not edit here
test_suite_consistency.py the PyPI version-lockstep checker, tested with stubbed metadata
test_docker_smoke.py builds the image and runs the CLI inside it (skipped without Docker)
data/ small fixtures (CSV, JSON)
examples/ numbered, self-checking scripts; every one runs in CI
benches/ pytest-benchmark suites
fuzz/ Atheris harness for the raw-input validators
Conventions that bite: sample CSVs under pain001/templates/ and
examples/data/ are linted for IBAN, BIC and currency validity; any
column ending in IBAN or BIC is checked by suffix. Changing a
template, a preparer or a sample CSV requires regenerating the golden
files and, for CSV changes, scripts/regenerate_template_dbs.py.
Documentation#
Sphinx with MyST under docs/; make docs builds to
docs/_build/html. Root Markdown files (ARCHITECTURE.md, this file,
SCHEMES.md, …) are included into the rendered manual by thin chapter
files under docs/, so they are edited in one place. Architecture
decisions live in docs/adr/.
Versioning and release#
One version number, restated in
pyproject.toml,pain001/__init__.py,pain001/constants.py,CITATION.cffand theSECURITY.mdsupport table;scripts/preflight_release.pyrefuses to proceed when they disagree.The line is
0.0.xand every release is one step up; every member of the suite ships the same number (ADR-0001).Releases are cut by tag; the tag is SSH-signed;
ci.ymlbuilds, attests and publishes to PyPI with trusted publishing. RELEASING.md is the checklist,make release-checkits executable form.Commits need a
Signed-off-bytrailer (DCO) and are expected to be signed; see KEYS.asc for the maintainer key.