mirror of
https://github.com/saymrwulf/proof-aware-crypto-tooling-agent.git
synced 2026-09-05 20:10:34 +00:00
66 lines
2.3 KiB
Python
66 lines
2.3 KiB
Python
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
from dataclasses import dataclass, field
|
||
|
|
from pathlib import Path
|
||
|
|
from typing import Any
|
||
|
|
|
||
|
|
from .yamlio import load_data
|
||
|
|
|
||
|
|
|
||
|
|
STANDARD_LEAN_AXIOMS = ["propext", "Classical.choice", "Quot.sound"]
|
||
|
|
|
||
|
|
|
||
|
|
@dataclass(slots=True)
|
||
|
|
class RepoConfig:
|
||
|
|
name: str
|
||
|
|
url: str | None = None
|
||
|
|
kind: str = "unknown"
|
||
|
|
verification_dir: str = "verification"
|
||
|
|
verified_backend: str | None = None
|
||
|
|
backend_warning: str | None = None
|
||
|
|
known_status: str | None = None
|
||
|
|
certificates: list[str] = field(default_factory=list)
|
||
|
|
expected_axioms: list[str] = field(default_factory=lambda: STANDARD_LEAN_AXIOMS.copy())
|
||
|
|
known_exclusions: list[str] = field(default_factory=list)
|
||
|
|
axiom_imports: list[str] = field(default_factory=list)
|
||
|
|
|
||
|
|
@classmethod
|
||
|
|
def from_dict(cls, raw: dict[str, Any]) -> "RepoConfig":
|
||
|
|
if "name" not in raw:
|
||
|
|
raise ValueError("Repo config is missing required field 'name'")
|
||
|
|
return cls(
|
||
|
|
name=str(raw["name"]),
|
||
|
|
url=raw.get("url"),
|
||
|
|
kind=str(raw.get("kind", "unknown")),
|
||
|
|
verification_dir=str(raw.get("verification_dir", "verification")),
|
||
|
|
verified_backend=raw.get("verified_backend"),
|
||
|
|
backend_warning=raw.get("backend_warning"),
|
||
|
|
known_status=raw.get("known_status"),
|
||
|
|
certificates=list(raw.get("certificates") or []),
|
||
|
|
expected_axioms=list(raw.get("expected_axioms") or STANDARD_LEAN_AXIOMS),
|
||
|
|
known_exclusions=list(raw.get("known_exclusions") or []),
|
||
|
|
axiom_imports=list(raw.get("axiom_imports") or []),
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
@dataclass(slots=True)
|
||
|
|
class AppConfig:
|
||
|
|
repos: list[RepoConfig]
|
||
|
|
|
||
|
|
def repo_named(self, name: str) -> RepoConfig:
|
||
|
|
for repo in self.repos:
|
||
|
|
if repo.name == name:
|
||
|
|
return repo
|
||
|
|
available = ", ".join(repo.name for repo in self.repos)
|
||
|
|
raise KeyError(f"Unknown repo '{name}'. Available: {available}")
|
||
|
|
|
||
|
|
|
||
|
|
def load_config(path: str | Path) -> AppConfig:
|
||
|
|
raw = load_data(path)
|
||
|
|
if not isinstance(raw, dict) or "repos" not in raw:
|
||
|
|
raise ValueError(f"{path} must contain a top-level 'repos' list")
|
||
|
|
repos = raw["repos"]
|
||
|
|
if not isinstance(repos, list):
|
||
|
|
raise ValueError("'repos' must be a list")
|
||
|
|
return AppConfig(repos=[RepoConfig.from_dict(item) for item in repos])
|