trainlog/tools/export_equipment_associations.py

67 lines
3.1 KiB
Python

#!/usr/bin/env python3
"""Export stable desktop session/exercise equipment associations."""
import argparse
import json
import sqlite3
import os
from datetime import datetime
from pathlib import Path
DEFAULT_CATALOG = Path(__file__).resolve().parents[1] / "catalog" / "equipment-v1.json"
def load_supplied_equipment_ids(path):
catalog = json.loads(path.read_text(encoding="utf-8"))
if catalog.get("format") != "trainlog-equipment-catalog" or catalog.get("version") != 1:
raise ValueError("catalogue équipement v1 invalide")
return {item["id"] for item in catalog["equipment"]}
def main():
parser = argparse.ArgumentParser()
parser.add_argument("output", type=Path)
parser.add_argument("--database", type=Path,
default=Path(os.environ.get("XDG_DATA_HOME", str(Path.home() / ".local/share"))) / "trainlog" / "trainlog.db")
parser.add_argument("--catalog", type=Path, default=DEFAULT_CATALOG)
args = parser.parse_args()
connection = sqlite3.connect(args.database)
try:
if connection.execute("PRAGMA user_version;").fetchone()[0] not in (8, 9, 10, 11, 12):
raise ValueError("schema desktop v8 à v12 requis")
known_equipment = load_supplied_equipment_ids(args.catalog)
known_equipment.update(row[0] for row in connection.execute(
"SELECT equipment_id FROM custom_equipment"))
rows = connection.execute(
"SELECT s.session_id,se.entry_id,e.exercise_id,se.equipment_id FROM session_exercises se "
"JOIN sessions s ON s.id=se.session_row_id JOIN exercises e ON e.id=se.exercise_row_id "
"ORDER BY s.started_at,s.id,se.position").fetchall()
payload = {"format": "trainlog-equipment-associations", "version": 2,
"generated_at": datetime.now().astimezone().isoformat(), "associations": []}
for session_id, entry_id, exercise_id, equipment_id in rows:
# CONTRACT: definitions-v1 is published before this unchanged v2
# reference artifact, so every referenced custom ID must exist.
if equipment_id is not None and equipment_id not in known_equipment:
raise ValueError(
"équipement non transportable "
f"session_id={session_id} entry_id={entry_id} "
f"equipment_id={equipment_id}"
)
item = {"session_id": session_id, "entry_id": entry_id, "exercise_id": exercise_id,
"state": "set" if equipment_id is not None else "cleared"}
if equipment_id is not None:
item["equipment_id"] = equipment_id
payload["associations"].append(item)
args.output.write_text(json.dumps(payload, ensure_ascii=False, separators=(",", ":")), encoding="utf-8")
print("EQUIPMENT_ASSOCIATIONS_EXPORT=PASS")
print(f"associations={len(rows)}")
finally:
connection.close()
if __name__ == "__main__":
try:
main()
except Exception as error:
print(f"EQUIPMENT_ASSOCIATIONS_EXPORT=FAIL {error}")
raise SystemExit(1)