128 lines
4.8 KiB
Python
128 lines
4.8 KiB
Python
from __future__ import annotations
|
|
|
|
import importlib.util
|
|
from pathlib import Path
|
|
import sys
|
|
|
|
|
|
def _load_semantic_lint_module():
|
|
repo_root = Path(__file__).resolve().parents[2]
|
|
module_path = repo_root / "scripts" / "semantic_lint.py"
|
|
spec = importlib.util.spec_from_file_location("semantic_lint", module_path)
|
|
assert spec is not None and spec.loader is not None
|
|
module = importlib.util.module_from_spec(spec)
|
|
sys.modules[spec.name] = module
|
|
spec.loader.exec_module(module)
|
|
return module
|
|
|
|
|
|
def test_semantic_lint_flags_new_scattered_hint_tables(tmp_path) -> None:
|
|
module = _load_semantic_lint_module()
|
|
target = tmp_path / "backend" / "app" / "services" / "integrations" / "foo.py"
|
|
target.parent.mkdir(parents=True, exist_ok=True)
|
|
target.write_text('PROJECT_CREATE_HINTS = ("创建项目",)\\n', encoding="utf-8")
|
|
|
|
problems = module.collect_problems(
|
|
root=tmp_path,
|
|
scan_roots=(Path("backend/app/services/integrations"),),
|
|
baseline_path=Path("scripts/semantic_lint_baseline.txt"),
|
|
)
|
|
|
|
assert len(problems) == 1
|
|
assert problems[0].rule_id == "semantic_hint_constant"
|
|
|
|
|
|
def test_semantic_lint_flags_workflow_semantic_planner_directory(tmp_path) -> None:
|
|
module = _load_semantic_lint_module()
|
|
target = tmp_path / "backend" / "app" / "services" / "ai_pmo" / "workflow_semantic_planner" / "foo.py"
|
|
target.parent.mkdir(parents=True, exist_ok=True)
|
|
target.write_text('PROJECT_CREATE_HINTS = ("创建项目",)\\n', encoding="utf-8")
|
|
|
|
problems = module.collect_problems(
|
|
root=tmp_path,
|
|
scan_roots=(Path("backend/app/services/ai_pmo"),),
|
|
baseline_path=Path("scripts/semantic_lint_baseline.txt"),
|
|
)
|
|
|
|
assert len(problems) == 1
|
|
assert problems[0].rule_id == "semantic_hint_constant"
|
|
|
|
|
|
def test_semantic_lint_flags_query_route_object_tables_in_adaptive_rag(tmp_path) -> None:
|
|
module = _load_semantic_lint_module()
|
|
target = tmp_path / "backend" / "app" / "services" / "adaptive_rag_service" / "route_gateway.py"
|
|
target.parent.mkdir(parents=True, exist_ok=True)
|
|
target.write_text('_INTERNAL_ROUTE_OBJECTS = {"system_config"}\n', encoding="utf-8")
|
|
|
|
problems = module.collect_problems(
|
|
root=tmp_path,
|
|
scan_roots=(Path("backend/app/services/adaptive_rag_service"),),
|
|
baseline_path=Path("scripts/semantic_lint_baseline.txt"),
|
|
)
|
|
|
|
assert len(problems) == 1
|
|
assert problems[0].rule_id == "semantic_route_object_table"
|
|
|
|
|
|
def test_semantic_lint_flags_query_route_probe_helpers_in_adaptive_rag(tmp_path) -> None:
|
|
module = _load_semantic_lint_module()
|
|
target = tmp_path / "backend" / "app" / "services" / "adaptive_rag_service" / "route_gateway.py"
|
|
target.parent.mkdir(parents=True, exist_ok=True)
|
|
target.write_text("def _external_probe_is_strong(snapshot):\n return bool(snapshot)\n", encoding="utf-8")
|
|
|
|
problems = module.collect_problems(
|
|
root=tmp_path,
|
|
scan_roots=(Path("backend/app/services/adaptive_rag_service"),),
|
|
baseline_path=Path("scripts/semantic_lint_baseline.txt"),
|
|
)
|
|
|
|
assert len(problems) == 1
|
|
assert problems[0].rule_id == "semantic_route_probe_helper"
|
|
|
|
|
|
def test_semantic_lint_flags_external_object_kind_mapping(tmp_path) -> None:
|
|
module = _load_semantic_lint_module()
|
|
target = tmp_path / "backend" / "app" / "services" / "external_query_service" / "planner.py"
|
|
target.parent.mkdir(parents=True, exist_ok=True)
|
|
target.write_text(
|
|
'if "weather" in referenced_objects:\n query_kind = "weather"\n',
|
|
encoding="utf-8",
|
|
)
|
|
|
|
problems = module.collect_problems(
|
|
root=tmp_path,
|
|
scan_roots=(Path("backend/app/services/external_query_service"),),
|
|
baseline_path=Path("scripts/semantic_lint_baseline.txt"),
|
|
)
|
|
|
|
assert len(problems) == 1
|
|
assert problems[0].rule_id == "semantic_object_kind_mapping"
|
|
|
|
|
|
def test_semantic_lint_default_roots_cover_adaptive_rag_and_external_query() -> None:
|
|
module = _load_semantic_lint_module()
|
|
|
|
assert Path("backend/app/services/adaptive_rag_service") in module.DEFAULT_SCAN_ROOTS
|
|
assert Path("backend/app/services/external_query_service") in module.DEFAULT_SCAN_ROOTS
|
|
|
|
|
|
def test_semantic_lint_repo_has_no_compat_baseline_exceptions() -> None:
|
|
repo_root = Path(__file__).resolve().parents[2]
|
|
baseline_path = repo_root / "scripts" / "semantic_lint_baseline.txt"
|
|
baseline_rows = [
|
|
line.strip()
|
|
for line in baseline_path.read_text(encoding="utf-8").splitlines()
|
|
if line.strip() and not line.strip().startswith("#")
|
|
]
|
|
|
|
assert baseline_rows == []
|
|
|
|
module = _load_semantic_lint_module()
|
|
problems = module.collect_problems(
|
|
root=repo_root,
|
|
scan_roots=module.DEFAULT_SCAN_ROOTS,
|
|
baseline_path=Path("scripts/semantic_lint_baseline.txt"),
|
|
)
|
|
|
|
assert problems == []
|