Files
wehub-resource-sync 7a0da7932b
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:08:55 +08:00

128 lines
3.5 KiB
Python
Executable File

#!/usr/bin/env python3
"""Pre-commit hook to enforce that infrastructure packages do not import from web/.
Packages like settings/, utilities/, security/, and config/ should not depend
on web/ — this breaks CLI, MCP, and programmatic API usage.
"""
import re
import sys
# Infrastructure packages that must not import from web/
PROTECTED_PACKAGES = {
"settings",
"utilities",
"security",
"config",
}
# Existing violations that are allowlisted (file path substring -> allowed import patterns)
ALLOWLIST = {
"settings/manager.py": [
"web.models.settings",
"web.themes",
"web.services.socket_service",
],
"utilities/log_utils.py": [
"web.services.socket_service",
],
"security/rate_limiter.py": [
"web.server_config",
],
}
# Match import statements that reference .web. or from ..web
WEB_IMPORT_PATTERN = re.compile(
r"^\s*(?:from\s+(?:\.+)?(?:local_deep_research\.)?web\b|"
r"import\s+(?:local_deep_research\.)?web\b)"
)
def get_package(filepath):
"""Extract the package name from file path."""
parts = filepath.replace("\\", "/").split("/")
try:
ldr_idx = parts.index("local_deep_research")
except ValueError:
return None
if ldr_idx + 1 < len(parts) and parts[ldr_idx + 1] in PROTECTED_PACKAGES:
return parts[ldr_idx + 1]
return None
def is_allowlisted(filepath, line):
"""Check if a specific import is in the allowlist."""
for path_substr, allowed_imports in ALLOWLIST.items():
if path_substr in filepath:
for allowed in allowed_imports:
if allowed in line:
return True
return False
def is_type_checking_block(lines, lineno):
"""Simple heuristic: check if line is inside a TYPE_CHECKING block."""
for i in range(lineno - 1, max(0, lineno - 20), -1):
stripped = lines[i].strip()
if stripped.startswith("if TYPE_CHECKING"):
return True
if (
stripped
and not stripped.startswith("#")
and not stripped.startswith("from")
and not stripped.startswith("import")
):
break
return False
def check_file(filepath):
errors = []
try:
with open(filepath, encoding="utf-8") as f:
lines = f.readlines()
except (OSError, UnicodeDecodeError):
return errors
pkg = get_package(filepath)
if not pkg:
return errors
for lineno, line in enumerate(lines):
if WEB_IMPORT_PATTERN.search(line):
if is_allowlisted(filepath, line):
continue
if is_type_checking_block(lines, lineno):
continue
errors.append((lineno + 1, line.rstrip()))
return errors
def main():
exit_code = 0
for filepath in sys.argv[1:]:
if not filepath.endswith(".py"):
continue
errors = check_file(filepath)
for lineno, line in errors:
pkg = get_package(filepath)
print(
f"{filepath}:{lineno}: {pkg}/ must not import from web/ — "
f"this breaks CLI/MCP/API usage"
)
print(f" {line.strip()}")
exit_code = 1
if exit_code:
print(
"\nInfrastructure packages (settings/, utilities/, security/, config/) "
"should not depend on the web layer."
)
print(
"Move shared types to a common module or use dependency injection."
)
return exit_code
if __name__ == "__main__":
sys.exit(main())