fix: missing dependencies of py_binary (#1630)
When multiple main modules import the same package, the package is only
added to one of the main module's deps, this is because the `allDeps`
set returned from `parse` removed the duplicates based on the import's
name.
This PR have every main module maintains a list of deps it imports to
avoid this issue.
diff --git a/gazelle/python/generate.go b/gazelle/python/generate.go
index 8d9b169..95f5396 100644
--- a/gazelle/python/generate.go
+++ b/gazelle/python/generate.go
@@ -238,9 +238,13 @@
}
if !hasPyBinaryEntryPointFile {
- sort.Strings(mainModules)
// Creating one py_binary target per main module when __main__.py doesn't exist.
- for _, filename := range mainModules {
+ mainFileNames := make([]string, 0, len(mainModules))
+ for name := range mainModules {
+ mainFileNames = append(mainFileNames, name)
+ }
+ sort.Strings(mainFileNames)
+ for _, filename := range mainFileNames {
pyBinaryTargetName := strings.TrimSuffix(filepath.Base(filename), ".py")
if err := ensureNoCollision(args.File, pyBinaryTargetName, actualPyBinaryKind); err != nil {
fqTarget := label.New("", args.Rel, pyBinaryTargetName)
@@ -248,13 +252,10 @@
fqTarget.String(), actualPyBinaryKind, err)
continue
}
- binaryDeps := allDeps.Select(func(index int, value interface{}) bool {
- return value.(module).Filepath == filepath.Join(args.Rel, filename)
- })
pyBinary := newTargetBuilder(pyBinaryKind, pyBinaryTargetName, pythonProjectRoot, args.Rel, pyFileNames).
addVisibility(visibility).
addSrc(filename).
- addModuleDependencies(binaryDeps).
+ addModuleDependencies(mainModules[filename]).
generateImportsAttribute().build()
result.Gen = append(result.Gen, pyBinary)
result.Imports = append(result.Imports, pyBinary.PrivateAttr(config.GazelleImportsKey))
diff --git a/gazelle/python/parser.go b/gazelle/python/parser.go
index d22850b..9b00b83 100644
--- a/gazelle/python/parser.go
+++ b/gazelle/python/parser.go
@@ -101,7 +101,7 @@
// parseSingle parses a single Python file and returns the extracted modules
// from the import statements as well as the parsed comments.
-func (p *python3Parser) parseSingle(pyFilename string) (*treeset.Set, []string, error) {
+func (p *python3Parser) parseSingle(pyFilename string) (*treeset.Set, map[string]*treeset.Set, error) {
pyFilenames := treeset.NewWith(godsutils.StringComparator)
pyFilenames.Add(pyFilename)
return p.parse(pyFilenames)
@@ -109,7 +109,7 @@
// parse parses multiple Python files and returns the extracted modules from
// the import statements as well as the parsed comments.
-func (p *python3Parser) parse(pyFilenames *treeset.Set) (*treeset.Set, []string, error) {
+func (p *python3Parser) parse(pyFilenames *treeset.Set) (*treeset.Set, map[string]*treeset.Set, error) {
parserMutex.Lock()
defer parserMutex.Unlock()
@@ -136,10 +136,10 @@
return nil, nil, fmt.Errorf("failed to parse: %w", err)
}
- var mainModules []string
+ mainModules := make(map[string]*treeset.Set, len(allRes))
for _, res := range allRes {
if res.HasMain {
- mainModules = append(mainModules, res.FileName)
+ mainModules[res.FileName] = treeset.NewWith(moduleComparator)
}
annotations, err := annotationsFromComments(res.Comments)
if err != nil {
@@ -160,6 +160,9 @@
}
modules.Add(m)
+ if res.HasMain {
+ mainModules[res.FileName].Add(m)
+ }
}
}
diff --git a/gazelle/python/testdata/binary_without_entrypoint/BUILD.out b/gazelle/python/testdata/binary_without_entrypoint/BUILD.out
index 72fc670..9af8152 100644
--- a/gazelle/python/testdata/binary_without_entrypoint/BUILD.out
+++ b/gazelle/python/testdata/binary_without_entrypoint/BUILD.out
@@ -13,7 +13,10 @@
name = "main",
srcs = ["main.py"],
visibility = ["//:__subpackages__"],
- deps = ["@pip//:pandas"],
+ deps = [
+ ":py_default_library",
+ "@pip//:pandas",
+ ],
)
py_binary(
diff --git a/gazelle/python/testdata/binary_without_entrypoint/main.py b/gazelle/python/testdata/binary_without_entrypoint/main.py
index f13cbe5..f7b3170 100644
--- a/gazelle/python/testdata/binary_without_entrypoint/main.py
+++ b/gazelle/python/testdata/binary_without_entrypoint/main.py
@@ -1,3 +1,4 @@
+import collided_main
import pandas
if __name__ == "__main__":