Spaces:
Sleeping
Sleeping
File size: 2,167 Bytes
7952f32 | 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 | """Parse-only validator.
Calls Python's own ``compile()`` on each materialized file and reports any
syntax / lexer errors. This is the cheapest gate; the agent receives this
feedback as part of ``materialize_and_validate``.
Heavier checks (import-resolution, ``mypy --strict``, behavioral tests) live
elsewhere in :mod:`graphforge.validator` and :mod:`graphforge.behavioral` —
intentionally separated so the agent can pay for verification incrementally.
"""
from __future__ import annotations
from dataclasses import dataclass, field
@dataclass(frozen=True)
class ParseError:
filename: str
line: int | None
column: int | None
message: str
@dataclass
class ValidationReport:
parse_errors: list[ParseError] = field(default_factory=list)
@property
def ok(self) -> bool:
return not self.parse_errors
def to_dict(self) -> dict[str, object]:
return {
"ok": self.ok,
"parse_errors": [
{
"filename": e.filename,
"line": e.line,
"column": e.column,
"message": e.message,
}
for e in self.parse_errors
],
}
def parse_check(files: dict[str, str]) -> list[ParseError]:
"""Compile each ``files[name]`` source. Return collected errors.
An empty list means every file parsed cleanly.
"""
errors: list[ParseError] = []
for filename, source in files.items():
try:
compile(source, filename, "exec")
except SyntaxError as e:
errors.append(
ParseError(
filename=filename,
line=e.lineno,
column=e.offset,
message=e.msg,
)
)
return errors
def full_check(files: dict[str, str]) -> ValidationReport:
"""Run every validator gate that's currently implemented.
Today: parse-only. ``mypy --strict`` and import-resolution are added in
follow-up commits but the report shape stays the same.
"""
return ValidationReport(parse_errors=parse_check(files))
|