51 lines
1.4 KiB
Python
51 lines
1.4 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
from jsonschema import Draft202012Validator
|
|
|
|
BASE_DIR = Path(__file__).resolve().parent
|
|
SCHEMA_DIR = BASE_DIR / "schemas"
|
|
|
|
|
|
def load_schema(name: str) -> dict[str, Any]:
|
|
path = SCHEMA_DIR / name
|
|
with path.open("r", encoding="utf-8") as handle:
|
|
return json.load(handle)
|
|
|
|
|
|
REPORT_SCHEMA = load_schema("report-payload.schema.json")
|
|
CLAUDE_SCHEMA = load_schema("claude-output.schema.json")
|
|
REPORT_VALIDATOR = Draft202012Validator(REPORT_SCHEMA)
|
|
CLAUDE_VALIDATOR = Draft202012Validator(CLAUDE_SCHEMA)
|
|
|
|
|
|
def _format_path(path_parts) -> str:
|
|
path = "$"
|
|
for part in path_parts:
|
|
if isinstance(part, int):
|
|
path += f"[{part}]"
|
|
else:
|
|
path += f".{part}"
|
|
return path
|
|
|
|
|
|
def collect_errors(payload: Any, validator: Draft202012Validator) -> list[dict[str, str]]:
|
|
errors = []
|
|
for error in sorted(validator.iter_errors(payload), key=lambda item: list(item.path)):
|
|
errors.append({
|
|
"path": _format_path(error.absolute_path),
|
|
"message": error.message,
|
|
})
|
|
return errors
|
|
|
|
|
|
def validate_report(payload: Any) -> list[dict[str, str]]:
|
|
return collect_errors(payload, REPORT_VALIDATOR)
|
|
|
|
|
|
def validate_claude_output(payload: Any) -> list[dict[str, str]]:
|
|
return collect_errors(payload, CLAUDE_VALIDATOR)
|