Files
lescarnetsdakkadien.netig.net/scripts/update-content.py
T

89 lines
2.5 KiB
Python
Executable File
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
"""Horodate la dernière modification substantielle dune 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<body>.*?)(?:\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())