feat: add logic from #1029 back with fix (#1039)
diff --git a/gazelle/python/generate.go b/gazelle/python/generate.go index 4ebb40f..3d63124 100644 --- a/gazelle/python/generate.go +++ b/gazelle/python/generate.go
@@ -76,6 +76,7 @@ pyLibraryFilenames := treeset.NewWith(godsutils.StringComparator) pyTestFilenames := treeset.NewWith(godsutils.StringComparator) + pyFileNames := treeset.NewWith(godsutils.StringComparator) // hasPyBinary controls whether a py_binary target should be generated for // this package or not. @@ -92,16 +93,19 @@ continue } ext := filepath.Ext(f) - if !hasPyBinary && f == pyBinaryEntrypointFilename { - hasPyBinary = true - } else if !hasPyTestEntryPointFile && f == pyTestEntrypointFilename { - hasPyTestEntryPointFile = true - } else if f == conftestFilename { - hasConftestFile = true - } else if strings.HasSuffix(f, "_test.py") || (strings.HasPrefix(f, "test_") && ext == ".py") { - pyTestFilenames.Add(f) - } else if ext == ".py" { - pyLibraryFilenames.Add(f) + if ext == ".py" { + pyFileNames.Add(f) + if !hasPyBinary && f == pyBinaryEntrypointFilename { + hasPyBinary = true + } else if !hasPyTestEntryPointFile && f == pyTestEntrypointFilename { + hasPyTestEntryPointFile = true + } else if f == conftestFilename { + hasConftestFile = true + } else if strings.HasSuffix(f, "_test.py") || strings.HasPrefix(f, "test_") { + pyTestFilenames.Add(f) + } else { + pyLibraryFilenames.Add(f) + } } } @@ -223,8 +227,7 @@ } } - pyLibrary = newTargetBuilder(pyLibraryKind, pyLibraryTargetName, pythonProjectRoot, args.Rel, pyLibraryFilenames.Union(pyTestFilenames)). - setUUID(label.New("", args.Rel, pyLibraryTargetName).String()). + pyLibrary = newTargetBuilder(pyLibraryKind, pyLibraryTargetName, pythonProjectRoot, args.Rel, pyFileNames). addVisibility(visibility). addSrcs(pyLibraryFilenames). addModuleDependencies(deps). @@ -260,17 +263,13 @@ } } - pyBinaryTarget := newTargetBuilder(pyBinaryKind, pyBinaryTargetName, pythonProjectRoot, args.Rel, pyLibraryFilenames.Union(pyTestFilenames)). + pyBinaryTarget := newTargetBuilder(pyBinaryKind, pyBinaryTargetName, pythonProjectRoot, args.Rel, pyFileNames). setMain(pyBinaryEntrypointFilename). addVisibility(visibility). addSrc(pyBinaryEntrypointFilename). addModuleDependencies(deps). generateImportsAttribute() - if pyLibrary != nil { - pyBinaryTarget.addModuleDependency(module{Name: pyLibrary.PrivateAttr(uuidKey).(string)}) - } - pyBinary := pyBinaryTarget.build() result.Gen = append(result.Gen, pyBinary) @@ -300,8 +299,7 @@ } } - conftestTarget := newTargetBuilder(pyLibraryKind, conftestTargetname, pythonProjectRoot, args.Rel, pyLibraryFilenames.Union(pyTestFilenames)). - setUUID(label.New("", args.Rel, conftestTargetname).String()). + conftestTarget := newTargetBuilder(pyLibraryKind, conftestTargetname, pythonProjectRoot, args.Rel, pyFileNames). addSrc(conftestFilename). addModuleDependencies(deps). addVisibility(visibility). @@ -315,8 +313,8 @@ } var pyTestTargets []*targetBuilder - newPyTestTargetBuilder := func(pyTestFilenames *treeset.Set, pyTestTargetName string) *targetBuilder { - deps, err := parser.parse(pyTestFilenames) + newPyTestTargetBuilder := func(srcs *treeset.Set, pyTestTargetName string) *targetBuilder { + deps, err := parser.parse(srcs) if err != nil { log.Fatalf("ERROR: %v\n", err) } @@ -336,8 +334,8 @@ } } } - return newTargetBuilder(pyTestKind, pyTestTargetName, pythonProjectRoot, args.Rel, pyLibraryFilenames.Union(pyTestFilenames)). - addSrcs(pyTestFilenames). + return newTargetBuilder(pyTestKind, pyTestTargetName, pythonProjectRoot, args.Rel, pyFileNames). + addSrcs(srcs). addModuleDependencies(deps). generateImportsAttribute() } @@ -371,14 +369,9 @@ } for _, pyTestTarget := range pyTestTargets { - if pyLibrary != nil { - pyTestTarget.addModuleDependency(module{Name: pyLibrary.PrivateAttr(uuidKey).(string)}) - } - if conftest != nil { - pyTestTarget.addModuleDependency(module{Name: conftest.PrivateAttr(uuidKey).(string)}) + pyTestTarget.addModuleDependency(module{Name: strings.TrimSuffix(conftestFilename, ".py")}) } - pyTest := pyTestTarget.build() result.Gen = append(result.Gen, pyTest)
diff --git a/gazelle/python/resolve.go b/gazelle/python/resolve.go index 607776a..46014e5 100644 --- a/gazelle/python/resolve.go +++ b/gazelle/python/resolve.go
@@ -39,10 +39,6 @@ // 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 @@ -71,13 +67,6 @@ 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 69711ce..fdc99fc 100644 --- a/gazelle/python/target.go +++ b/gazelle/python/target.go
@@ -15,12 +15,11 @@ 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. @@ -29,7 +28,6 @@ name string pythonProjectRoot string bzlPackage string - uuid string srcs *treeset.Set siblingSrcs *treeset.Set deps *treeset.Set @@ -55,15 +53,6 @@ } } -// 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) @@ -81,9 +70,16 @@ // addModuleDependency adds a single module dep to the target. func (t *targetBuilder) addModuleDependency(dep module) *targetBuilder { - if dep.Name+".py" == filepath.Base(dep.Filepath) || !t.siblingSrcs.Contains(dep.Name+".py") { - t.deps.Add(dep) + fileName := dep.Name + ".py" + if dep.From != "" { + fileName = dep.From + ".py" } + 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 } @@ -138,9 +134,6 @@ // 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 48df068..e8e304c 100644 --- a/gazelle/python/testdata/generated_test_entrypoint/BUILD.out +++ b/gazelle/python/testdata/generated_test_entrypoint/BUILD.out
@@ -17,8 +17,5 @@ name = "generated_test_entrypoint_test", srcs = [":__test__"], main = ":__test__.py", - deps = [ - ":__test__", - ":generated_test_entrypoint", - ], + deps = [":__test__"], )
diff --git a/gazelle/python/testdata/naming_convention/__main__.py b/gazelle/python/testdata/naming_convention/__main__.py index 7307559..a3afc79 100644 --- a/gazelle/python/testdata/naming_convention/__main__.py +++ b/gazelle/python/testdata/naming_convention/__main__.py
@@ -13,3 +13,4 @@ # 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 7307559..a3afc79 100644 --- a/gazelle/python/testdata/naming_convention/__test__.py +++ b/gazelle/python/testdata/naming_convention/__test__.py
@@ -13,3 +13,4 @@ # 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 7307559..a3afc79 100644 --- a/gazelle/python/testdata/naming_convention/dont_rename/__main__.py +++ b/gazelle/python/testdata/naming_convention/dont_rename/__main__.py
@@ -13,3 +13,4 @@ # 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 7307559..a3afc79 100644 --- a/gazelle/python/testdata/naming_convention/dont_rename/__test__.py +++ b/gazelle/python/testdata/naming_convention/dont_rename/__test__.py
@@ -13,3 +13,4 @@ # 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 7307559..a3afc79 100644 --- a/gazelle/python/testdata/naming_convention/resolve_conflict/__main__.py +++ b/gazelle/python/testdata/naming_convention/resolve_conflict/__main__.py
@@ -13,3 +13,4 @@ # 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 7307559..a3afc79 100644 --- a/gazelle/python/testdata/naming_convention/resolve_conflict/__test__.py +++ b/gazelle/python/testdata/naming_convention/resolve_conflict/__test__.py
@@ -13,3 +13,4 @@ # 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 2f03211..e390866 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,5 +13,6 @@ # 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 7307559..a3afc79 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,3 +13,4 @@ # 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 new file mode 100644 index 0000000..e59be07 --- /dev/null +++ b/gazelle/python/testdata/sibling_imports/README.md
@@ -0,0 +1,3 @@ +# 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 new file mode 100644 index 0000000..faff6af --- /dev/null +++ b/gazelle/python/testdata/sibling_imports/WORKSPACE
@@ -0,0 +1 @@ +# 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 new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/gazelle/python/testdata/sibling_imports/pkg/BUILD.in
diff --git a/gazelle/python/testdata/sibling_imports/pkg/BUILD.out b/gazelle/python/testdata/sibling_imports/pkg/BUILD.out new file mode 100644 index 0000000..edb40a8 --- /dev/null +++ b/gazelle/python/testdata/sibling_imports/pkg/BUILD.out
@@ -0,0 +1,29 @@ +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 new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/gazelle/python/testdata/sibling_imports/pkg/__init__.py
diff --git a/gazelle/python/testdata/sibling_imports/pkg/a.py b/gazelle/python/testdata/sibling_imports/pkg/a.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/gazelle/python/testdata/sibling_imports/pkg/a.py
diff --git a/gazelle/python/testdata/sibling_imports/pkg/b.py b/gazelle/python/testdata/sibling_imports/pkg/b.py new file mode 100644 index 0000000..7095bdc --- /dev/null +++ b/gazelle/python/testdata/sibling_imports/pkg/b.py
@@ -0,0 +1,2 @@ +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 new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/gazelle/python/testdata/sibling_imports/pkg/test_util.py
diff --git a/gazelle/python/testdata/sibling_imports/pkg/unit_test.py b/gazelle/python/testdata/sibling_imports/pkg/unit_test.py new file mode 100644 index 0000000..a3218e2 --- /dev/null +++ b/gazelle/python/testdata/sibling_imports/pkg/unit_test.py
@@ -0,0 +1,3 @@ +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 new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/gazelle/python/testdata/sibling_imports/test.yaml
@@ -0,0 +1 @@ +---
diff --git a/gazelle/python/testdata/simple_binary_with_library/__main__.py b/gazelle/python/testdata/simple_binary_with_library/__main__.py index 7307559..bc7ddf0 100644 --- a/gazelle/python/testdata/simple_binary_with_library/__main__.py +++ b/gazelle/python/testdata/simple_binary_with_library/__main__.py
@@ -13,3 +13,4 @@ # limitations under the License. # For test purposes only. +import foo
diff --git a/gazelle/python/testdata/simple_test_with_conftest/bar/BUILD.in b/gazelle/python/testdata/simple_test_with_conftest/bar/BUILD.in new file mode 100644 index 0000000..3f2beb3 --- /dev/null +++ b/gazelle/python/testdata/simple_test_with_conftest/bar/BUILD.in
@@ -0,0 +1 @@ +load("@rules_python//python:defs.bzl", "py_library")
diff --git a/gazelle/python/testdata/simple_test_with_conftest/bar/BUILD.out b/gazelle/python/testdata/simple_test_with_conftest/bar/BUILD.out new file mode 100644 index 0000000..e42c499 --- /dev/null +++ b/gazelle/python/testdata/simple_test_with_conftest/bar/BUILD.out
@@ -0,0 +1,30 @@ +load("@rules_python//python:defs.bzl", "py_library", "py_test") + +py_library( + name = "bar", + srcs = [ + "__init__.py", + "bar.py", + ], + imports = [".."], + visibility = ["//:__subpackages__"], +) + +py_library( + name = "conftest", + testonly = True, + srcs = ["conftest.py"], + imports = [".."], + visibility = ["//:__subpackages__"], +) + +py_test( + name = "bar_test", + srcs = ["__test__.py"], + imports = [".."], + main = "__test__.py", + deps = [ + ":bar", + ":conftest", + ], +)
diff --git a/gazelle/python/testdata/simple_test_with_conftest/bar/__init__.py b/gazelle/python/testdata/simple_test_with_conftest/bar/__init__.py new file mode 100644 index 0000000..3f0275e --- /dev/null +++ b/gazelle/python/testdata/simple_test_with_conftest/bar/__init__.py
@@ -0,0 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from bar import bar + +_ = bar
diff --git a/gazelle/python/testdata/simple_test_with_conftest/bar/__test__.py b/gazelle/python/testdata/simple_test_with_conftest/bar/__test__.py new file mode 100644 index 0000000..00c4c28 --- /dev/null +++ b/gazelle/python/testdata/simple_test_with_conftest/bar/__test__.py
@@ -0,0 +1,26 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest + +from __init__ import bar + + +class BarTest(unittest.TestCase): + def test_bar(self): + self.assertEqual("bar", bar()) + + +if __name__ == "__main__": + unittest.main()
diff --git a/gazelle/python/testdata/simple_test_with_conftest/bar/bar.py b/gazelle/python/testdata/simple_test_with_conftest/bar/bar.py new file mode 100644 index 0000000..ba6a62d --- /dev/null +++ b/gazelle/python/testdata/simple_test_with_conftest/bar/bar.py
@@ -0,0 +1,17 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +def bar(): + return "bar"
diff --git a/gazelle/python/testdata/simple_test_with_conftest/bar/conftest.py b/gazelle/python/testdata/simple_test_with_conftest/bar/conftest.py new file mode 100644 index 0000000..4101095 --- /dev/null +++ b/gazelle/python/testdata/simple_test_with_conftest/bar/conftest.py
@@ -0,0 +1,13 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License.
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 7307559..bd0fe61 100644 --- a/gazelle/python/testdata/subdir_sources/foo/has_main/__main__.py +++ b/gazelle/python/testdata/subdir_sources/foo/has_main/__main__.py
@@ -13,3 +13,4 @@ # 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 7307559..3c9ed1a 100644 --- a/gazelle/python/testdata/subdir_sources/foo/has_test/__test__.py +++ b/gazelle/python/testdata/subdir_sources/foo/has_test/__test__.py
@@ -13,3 +13,4 @@ # 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 2da7f2b..2a97d8b 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 @@ srcs = ["__main__.py"], main = "__main__.py", visibility = ["//:__subpackages__"], - deps = [":with_third_party_requirements"], + deps = ["@gazelle_python_test_baz//:pkg"], )