#!/usr/bin/env python3 """Reject UI, Windows, SQLite, and app-layer imports from the core module.""" import json import os import pathlib import subprocess import sys FORBIDDEN_IMPORT_PREFIXES = ( "gioui.org", "golang.org/x/sys/windows", "github.com/mattn/go-sqlite3", "modernc.org/sqlite", "softbox.local/app-modern", "softbox.local/app-win7", ) def is_forbidden(import_path): return any( import_path == prefix or import_path.startswith(prefix + "/") for prefix in FORBIDDEN_IMPORT_PREFIXES ) def decode_json_stream(text): decoder = json.JSONDecoder() index = 0 while index < len(text): while index < len(text) and text[index].isspace(): index += 1 if index >= len(text): return value, index = decoder.raw_decode(text, index) yield value def list_core_packages(repo_root): environment = os.environ.copy() environment["GOWORK"] = "off" result = subprocess.run( ["go", "list", "-json", "./..."], cwd=str(repo_root / "core"), env=environment, check=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, ) if result.returncode != 0: print(result.stderr, file=sys.stderr, end="") raise SystemExit(result.returncode) return list(decode_json_stream(result.stdout)) def run_self_test(): cases = ( ("gioui.org/layout", True), ("golang.org/x/sys/windows/registry", True), ("modernc.org/sqlite/lib", True), ("softbox.local/app-modern/ui/gio", True), ("context", False), ("crypto/sha256", False), ) failures = [ import_path for import_path, expected in cases if is_forbidden(import_path) != expected ] if failures: print( "ERROR: boundary matcher self-test failed for {}".format( ", ".join(failures) ), file=sys.stderr, ) raise SystemExit(1) print("core boundary matcher self-test passed.") def main(): if sys.argv[1:] == ["--self-test"]: run_self_test() return if len(sys.argv) != 1: print( "usage: python scripts/check_core_boundaries.py [--self-test]", file=sys.stderr, ) raise SystemExit(2) repo_root = pathlib.Path(__file__).resolve().parents[1] violations = [] for package in list_core_packages(repo_root): imports = set(package.get("Imports", [])) imports.update(package.get("TestImports", [])) imports.update(package.get("XTestImports", [])) for import_path in sorted(imports): if is_forbidden(import_path): violations.append((package["ImportPath"], import_path)) if violations: for package, import_path in violations: print( "ERROR: {} imports forbidden dependency {}".format( package, import_path ), file=sys.stderr, ) raise SystemExit(1) print( "core boundary check passed: {} forbidden prefixes absent.".format( len(FORBIDDEN_IMPORT_PREFIXES) ) ) if __name__ == "__main__": main()