"""Verify the public PyInstaller onedir output and reject internal artifacts.""" from __future__ import annotations import json import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[1] DIST = ROOT / "dist" / "SensorBench" # Paths / substrings that must never appear in a public customer build. FORBIDDEN_RELATIVE_PATHS = ( "steps", "steps/default.json", "config/options.json", "internal", ) FORBIDDEN_NAME_FRAGMENTS = ( "sensor_bench_operator", "sensor_bench.app", "operator-ui", ) FORBIDDEN_LOCALE_KEYS = ( "workflow", ) FORBIDDEN_TEXT_SNIPPETS = ( "Inspection Workflow", "检测流程", "新样品", "冯总", "operator-ui", ) def require(path: Path) -> None: if not path.exists(): raise FileNotFoundError(f"Missing build artifact: {path}") def forbid(path: Path, *, reason: str) -> None: if path.exists(): raise RuntimeError(f"Public dist must not include {reason}: {path}") def _iter_text_files(root: Path) -> list[Path]: files: list[Path] = [] for path in root.rglob("*"): if not path.is_file(): continue if path.suffix.lower() in {".json", ".txt", ".md", ".py", ".toc", ".html"}: files.append(path) # PyInstaller may leave .pyc / .py modules under _internal if path.suffix.lower() == ".pyc" and "operator" in path.name.lower(): files.append(path) return files def _assert_no_forbidden_names(root: Path) -> None: for path in root.rglob("*"): rel = path.relative_to(root).as_posix().lower() name = path.name.lower() for fragment in FORBIDDEN_NAME_FRAGMENTS: if fragment.lower() in rel or fragment.lower() in name: raise RuntimeError( f"Public dist contains forbidden name '{fragment}': {path}" ) def _assert_locale_public(path: Path) -> None: data = json.loads(path.read_text(encoding="utf-8")) for key in FORBIDDEN_LOCALE_KEYS: if key in data: raise RuntimeError(f"Public locale {path.name} still contains '{key}'") status = data.get("status") if isinstance(status, dict) and "workflow_done" in status: raise RuntimeError(f"Public locale {path.name} still contains status.workflow_done") def _assert_no_forbidden_text(root: Path) -> None: for path in _iter_text_files(root): try: text = path.read_text(encoding="utf-8", errors="ignore") except Exception: # noqa: BLE001 continue for snippet in FORBIDDEN_TEXT_SNIPPETS: if snippet in text: raise RuntimeError( f"Public dist text contains forbidden snippet {snippet!r} in {path}" ) def main() -> int: require(DIST / "SensorBench.exe") require(DIST / "config" / "locales" / "zh_CN.json") require(DIST / "config" / "locales" / "en_US.json") require(DIST / "config" / "ddjx01.json") require(DIST / "_internal") for rel in FORBIDDEN_RELATIVE_PATHS: forbid(DIST / rel, reason=rel) _assert_no_forbidden_names(DIST) _assert_locale_public(DIST / "config" / "locales" / "zh_CN.json") _assert_locale_public(DIST / "config" / "locales" / "en_US.json") _assert_no_forbidden_text(DIST / "config") print(f"Verified public SensorBench dist layout: {DIST}") return 0 if __name__ == "__main__": raise SystemExit(main())