|
#!/usr/bin/env python3
|
|
import re
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
|
|
ALLOW_PREFIXES = (
|
|
ROOT / "devplacepy" / "database",
|
|
ROOT / "devplacepy" / "db_client.py",
|
|
ROOT / "devplacepy_services" / "database",
|
|
ROOT / "scripts" / "migrate_db_imports.py",
|
|
ROOT / "scripts" / "check_database_imports.py",
|
|
)
|
|
|
|
PATTERNS = [
|
|
re.compile(r"from devplacepy\.database(?:\.[a-z_]+)? import"),
|
|
re.compile(r"import devplacepy\.database\b"),
|
|
]
|
|
|
|
# Only flagged outside tests/: unit tests may legitimately use `local_db` /
|
|
# `from devplacepy import database` directly (Section 13.4). Source code must
|
|
# always go through `devplacepy.db_client` so the remote broker patch applies.
|
|
SOURCE_ONLY_PATTERNS = [
|
|
re.compile(r"from devplacepy import(?:\s+\w+,)*\s+database\b"),
|
|
]
|
|
|
|
|
|
def allowed(path: Path) -> bool:
|
|
for prefix in ALLOW_PREFIXES:
|
|
if path == prefix or str(path).startswith(str(prefix) + "/"):
|
|
return True
|
|
return False
|
|
|
|
|
|
def main() -> int:
|
|
errors: list[str] = []
|
|
for pattern in ("devplacepy/**/*.py", "devplacepy_services/**/*.py", "tests/**/*.py"):
|
|
is_source = not pattern.startswith("tests/")
|
|
for path in ROOT.glob(pattern):
|
|
if not path.is_file() or allowed(path):
|
|
continue
|
|
try:
|
|
text = path.read_text(encoding="utf-8", errors="ignore")
|
|
except OSError:
|
|
continue
|
|
active_patterns = PATTERNS + SOURCE_ONLY_PATTERNS if is_source else PATTERNS
|
|
for lineno, line in enumerate(text.splitlines(), 1):
|
|
for rx in active_patterns:
|
|
if rx.search(line):
|
|
errors.append(f"{path.relative_to(ROOT)}:{lineno}: {line.strip()}")
|
|
break
|
|
if errors:
|
|
print("FORBIDDEN database imports (use devplacepy.db_client):")
|
|
for line in sorted(errors)[:80]:
|
|
print(f" {line}")
|
|
if len(errors) > 80:
|
|
print(f" ... and {len(errors) - 80} more")
|
|
return 1
|
|
print("check_database_imports: ok")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main()) |