git_conflict_env / server /phase2_validate.py
royalsanga's picture
Upload folder using huggingface_hub
c2c4503 verified
Raw History Blame Contribute Delete
3.24 kB
"""
Phase-2 grader harness — matches hackathon validator behavior.
Loads ``openenv.yaml`` ``tasks[].grader``, imports each class, runs
``float(Class().grade(None))``, and requires ``0 < score < 1``.
Run locally::
uv run validate-phase2
Or::
uv run python -m git_conflict_env.server.phase2_validate
In Docker (image ``WORKDIR`` is ``/app/env``; console script is on ``PATH``)::
docker run --rm git-conflict-env validate-phase2
Or::
docker run --rm git-conflict-env python -m git_conflict_env.server.phase2_validate
"""
from __future__ import annotations
import importlib
import os
import sys
import traceback
from pathlib import Path
import yaml
def _find_openenv_yaml() -> Path | None:
"""Locate manifest (works from repo root, Docker WORKDIR /app/env, or site-packages install)."""
env_root = os.environ.get("OPENENV_ROOT", "").strip()
if env_root:
p = Path(env_root) / "openenv.yaml"
if p.is_file():
return p
candidates: list[Path] = []
cwd = Path.cwd().resolve()
candidates.append(cwd / "openenv.yaml")
docker_env = Path("/app/env/openenv.yaml")
if docker_env.is_file():
candidates.append(docker_env)
# Dev layout: git_repo/server/phase2_validate.py -> repo root
here = Path(__file__).resolve()
candidates.append(here.parent.parent / "openenv.yaml")
cur = cwd
for _ in range(8):
candidates.append(cur / "openenv.yaml")
if cur.parent == cur:
break
cur = cur.parent
for p in candidates:
if p.is_file():
return p
return None
def _import_root_for_server_modules(yaml_path: Path) -> Path:
"""Directory that must be on sys.path for ``import server.grader``."""
return yaml_path.parent.resolve()
def run_harness() -> int:
"""Return 0 if all tasks pass, 1 otherwise."""
yaml_path = _find_openenv_yaml()
if yaml_path is None:
print(
"error: openenv.yaml not found (set OPENENV_ROOT or run from repo / Docker WORKDIR /app/env)",
file=sys.stderr,
)
return 2
root = _import_root_for_server_modules(yaml_path)
if str(root) not in sys.path:
sys.path.insert(0, str(root))
data = yaml.safe_load(yaml_path.read_text(encoding="utf-8"))
tasks = data.get("tasks") or []
if not tasks:
print("error: openenv.yaml has no tasks (Phase-2 requires tasks[].grader)", file=sys.stderr)
return 1
failed = False
for t in tasks:
tid = t.get("id", "?")
gpath = t.get("grader", "MISSING")
print(f"Task: {tid} | grader: {gpath}")
try:
mod_name, cls_name = str(gpath).rsplit(":", 1)
mod = importlib.import_module(mod_name)
cls = getattr(mod, cls_name)
score = float(cls().grade(None))
ok = 0 < score < 1
print(f" -> {score} {'OK' if ok else 'FAIL'}")
if not ok:
failed = True
except Exception:
traceback.print_exc()
print(" -> CRASHED")
failed = True
return 1 if failed else 0
def main() -> None:
raise SystemExit(run_harness())
if __name__ == "__main__":
main()