#!/usr/bin/env python3 from __future__ import annotations from pathlib import Path import csv, hashlib, json, re, sys root = Path(__file__).resolve().parents[1] errors: list[str] = [] warnings: list[str] = [] def fail(message: str) -> None: errors.append(message) def warn(message: str) -> None: warnings.append(message) def sha256(path: Path) -> str: digest = hashlib.sha256() with path.open('rb') as stream: for block in iter(lambda: stream.read(1024 * 1024), b''): digest.update(block) return digest.hexdigest() def read_csv(relative: str) -> tuple[list[str], list[dict[str, str]]]: path = root / relative if not path.exists(): fail(f'missing CSV {relative}') return [], [] with path.open(encoding='utf-8-sig', newline='') as stream: reader = csv.DictReader(stream) return reader.fieldnames or [], list(reader) # JSON and SFC/static source sanity. for path in root.rglob('*.json'): try: json.loads(path.read_text(encoding='utf-8-sig')) except Exception as exc: fail(f'JSON {path.relative_to(root)}: {exc}') for path in (root/'frontend/src').rglob('*.vue'): text = path.read_text(encoding='utf-8') if text.count(''): fail(f'unbalanced template tags: {path.relative_to(root)}') if '