"""Valida arenas/*.yaml y, si se indica la carpeta del dataset, también el manifiesto. Uso: python tools/validate.py # solo los yaml python tools/validate.py /ruta/al/dataset # yaml + manifiesto + imágenes """ from __future__ import annotations import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) import yaml # noqa: E402 from app.config import DEFAULT_ARENAS_DIR, ArenaConfig, validate_arena_dict # noqa: E402 from app.db import Database # noqa: E402 from app.ingest import ingest # noqa: E402 def main() -> int: rc = 0 print(f"Leyendo arenas de: {DEFAULT_ARENAS_DIR}") paths = sorted(DEFAULT_ARENAS_DIR.glob("*.yaml")) if not paths: print(" (no hay ningún .yaml en esa carpeta)") return 1 for path in paths: raw = yaml.safe_load(path.read_text(encoding="utf-8")) errs = validate_arena_dict(raw) if errs: rc = 1 print(f"✗ {path}\n - " + "\n - ".join(errs)) continue cfg = ArenaConfig(raw) cols = cfg.columns print(f"✓ {path}: yaml válido") print(f" candidatos: {cfg.candidate_keys}") print(f" columnas esperadas en el CSV (según el bloque `columns` de este fichero): " + ", ".join(f"{cols[k]}→{k}" for k in sorted(cols))) if len(sys.argv) > 1: root = Path(sys.argv[1]) manifest = root / cfg.data["manifest"] images = root / cfg.data.get("images_dir", "") print(f" manifiesto: {manifest}") rep = ingest(cfg, Database(), manifest, images, "salt") for w in rep.warnings: print(f" ! {w}") if rep.ok: print(f" ✓ manifiesto ok: {rep.n_cases} casos, {rep.n_assets} imágenes, " f"{rep.n_comparisons} comparaciones, segmentos {rep.segments}, " f"parámetros {rep.param_keys}") else: rc = 1 shown = rep.errors[:15] print(" ✗ manifiesto inválido:\n - " + "\n - ".join(shown)) if len(rep.errors) > len(shown): print(f" ... y {len(rep.errors) - len(shown)} errores más") return rc if __name__ == "__main__": sys.exit(main())