From 9710fc759712c5c5370ca4a31b35cf74cd317d99 Mon Sep 17 00:00:00 2001 From: Alex Martani Date: Thu, 26 Jun 2025 15:20:11 -0700 Subject: [PATCH 1/2] Fix per-file generation for existing multi-file targets --- gazelle/python/generate.go | 72 ++++++++++++++----- .../BUILD.out | 7 +- 2 files changed, 58 insertions(+), 21 deletions(-) diff --git a/gazelle/python/generate.go b/gazelle/python/generate.go index 5eedbd9601..11ccd63b43 100644 --- a/gazelle/python/generate.go +++ b/gazelle/python/generate.go @@ -223,9 +223,40 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes log.Printf("ERROR: %v\n", err) return language.GenerateResult{} } - } - - parser := newPython3Parser(args.Config.RepoRoot, args.Rel, cfg.IgnoresDependency) + } + + existingMultiLibs := []struct{ + name string + srcs *treeset.Set + }{} + if cfg.PerFileGeneration() && args.File != nil { + for _, r := range args.File.Rules { + if r.Kind() != actualPyLibraryKind { + continue + } + srcs := r.AttrStrings("srcs") + pySrcs := make([]string, 0, len(srcs)) + for _, s := range srcs { + if filepath.Ext(s) == ".py" { + pySrcs = append(pySrcs, s) + } + } + if len(pySrcs) <= 1 { + continue + } + set := treeset.NewWith(godsutils.StringComparator) + for _, s := range pySrcs { + set.Add(s) + pyLibraryFilenames.Remove(s) + } + existingMultiLibs = append(existingMultiLibs, struct{ + name string + srcs *treeset.Set + }{r.Name(), set}) + } + } + + parser := newPython3Parser(args.Config.RepoRoot, args.Rel, cfg.IgnoresDependency) visibility := cfg.Visibility() var result language.GenerateResult @@ -315,22 +346,25 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes result.Imports = append(result.Imports, pyLibrary.PrivateAttr(config.GazelleImportsKey)) } } - if cfg.PerFileGeneration() { - hasInit, nonEmptyInit := hasLibraryEntrypointFile(args.Dir) - pyLibraryFilenames.Each(func(index int, filename interface{}) { - pyLibraryTargetName := strings.TrimSuffix(filepath.Base(filename.(string)), ".py") - if filename == pyLibraryEntrypointFilename && !nonEmptyInit { - return // ignore empty __init__.py. - } - srcs := treeset.NewWith(godsutils.StringComparator, filename) - if cfg.PerFileGenerationIncludeInit() && hasInit && nonEmptyInit { - srcs.Add(pyLibraryEntrypointFilename) - } - appendPyLibrary(srcs, pyLibraryTargetName) - }) - } else { - appendPyLibrary(pyLibraryFilenames, cfg.RenderLibraryName(packageName)) - } + if cfg.PerFileGeneration() { + hasInit, nonEmptyInit := hasLibraryEntrypointFile(args.Dir) + pyLibraryFilenames.Each(func(index int, filename interface{}) { + pyLibraryTargetName := strings.TrimSuffix(filepath.Base(filename.(string)), ".py") + if filename == pyLibraryEntrypointFilename && !nonEmptyInit { + return // ignore empty __init__.py. + } + srcs := treeset.NewWith(godsutils.StringComparator, filename) + if cfg.PerFileGenerationIncludeInit() && hasInit && nonEmptyInit { + srcs.Add(pyLibraryEntrypointFilename) + } + appendPyLibrary(srcs, pyLibraryTargetName) + }) + for _, lib := range existingMultiLibs { + appendPyLibrary(lib.srcs, lib.name) + } + } else { + appendPyLibrary(pyLibraryFilenames, cfg.RenderLibraryName(packageName)) + } if hasPyBinaryEntryPointFile { deps, _, annotations, err := parser.parseSingle(pyBinaryEntrypointFilename) diff --git a/gazelle/python/testdata/per_file_respect_existing_multiple_srcs/BUILD.out b/gazelle/python/testdata/per_file_respect_existing_multiple_srcs/BUILD.out index b809be3981..5c56d141ed 100644 --- a/gazelle/python/testdata/per_file_respect_existing_multiple_srcs/BUILD.out +++ b/gazelle/python/testdata/per_file_respect_existing_multiple_srcs/BUILD.out @@ -5,10 +5,13 @@ load("@rules_python//python:defs.bzl", "py_library", "py_test") # This target should be maintained by gazelle (but should get a new deps). py_library( name = "custom", - srcs = ["bar.py", "baz.py"], + srcs = [ + "bar.py", + "baz.py", + ], + tags = ["cant_touch_this"], visibility = ["//visibility:private"], deps = [":foo"], - tags = ["cant_touch_this"], ) py_library( From bcd12618714d1605c84aa0408a1d483715af3b8d Mon Sep 17 00:00:00 2001 From: Alex Martani Date: Fri, 27 Jun 2025 11:43:57 -0700 Subject: [PATCH 2/2] Fix formatting --- gazelle/python/generate.go | 106 ++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/gazelle/python/generate.go b/gazelle/python/generate.go index 11ccd63b43..170938e3e2 100644 --- a/gazelle/python/generate.go +++ b/gazelle/python/generate.go @@ -223,40 +223,40 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes log.Printf("ERROR: %v\n", err) return language.GenerateResult{} } - } - - existingMultiLibs := []struct{ - name string - srcs *treeset.Set - }{} - if cfg.PerFileGeneration() && args.File != nil { - for _, r := range args.File.Rules { - if r.Kind() != actualPyLibraryKind { - continue - } - srcs := r.AttrStrings("srcs") - pySrcs := make([]string, 0, len(srcs)) - for _, s := range srcs { - if filepath.Ext(s) == ".py" { - pySrcs = append(pySrcs, s) - } - } - if len(pySrcs) <= 1 { - continue - } - set := treeset.NewWith(godsutils.StringComparator) - for _, s := range pySrcs { - set.Add(s) - pyLibraryFilenames.Remove(s) - } - existingMultiLibs = append(existingMultiLibs, struct{ - name string - srcs *treeset.Set - }{r.Name(), set}) - } - } - - parser := newPython3Parser(args.Config.RepoRoot, args.Rel, cfg.IgnoresDependency) + } + + existingMultiLibs := []struct { + name string + srcs *treeset.Set + }{} + if cfg.PerFileGeneration() && args.File != nil { + for _, r := range args.File.Rules { + if r.Kind() != actualPyLibraryKind { + continue + } + srcs := r.AttrStrings("srcs") + pySrcs := make([]string, 0, len(srcs)) + for _, s := range srcs { + if filepath.Ext(s) == ".py" { + pySrcs = append(pySrcs, s) + } + } + if len(pySrcs) <= 1 { + continue + } + set := treeset.NewWith(godsutils.StringComparator) + for _, s := range pySrcs { + set.Add(s) + pyLibraryFilenames.Remove(s) + } + existingMultiLibs = append(existingMultiLibs, struct { + name string + srcs *treeset.Set + }{r.Name(), set}) + } + } + + parser := newPython3Parser(args.Config.RepoRoot, args.Rel, cfg.IgnoresDependency) visibility := cfg.Visibility() var result language.GenerateResult @@ -346,25 +346,25 @@ func (py *Python) GenerateRules(args language.GenerateArgs) language.GenerateRes result.Imports = append(result.Imports, pyLibrary.PrivateAttr(config.GazelleImportsKey)) } } - if cfg.PerFileGeneration() { - hasInit, nonEmptyInit := hasLibraryEntrypointFile(args.Dir) - pyLibraryFilenames.Each(func(index int, filename interface{}) { - pyLibraryTargetName := strings.TrimSuffix(filepath.Base(filename.(string)), ".py") - if filename == pyLibraryEntrypointFilename && !nonEmptyInit { - return // ignore empty __init__.py. - } - srcs := treeset.NewWith(godsutils.StringComparator, filename) - if cfg.PerFileGenerationIncludeInit() && hasInit && nonEmptyInit { - srcs.Add(pyLibraryEntrypointFilename) - } - appendPyLibrary(srcs, pyLibraryTargetName) - }) - for _, lib := range existingMultiLibs { - appendPyLibrary(lib.srcs, lib.name) - } - } else { - appendPyLibrary(pyLibraryFilenames, cfg.RenderLibraryName(packageName)) - } + if cfg.PerFileGeneration() { + hasInit, nonEmptyInit := hasLibraryEntrypointFile(args.Dir) + pyLibraryFilenames.Each(func(index int, filename interface{}) { + pyLibraryTargetName := strings.TrimSuffix(filepath.Base(filename.(string)), ".py") + if filename == pyLibraryEntrypointFilename && !nonEmptyInit { + return // ignore empty __init__.py. + } + srcs := treeset.NewWith(godsutils.StringComparator, filename) + if cfg.PerFileGenerationIncludeInit() && hasInit && nonEmptyInit { + srcs.Add(pyLibraryEntrypointFilename) + } + appendPyLibrary(srcs, pyLibraryTargetName) + }) + for _, lib := range existingMultiLibs { + appendPyLibrary(lib.srcs, lib.name) + } + } else { + appendPyLibrary(pyLibraryFilenames, cfg.RenderLibraryName(packageName)) + } if hasPyBinaryEntryPointFile { deps, _, annotations, err := parser.parseSingle(pyBinaryEntrypointFilename)