Spaces:
Sleeping
Sleeping
File size: 1,389 Bytes
feb1b1c e776c3c | 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 |
from __future__ import annotations
from typing import final
from pydantic import BaseModel, ConfigDict, model_validator
from redstack.domain.enums import Severity, ValidationCode
_STRICT = ConfigDict(
frozen=True, extra="forbid", str_strip_whitespace=True, validate_default=True
)
@final
class ValidationFinding(BaseModel):
"""A single validation outcome."""
model_config = _STRICT
code: ValidationCode
severity: Severity
message: str
location: str | None
@final
class ValidationReport(BaseModel):
"""The validator verdict; valid iff no HARD finding."""
model_config = _STRICT
findings: tuple[ValidationFinding, ...]
is_valid: bool
checks_run: frozenset[ValidationCode]
@model_validator(mode="after")
def _check(self) -> ValidationReport:
if tuple(sorted(self.findings, key=lambda f: f.code.value)) != self.findings:
raise ValueError("validation findings must be sorted by code")
if self.is_valid != all(f.severity is not Severity.HARD for f in self.findings):
raise ValueError("is_valid must equal (no HARD finding)")
for finding in self.findings:
if finding.code not in self.checks_run:
raise ValueError("every finding's code must be in checks_run")
return self
__all__: tuple[str, ...] = ("ValidationFinding", "ValidationReport") |