Three issues found reviewing #2072:
- The import-edge repoint loop matched by target id regardless of the edge's
language, so a non-Python dotted import (C# `using Pkg.Mod;`, Java/Go) whose
dangling target coincided with a Python alias got repointed onto a Python file,
fabricating a cross-language import. Gate the rewrite on the edge being
Python-sourced.
- The resolver ancestor walk probed package dirs too, resolving an absolute
`from helpers import x` to a sibling in the current package (Python-2 implicit-
relative semantics) even when `helpers` is external. Only probe sys.path-root
candidates (ancestors without their own __init__.py).
- Bound the __init__.py package-root chain walk by the path depth so a
pathological `/__init__.py` can't loop.
Added a cross-language-guard regression test; fixed the tautological (or->and)
ambiguity assertion.
Python absolute imports were resolved only against the scan root, and file-node
ids are scan-root-relative, so a src-layout project (code under src/) lost most
of its imports/imports_from edges when scanned from the repo root — the dangling
edges were silently dropped, so the graph looked complete but wasn't. The chosen
scan root thus silently changed the graph.
Two fixes: (1) _resolve_python_module_path probes the scan root first, then walks
up from the importing file toward the root so a nested package root (src/pkg)
resolves (mirrors the Lua upward walk); (2) a Python post-pass detects each
file's package root via its __init__.py chain and repoints absolute-import edge
targets (dotted-module id -> real file-node id), guarded against shadowing an
existing id and against ambiguous aliases claimed by >1 file. Result: byte-
identical import edges whether scanned from the repo root or from src/.