Skip to content

fix: resolve service-rooted absolute imports in multi-root repositories#624

Open
pallav10 wants to merge 1 commit into
peteromallet:mainfrom
pallav10:fix/multi-root-absolute-import-resolution
Open

fix: resolve service-rooted absolute imports in multi-root repositories#624
pallav10 wants to merge 1 commit into
peteromallet:mainfrom
pallav10:fix/multi-root-absolute-import-resolution

Conversation

@pallav10

Copy link
Copy Markdown

Problem

resolve_absolute_import only tries <scan_root>/<module> and <project_root>/<module>. In repositories with nested service roots (e.g. a backend repo containing a Django service at pulse-core/ plus a FastAPI service at api-gateway/), absolute imports are rooted at the service directory: from accounting.services import X inside pulse-core/accounting/tasks.py resolves under pulse-core/, not the scan root.

Command: desloppify scan --path . over such a repo (2,545 files, 545K LOC).
Expected: import edges for service-rooted absolute imports.
Actual: those imports resolve to nothing, so the graph silently loses edges. Cascading effects observed on a real codebase:

  • 723 "orphaned" findings, most of them live modules wired by plain static imports (flagged "zero importers")
  • import-based test-coverage mapping cannot mark modules as directly tested
  • transitive coverage and coupling under-report

Fix

resolve_absolute_import gains an optional source_dir parameter and walks the importing file's ancestor directories (up to the scan root) as candidate package roots, preserving the existing scan-root-first, project-root-last order. resolve_python_import passes the source directory through. Dynamic-import resolution is unchanged (no source context).

Added regression test test_absolute_import_resolves_from_service_root modeling the Django service layout.

python -m pytest desloppify/tests/ -q: 5661 passed, 151 skipped, 3 failed — the 3 failures are lang/common/test_bash_unused_imports.py cases that fail identically on main without this change.

resolve_absolute_import only tried <scan_root>/<module path> and
<project_root>/<module path>. In repositories that contain nested service
roots (Django projects under backend/<service>/, src/ layouts, monorepo
subprojects), absolute imports are rooted at the service directory:
'from accounting.services import X' inside pulse-core/accounting/tasks.py
resolves under pulse-core/, not the scan root.

Those imports silently produced no graph edges, which cascaded into
detector false positives: hundreds of live modules flagged orphaned
(zero importers), import-based test-coverage mapping unable to mark
modules as directly tested, and broken transitive coverage.

resolve_absolute_import now also walks the importing file's ancestor
directories (source_dir up to scan_root) as candidate package roots,
keeping the existing scan-root-first then project-root order, and
resolve_python_import passes the source directory through. Backward
compatible: source_dir is optional and dynamic-import resolution is
unchanged.

Full test suite passes (3 pre-existing bash unused-import failures on
main are unrelated).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant