1
0
Files
Strategy-as-Code/tools/validate.py
Rihards Gailums bcdd26b8d9 NAP2027 kā dati: shēma strategija-0.1, lv-nap2027, datu līgums B06
475 numurētie punkti (mērķi, 131 indikators, 124 uzdevumi ar VPK ID,
telpiskās attīstības virzieni), 154 pamatojuma ieraksti, 34 zemsvītras
piezīmes. Pārbaude pret avota PDF ar citu nolasītāju — izturēta.
Katalogs planosanas-dokumenti.yaml, rīki parse/build/verify/validate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016679RwmHsuTFfxt26wP6rk
2026-10-11 12:47:18 +00:00

70 lines
3.2 KiB
Python

#!/usr/bin/env python3
"""Strategy-as-Code pārbaudītājs.
python3 tools/validate.py [--registry organizacijas.xml]
Katram dokumentam katalogā planosanas-dokumenti.yaml:
- datne atbilst XSD shēmai schemas/strategija-0.1.xsd (arī atslēgas un atsauces shēmā);
- datnes nosaukums = dokumenta identifikators;
- avota PDF sha256 sakrīt ar Metadata/Source/SHA256;
- visi VPK ID (Actors, Responsible, CoResponsible, Abbreviation, Developer) ir Valsts institūciju reģistrā;
- pārbaudes atskaite verification/<id>.verify.json ir par šo pašu avota PDF un ir izturēta.
Reģistrs pēc noklusējuma — ProcessGit Valdibas-Deklaracija-as-Code data/organizacijas.xml.
"""
import hashlib
import json
import os
import sys
import urllib.request
import yaml
from lxml import etree
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
NS = {"s": "urn:pppa:vpk:strategija:0.1"}
REG_URL = "https://processgit.org/Valsts-Pirmkods/Valdibas-Deklaracija-as-Code/raw/branch/main/data/organizacijas.xml"
def main():
reg_src = sys.argv[sys.argv.index("--registry") + 1] if "--registry" in sys.argv else REG_URL
reg = etree.parse(reg_src if os.path.exists(reg_src) else urllib.request.urlopen(reg_src))
ids = {o.get("id") for o in reg.getroot() if etree.QName(o).localname == "Organization"}
xsd = etree.XMLSchema(etree.parse(os.path.join(ROOT, "schemas/strategija-0.1.xsd")))
cat = yaml.safe_load(open(os.path.join(ROOT, "planosanas-dokumenti.yaml"), encoding="utf-8"))
errors, n = [], 0
for d in cat["documents"]:
if not d.get("as_code", {}).get("path"):
continue
n += 1
path = os.path.join(ROOT, d["as_code"]["path"])
doc = etree.parse(path)
if not xsd.validate(doc):
errors += [f"{d['id']}: XSD {e.line}: {e.message}" for e in list(xsd.error_log)[:10]]
root = doc.getroot()
if root.get("id") != d["id"] or os.path.basename(path) != d["id"] + ".xml":
errors.append(f"{d['id']}: datnes nosaukums vai id neatbilst katalogam")
src = os.path.join(ROOT, root.findtext("s:Metadata/s:Source/s:File", namespaces=NS))
sha = hashlib.sha256(open(src, "rb").read()).hexdigest()
if sha != root.findtext("s:Metadata/s:Source/s:SHA256", namespaces=NS):
errors.append(f"{d['id']}: avota sha256 nesakrīt")
used = {e.get("org") for e in root.iter() if e.get("org")}
missing = sorted(used - ids)
if missing:
errors.append(f"{d['id']}: VPK ID nav reģistrā: {', '.join(missing)}")
vpath = os.path.join(ROOT, "verification", d["id"] + ".verify.json")
if os.path.exists(vpath):
v = json.load(open(vpath, encoding="utf-8"))
if v.get("pdf_sha256") != sha or not v.get("passed"):
errors.append(f"{d['id']}: pārbaudes atskaite nav izturēta vai ir par citu avota datni")
else:
errors.append(f"{d['id']}: nav pārbaudes atskaites {vpath}")
print(f"{d['id']}: {len(doc.findall('.//s:Item', NS))} punkti, {len(used)} VPK ID")
for e in errors:
print("KĻŪDA", e)
print("pārbaudīti dokumenti:", n, "kļūdas:", len(errors))
sys.exit(1 if errors else 0)
if __name__ == "__main__":
main()