File size: 3,643 Bytes
9496a0e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#!/usr/bin/env python3
"""
Pre-submission checks for the OpenEnv hackathon SQL agent project.

Run from repo root:
  python hf/pre-validation-script.py

Or:
  cd hf && python pre-validation-script.py

Checks:
  - Required files exist (inference.py, Dockerfile, openenv.yaml, README, models, etc.)
  - inference.py contains mandatory stdout format helpers and tags
  - Python syntax compiles
  - openenv validate (if CLI installed)

Does not call external LLM APIs (no HF_TOKEN required for this script).
"""

from __future__ import annotations

import ast
import subprocess
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parent.parent


def ok(msg: str) -> None:
    print(f"[OK] {msg}", flush=True)


def fail(msg: str) -> bool:
    print(f"[FAIL] {msg}", flush=True)
    return False


def check_files() -> bool:
    good = True
    required = [
        ROOT / "inference.py",
        ROOT / "Dockerfile",
        ROOT / "openenv.yaml",
        ROOT / "README.md",
        ROOT / "models.py",
        ROOT / "client.py",
        ROOT / "server" / "app.py",
        ROOT / "server" / "environment.py",
        ROOT / "core" / "tasks.py",
        ROOT / "core" / "grader.py",
    ]
    for p in required:
        if not p.is_file():
            good &= fail(f"Missing file: {p.relative_to(ROOT)}")
    if good:
        ok("Required project files present")
    return good


def check_inference_stdout_contract() -> bool:
    path = ROOT / "inference.py"
    text = path.read_text(encoding="utf-8")
    tokens = [
        "def log_start",
        "def log_step",
        "def log_end",
        "[START]",
        "[STEP]",
        "[END]",
        "OpenAI(",
        "chat.completions.create",
        "HF_TOKEN",
        "API_BASE_URL",
        "MODEL_NAME",
    ]
    good = True
    for t in tokens:
        if t not in text:
            good &= fail(f"inference.py missing required fragment: {t!r}")
    if good:
        ok("inference.py stdout contract + OpenAI client config markers")
    return good


def check_syntax() -> bool:
    good = True
    for py in [
        ROOT / "inference.py",
        ROOT / "server" / "app.py",
        ROOT / "server" / "environment.py",
        ROOT / "models.py",
    ]:
        try:
            ast.parse(py.read_text(encoding="utf-8"), filename=str(py))
        except SyntaxError as e:
            good &= fail(f"Syntax error in {py.relative_to(ROOT)}: {e}")
    if good:
        ok("Core Python files parse (syntax)")
    return good


def check_openenv_validate() -> bool:
    try:
        r = subprocess.run(
            ["openenv", "validate"],
            cwd=str(ROOT),
            capture_output=True,
            text=True,
            timeout=120,
        )
    except FileNotFoundError:
        print(
            "[WARN] openenv CLI not on PATH — install openenv-core and ensure `openenv` is available",
            flush=True,
        )
        return True
    sys.stdout.write(r.stdout)
    sys.stderr.write(r.stderr)
    if r.returncode != 0:
        return fail("openenv validate returned non-zero")
    ok("openenv validate")
    return True


def main() -> int:
    print("=== Pre-submission validation ===", flush=True)
    print(f"ROOT: {ROOT}", flush=True)
    all_ok = True
    all_ok &= check_files()
    all_ok &= check_inference_stdout_contract()
    all_ok &= check_syntax()
    all_ok &= check_openenv_validate()
    if all_ok:
        print("\n=== All automated checks passed ===", flush=True)
        return 0
    print("\n=== Fix failures above before submitting ===", flush=True)
    return 1


if __name__ == "__main__":
    sys.exit(main())