generated from coulomb/repo-seed
66 lines
1.7 KiB
Python
66 lines
1.7 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass, field
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Declaration:
|
|
path: Path
|
|
data: dict[str, Any]
|
|
|
|
@property
|
|
def kind(self) -> str:
|
|
return str(self.data.get("kind", ""))
|
|
|
|
@property
|
|
def id(self) -> str:
|
|
return str(self.data.get("metadata", {}).get("id", ""))
|
|
|
|
@property
|
|
def spec(self) -> dict[str, Any]:
|
|
spec = self.data.get("spec", {})
|
|
return spec if isinstance(spec, dict) else {}
|
|
|
|
@property
|
|
def metadata(self) -> dict[str, Any]:
|
|
meta = self.data.get("metadata", {})
|
|
return meta if isinstance(meta, dict) else {}
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Diagnostic:
|
|
severity: str
|
|
code: str
|
|
message: str
|
|
path: Path | None = None
|
|
|
|
def format(self) -> str:
|
|
prefix = f"{self.severity} {self.code}"
|
|
if self.path is not None:
|
|
return f"{prefix} {self.path}: {self.message}"
|
|
return f"{prefix}: {self.message}"
|
|
|
|
|
|
@dataclass
|
|
class ValidationReport:
|
|
diagnostics: list[Diagnostic] = field(default_factory=list)
|
|
|
|
@property
|
|
def errors(self) -> list[Diagnostic]:
|
|
return [d for d in self.diagnostics if d.severity == "ERROR"]
|
|
|
|
@property
|
|
def warnings(self) -> list[Diagnostic]:
|
|
return [d for d in self.diagnostics if d.severity == "WARN"]
|
|
|
|
def add(self, severity: str, code: str, message: str, path: Path | None = None) -> None:
|
|
self.diagnostics.append(Diagnostic(severity, code, message, path))
|
|
|
|
def summary(self) -> str:
|
|
return (
|
|
f"Validation complete: {len(self.errors)} error(s), "
|
|
f"{len(self.warnings)} warning(s)"
|
|
)
|