Aplicar ruff format a todo el código
Cambio mecánico, sin efecto en el comportamiento: la suite pasa igual antes y después. Va en un commit propio para no tapar los cambios con sentido. Se agregan además dos flujos de verificación que corren en cada carga al repositorio: - YAML: yamllint para sintaxis y estilo, más la carga de cada config contra su esquema de pydantic. Son cosas distintas — un YAML puede ser sintácticamente perfecto y estar roto igual, con 'run_nombre' en vez de 'run_name'. Ese paso no instala torch: se verificó que la capa de configuración no lo importa, así que corre en segundos en vez de descargar dos gigas y medio de CUDA. - Python: ruff check, ruff format --check y la suite completa con torch de CPU. Las rutas ignoradas de .yamllint.yml van ancladas con barra inicial. Sin anclar, 'data/' y 'runs/' excluían configs/data/ y configs/runs/ — siete archivos, justo los que más importa revisar — y el linter pasaba en verde sin haber mirado nada. Es el mismo defecto que ya había aparecido en .gitignore.
This commit is contained in:
Executable
+76
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Valida que todas las configs del repositorio carguen y pasen su esquema.
|
||||
|
||||
Un YAML sintácticamente correcto puede seguir estando roto: `n_layers` en vez de
|
||||
`n_layer`, un schedule que no entra en `max_steps`, float16 sin GradScaler. Eso
|
||||
no lo ve un linter de sintaxis — lo ven los validadores de pydantic, que ya
|
||||
existen. Esto los ejecuta sobre cada config del repositorio.
|
||||
|
||||
No importa torch a propósito: así el CI valida configs en segundos en vez de
|
||||
descargar los dos gigas y medio de CUDA.
|
||||
|
||||
python scripts/validar_configs.py
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
RAIZ = Path(__file__).resolve().parent.parent
|
||||
sys.path.insert(0, str(RAIZ))
|
||||
|
||||
from enlace.config.load import ( # noqa: E402
|
||||
ConfigError,
|
||||
load_agent_config,
|
||||
load_config,
|
||||
load_distill_config,
|
||||
)
|
||||
|
||||
|
||||
def validar() -> int:
|
||||
fallas: list[tuple[Path, str]] = []
|
||||
verificadas = 0
|
||||
|
||||
# Las configs de corrida componen las cuatro capas, así que validarlas
|
||||
# cubre transitivamente hardware, modelo, entrenamiento y datos.
|
||||
for path in sorted((RAIZ / "configs" / "runs").glob("*.yaml")):
|
||||
try:
|
||||
cfg = load_config(path)
|
||||
verificadas += 1
|
||||
print(
|
||||
f" OK {path.relative_to(RAIZ)} "
|
||||
f"({cfg.hardware.name} / {cfg.model.name} / {cfg.train.run_name})"
|
||||
)
|
||||
except ConfigError as exc:
|
||||
fallas.append((path, str(exc)))
|
||||
print(f" FALLA {path.relative_to(RAIZ)}")
|
||||
|
||||
# Los árboles que no son de entrenamiento se cargan aparte.
|
||||
for etiqueta, cargador, path in (
|
||||
("agente", load_agent_config, RAIZ / "configs" / "agent" / "tools.yaml"),
|
||||
("destilación", load_distill_config, RAIZ / "configs" / "data" / "distill.yaml"),
|
||||
):
|
||||
try:
|
||||
cargador(path)
|
||||
verificadas += 1
|
||||
print(f" OK {path.relative_to(RAIZ)} ({etiqueta})")
|
||||
except ConfigError as exc:
|
||||
fallas.append((path, str(exc)))
|
||||
print(f" FALLA {path.relative_to(RAIZ)}")
|
||||
|
||||
print()
|
||||
if fallas:
|
||||
for path, motivo in fallas:
|
||||
print(f"--- {path.relative_to(RAIZ)} ---")
|
||||
print(motivo)
|
||||
print()
|
||||
print(f"{len(fallas)} config(s) inválida(s) de {verificadas + len(fallas)}.")
|
||||
return 1
|
||||
|
||||
print(f"{verificadas} configs válidas.")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(validar())
|
||||
Reference in New Issue
Block a user