Contributing
Several organisations share this tool. Keep reports comparable: a rule must mean the same thing everywhere, and every rule must point to the SDMx text that justifies it. The target is a direct SDMx 2.1 -> SDMx 3.1 move.
Set-up
uv sync --extra web # the web extra is needed for tests/test_web.py
uv run pytest
Develop against cached data, so that you do not hammer production services:
uv run sdmx-readiness scan -e spc # once, online
uv run sdmx-readiness scan -e spc --from-cache reports/spc/<date> --out /tmp/x # then offline
Adding an endpoint
-
Add a block to
endpoints.toml. The fields are documented at the top of the file. -
Run
uv run sdmx-readiness scan -e <name>. -
Check
fetch_log.csv. Rows markedunsupportedorerrorare classes that were not assessed.- 2.1 queries should all be
okorempty. - 3.1 queries answer
unsupported(406) until the server offers SDMX-ML 3.1.
If a server uses a status code that we interpret wrongly, fix
client.outcome_forand name the server in the comment. - 2.1 queries should all be
-
Commit the endpoint block. Committing a report is optional; never commit
raw/.
Adding or changing a rule
-
Find the source, and its strength. Quote the exact text and give its location. Then choose the
basis(definitions insdmx_readiness/rules/engine.pyanddocs/METHODOLOGY.md§6):SCHEMAif the SDMX-ML 3.1 XSD enforces or states it. Compare tagsv2.1andv3.1.0ofsdmx-twg/sdmx-ml.STANDARDfor a MUST/SHOULD in a 3.1 document that the XSD does not enforce.GUIDELINEfor non-normative guidance, a MAY, or a consequence you derive.OBSERVEDfor endpoint behaviour.
-
Write the rule in the module for its category under
sdmx_readiness/rules/:@rule( id="DSD-011", # stable: never renumber or reuse a published id title="...", # one line, says what is wrong severity=WARNING, # BLOCKER / WARNING / INFO basis=SCHEMA, # SCHEMA / STANDARD / GUIDELINE / OBSERVED change=MECHANICAL, # mechanical / decision / remodel / none category=CATEGORY_DSD, applies_to="...", # which artefacts are examined spec="SDMX-ML 3.1 SDMXStructureDataStructure.xsd ...: '<exact quote>'", rationale="why it matters for a 2.1 -> 3.1 move", fix="what the owner should do", ) def dsd_something(ctx: Context): for a in ctx.primary: ... yield Finding("DSD-011", WARNING, a, "message naming the offending value")Rules read only
Artefact/Reference/Inventory, never XML. If you need a new fact from the XML, add it toArtefact.propsinparse.py(for DSDs:_dsd_facts) and document the key there. -
Test it in
tests/test_rules.pyortests/test_structures.py, with one case that fires and the nearest case that must not. The fixture builders are intests/sdmx_fixtures.py. -
Regenerate the docs:
uv run sdmx-readiness rules --markdown > docs/RULES.md uv run sdmx-readiness rules --review docs/rules_review.xlsx --evidence spc=reports/spc/<date>/findings.csv ... -
Re-run on cached scans and read the new findings yourself before merging.
-
Get it validated. Add the rule to the table in
docs/RULES_REVIEW.md§4. If it rests on an undocumented mapping or a judgement call, add an open question in §5.
Rule id prefixes:
| Prefix | Category |
|---|---|
VER |
versioning |
REF |
references |
MOD |
artefact-level 2.1 -> 3.1 model changes |
DSD |
DSD structure and modelling guidelines |
MSD |
MSD structure |
XF |
2.1 vs 3.1 output of the same endpoint |
Conventions
- Spelling: SDMx. The standard was renamed in June 2026 ("SDMX Evolves into SDMx",
https://sdmx.org/news/sdmx-evolves-into-sdmx-the-standard-for-statistical-data-and-metadata/).
Write SDMx in our own text (code strings, docs, reports). Keep the original spelling where
it is not ours to change:
- format names: SDMX-ML, SDMX-JSON, SDMX-CSV;
- identifiers: media types, XML namespaces, XSD file names (
SDMXCommon.xsd), URLs, ids in data (e.g. the agencySDMX); - verbatim quotes and the output of other tools.
- Version strings are interpreted only in
versions.py, which follows the SDMX-ML 3.1 schema. - Class names follow the SDMX-ML element names. 2.1/3.1 differences are aligned only in
model.CANONICAL_CLASS. - Changing what a metric counts changes every organisation's numbers. Update
docs/METHODOLOGY.md§8 in the same change. - Probes (
capabilities.py) must stay header-only (stream=True).