#!/usr/bin/env python3 """Horodate la dernière modification substantielle d’une fiche.""" import argparse import re import sys from datetime import datetime from pathlib import Path from zoneinfo import ZoneInfo, ZoneInfoNotFoundError ROOT = Path(__file__).resolve().parent.parent CONTENT = (ROOT / "src" / "content").resolve() FRONT_MATTER_RE = re.compile( r"\A\+\+\+\r?\n(?P.*?)(?:\r?\n\+\+\+(?=\r?\n|\Z))", re.DOTALL, ) UPDATED_RE = re.compile(r"(?m)^(?:#\s*)?updated\s*=.*?(?=\r?$)") def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument( "fiche", help="chemin depuis la racine du dépôt ou depuis src/content/", ) return parser.parse_args() def resolve_path(value: str) -> Path: path = Path(value).expanduser() if not path.is_absolute(): path = ROOT / path if path.parts[:2] == ("src", "content") else CONTENT / path path = path.resolve() if not path.is_relative_to(CONTENT): raise ValueError("la fiche doit se trouver dans src/content/") if not path.is_file(): raise ValueError(f"fichier introuvable : {path}") if path.suffix != ".md" or path.name == "_index.md": raise ValueError("le chemin doit désigner une fiche Markdown, pas un index") return path def update_timestamp(path: Path) -> str: text = path.read_bytes().decode("utf-8") front_matter = FRONT_MATTER_RE.match(text) if front_matter is None: raise ValueError("front matter TOML délimité par +++ absent") matches = list(UPDATED_RE.finditer(front_matter.group("body"))) if len(matches) != 1: raise ValueError("la fiche doit contenir exactement une ligne updated") timestamp = datetime.now(ZoneInfo("Europe/Paris")).isoformat(timespec="seconds") match = matches[0] offset = front_matter.start("body") start = offset + match.start() end = offset + match.end() path.write_bytes( (text[:start] + f"updated = {timestamp}" + text[end:]).encode("utf-8") ) return timestamp def main() -> int: args = parse_args() try: path = resolve_path(args.fiche) timestamp = update_timestamp(path) except (OSError, UnicodeError, ValueError, ZoneInfoNotFoundError) as exc: print(f"Erreur : {exc}", file=sys.stderr) return 1 print(f"Fiche mise à jour : {path.relative_to(ROOT)}") print(f"updated = {timestamp}") return 0 if __name__ == "__main__": raise SystemExit(main())