81 lines
2.6 KiB
Python
81 lines
2.6 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
check_goldens.py — C0 · goldens de non-régression du moteur
|
|
===========================================================
|
|
Rend chaque golden_*.yaml présent et compare sa STRUCTURE (nb de
|
|
slides, nb de shapes par slide) au manifeste goldens_manifest.json.
|
|
Le PPTX contient des timestamps : un diff binaire est impossible — la
|
|
structure, elle, est déterministe et attrape les régressions de rendu
|
|
(shape manquante, layout cassé, exception).
|
|
|
|
python3 check_goldens.py → vérifie (code retour 1 si écart)
|
|
python3 check_goldens.py --update → (re)génère le manifeste
|
|
|
|
À lancer avant tout push moteur (ou en tâche DSM hebdo).
|
|
"""
|
|
import glob
|
|
import json
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
MANIFEST = Path("goldens_manifest.json")
|
|
|
|
|
|
def structure(pptx_path):
|
|
from pptx import Presentation
|
|
prs = Presentation(pptx_path)
|
|
return [len(list(s.shapes)) for s in prs.slides]
|
|
|
|
|
|
def render_all():
|
|
out = {}
|
|
for y in sorted(glob.glob("golden_*.yaml")):
|
|
pptx = "_check_%s.pptx" % Path(y).stem
|
|
r = subprocess.run(
|
|
["python3", "render_engine_v2.py", y, pptx,
|
|
"--assets", "assets"],
|
|
capture_output=True, text=True)
|
|
if r.returncode != 0:
|
|
print(" ! %s : le rendu ÉCHOUE\n%s" % (y, r.stdout[-400:]))
|
|
sys.exit(1)
|
|
out[y] = structure(pptx)
|
|
Path(pptx).unlink(missing_ok=True)
|
|
return out
|
|
|
|
|
|
def main():
|
|
got = render_all()
|
|
if "--update" in sys.argv:
|
|
MANIFEST.write_text(json.dumps(got, indent=2))
|
|
print(" + Manifeste écrit : %d goldens, %d slides au total."
|
|
% (len(got), sum(len(v) for v in got.values())))
|
|
return
|
|
if not MANIFEST.exists():
|
|
print(" ! Pas de manifeste — lancer d'abord : "
|
|
"python3 check_goldens.py --update")
|
|
sys.exit(1)
|
|
want = json.loads(MANIFEST.read_text())
|
|
ok = True
|
|
for y, shapes in got.items():
|
|
ref = want.get(y)
|
|
if ref is None:
|
|
print(" ~ %s : nouveau golden (absent du manifeste)" % y)
|
|
continue
|
|
if shapes != ref:
|
|
ok = False
|
|
print(" ! %s : ÉCART — slides/shapes %s ≠ attendu %s"
|
|
% (y, shapes, ref))
|
|
for y in want:
|
|
if y not in got:
|
|
ok = False
|
|
print(" ! %s : golden du manifeste INTROUVABLE" % y)
|
|
print(" %s" % ("✓ goldens conformes (%d fichiers)" % len(got)
|
|
if ok else "✗ régression détectée"))
|
|
sys.exit(0 if ok else 1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|