Code/app/fiches/utils/fiche_utils.py
Fabrication du Numérique 120f5a7af8 Modifications mineures
2025-05-11 22:48:13 +02:00

116 lines
4.0 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.

"""
fiche_utils.py  outils de lecture / rendu des fiches Markdown (indices et opérations)
Dépendances :
pip install python-frontmatter pyyaml jinja2
Usage :
from fiche_utils import load_seuils, render_fiche_markdown
seuils = load_seuils("config/indices_seuils.yaml")
markdown_rendered = render_fiche_markdown(raw_md_text, seuils)
"""
from __future__ import annotations
import frontmatter, yaml, jinja2, re, pathlib
from typing import Dict
from datetime import datetime, timezone
import os
from utils.gitea import recuperer_date_dernier_commit
def load_seuils(path: str | pathlib.Path = "config/indices_seuils.yaml") -> Dict:
"""Charge le fichier YAML des seuils et renvoie le dict 'seuils'."""
data = yaml.safe_load(pathlib.Path(path).read_text(encoding="utf-8"))
return data.get("seuils", {})
def _migrate_metadata(meta: Dict) -> Dict:
"""Normalise les clés YAML (ex : sheet_type → type_fiche)."""
keymap = {
"sheet_type": "type_fiche",
"indice_code": "indice_court", # si besoin
}
for old, new in keymap.items():
if old in meta and new not in meta:
meta[new] = meta.pop(old)
return meta
def render_fiche_markdown(md_text: str, seuils: Dict, license_path: str = "assets/licence.md") -> str:
"""Renvoie la fiche rendue (Markdown) :
placeholders Jinja2 remplacés ({{ … }})
table seuils injectée via dict 'seuils'.
- licence ajoutée après le tableau de version et avant le premier titre de niveau 2
"""
post = frontmatter.loads(md_text)
meta = _migrate_metadata(dict(post.metadata))
body_template = post.content
# Instancie Jinja2 en 'StrictUndefined' pour signaler les placeholders manquants.
env = jinja2.Environment(
undefined=jinja2.StrictUndefined,
autoescape=False,
trim_blocks=True,
lstrip_blocks=True,
)
tpl = env.from_string(body_template)
rendered_body = tpl.render(**meta, seuils=seuils)
# Option : ajoute automatiquement titre + tableau version si absent.
header = f"# {meta.get('indice', meta.get('titre',''))} ({meta.get('indice_court','')})"
if not re.search(r"^# ", rendered_body, flags=re.M):
rendered_body = f"""{header}
{rendered_body}"""
# Charger le contenu de la licence
try:
license_content = pathlib.Path(license_path).read_text(encoding="utf-8")
# Insérer la licence après le tableau de version et avant le premier titre h2
# Trouver la position du premier titre h2
h2_match = re.search(r"^## ", rendered_body, flags=re.M)
if h2_match:
h2_position = h2_match.start()
rendered_body = f"{rendered_body[:h2_position]}\n\n{license_content}\n\n{rendered_body[h2_position:]}"
else:
# S'il n'y a pas de titre h2, ajouter la licence à la fin
rendered_body = f"{rendered_body}\n\n{license_content}"
except Exception as e:
# En cas d'erreur lors de la lecture du fichier de licence, continuer sans l'ajouter
pass
return rendered_body
def fichier_plus_recent(chemin_fichier, reference):
try:
modif = datetime.fromtimestamp(os.path.getmtime(chemin_fichier), tz=timezone.utc)
return modif > reference
except Exception:
return False
def doit_regenerer_fiche(html_path, fiche_type, fiche_choisie, commit_url, fichiers_criticite):
if not os.path.exists(html_path):
return True
local_mtime = datetime.fromtimestamp(os.path.getmtime(html_path), tz=timezone.utc)
remote_mtime = recuperer_date_dernier_commit(commit_url)
if remote_mtime is None or remote_mtime > local_mtime:
return True
if fichier_plus_recent(fichiers_criticite.get("IHH"), local_mtime):
return True
if fiche_type == "minerai" or "minerai" in fiche_choisie.lower():
if fichier_plus_recent(fichiers_criticite.get("IVC"), local_mtime):
return True
if fichier_plus_recent(fichiers_criticite.get("ICS"), local_mtime):
return True
return False