#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ patch_render_engine_c5fin.py — Finitions C5 (2 micro-fixes visuels) =================================================================== F1. bar_chart horizontal : PowerPoint affiche les catégories de BAS en HAUT en BAR_CLUSTERED — la première catégorie du YAML se retrouvait en bas. On inverse catégories ET valeurs quand horizontal, pour un ordre de lecture naturel (haut → bas). F2. waterfall : les libellés de catégories longs (Décommissionnements…) wrappaient en orphelin. Réduction automatique à 9 pt au-delà de 14 caractères. Usage (dossier du pipeline) : python3 patches/patch_render_engine_c5fin.py Vérifie les ancres, écrit .bak-c5fin, compile, idempotent. """ import py_compile import shutil import sys from pathlib import Path TARGET = Path("render_engine_v2.py") P1_OLD = """ cd = CategoryChartData() cd.categories = cats for s in series: vals = [self._num(v) for v in (s.get("values") or [])][:len(cats)] vals += [0.0] * (len(cats) - len(vals)) cd.add_series(pick(s, "label", default="Série"), tuple(vals)) x, y, w, h = self._chart_zone(d) horiz = bool(d.get("horizontal")) """ P1_NEW = """ horiz = bool(d.get("horizontal")) if horiz: # BAR_CLUSTERED trace de bas en haut : on inverse pour un # ordre de lecture naturel (1re catégorie du YAML en haut). cats = cats[::-1] cd = CategoryChartData() cd.categories = cats for s in series: vals = [self._num(v) for v in (s.get("values") or [])][:len(cats)] vals += [0.0] * (len(cats) - len(vals)) if horiz: vals = vals[::-1] cd.add_series(pick(s, "label", default="Série"), tuple(vals)) x, y, w, h = self._chart_zone(d) """ P2_OLD = """ def cat_label(i, label): self._text(slide, zx + i * slot + 0.05, chart_b + 0.15, slot - 0.1, 1.05, label, size=10, color=self.C["slate"], align=PP_ALIGN.CENTER) """ P2_NEW = """ def cat_label(i, label): sz = 9 if len(str(label)) > 14 else 10 self._text(slide, zx + i * slot + 0.05, chart_b + 0.15, slot - 0.1, 1.05, label, size=sz, color=self.C["slate"], align=PP_ALIGN.CENTER) """ def fail(m): print(" ! %s" % m) sys.exit(1) def main(): if not TARGET.exists(): fail("%s introuvable." % TARGET) c = TARGET.read_text(encoding="utf-8") if "cats = cats[::-1]" in c: fail("Déjà patché — rien à faire.") for i, old in enumerate((P1_OLD, P2_OLD), 1): if c.count(old) != 1: fail("Ancre F%d introuvable ou non unique." % i) shutil.copy2(TARGET, str(TARGET) + ".bak-c5fin") c = c.replace(P1_OLD, P1_NEW).replace(P2_OLD, P2_NEW) TARGET.write_text(c, encoding="utf-8") try: py_compile.compile(str(TARGET), doraise=True) except py_compile.PyCompileError as e: shutil.copy2(str(TARGET) + ".bak-c5fin", TARGET) fail("Compilation : %s" % e) print(" + F1 (ordre bar horizontal) + F2 (labels waterfall) OK.") if __name__ == "__main__": main()