Files
sliding-automation/patches/patch_facilitator_c4.py
T

143 lines
5.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
patch_facilitator_c4.py — Chantier C4 (Assets & images)
=======================================================
Patch strict de facilitator_v9.py :
P1. validate_freeform accepte le nouveau type de bloc « image ».
P2. /lire inventorie aussi projets/<slug>/assets/ (images + dimensions)
et injecte la liste dans le contexte Narrator — le Narrator peut
alors référencer les fichiers par nom dans les layouts image_*.
Le dossier assets/ est créé au premier /lire s'il n'existe pas.
P3. Insère list_assets() (inventaire, dimensions via Pillow si
disponible, sinon noms seuls).
Usage (dossier du pipeline, single-line) :
python3 patch_facilitator_c4.py
Compatible tout ordre avec C1/C2/C3. Vérifie chaque ancre, écrit
.bak-fc4, compile, idempotent.
"""
import py_compile
import shutil
import sys
from pathlib import Path
TARGET = Path("facilitator_v9.py")
FUNC = '''
def list_assets(proj: "Project"):
"""Inventaire des images de projets/<slug>/assets/ (chantier C4).
Crée le dossier au premier appel. Retourne un bloc texte destiné au
contexte Narrator, ou une chaîne vide si aucune image."""
assets = proj.root / "assets"
assets.mkdir(exist_ok=True)
exts = {".png", ".jpg", ".jpeg", ".webp"}
files = sorted(p for p in assets.iterdir()
if p.suffix.lower() in exts and p.is_file())
if not files:
return ""
lines = ["IMAGES DISPONIBLES DANS assets/ (utilisables dans les "
"layouts image_split / image_full et le bloc freeform "
"image, par leur nom de fichier) :"]
for p in files:
dims = ""
try:
from PIL import Image
with Image.open(p) as im:
dims = f" ({im.size[0]}×{im.size[1]})"
except Exception:
pass
lines.append(f"- {p.name}{dims}")
return "\\n".join(lines)
'''
PATCHES = [
# P1 — type de bloc freeform « image »
(
'VALID_BLOCK_TYPES = {"title", "heading", "text", "stat", '
'"circle",\n'
' "badge", "card", "rect", "line"}\n',
'VALID_BLOCK_TYPES = {"title", "heading", "text", "stat", '
'"circle",\n'
' "badge", "card", "rect", "line", "image"}\n',
),
# P2 — /lire : inventaire des assets
(
' elif cmd == "/lire":\n'
' context, new_files = load_documents(proj, '
'loaded_docs)\n'
' if not new_files:\n'
' info("Aucun nouveau document dans inputs/.")\n'
' continue\n',
' elif cmd == "/lire":\n'
' context, new_files = load_documents(proj, '
'loaded_docs)\n'
' assets_info = list_assets(proj)\n'
' if assets_info:\n'
' context = ((context or "").strip()\n'
' + "\\n\\n" + assets_info).strip()\n'
' ok(f"{len(assets_info.splitlines()) - 1} '
'image(s) dans assets/.")\n'
' if not new_files and not assets_info:\n'
' info("Aucun nouveau document dans inputs/ ni '
'image dans assets/.")\n'
' continue\n',
),
]
MARKER = "def list_assets"
ANCHOR_SECTION = "# FLUX LIBRE — THE FREE DESIGNER"
def fail(msg):
print(" ! %s" % msg)
sys.exit(1)
def main():
if not TARGET.exists():
fail("%s introuvable — lancer depuis le dossier du pipeline."
% TARGET)
content = TARGET.read_text(encoding="utf-8")
if MARKER in content:
fail("Déjà patché (list_assets présent) — rien à faire.")
for i, (old, _) in enumerate(PATCHES, 1):
n = content.count(old)
if n == 0:
fail("Ancre du patch %d introuvable — facilitator inattendu."
% i)
if n > 1:
fail("Ancre du patch %d non unique (%d occurrences)." % (i, n))
if content.count(ANCHOR_SECTION) != 1:
fail("Ancre de section FREE DESIGNER introuvable ou non unique.")
shutil.copy2(TARGET, str(TARGET) + ".bak-fc4")
print(" + Sauvegarde : %s.bak-fc4" % TARGET)
for old, new in PATCHES:
content = content.replace(old, new)
lines = content.split("\n")
idx = next(i for i, l in enumerate(lines) if ANCHOR_SECTION in l)
ins = idx - 1 if lines[idx - 1].startswith("# ───") else idx
lines[ins:ins] = FUNC.split("\n")
content = "\n".join(lines)
TARGET.write_text(content, encoding="utf-8")
print(" + 2 patchs + list_assets appliqués.")
try:
py_compile.compile(str(TARGET), doraise=True)
print(" + Compilation OK.")
except py_compile.PyCompileError as e:
shutil.copy2(str(TARGET) + ".bak-fc4", TARGET)
fail("Erreur de compilation — fichier restauré :\n%s" % e)
print("\n Dépose tes images dans projets/<slug>/assets/ puis /lire "
"dans la session.")
if __name__ == "__main__":
main()