#!/usr/bin/env python3 """Reject oncology, cancer, drug, and target imports in the generic UI.""" from __future__ import annotations import re import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[1] UI = ROOT / "ui" SOURCE_SUFFIXES = {".ts", ".tsx", ".css", ".mjs"} IMPORT_STATEMENT = re.compile( r"""(?:^|\n)\s*import\b[\s\S]*?\bfrom\s+['"][^'"]+['"]""" r"""|(?:^|\n)\s*import\s+['"][^'"]+['"]""" r"""|import\s*\(\s*['"][^'"]+['"]\s*\)""" r"""|require\s*\(\s*['"][^'"]+['"]\s*\)""" r"""|@import\s+['"][^'"]+['"]""", ) # The token may start an identifier such as CancerIcon or targetThumb. FORBIDDEN = re.compile(r"\b(?:oncology|cancers?|drugs?|targets?)", re.IGNORECASE) def import_problems(text: str, label: str) -> list[str]: problems: list[str] = [] for match in IMPORT_STATEMENT.finditer(text): statement = " ".join(match.group(0).split()) if FORBIDDEN.search(statement): problems.append(f"{label}: {statement}") return problems def tree_problems(root: Path = UI) -> list[str]: problems: list[str] = [] for path in sorted(root.rglob("*")): if not path.is_file() or "node_modules" in path.parts or ".next" in path.parts: continue if path.suffix not in SOURCE_SUFFIXES: continue problems.extend(import_problems(path.read_text(encoding="utf-8"), str(path.relative_to(ROOT)))) notice = root / "NOTICE" if not notice.is_file(): problems.append("ui/NOTICE is missing") else: text = notice.read_text(encoding="utf-8") if "Copyright (c) 2026 OnCo" not in text or "MIT License" not in text: problems.append("ui/NOTICE is missing the OnCo MIT copyright and permission notice") return problems def main() -> int: problems = tree_problems() if problems: print("\n".join(problems)) return 1 print("ui boundary: no oncology, cancer, drug, or target imports; NOTICE retains the OnCo MIT text") return 0 if __name__ == "__main__": sys.exit(main())