-
Notifications
You must be signed in to change notification settings - Fork 284
Expand file tree
/
Copy pathvalidate_submission.py
More file actions
87 lines (64 loc) · 2.28 KB
/
Copy pathvalidate_submission.py
File metadata and controls
87 lines (64 loc) · 2.28 KB
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
"""
Validate one or more benchmark submission JSON files against the schema.
Usage:
python scripts/validate_submission.py path/to/sub1.json [path/to/sub2.json ...]
Exit code 0 if all submissions are valid, 1 otherwise.
"""
from __future__ import annotations
import json
import sys
from pathlib import Path
from typing import Iterable
import jsonschema
REPO_ROOT = Path(__file__).resolve().parent.parent
SCHEMA_PATH = REPO_ROOT / "benchmark" / "schemas" / "submission.schema.json"
def _load_schema() -> dict:
with SCHEMA_PATH.open("r", encoding="utf-8") as f:
return json.load(f)
def _format_error(err: jsonschema.ValidationError) -> str:
location = "/".join(str(p) for p in err.absolute_path) or "<root>"
return f"{location}: {err.message}"
def validate(path: Path, validator: jsonschema.Draft202012Validator) -> list[str]:
try:
with path.open("r", encoding="utf-8") as f:
data = json.load(f)
except (OSError, json.JSONDecodeError) as exc:
return [f"Failed to read JSON: {exc}"]
errors = sorted(validator.iter_errors(data), key=lambda e: list(e.absolute_path))
return [_format_error(e) for e in errors]
def run(paths: Iterable[Path]) -> int:
schema = _load_schema()
validator = jsonschema.Draft202012Validator(schema)
failed = 0
paths = list(paths)
if not paths:
print("No submission files provided.")
return 0
for path in paths:
if not path.is_file():
print(f"[FAIL] {path}: file not found")
failed += 1
continue
errors = validate(path, validator)
if errors:
print(f"[FAIL] {path} ({len(errors)} error(s)):")
for err in errors[:25]:
print(f" - {err}")
if len(errors) > 25:
print(f" ... and {len(errors) - 25} more")
failed += 1
else:
print(f"[OK] {path}")
if failed:
print(f"\n{failed} of {len(paths)} submission(s) failed validation.")
return 1
print(f"\nAll {len(paths)} submission(s) are valid.")
return 0
def main() -> int:
if len(sys.argv) < 2:
print(__doc__)
return 0
paths = [Path(p) for p in sys.argv[1:]]
return run(paths)
if __name__ == "__main__":
sys.exit(main())