Skip to content

Commit e63fac5

Browse files
committed
fix[gazelle]: handle auto-included __init__.py when generating py_binary targets.
Fixes bazel-contrib#3729
1 parent ccdfc8a commit e63fac5

5 files changed

Lines changed: 40 additions & 7 deletions

File tree

gazelle/python/generate.go

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,15 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes
258258
// Create a validFilesMap of mainModules to validate if python macros have valid srcs.
259259
validFilesMap := make(map[string]struct{})
260260

261+
// Determine whether we have an __init__.py file in this package and whether we'll implicitly include it in srcs.
262+
var nonEmptyInit bool
263+
var autoIncludeInit bool
264+
if cfg.PerFileGeneration() {
265+
hasInit, nei := hasLibraryEntrypointFile(args.Dir)
266+
nonEmptyInit = nei
267+
autoIncludeInit = cfg.PerFileGenerationIncludeInit() && hasInit && nonEmptyInit
268+
}
269+
261270
appendPyLibrary := func(srcs *treeset.Set, pyLibraryTargetName string) {
262271
allDeps, mainModules, annotations, err := parser.parse(srcs)
263272
for name := range mainModules {
@@ -277,6 +286,10 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes
277286
// that we don't also generate a py_library target for it.
278287
if cfg.PerFileGeneration() {
279288
srcs.Remove(name)
289+
// Also remove the __init__.py that was added earlier.
290+
if autoIncludeInit {
291+
srcs.Remove(pyLibraryEntrypointFilename)
292+
}
280293
}
281294
}
282295

@@ -294,15 +307,20 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes
294307
filenames := treeset.NewWith(godsutils.StringComparator, filename)
295308
pyiSrcs, _ := getPyiFilenames(filenames, cfg.GeneratePyiSrcs(), args.Dir)
296309

297-
pyBinary := newTargetBuilder(pyBinaryKind, pyBinaryTargetName, pythonProjectRoot, args.Rel, pyFileNames, cfg.ResolveSiblingImports()).
310+
pyBinaryBuilder := newTargetBuilder(pyBinaryKind, pyBinaryTargetName, pythonProjectRoot, args.Rel, pyFileNames, cfg.ResolveSiblingImports()).
298311
addVisibility(visibility).
299312
addSrc(filename).
300313
addPyiSrcs(pyiSrcs).
301314
addModuleDependencies(mainModules[filename]).
302315
addResolvedDependencies(annotations.includeDeps).
303316
generateImportsAttribute().
304-
setAnnotations(*annotations).
305-
build()
317+
setAnnotations(*annotations)
318+
319+
if autoIncludeInit {
320+
pyBinaryBuilder.addSrc(pyLibraryEntrypointFilename)
321+
}
322+
323+
pyBinary := pyBinaryBuilder.build()
306324
result.Gen = append(result.Gen, pyBinary)
307325
result.Imports = append(result.Imports, pyBinary.PrivateAttr(config.GazelleImportsKey))
308326
}
@@ -357,15 +375,15 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes
357375
result.Imports = append(result.Imports, pyLibrary.PrivateAttr(config.GazelleImportsKey))
358376
}
359377
}
378+
360379
if cfg.PerFileGeneration() {
361-
hasInit, nonEmptyInit := hasLibraryEntrypointFile(args.Dir)
362380
pyLibraryFilenames.Each(func(index int, filename interface{}) {
363381
pyLibraryTargetName := strings.TrimSuffix(filepath.Base(filename.(string)), ".py")
364382
if filename == pyLibraryEntrypointFilename && !nonEmptyInit {
365383
return // ignore empty __init__.py.
366384
}
367385
srcs := treeset.NewWith(godsutils.StringComparator, filename)
368-
if cfg.PerFileGenerationIncludeInit() && hasInit && nonEmptyInit {
386+
if autoIncludeInit {
369387
srcs.Add(pyLibraryEntrypointFilename)
370388
}
371389
appendPyLibrary(srcs, pyLibraryTargetName)

gazelle/python/testdata/per_file_non_empty_init/BUILD.out

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
load("@rules_python//python:defs.bzl", "py_library")
1+
load("@rules_python//python:defs.bzl", "py_binary", "py_library")
22

33
# gazelle:python_generation_mode file
44
# gazelle:python_generation_mode_per_file_include_init true
@@ -18,3 +18,13 @@ py_library(
1818
],
1919
visibility = ["//:__subpackages__"],
2020
)
21+
22+
py_binary(
23+
name = "foobin",
24+
srcs = [
25+
"__init__.py",
26+
"foobin.py",
27+
],
28+
visibility = ["//:__subpackages__"],
29+
deps = [":foo"],
30+
)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# Per-file generation
22

3-
This test case generates one `py_library` per file, including `__init__.py`.
3+
This test case generates one `py_library` or `py_binary` per file, including `__init__.py`.

gazelle/python/testdata/per_file_non_empty_init/foo.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@
1313
# limitations under the License.
1414

1515
# For test purposes only.
16+
BAR = "baz"
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from foo import BAR
2+
3+
if __name__ == "__main__":
4+
print(BAR)

0 commit comments

Comments
 (0)