Skip to content

Python: Fix resolution of relative imports from namespace packages#21459

Open
tausbn wants to merge 3 commits intomainfrom
tausbn/python-fix-missing-relative-imports
Open

Python: Fix resolution of relative imports from namespace packages#21459
tausbn wants to merge 3 commits intomainfrom
tausbn/python-fix-missing-relative-imports

Conversation

@tausbn
Copy link
Contributor

@tausbn tausbn commented Mar 11, 2026

Fixes an issue that was causing us to not resolve relative imports from namespace packages correctly (thankfully a relatively uncommon occurrence).

Should be reviewed commit-by-commit. The first commit adds a test that demonstrates the issue (indirectly, by observing a lack of data-flow), and the second fixes the issue and updates the test to reflect this.

@tausbn tausbn force-pushed the tausbn/python-fix-missing-relative-imports branch from a57c994 to d2e760f Compare March 11, 2026 23:06
@tausbn tausbn changed the title Python: Fix missing relative imports Python: Fix resolution of relative imports from namespace packages Mar 11, 2026
@tausbn tausbn marked this pull request as ready for review March 12, 2026 12:25
@tausbn tausbn requested a review from a team as a code owner March 12, 2026 12:25
Copilot AI review requested due to automatic review settings March 12, 2026 12:25
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates Python import resolution to correctly handle relative imports (for example from . import helper) within namespace packages (directories without __init__.py), and adds a regression test + changelog entry to cover the scenario.

Changes:

  • Extend Python import name validation to treat namespace-package names as valid during import resolution.
  • Add a new experimental InlineExpectations-based test case covering relative imports inside a namespace package.
  • Add a change note documenting the fix.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
python/ql/test/experimental/import-resolution-namespace-relative/test.ql New InlineExpectations test query exercising taint flow across a relative import in a namespace package.
python/ql/test/experimental/import-resolution-namespace-relative/test.expected Expected-output file for the new test.
python/ql/test/experimental/import-resolution-namespace-relative/pkg/helper.py Python fixture defining the sink usage annotated with an inline expectation.
python/ql/test/experimental/import-resolution-namespace-relative/pkg/caller.py Python fixture performing from . import helper and passing tainted data across the boundary.
python/ql/test/experimental/import-resolution-namespace-relative/options Extractor configuration for the new test case.
python/ql/lib/semmle/python/Import.qll Library change to support namespace-package names during import resolution.
python/ql/lib/change-notes/2026-03-11-fix-unresolved-relative-imports.md Change note describing the user-visible impact of the fix.
Comments suppressed due to low confidence (1)

python/ql/test/experimental/import-resolution-namespace-relative/test.expected:2

  • This .expected file contains blank line(s). Most InlineExpectationsTest-based tests in this repo use a truly empty .expected file (0 lines) when all expectations are encoded inline, so extra blank lines may cause an unnecessary mismatch in output comparison. Consider making this file empty to match the existing pattern.

You can also share your feedback on Copilot code review. Take the survey.

tausbn added 3 commits March 12, 2026 13:29
The fix may look a bit obscure, so here's what's going on.

When we see `from . import helper`, we create an `ImportExpr` with level
equal to 1 (corresponding to the number of dots). To resolve such
imports, we compute the name of the enclosing package, as part of
`ImportExpr.qualifiedTopName()`. For this form of import expression, it
is equivalent to `this.getEnclosingModule().getPackageName()`. But
`qualifiedTopName` requires that `valid_module_name` holds for its
result, and this was _not_ the case for namespace packages.

To fix this, we extend `valid_module_name` to include the module names
of _any_ folder, not just regular package (which are the ones where
there's a `__init__.py` in the folder). Note that this doesn't simply
include all folders -- only the ones that result in valid module names
in Python.
@tausbn tausbn force-pushed the tausbn/python-fix-missing-relative-imports branch from f48d7ac to 48bf4fd Compare March 12, 2026 13:29
@tausbn tausbn marked this pull request as draft March 12, 2026 13:30
@tausbn tausbn marked this pull request as ready for review March 12, 2026 14:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants