test: known-path ratchet walks nested join() arguments; allowlist moves to tests/fixtures

Known-path tables build rows with nested os.path.join() calls, which the first scanner missed.
Walking nested arguments covers those tables.
The allowlist lives in tests/fixtures/ because tests/data/ is gitignored.
This commit is contained in:
alt-glitch
2026-09-20 19:18:08 +05:30
committed by GitHub
parent a0f0ab8f36
commit 0f9007178d
2 changed files with 26 additions and 16 deletions

View File

@@ -1,9 +1,4 @@
[
{
"path": "agent/anthropic_adapter.py",
"symbol": "<module>",
"kind": "known_path_table"
},
{
"path": "agent/anthropic_adapter.py",
"symbol": "_claude_code_candidates",
@@ -703,5 +698,25 @@
"path": "tui_gateway/methods_prompt.py",
"symbol": "_",
"kind": "bare_which"
},
{
"path": "agent/anthropic_adapter.py",
"symbol": "<module>",
"kind": "known_path_table"
},
{
"path": "hermes_cli/_early_recovery.py",
"symbol": "_find_uv_binary",
"kind": "known_path_table"
},
{
"path": "hermes_cli/copilot_auth.py",
"symbol": "_gh_cli_candidates",
"kind": "known_path_table"
},
{
"path": "tools/computer_use/cua_backend_driver.py",
"symbol": "_candidate_cua_driver_commands",
"kind": "known_path_table"
}
]

View File

@@ -35,7 +35,7 @@ import pytest
REPO_ROOT = Path(__file__).resolve().parents[1]
MODULE_MARKER = "<module>"
_RESOLUTION_ALLOWLIST_PATH = REPO_ROOT / "tests/data/resolution_allowlist.json"
_RESOLUTION_ALLOWLIST_PATH = REPO_ROOT / "tests/fixtures/resolution_allowlist.json"
_KNOWN_PATH_FRAGMENTS = (
".local/bin",
".cargo/bin",
@@ -137,8 +137,6 @@ def _iter_which_calls(tree: ast.AST):
class _ResolutionSiteVisitor(ast.NodeVisitor):
"""Collect bare PATH lookups and known-path tables by enclosing symbol."""
def __init__(self, tree: ast.Module) -> None:
self._scope: list[tuple[str, bool]] = []
self._shutil_aliases = {"shutil"}
@@ -204,16 +202,13 @@ class _ResolutionSiteVisitor(ast.NodeVisitor):
self.generic_visit(node)
def _visit_path_table(self, node: ast.List | ast.Tuple) -> None:
# Re-join fragments split across path-construction arguments before matching.
strings = [
element.value
for element in node.elts
if isinstance(element, ast.Constant) and isinstance(element.value, str)
child.value for child in ast.walk(node)
if isinstance(child, ast.Constant) and isinstance(child.value, str)
]
fragments = {
fragment
for fragment in _KNOWN_PATH_FRAGMENTS
if any(fragment in value for value in strings)
}
joined = "/".join(strings)
fragments = {fragment for fragment in _KNOWN_PATH_FRAGMENTS if fragment in joined}
if len(fragments) >= 2:
self.sites.add((self._symbol, "known_path_table"))