Skip to content
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

Can Gazelle's 'resolve' directive be smarter? Or am I just using it wrong? #1877

Open
dougthor42 opened this issue May 6, 2024 · 1 comment
Labels
gazelle Gazelle plugin related issues type: feature request

Comments

@dougthor42
Copy link
Contributor

❓ question | possible πŸš€ feature request

Relevant Rules

  • gazelle

Description

Can Gazelle's 'resolve' directive be smarter? Or am I just using it wrong?

Example:

# gazelle:resolve py foo @other//foo
Import Expected Dep Actual Dep
import foo.bar.baz "@other//foo/bar:baz" "@other//foo"
from foo import bar "@other//foo:bar" "@other//foo"
import foo.bar as bar "@other//foo/bar" "@other//foo"

This is coming about because we have a nested project with a dir structure like:

./main_project_repo
+ BUILD.bazel
+ MODULE.bazel  # module(name = "main_project_repo")
+ src/
    + BUILD.bazel  # sets python_root
    + main_project/
        + BUILD.bazel
        + foo.py      # imports other_project_repo/src/other_project/bar.py
                      # via `import other_project.bar` thanks to PYTHONPATH
        + private.py
+ other_project_repo/
    + BUILD.bazel
    + MODULE.bazel  # module(name = "other_project_repo")
    + src/
        + BUILD.bazel  # sets python_root
        + other_project/
            + BUILD.bazel
            + bar.py

And ./main_project_repo/src/main_project/BUILD.bazel looks like so to work:

# //src/main_project:foo
py_library(
    name = "foo",
    srcs = ["foo.py"],
    deps = [
        ":private",
        "@other_project_repo//src/other_project:bar"
    ],
)

With the current functionality, I'd have to write out resolve directives for every import used

# gazelle:resolve py other_project @other_project_repo//src/other_project
# gazelle:resolve py other_project.bar @other_project_repo//src/other_project:bar
# gazelle:resolve py other_project.foobar @other_project_repo//src/other_project/foobar
# gazelle:resolve py other_project.foobar.hello @other_project_repo//src/other_project/foobar:hello
# gazelle:resolve py other_project.foobar.goodbye @other_project_repo//src/other_project/foobar:goodbye
...

Sadly this is not feasible given the size of our codebases.

Describe the solution you'd like

I may be in the wrong, but it seems like the directive should match the start of the import and then follow the rest of the import path. I'm not exactly sure how, or even if, this would work though (see example 2).

Example 1

# gazelle:resolve py foo @other//foo
# import foo      -->  @other//foo
# import foo.bar  -->  @other//foo:bar

Example 2

# gazelle resolve py hello.world //goodbye:world
# import hello              -->  //hello   # no change because it's not matched by resolve.
# import hello.world        -->  //goodbye:world  # no change from current functionality
# import hello.world.again  -->  ... I donno. Can't be //goodbye:world:again haha

Describe alternatives you've considered

We might be able to run buildozer and modify all the deps in ./main_project_repo/src after Gazelle generates them, but I haven't looked into how feasible that actually is.

@dougthor42
Copy link
Contributor Author

We might be able to run buildozer and modify all the deps ...

Actually that won't work. Well, it would work if Gazelle ran to completion and just naively added deps that look like:

# //src/main_project:foo
py_library(
    name = "foo",
    srcs = ["foo.py"],
    deps = [
        ":private",
        "//src/other_project:bar"   # actually @other_project_repo//src/other_project:bar
    ],
)

but Gazelle doesn't complete because it can't validate dependencies:

gazelle: ERROR: failed to validate dependencies for target "//src/main_project/fab:doug": "other_project.util.file" at line 9 from "src/main_project/fab/doug.py" is an invalid dependency: possible solutions:
        1. Add it as a dependency in the requirements.txt file.
        2. Instruct Gazelle to resolve to a known dependency using the gazelle:resolve directive.
        3. Ignore it with a comment '# gazelle:ignore other_project.util.file' in the Python file.

"other_project.util" at line 9 from "src/main_project/fab/doug.py" is an invalid dependency: possible solutions:
        1. Add it as a dependency in the requirements.txt file.
        2. Instruct Gazelle to resolve to a known dependency using the gazelle:resolve directive.
        3. Ignore it with a comment '# gazelle:ignore other_project.util' in the Python file.

"other_project" at line 9 from "src/main_project/fab/doug.py" is an invalid dependency: possible solutions:
        1. Add it as a dependency in the requirements.txt file.
        2. Instruct Gazelle to resolve to a known dependency using the gazelle:resolve directive.
        3. Ignore it with a comment '# gazelle:ignore other_project' in the Python file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
gazelle Gazelle plugin related issues type: feature request
Projects
None yet
Development

No branches or pull requests

2 participants