diff --git a/gazelle/python/generate.go b/gazelle/python/generate.go index 74e5f66509..4ebb40f6bb 100644 --- a/gazelle/python/generate.go +++ b/gazelle/python/generate.go @@ -224,6 +224,7 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } pyLibrary = newTargetBuilder(pyLibraryKind, pyLibraryTargetName, pythonProjectRoot, args.Rel, pyLibraryFilenames.Union(pyTestFilenames)). + setUUID(label.New("", args.Rel, pyLibraryTargetName).String()). addVisibility(visibility). addSrcs(pyLibraryFilenames). addModuleDependencies(deps). @@ -266,6 +267,10 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes addModuleDependencies(deps). generateImportsAttribute() + if pyLibrary != nil { + pyBinaryTarget.addModuleDependency(module{Name: pyLibrary.PrivateAttr(uuidKey).(string)}) + } + pyBinary := pyBinaryTarget.build() result.Gen = append(result.Gen, pyBinary) @@ -296,6 +301,7 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } conftestTarget := newTargetBuilder(pyLibraryKind, conftestTargetname, pythonProjectRoot, args.Rel, pyLibraryFilenames.Union(pyTestFilenames)). + setUUID(label.New("", args.Rel, conftestTargetname).String()). addSrc(conftestFilename). addModuleDependencies(deps). addVisibility(visibility). @@ -309,8 +315,8 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } var pyTestTargets []*targetBuilder - newPyTestTargetBuilder := func(srcs *treeset.Set, pyTestTargetName string) *targetBuilder { - deps, err := parser.parse(srcs) + newPyTestTargetBuilder := func(pyTestFilenames *treeset.Set, pyTestTargetName string) *targetBuilder { + deps, err := parser.parse(pyTestFilenames) if err != nil { log.Fatalf("ERROR: %v\n", err) } @@ -331,7 +337,7 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } } return newTargetBuilder(pyTestKind, pyTestTargetName, pythonProjectRoot, args.Rel, pyLibraryFilenames.Union(pyTestFilenames)). - addSrcs(srcs). + addSrcs(pyTestFilenames). addModuleDependencies(deps). generateImportsAttribute() } @@ -365,9 +371,14 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes } for _, pyTestTarget := range pyTestTargets { + if pyLibrary != nil { + pyTestTarget.addModuleDependency(module{Name: pyLibrary.PrivateAttr(uuidKey).(string)}) + } + if conftest != nil { - pyTestTarget.addModuleDependency(module{Name: strings.TrimSuffix(conftestFilename, ".py")}) + pyTestTarget.addModuleDependency(module{Name: conftest.PrivateAttr(uuidKey).(string)}) } + pyTest := pyTestTarget.build() result.Gen = append(result.Gen, pyTest) diff --git a/gazelle/python/resolve.go b/gazelle/python/resolve.go index 46014e50ec..607776aee3 100644 --- a/gazelle/python/resolve.go +++ b/gazelle/python/resolve.go @@ -39,6 +39,10 @@ const ( // resolvedDepsKey is the attribute key used to pass dependencies that don't // need to be resolved by the dependency resolver in the Resolver step. resolvedDepsKey = "_gazelle_python_resolved_deps" + // uuidKey is the attribute key used to uniquely identify a py_library + // target that should be imported by a py_test or py_binary in the same + // Bazel package. + uuidKey = "_gazelle_python_library_uuid" ) // Resolver satisfies the resolve.Resolver interface. It resolves dependencies @@ -67,6 +71,13 @@ func (py *Resolver) Imports(c *config.Config, r *rule.Rule, f *rule.File) []reso provides = append(provides, provide) } } + if r.PrivateAttr(uuidKey) != nil { + provide := resolve.ImportSpec{ + Lang: languageName, + Imp: r.PrivateAttr(uuidKey).(string), + } + provides = append(provides, provide) + } if len(provides) == 0 { return nil } diff --git a/gazelle/python/target.go b/gazelle/python/target.go index fdc99fc68c..69711ce643 100644 --- a/gazelle/python/target.go +++ b/gazelle/python/target.go @@ -15,11 +15,12 @@ package python import ( + "path/filepath" + "github.com/bazelbuild/bazel-gazelle/config" "github.com/bazelbuild/bazel-gazelle/rule" "github.com/emirpasic/gods/sets/treeset" godsutils "github.com/emirpasic/gods/utils" - "path/filepath" ) // targetBuilder builds targets to be generated by Gazelle. @@ -28,6 +29,7 @@ type targetBuilder struct { name string pythonProjectRoot string bzlPackage string + uuid string srcs *treeset.Set siblingSrcs *treeset.Set deps *treeset.Set @@ -53,6 +55,15 @@ func newTargetBuilder(kind, name, pythonProjectRoot, bzlPackage string, siblingS } } +// setUUID sets the given UUID for the target. It's used to index the generated +// target based on this value in addition to the other ways the targets can be +// imported. py_{binary,test} targets in the same Bazel package can add a +// virtual dependency to this UUID that gets resolved in the Resolver interface. +func (t *targetBuilder) setUUID(uuid string) *targetBuilder { + t.uuid = uuid + return t +} + // addSrc adds a single src to the target. func (t *targetBuilder) addSrc(src string) *targetBuilder { t.srcs.Add(src) @@ -70,16 +81,9 @@ func (t *targetBuilder) addSrcs(srcs *treeset.Set) *targetBuilder { // addModuleDependency adds a single module dep to the target. func (t *targetBuilder) addModuleDependency(dep module) *targetBuilder { - fileName := dep.Name + ".py" - if dep.From != "" { - fileName = dep.From + ".py" + if dep.Name+".py" == filepath.Base(dep.Filepath) || !t.siblingSrcs.Contains(dep.Name+".py") { + t.deps.Add(dep) } - if t.siblingSrcs.Contains(fileName) && fileName != filepath.Base(dep.Filepath) { - // importing another module from the same package, converting to absolute imports to make - // dependency resolution easier - dep.Name = importSpecFromSrc(t.pythonProjectRoot, t.bzlPackage, fileName).Imp - } - t.deps.Add(dep) return t } @@ -134,6 +138,9 @@ func (t *targetBuilder) generateImportsAttribute() *targetBuilder { // build returns the assembled *rule.Rule for the target. func (t *targetBuilder) build() *rule.Rule { r := rule.NewRule(t.kind, t.name) + if t.uuid != "" { + r.SetPrivateAttr(uuidKey, t.uuid) + } if !t.srcs.Empty() { r.SetAttr("srcs", t.srcs.Values()) } diff --git a/gazelle/python/testdata/generated_test_entrypoint/BUILD.out b/gazelle/python/testdata/generated_test_entrypoint/BUILD.out index e8e304c72b..48df0688a6 100644 --- a/gazelle/python/testdata/generated_test_entrypoint/BUILD.out +++ b/gazelle/python/testdata/generated_test_entrypoint/BUILD.out @@ -17,5 +17,8 @@ py_test( name = "generated_test_entrypoint_test", srcs = [":__test__"], main = ":__test__.py", - deps = [":__test__"], + deps = [ + ":__test__", + ":generated_test_entrypoint", + ], ) diff --git a/gazelle/python/testdata/naming_convention/__main__.py b/gazelle/python/testdata/naming_convention/__main__.py index a3afc79dcd..730755995d 100644 --- a/gazelle/python/testdata/naming_convention/__main__.py +++ b/gazelle/python/testdata/naming_convention/__main__.py @@ -13,4 +13,3 @@ # limitations under the License. # For test purposes only. -import __init__ \ No newline at end of file diff --git a/gazelle/python/testdata/naming_convention/__test__.py b/gazelle/python/testdata/naming_convention/__test__.py index a3afc79dcd..730755995d 100644 --- a/gazelle/python/testdata/naming_convention/__test__.py +++ b/gazelle/python/testdata/naming_convention/__test__.py @@ -13,4 +13,3 @@ # limitations under the License. # For test purposes only. -import __init__ \ No newline at end of file diff --git a/gazelle/python/testdata/naming_convention/dont_rename/__main__.py b/gazelle/python/testdata/naming_convention/dont_rename/__main__.py index a3afc79dcd..730755995d 100644 --- a/gazelle/python/testdata/naming_convention/dont_rename/__main__.py +++ b/gazelle/python/testdata/naming_convention/dont_rename/__main__.py @@ -13,4 +13,3 @@ # limitations under the License. # For test purposes only. -import __init__ \ No newline at end of file diff --git a/gazelle/python/testdata/naming_convention/dont_rename/__test__.py b/gazelle/python/testdata/naming_convention/dont_rename/__test__.py index a3afc79dcd..730755995d 100644 --- a/gazelle/python/testdata/naming_convention/dont_rename/__test__.py +++ b/gazelle/python/testdata/naming_convention/dont_rename/__test__.py @@ -13,4 +13,3 @@ # limitations under the License. # For test purposes only. -import __init__ \ No newline at end of file diff --git a/gazelle/python/testdata/naming_convention/resolve_conflict/__main__.py b/gazelle/python/testdata/naming_convention/resolve_conflict/__main__.py index a3afc79dcd..730755995d 100644 --- a/gazelle/python/testdata/naming_convention/resolve_conflict/__main__.py +++ b/gazelle/python/testdata/naming_convention/resolve_conflict/__main__.py @@ -13,4 +13,3 @@ # limitations under the License. # For test purposes only. -import __init__ \ No newline at end of file diff --git a/gazelle/python/testdata/naming_convention/resolve_conflict/__test__.py b/gazelle/python/testdata/naming_convention/resolve_conflict/__test__.py index a3afc79dcd..730755995d 100644 --- a/gazelle/python/testdata/naming_convention/resolve_conflict/__test__.py +++ b/gazelle/python/testdata/naming_convention/resolve_conflict/__test__.py @@ -13,4 +13,3 @@ # limitations under the License. # For test purposes only. -import __init__ \ No newline at end of file diff --git a/gazelle/python/testdata/python_target_with_test_in_name/real_test.py b/gazelle/python/testdata/python_target_with_test_in_name/real_test.py index e390866be3..2f032112ef 100644 --- a/gazelle/python/testdata/python_target_with_test_in_name/real_test.py +++ b/gazelle/python/testdata/python_target_with_test_in_name/real_test.py @@ -13,6 +13,5 @@ # limitations under the License. import boto3 -import __init__ _ = boto3 diff --git a/gazelle/python/testdata/python_target_with_test_in_name/test_reality.py b/gazelle/python/testdata/python_target_with_test_in_name/test_reality.py index a3afc79dcd..730755995d 100644 --- a/gazelle/python/testdata/python_target_with_test_in_name/test_reality.py +++ b/gazelle/python/testdata/python_target_with_test_in_name/test_reality.py @@ -13,4 +13,3 @@ # limitations under the License. # For test purposes only. -import __init__ \ No newline at end of file diff --git a/gazelle/python/testdata/sibling_imports/README.md b/gazelle/python/testdata/sibling_imports/README.md deleted file mode 100644 index e59be07634..0000000000 --- a/gazelle/python/testdata/sibling_imports/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Sibling imports - -This test case asserts that imports from sibling modules are resolved correctly. It covers 3 different types of imports in `pkg/unit_test.py` \ No newline at end of file diff --git a/gazelle/python/testdata/sibling_imports/WORKSPACE b/gazelle/python/testdata/sibling_imports/WORKSPACE deleted file mode 100644 index faff6af87a..0000000000 --- a/gazelle/python/testdata/sibling_imports/WORKSPACE +++ /dev/null @@ -1 +0,0 @@ -# This is a Bazel workspace for the Gazelle test data. diff --git a/gazelle/python/testdata/sibling_imports/pkg/BUILD.in b/gazelle/python/testdata/sibling_imports/pkg/BUILD.in deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/gazelle/python/testdata/sibling_imports/pkg/BUILD.out b/gazelle/python/testdata/sibling_imports/pkg/BUILD.out deleted file mode 100644 index edb40a8bcb..0000000000 --- a/gazelle/python/testdata/sibling_imports/pkg/BUILD.out +++ /dev/null @@ -1,29 +0,0 @@ -load("@rules_python//python:defs.bzl", "py_library", "py_test") - -py_library( - name = "pkg", - srcs = [ - "__init__.py", - "a.py", - "b.py", - ], - imports = [".."], - visibility = ["//:__subpackages__"], -) - -py_test( - name = "test_util", - srcs = ["test_util.py"], - imports = [".."], -) - -py_test( - name = "unit_test", - srcs = ["unit_test.py"], - imports = [".."], - deps = [ - ":pkg", - ":test_util", - ], -) - diff --git a/gazelle/python/testdata/sibling_imports/pkg/__init__.py b/gazelle/python/testdata/sibling_imports/pkg/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/gazelle/python/testdata/sibling_imports/pkg/a.py b/gazelle/python/testdata/sibling_imports/pkg/a.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/gazelle/python/testdata/sibling_imports/pkg/b.py b/gazelle/python/testdata/sibling_imports/pkg/b.py deleted file mode 100644 index 7095bdcfb2..0000000000 --- a/gazelle/python/testdata/sibling_imports/pkg/b.py +++ /dev/null @@ -1,2 +0,0 @@ -def run(): - pass \ No newline at end of file diff --git a/gazelle/python/testdata/sibling_imports/pkg/test_util.py b/gazelle/python/testdata/sibling_imports/pkg/test_util.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/gazelle/python/testdata/sibling_imports/pkg/unit_test.py b/gazelle/python/testdata/sibling_imports/pkg/unit_test.py deleted file mode 100644 index a3218e2ec2..0000000000 --- a/gazelle/python/testdata/sibling_imports/pkg/unit_test.py +++ /dev/null @@ -1,3 +0,0 @@ -import a -from b import run -import test_util \ No newline at end of file diff --git a/gazelle/python/testdata/sibling_imports/test.yaml b/gazelle/python/testdata/sibling_imports/test.yaml deleted file mode 100644 index ed97d539c0..0000000000 --- a/gazelle/python/testdata/sibling_imports/test.yaml +++ /dev/null @@ -1 +0,0 @@ ---- diff --git a/gazelle/python/testdata/simple_binary_with_library/__main__.py b/gazelle/python/testdata/simple_binary_with_library/__main__.py index bc7ddf0a71..730755995d 100644 --- a/gazelle/python/testdata/simple_binary_with_library/__main__.py +++ b/gazelle/python/testdata/simple_binary_with_library/__main__.py @@ -13,4 +13,3 @@ # limitations under the License. # For test purposes only. -import foo diff --git a/gazelle/python/testdata/subdir_sources/foo/has_main/__main__.py b/gazelle/python/testdata/subdir_sources/foo/has_main/__main__.py index bd0fe61faa..730755995d 100644 --- a/gazelle/python/testdata/subdir_sources/foo/has_main/__main__.py +++ b/gazelle/python/testdata/subdir_sources/foo/has_main/__main__.py @@ -13,4 +13,3 @@ # limitations under the License. # For test purposes only. -import foo.has_main.python.my_module \ No newline at end of file diff --git a/gazelle/python/testdata/subdir_sources/foo/has_test/__test__.py b/gazelle/python/testdata/subdir_sources/foo/has_test/__test__.py index 3c9ed1a1bd..730755995d 100644 --- a/gazelle/python/testdata/subdir_sources/foo/has_test/__test__.py +++ b/gazelle/python/testdata/subdir_sources/foo/has_test/__test__.py @@ -13,4 +13,3 @@ # limitations under the License. # For test purposes only. -import foo.has_test.python.my_module \ No newline at end of file diff --git a/gazelle/python/testdata/with_third_party_requirements/BUILD.out b/gazelle/python/testdata/with_third_party_requirements/BUILD.out index 2a97d8bc1e..2da7f2bd86 100644 --- a/gazelle/python/testdata/with_third_party_requirements/BUILD.out +++ b/gazelle/python/testdata/with_third_party_requirements/BUILD.out @@ -20,5 +20,5 @@ py_binary( srcs = ["__main__.py"], main = "__main__.py", visibility = ["//:__subpackages__"], - deps = ["@gazelle_python_test_baz//:pkg"], + deps = [":with_third_party_requirements"], )