Andrey Epifancev 0b389ee7e4 perf: формат манифеста и результатов, агрегатор
Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 21:08:45 +04:00

93 lines
2.7 KiB
Python

"""Манифест стенда: что есть в БД и какие URL/пользователей использовать в сценариях.
Путь: perf/results/manifest-s{scale}.json.
Сегмент {direction} в URL листа: web/src/components/common/TableList/TableList.jsx
строит путь как `${table?.direction}`, поэтому при direction == null (JSON null из API)
в URL попадает литерал "null" (маршрут в web/src/app/Routes.jsx:
/table/form/:formId/form-type/:formType/:sheetName/:direction/:year).
Task 3 заполняет `svods` и `modal_pages` по маршрутам Routes.jsx
(/svod, /svod/2, /svods-navigator, /projects/summaries и т.д.) — это просто списки Page(name, url).
"""
from __future__ import annotations
import json
from dataclasses import dataclass, field, asdict
from pathlib import Path
from . import RESULTS_DIR
NO_DIRECTION = "null" # см. docstring модуля
USER_KEYS = ("admin", "rf", "rf_coauthor", "dfip")
@dataclass
class Sheet:
form_id: int
form_type: str
sheet: str
direction: str | None
year: int
url: str
rows: int
@staticmethod
def build_url(form_id, form_type, sheet, direction, year) -> str:
d = NO_DIRECTION if direction is None else direction
return f"/table/form/{form_id}/form-type/{form_type}/{sheet}/{d}/{year}"
@dataclass
class ProjectReport:
project_id: int
year: int
report_type: str
url: str
rows: int
@dataclass
class Page:
name: str
url: str
@dataclass
class User:
username: str
password: str
role_id: int
@dataclass
class Manifest:
scale: int
users: dict[str, User] = field(default_factory=dict)
sheets: list[Sheet] = field(default_factory=list)
project_reports: list[ProjectReport] = field(default_factory=list)
svods: list[Page] = field(default_factory=list)
modal_pages: list[Page] = field(default_factory=list)
def manifest_path(scale: int, results_dir: Path | None = None) -> Path:
return Path(results_dir or RESULTS_DIR) / f"manifest-s{scale}.json"
def dump(m: Manifest, path) -> None:
path = Path(path)
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(json.dumps(asdict(m), ensure_ascii=False, indent=2), encoding="utf-8")
def load(path) -> Manifest:
d = json.loads(Path(path).read_text(encoding="utf-8"))
return Manifest(
scale=d["scale"],
users={k: User(**v) for k, v in d.get("users", {}).items()},
sheets=[Sheet(**x) for x in d.get("sheets", [])],
project_reports=[ProjectReport(**x) for x in d.get("project_reports", [])],
svods=[Page(**x) for x in d.get("svods", [])],
modal_pages=[Page(**x) for x in d.get("modal_pages", [])],
)