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
This commit is contained in:
69
tools/validate.py
Normal file
69
tools/validate.py
Normal file
@@ -0,0 +1,69 @@
|
||||
#!/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()
|
||||
Reference in New Issue
Block a user