Add Gio app shells and platform stubs (T-003)
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
#!/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()
|
||||
Reference in New Issue
Block a user