Skip to content

feat(gazelle): Allow disabling sibling module resolution #3106

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

amartani
Copy link
Contributor

@amartani amartani commented Jul 19, 2025

Currently, gazelle allows absolute imports to be resolved to sibling modules: an import foo statement will resolve to a foo.py file in the same folder if such file exists. This seems to be a Python 2 behavior (ie. pre-from __future__ import absolute_import), and doesn't work on the current rules_python setup.

This behavior is explicitly tested in the siblings_import test case. However, recreating the exact same repository layout from this test case and running bazel test //pkg:unit_test, the test fails with the import failing.

This PR adds a new directive, gazelle:python_resolve_sibling_imports, to allow disabling such behavior.

The actual changes are in 2 places:

  • In gazelle/python/target.go, the directive is added to if t.siblingSrcs.Contains(fileName) && fileName != filepath.Base(dep.Filepath), which is where the import is converted to a full absolute import if it matches a sibling file;
  • In gazelle/python/generate.go, the handling of conftest.py was dependent on this behavior (ie. it added a dependency on the module conftest, assuming that it would be resolved to the relative module). That was modified to compute the full absolute module path instead.

I also explicitly added gazelle:python_resolve_sibling_imports true to any test that breaks if the default value of this directive is changed to false.

@amartani amartani marked this pull request as ready for review July 19, 2025 01:58
@aignas
Copy link
Collaborator

aignas commented Jul 24, 2025

Thanks for the PR. Since the current gazelle code would result in un-runnable code, is there a good reason to not default to the correct behaviour and have the flag in case some user wants to do this step-wise?

@amartani
Copy link
Contributor Author

Thanks for the PR. Since the current gazelle code would result in un-runnable code, is there a good reason to not default to the correct behaviour and have the flag in case some user wants to do this step-wise?

Honestly, my main reason is a feeling of "I must be missing something" about it. The sibling import behavior is not accidental: there's code added that only exists for resolving sibling imports, a test that explicitly tests for this behavior, and multiple other tests that implicitly depend on it. And, as far as I know, it was all written much after python2 was unsupported, which is the only reason that I can think of for why this would be desired. That said, I'd be happy to switch the default if you believe that would be ok.

@aignas
Copy link
Collaborator

aignas commented Jul 25, 2025

I'll wait for other to chime in on here. @arrdem, your insight from the Aspect.dev point of view would be valuable here as well.

Copy link
Collaborator

@dougthor42 dougthor42 left a comment

Choose a reason for hiding this comment

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

I ran this branch against our QuantumIA code base with the directive set to true and false.

When false, there were some changes made. I checked them all and they were indeed because the original behavior was incorrect - foo.py importing math but Gazelle thinks its the sibling math.py.

This is super nice and caught some issues for us, thank you!

is there a good reason to not default to the correct behaviour and have the flag in case some user wants to do this step-wise?

I think one argument against is just subverting expectations. People are probably used to the current behavior and adjusting the current behavior would be disruptive.

The current behavior is not necessarily broken in that it always causes bazel build to fail, but it does mean that targets have more dependencies than strictly required. Those additional deps can cause circular dependencies, especially in file generation mode.

Thus my vote is to adjust the default to the correct behavior: python_resolve_sibling_imports false.

@@ -116,6 +116,10 @@ END_UNRELEASED_TEMPLATE
dep is not added to the {obj}`py_test` target.
* (gazelle) New directive `gazelle:python_generate_proto`; when `true`,
Gazelle generates `py_proto_library` rules for `proto_library`. `false` by default.
* (gazelle) Added directive `# gazelle:python_resolve_sibling_imports` (default
`enabled` for backwards-compatibility). When enabled, gazelle will allow absolute
Copy link
Collaborator

Choose a reason for hiding this comment

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

s/enabled/true

- `import test_util` - resolves to the root-level `test_util.py` instead of
the sibling `pkg/test_util.py`
- `from b import run` - resolves to the root-level `b.py` instead of the
sibling `pkg/b.py`
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we add test cases for:

Not all of these need to be separate complete test case directory. I think relative imports and shadowed stdlib checks are pretty easy to add within this test case directory.

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.

3 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy