fix(code-graph): python __init__.py at root must not emit module scope

Problem

python_module_from_path collapses pkg/__init__.pypkg by
stripping the trailing .__init__ segment. However, a bare __init__.py
at the repository root has no package prefix, so strip_suffix leaves
the string unchanged. The is_empty() guard on the next line does not
catch it, and "__init__" escapes as the module scope.

Consequence: every symbol defined in a root-level __init__.py is
recorded with module_scope = "\"__init__\"" in the graph, and every
relative import from that file resolves against a non-existent module
called "__init__", silently producing bad edges.

Fix

Add an explicit module == "__init__" guard and return None,
consistent with the is_empty() guard already present.

Also in this MR

  • Move the misplaced doc comment from resolve_python_relative_import
    to python_module_from_path where it belongs.
  • Add unit tests for both python_module_from_path and resolve_python_relative_import — neither function had any.

Tests

cargo test -p code-graph -- python

New tests added:

  • module_from_path_regular_file
  • module_from_path_package_init
  • module_from_path_nested_package_init
  • module_from_path_top_level_file
  • module_from_path_bare_init_is_none ← regression test for the bug
  • relative_import_one_dot
  • relative_import_two_dots
  • relative_import_too_many_dots_returns_none
  • relative_import_dot_only_same_package
  • relative_import_absolute_path_returns_none

What does this MR do and why?

Testing

Performance Analysis

  • This merge request does not introduce any performance regression. If a performance regression is expected, explain why.
Agent context — long-form analysis, file-by-file walkthroughs, profiler output, alternatives considered
  • fix(code-graph): python init.py at root must not emit module scope

python_module_from_path strips a dot-prefixed .__init__ segment when a file lives inside a package (e.g. pkg/__init__.pypkg). A bare __init__.py at the repository root has no package prefix, so strip_suffix leaves the string unchanged and the empty-check on the next line lets "__init__" escape as the module scope.

Any symbol defined in a root-level __init__.py would therefore be recorded with module_scope = "__init__", and every relative import resolved from it would target a non-existent module called "__init__", silently polluting the graph.

Fix: add an explicit guard for module == "__init__" and return None, consistent with the empty-string guard already present.

Also add unit tests for both python_module_from_path and resolve_python_relative_import, which previously had none, and move the misplaced doc comment from resolve_python_relative_import to python_module_from_path where it belongs.

What does this MR do and why?

A root-level init.py with no enclosing package was incorrectly assigned the module scope "init". As a result, symbols and relative imports originating from that file could be linked to a non-existent module in the graph. This change treats a repository-root init.py as having no module scope, preventing incorrect graph edges.

Testing

Added ten unit tests covering normal paths, the init.py regression case, and documented edge cases of relative-import resolution. Neither function had test coverage before this change.

Run with:

cargo test -p code-graph -- python

Performance Analysis
[x] This merge request does not introduce any performance regression.

[skip query-dsl-version-check].

Edited by Anna Tchijova

Merge request reports

Loading