feat(saints-dictons): table saint_du_jour + API + import standalone 366j
- Nouveau modèle SaintDuJour (mois+jour+saints_json, indépendant de l'année) - Router /api/saints et /api/saints/jour (mois+jour → liste de prénoms) - Script standalone import_webapp_db.py : saints_du_jour.json → saint_du_jour, dictons_du_jour.json → dicton ; modes replace/append, --dry-run, --region - Données JSON 366 jours : saints_du_jour.json + dictons_du_jour.json - Scripts scraping/export calendrier_lunaire/saints_dictons/ Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
113
calendrier_lunaire/saints_dictons/export_saints_dictons_json.py
Normal file
113
calendrier_lunaire/saints_dictons/export_saints_dictons_json.py
Normal file
@@ -0,0 +1,113 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def _parse_mmdd(mmdd: str) -> tuple[int, int]:
|
||||
if len(mmdd) != 4 or not mmdd.isdigit():
|
||||
raise ValueError(f"MMDD invalide: {mmdd}")
|
||||
month = int(mmdd[:2])
|
||||
day = int(mmdd[2:])
|
||||
if not (1 <= month <= 12 and 1 <= day <= 31):
|
||||
raise ValueError(f"MMDD hors plage: {mmdd}")
|
||||
return month, day
|
||||
|
||||
|
||||
def _as_list(value: object) -> list[str]:
|
||||
if not value:
|
||||
return []
|
||||
if isinstance(value, list):
|
||||
out: list[str] = []
|
||||
for item in value:
|
||||
txt = str(item).strip()
|
||||
if txt and txt not in out:
|
||||
out.append(txt)
|
||||
return out
|
||||
txt = str(value).strip()
|
||||
return [txt] if txt else []
|
||||
|
||||
|
||||
def export_files(source_file: Path, saints_out: Path, dictons_out: Path) -> tuple[int, int]:
|
||||
source = json.loads(source_file.read_text(encoding="utf-8"))
|
||||
rows = source.get("data", [])
|
||||
saints_rows: list[dict] = []
|
||||
dictons_rows: list[dict] = []
|
||||
|
||||
for row in rows:
|
||||
mmdd = str(row.get("mmdd", "")).strip()
|
||||
if not mmdd:
|
||||
continue
|
||||
try:
|
||||
month, day = _parse_mmdd(mmdd)
|
||||
except ValueError:
|
||||
continue
|
||||
|
||||
saints = _as_list(row.get("saints"))
|
||||
dictons = _as_list(row.get("dictons"))
|
||||
source_url = row.get("source_url")
|
||||
|
||||
if saints:
|
||||
saints_rows.append(
|
||||
{
|
||||
"mois": month,
|
||||
"jour": day,
|
||||
"saints": saints,
|
||||
"source_url": source_url,
|
||||
}
|
||||
)
|
||||
|
||||
if dictons:
|
||||
dictons_rows.append(
|
||||
{
|
||||
"mois": month,
|
||||
"jour": day,
|
||||
"dictons": dictons,
|
||||
"source_url": source_url,
|
||||
}
|
||||
)
|
||||
|
||||
saints_rows.sort(key=lambda r: (r["mois"], r["jour"]))
|
||||
dictons_rows.sort(key=lambda r: (r["mois"], r["jour"]))
|
||||
|
||||
saints_out.parent.mkdir(parents=True, exist_ok=True)
|
||||
dictons_out.parent.mkdir(parents=True, exist_ok=True)
|
||||
saints_out.write_text(json.dumps(saints_rows, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
dictons_out.write_text(json.dumps(dictons_rows, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
return len(saints_rows), len(dictons_rows)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Génère saints_du_jour.json et dictons_du_jour.json depuis saints_YYYY.json."
|
||||
)
|
||||
parser.add_argument(
|
||||
"--source",
|
||||
default="calendrier_lunaire/saints_dictons/saints_2026.json",
|
||||
help="Source JSON issue du scraper annuel",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--saints-out",
|
||||
default="calendrier_lunaire/saints_dictons/saints_du_jour.json",
|
||||
help="Fichier JSON de sortie pour les saints",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--dictons-out",
|
||||
default="calendrier_lunaire/saints_dictons/dictons_du_jour.json",
|
||||
help="Fichier JSON de sortie pour les dictons",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
source_file = Path(args.source)
|
||||
saints_out = Path(args.saints_out)
|
||||
dictons_out = Path(args.dictons_out)
|
||||
saints_count, dictons_count = export_files(source_file, saints_out, dictons_out)
|
||||
print(f"Saints exportés : {saints_count} jours -> {saints_out}")
|
||||
print(f"Dictons exportés : {dictons_count} jours -> {dictons_out}")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user