From d07619f8165b69ac0398655800c8e948d71e42de Mon Sep 17 00:00:00 2001 From: Charles Guo Date: Sun, 20 Jul 2025 18:10:02 -0400 Subject: [PATCH 1/9] [wip] Begin implementation of module-level py_proto_library import support --- gazelle/python/generate.go | 9 +++ gazelle/python/resolve.go | 61 ++++++++++++++++++- .../README.md | 2 +- .../testdata/resolves_proto_imports/BUILD.in | 0 .../testdata/resolves_proto_imports/BUILD.out | 0 .../testdata/resolves_proto_imports/README.md | 9 +++ .../testdata/resolves_proto_imports/WORKSPACE | 0 .../testdata/resolves_proto_imports/test.yaml | 0 .../test1_generates_dependency/BUILD.in | 0 .../test1_generates_dependency/BUILD.out | 8 +++ .../test1_generates_dependency/bar.py | 3 + .../test1_generates_dependency/foo/BUILD.in | 1 + .../test1_generates_dependency/foo/BUILD.out | 16 +++++ .../test1_generates_dependency/foo/foo.proto | 7 +++ .../test2_generates_using_resolve/BUILD.in | 1 + .../test2_generates_using_resolve/BUILD.out | 10 +++ .../bar/BUILD.in | 1 + .../bar/BUILD.out | 16 +++++ .../bar/bar.proto | 7 +++ .../test2_generates_using_resolve/baz.py | 3 + .../test3_uses_naming_convention/BUILD.in | 1 + .../test3_uses_naming_convention/BUILD.out | 10 +++ .../test3_uses_naming_convention/bar/BUILD.in | 1 + .../bar/BUILD.out | 16 +++++ .../bar/bar.proto | 7 +++ .../test3_uses_naming_convention/baz.py | 3 + 26 files changed, 188 insertions(+), 4 deletions(-) create mode 100644 gazelle/python/testdata/resolves_proto_imports/BUILD.in create mode 100644 gazelle/python/testdata/resolves_proto_imports/BUILD.out create mode 100644 gazelle/python/testdata/resolves_proto_imports/README.md create mode 100644 gazelle/python/testdata/resolves_proto_imports/WORKSPACE create mode 100644 gazelle/python/testdata/resolves_proto_imports/test.yaml create mode 100644 gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/BUILD.in create mode 100644 gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/BUILD.out create mode 100644 gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/bar.py create mode 100644 gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/foo/BUILD.in create mode 100644 gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/foo/BUILD.out create mode 100644 gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/foo/foo.proto create mode 100644 gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/BUILD.in create mode 100644 gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/BUILD.out create mode 100644 gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/bar/BUILD.in create mode 100644 gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/bar/BUILD.out create mode 100644 gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/bar/bar.proto create mode 100644 gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/baz.py create mode 100644 gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/BUILD.in create mode 100644 gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/BUILD.out create mode 100644 gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/bar/BUILD.in create mode 100644 gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/bar/BUILD.out create mode 100644 gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/bar/bar.proto create mode 100644 gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/baz.py diff --git a/gazelle/python/generate.go b/gazelle/python/generate.go index 5b6ba79d69..cd11693b59 100644 --- a/gazelle/python/generate.go +++ b/gazelle/python/generate.go @@ -42,6 +42,8 @@ const ( pyTestEntrypointTargetname = "__test__" conftestFilename = "conftest.py" conftestTargetname = "conftest" + protoKey = "_proto_target" + protoRelKey = "_proto_rel" ) var ( @@ -572,11 +574,16 @@ func ensureNoCollision(file *rule.File, targetName, kind string) error { func generateProtoLibraries(args language.GenerateArgs, cfg *pythonconfig.Config, pythonProjectRoot string, visibility []string, res *language.GenerateResult) { // First, enumerate all the proto_library in this package. var protoRuleNames []string + protoRules := map[string]*rule.Rule{} + protoRel := map[string]string{} + for _, r := range args.OtherGen { if r.Kind() != "proto_library" { continue } protoRuleNames = append(protoRuleNames, r.Name()) + protoRules[r.Name()] = r + protoRel[r.Name()] = args.Rel } sort.Strings(protoRuleNames) @@ -609,6 +616,8 @@ func generateProtoLibraries(args language.GenerateArgs, cfg *pythonconfig.Config addVisibility(visibility). addResolvedDependency(":" + protoRuleName). generateImportsAttribute().build() + pyProtoLibrary.SetPrivateAttr(protoKey, protoRuleName) + pyProtoLibrary.SetPrivateAttr(protoRelKey, protoRel[protoRuleName]) res.Gen = append(res.Gen, pyProtoLibrary) res.Imports = append(res.Imports, pyProtoLibrary.PrivateAttr(config.GazelleImportsKey)) diff --git a/gazelle/python/resolve.go b/gazelle/python/resolve.go index 0dd80841d4..705ae2937f 100644 --- a/gazelle/python/resolve.go +++ b/gazelle/python/resolve.go @@ -57,7 +57,18 @@ func (*Resolver) Name() string { return languageName } func (py *Resolver) Imports(c *config.Config, r *rule.Rule, f *rule.File) []resolve.ImportSpec { cfgs := c.Exts[languageName].(pythonconfig.Configs) cfg := cfgs[f.Pkg] + srcs := r.AttrStrings("srcs") + if srcs != nil { + return importsSrcLibrary(cfg, srcs, f) + } else if isProtoLibrary(r) { + return importsProtoLibrary(cfg, r, f) + } + + return nil +} + +func importsSrcLibrary(cfg *pythonconfig.Config, srcs []string, f *rule.File) []resolve.ImportSpec { provides := make([]resolve.ImportSpec, 0, len(srcs)+1) for _, src := range srcs { ext := filepath.Ext(src) @@ -114,6 +125,42 @@ func importSpecFromSrc(pythonProjectRoot, bzlPkg, src string) resolve.ImportSpec } } +func isProtoLibrary(r *rule.Rule) bool { + return r.Kind() == pyProtoLibraryKind +} + +func importsProtoLibrary(cfg *pythonconfig.Config, r *rule.Rule, f *rule.File) []resolve.ImportSpec { + specs := []resolve.ImportSpec{} + + // First, determine the root module and emit an import for that, + // i.e. for //foo:foo_py_pb2, we'd get foo.foo_pb2 + protoRuleAttr := r.PrivateAttr(protoKey) + protoRelAttr := r.PrivateAttr(protoRelKey) + if protoRuleAttr == nil || protoRelAttr == nil { + return specs + } + + protoRule := protoRuleAttr.(string) + generatedPbFileName := strings.TrimSuffix(protoRule, "_proto") + "_pb2.py" + protoRel := protoRelAttr.(string) + + specs = append(specs, importSpecFromSrc(cfg.PythonProjectRoot(), protoRel, generatedPbFileName)) + + // TODO: use parsed proto FileInfo to enumerate importable constants, like messages, + // and emit ImportSpec for them + // protoPkg := r.PrivateAttr(proto.PackageKey).(proto.Package) + // for _, protoFileInfo := range protoPkg.Files { + // for _, svc := range protoFileInfo.Services { + // specs = append(specs, resolve.ImportSpec{ + // Lang: languageName, + // Imp: fmt.Sprintf("%s.%s", rootPath, svc), + // }) + // } + // Repeat for Messages, Enums + + return specs +} + // Embeds returns a list of labels of rules that the given rule embeds. If // a rule is embedded by another importable rule of the same language, only // the embedding rule will be indexed. The embedding rule will inherit @@ -210,9 +257,9 @@ func (py *Resolver) Resolve( baseParts = pkgParts[:len(pkgParts)-(relativeDepth-1)] } // Build absolute module path - absParts := append([]string{}, baseParts...) // base path - absParts = append(absParts, fromParts...) // subpath from 'from' - absParts = append(absParts, imported) // actual imported symbol + absParts := append([]string{}, baseParts...) // base path + absParts = append(absParts, fromParts...) // subpath from 'from' + absParts = append(absParts, imported) // actual imported symbol moduleName = strings.Join(absParts, ".") } @@ -282,6 +329,9 @@ func (py *Resolver) Resolve( // Check if the imported module is part of the standard library. if isStdModule(Module{Name: moduleName}) { continue MODULES_LOOP + } else if r.Kind() == pyProtoLibraryKind { + // For py_proto_library, fall back to guessing the label based on the proto_library rule name. + matches = py.resolveProtoFallback(cfg) } else if cfg.ValidateImportStatements() { err := fmt.Errorf( "%[1]q, line %[2]d: %[3]q is an invalid dependency: possible solutions:\n"+ @@ -372,6 +422,11 @@ func (py *Resolver) Resolve( } } +func (*Resolver) resolveProtoFallback(c *pythonconfig.Config) []resolve.FindResult { + // TODO + return []resolve.FindResult{} +} + // addResolvedDeps adds the pre-resolved dependencies from the rule's private attributes // to the provided deps set. func addResolvedDeps( diff --git a/gazelle/python/testdata/directive_python_proto_naming_convention/README.md b/gazelle/python/testdata/directive_python_proto_naming_convention/README.md index 594379cdfc..48b883a634 100644 --- a/gazelle/python/testdata/directive_python_proto_naming_convention/README.md +++ b/gazelle/python/testdata/directive_python_proto_naming_convention/README.md @@ -6,4 +6,4 @@ correctly: 1. Has no effect on pre-existing `py_proto_library` when `gazelle:python_generate_proto` is disabled. 2. Uses the default value when proto generation is on and `python_proto_naming_convention` is not set. 3. Uses the provided naming convention when proto generation is on and `python_proto_naming_convention` is set. -4. With a pre-existing `py_proto_library` not following a given naming convention, keeps it intact and does not rename it. \ No newline at end of file +4. With a pre-existing `py_proto_library` not following a given naming convention, keeps it intact and does not rename it. diff --git a/gazelle/python/testdata/resolves_proto_imports/BUILD.in b/gazelle/python/testdata/resolves_proto_imports/BUILD.in new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gazelle/python/testdata/resolves_proto_imports/BUILD.out b/gazelle/python/testdata/resolves_proto_imports/BUILD.out new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gazelle/python/testdata/resolves_proto_imports/README.md b/gazelle/python/testdata/resolves_proto_imports/README.md new file mode 100644 index 0000000000..6de0bf7452 --- /dev/null +++ b/gazelle/python/testdata/resolves_proto_imports/README.md @@ -0,0 +1,9 @@ +# Resolves proto imports + +This test asserts that Gazelle can resolve imports from `py_proto_library` targets: + +1. Generates a dependency in the default case. +2. Uses `gazelle:resolve` to generate dependencies. +3. Uses `python_proto_naming_convention` to generate dependencies. + +[gh-1703]: https://github.com/bazel-contrib/rules_python/issues/1703 diff --git a/gazelle/python/testdata/resolves_proto_imports/WORKSPACE b/gazelle/python/testdata/resolves_proto_imports/WORKSPACE new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gazelle/python/testdata/resolves_proto_imports/test.yaml b/gazelle/python/testdata/resolves_proto_imports/test.yaml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/BUILD.in b/gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/BUILD.in new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/BUILD.out b/gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/BUILD.out new file mode 100644 index 0000000000..8631249d53 --- /dev/null +++ b/gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/BUILD.out @@ -0,0 +1,8 @@ +load("@rules_python//python:defs.bzl", "py_library") + +py_library( + name = "test1_generates_dependency", + srcs = ["bar.py"], + visibility = ["//:__subpackages__"], + deps = ["//test1_generates_dependency/foo:test1_generates_dependency_foo_py_pb2"], +) \ No newline at end of file diff --git a/gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/bar.py b/gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/bar.py new file mode 100644 index 0000000000..8950618429 --- /dev/null +++ b/gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/bar.py @@ -0,0 +1,3 @@ +import test1_generates_dependency.foo.test1_generates_dependency_foo_pb2 + +x = Foo() \ No newline at end of file diff --git a/gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/foo/BUILD.in b/gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/foo/BUILD.in new file mode 100644 index 0000000000..ce3eec6001 --- /dev/null +++ b/gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/foo/BUILD.in @@ -0,0 +1 @@ +# gazelle:python_generate_proto true diff --git a/gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/foo/BUILD.out b/gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/foo/BUILD.out new file mode 100644 index 0000000000..d7c43c2e39 --- /dev/null +++ b/gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/foo/BUILD.out @@ -0,0 +1,16 @@ +load("@rules_proto//proto:defs.bzl", "proto_library") +load("@com_google_protobuf//bazel:py_proto_library.bzl", "py_proto_library") + +# gazelle:python_generate_proto true + +proto_library( + name = "test1_generates_dependency_foo_proto", + srcs = ["foo.proto"], + visibility = ["//visibility:public"], +) + +py_proto_library( + name = "test1_generates_dependency_foo_py_pb2", + visibility = ["//:__subpackages__"], + deps = [":test1_generates_dependency_foo_proto"], +) diff --git a/gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/foo/foo.proto b/gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/foo/foo.proto new file mode 100644 index 0000000000..107ab9137e --- /dev/null +++ b/gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/foo/foo.proto @@ -0,0 +1,7 @@ +syntax = "proto3"; + +package test1_generates_dependency.foo; + +message Foo { + bool bar = 1; +} \ No newline at end of file diff --git a/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/BUILD.in b/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/BUILD.in new file mode 100644 index 0000000000..5a471573e1 --- /dev/null +++ b/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/BUILD.in @@ -0,0 +1 @@ +# gazelle:resolve py test2_generates_using_resolve.foo.test2_generates_using_resolve_foo_pb2 //test2_generates_using_resolve/bar:bar_py_pb2 diff --git a/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/BUILD.out b/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/BUILD.out new file mode 100644 index 0000000000..a03238c137 --- /dev/null +++ b/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/BUILD.out @@ -0,0 +1,10 @@ +load("@rules_python//python:defs.bzl", "py_library") + +# gazelle:resolve py test2_generates_using_resolve.foo.test2_generates_using_resolve_foo_pb2 //test2_generates_using_resolve/bar:bar_py_pb2 + +py_library( + name = "test2_generates_using_resolve", + srcs = ["baz.py"], + visibility = ["//:__subpackages__"], + deps = ["//test2_generates_using_resolve/bar:bar_py_pb2"], +) \ No newline at end of file diff --git a/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/bar/BUILD.in b/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/bar/BUILD.in new file mode 100644 index 0000000000..ce3eec6001 --- /dev/null +++ b/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/bar/BUILD.in @@ -0,0 +1 @@ +# gazelle:python_generate_proto true diff --git a/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/bar/BUILD.out b/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/bar/BUILD.out new file mode 100644 index 0000000000..ea987fd2a9 --- /dev/null +++ b/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/bar/BUILD.out @@ -0,0 +1,16 @@ +load("@rules_proto//proto:defs.bzl", "proto_library") +load("@com_google_protobuf//bazel:py_proto_library.bzl", "py_proto_library") + +# gazelle:python_generate_proto true + +proto_library( + name = "test2_generates_using_resolve_bar_proto", + srcs = ["bar.proto"], + visibility = ["//visibility:public"], +) + +py_proto_library( + name = "test2_generates_using_resolve_bar_py_pb2", + visibility = ["//:__subpackages__"], + deps = [":test2_generates_using_resolve_bar_proto"], +) diff --git a/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/bar/bar.proto b/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/bar/bar.proto new file mode 100644 index 0000000000..1d8ce6fef7 --- /dev/null +++ b/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/bar/bar.proto @@ -0,0 +1,7 @@ +syntax = "proto3"; + +package test2_generates_using_resolve.bar; + +message Bar { + bool bar = 1; +} \ No newline at end of file diff --git a/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/baz.py b/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/baz.py new file mode 100644 index 0000000000..5d5aed5e2c --- /dev/null +++ b/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/baz.py @@ -0,0 +1,3 @@ +import test2_generates_using_resolve.foo.test2_generates_using_resolve_foo_pb2 + +x = Foo() \ No newline at end of file diff --git a/gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/BUILD.in b/gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/BUILD.in new file mode 100644 index 0000000000..4f51c66b9d --- /dev/null +++ b/gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/BUILD.in @@ -0,0 +1 @@ +# gazelle:python_proto_naming_convention some_$proto_name$_value diff --git a/gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/BUILD.out b/gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/BUILD.out new file mode 100644 index 0000000000..c5223f92a5 --- /dev/null +++ b/gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/BUILD.out @@ -0,0 +1,10 @@ +load("@rules_python//python:defs.bzl", "py_library") + +# gazelle:python_proto_naming_convention some_$proto_name$_value + +py_library( + name = "test3_uses_naming_convention", + srcs = ["baz.py"], + visibility = ["//:__subpackages__"], + deps = ["//test3_uses_naming_convention/bar:some_test3_uses_naming_convention_bar_value"], +) \ No newline at end of file diff --git a/gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/bar/BUILD.in b/gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/bar/BUILD.in new file mode 100644 index 0000000000..ce3eec6001 --- /dev/null +++ b/gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/bar/BUILD.in @@ -0,0 +1 @@ +# gazelle:python_generate_proto true diff --git a/gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/bar/BUILD.out b/gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/bar/BUILD.out new file mode 100644 index 0000000000..9c8aab645f --- /dev/null +++ b/gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/bar/BUILD.out @@ -0,0 +1,16 @@ +load("@rules_proto//proto:defs.bzl", "proto_library") +load("@com_google_protobuf//bazel:py_proto_library.bzl", "py_proto_library") + +# gazelle:python_generate_proto true + +proto_library( + name = "test3_uses_naming_convention_bar_proto", + srcs = ["bar.proto"], + visibility = ["//visibility:public"], +) + +py_proto_library( + name = "some_test3_uses_naming_convention_bar_value", + visibility = ["//:__subpackages__"], + deps = [":test3_uses_naming_convention_bar_proto"], +) diff --git a/gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/bar/bar.proto b/gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/bar/bar.proto new file mode 100644 index 0000000000..8e6c9e909d --- /dev/null +++ b/gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/bar/bar.proto @@ -0,0 +1,7 @@ +syntax = "proto3"; + +package test3_uses_naming_convention.bar; + +message Bar { + bool bar = 1; +} \ No newline at end of file diff --git a/gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/baz.py b/gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/baz.py new file mode 100644 index 0000000000..4f1796cc83 --- /dev/null +++ b/gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/baz.py @@ -0,0 +1,3 @@ +import test3_uses_naming_convention.bar.test3_uses_naming_convention_bar_pb2 + +x = Bar() \ No newline at end of file From 49248b634180af56f95ea80ca20dffc39a06f4e2 Mon Sep 17 00:00:00 2001 From: Charles Guo Date: Sun, 20 Jul 2025 19:16:31 -0400 Subject: [PATCH 2/9] Clean up comments --- gazelle/python/resolve.go | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/gazelle/python/resolve.go b/gazelle/python/resolve.go index 705ae2937f..4e43cc817a 100644 --- a/gazelle/python/resolve.go +++ b/gazelle/python/resolve.go @@ -132,7 +132,7 @@ func isProtoLibrary(r *rule.Rule) bool { func importsProtoLibrary(cfg *pythonconfig.Config, r *rule.Rule, f *rule.File) []resolve.ImportSpec { specs := []resolve.ImportSpec{} - // First, determine the root module and emit an import for that, + // Determine the root module and emit an import for that, // i.e. for //foo:foo_py_pb2, we'd get foo.foo_pb2 protoRuleAttr := r.PrivateAttr(protoKey) protoRelAttr := r.PrivateAttr(protoRelKey) @@ -146,18 +146,6 @@ func importsProtoLibrary(cfg *pythonconfig.Config, r *rule.Rule, f *rule.File) [ specs = append(specs, importSpecFromSrc(cfg.PythonProjectRoot(), protoRel, generatedPbFileName)) - // TODO: use parsed proto FileInfo to enumerate importable constants, like messages, - // and emit ImportSpec for them - // protoPkg := r.PrivateAttr(proto.PackageKey).(proto.Package) - // for _, protoFileInfo := range protoPkg.Files { - // for _, svc := range protoFileInfo.Services { - // specs = append(specs, resolve.ImportSpec{ - // Lang: languageName, - // Imp: fmt.Sprintf("%s.%s", rootPath, svc), - // }) - // } - // Repeat for Messages, Enums - return specs } From 083f3ee6974751ece4c122f112c4bb72d1015a8c Mon Sep 17 00:00:00 2001 From: Charles Guo Date: Sun, 20 Jul 2025 19:17:17 -0400 Subject: [PATCH 3/9] Remove unused arg --- gazelle/python/resolve.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gazelle/python/resolve.go b/gazelle/python/resolve.go index 4e43cc817a..6d2696473c 100644 --- a/gazelle/python/resolve.go +++ b/gazelle/python/resolve.go @@ -62,7 +62,7 @@ func (py *Resolver) Imports(c *config.Config, r *rule.Rule, f *rule.File) []reso if srcs != nil { return importsSrcLibrary(cfg, srcs, f) } else if isProtoLibrary(r) { - return importsProtoLibrary(cfg, r, f) + return importsProtoLibrary(cfg, r) } return nil @@ -129,7 +129,7 @@ func isProtoLibrary(r *rule.Rule) bool { return r.Kind() == pyProtoLibraryKind } -func importsProtoLibrary(cfg *pythonconfig.Config, r *rule.Rule, f *rule.File) []resolve.ImportSpec { +func importsProtoLibrary(cfg *pythonconfig.Config, r *rule.Rule) []resolve.ImportSpec { specs := []resolve.ImportSpec{} // Determine the root module and emit an import for that, From 2878c0d16627c8db3e9d03e497df3ebc2aa01f9a Mon Sep 17 00:00:00 2001 From: Charles Guo Date: Sun, 20 Jul 2025 19:19:14 -0400 Subject: [PATCH 4/9] Remove some unused stuff --- gazelle/python/generate.go | 2 -- gazelle/python/resolve.go | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/gazelle/python/generate.go b/gazelle/python/generate.go index cd11693b59..54adc634cd 100644 --- a/gazelle/python/generate.go +++ b/gazelle/python/generate.go @@ -574,7 +574,6 @@ func ensureNoCollision(file *rule.File, targetName, kind string) error { func generateProtoLibraries(args language.GenerateArgs, cfg *pythonconfig.Config, pythonProjectRoot string, visibility []string, res *language.GenerateResult) { // First, enumerate all the proto_library in this package. var protoRuleNames []string - protoRules := map[string]*rule.Rule{} protoRel := map[string]string{} for _, r := range args.OtherGen { @@ -582,7 +581,6 @@ func generateProtoLibraries(args language.GenerateArgs, cfg *pythonconfig.Config continue } protoRuleNames = append(protoRuleNames, r.Name()) - protoRules[r.Name()] = r protoRel[r.Name()] = args.Rel } sort.Strings(protoRuleNames) diff --git a/gazelle/python/resolve.go b/gazelle/python/resolve.go index 6d2696473c..fede236a77 100644 --- a/gazelle/python/resolve.go +++ b/gazelle/python/resolve.go @@ -137,7 +137,7 @@ func importsProtoLibrary(cfg *pythonconfig.Config, r *rule.Rule) []resolve.Impor protoRuleAttr := r.PrivateAttr(protoKey) protoRelAttr := r.PrivateAttr(protoRelKey) if protoRuleAttr == nil || protoRelAttr == nil { - return specs + return nil } protoRule := protoRuleAttr.(string) From 9ae7af60fd29dd9261c405a8ccfa65c562cae2bc Mon Sep 17 00:00:00 2001 From: Charles Guo Date: Sun, 20 Jul 2025 19:21:55 -0400 Subject: [PATCH 5/9] Fix python imports in tests --- .../resolves_proto_imports/test1_generates_dependency/bar.py | 2 +- .../resolves_proto_imports/test2_generates_using_resolve/baz.py | 2 +- .../resolves_proto_imports/test3_uses_naming_convention/baz.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/bar.py b/gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/bar.py index 8950618429..265535ce3e 100644 --- a/gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/bar.py +++ b/gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/bar.py @@ -1,3 +1,3 @@ import test1_generates_dependency.foo.test1_generates_dependency_foo_pb2 -x = Foo() \ No newline at end of file +x = test1_generates_dependency_foo_pb2.Foo() \ No newline at end of file diff --git a/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/baz.py b/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/baz.py index 5d5aed5e2c..e38e1072a8 100644 --- a/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/baz.py +++ b/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/baz.py @@ -1,3 +1,3 @@ import test2_generates_using_resolve.foo.test2_generates_using_resolve_foo_pb2 -x = Foo() \ No newline at end of file +x = test2_generates_using_resolve_foo_pb2.Bar() \ No newline at end of file diff --git a/gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/baz.py b/gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/baz.py index 4f1796cc83..28596403a7 100644 --- a/gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/baz.py +++ b/gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/baz.py @@ -1,3 +1,3 @@ import test3_uses_naming_convention.bar.test3_uses_naming_convention_bar_pb2 -x = Bar() \ No newline at end of file +x = test3_uses_naming_convention_bar_pb2.Bar() \ No newline at end of file From 50980b1a80cf5023c1854a8a92f2fa4b3828fde8 Mon Sep 17 00:00:00 2001 From: Charles Guo Date: Sun, 20 Jul 2025 19:25:32 -0400 Subject: [PATCH 6/9] Update README, CHANGELOG --- CHANGELOG.md | 3 +++ gazelle/README.md | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d54d3a8881..e8aaadec03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -118,6 +118,9 @@ END_UNRELEASED_TEMPLATE Gazelle generates `py_proto_library` rules for `proto_library`. `false` by default. * (gazelle) New directive `gazelle:python_proto_naming_convention`; controls naming of `py_proto_library` rules. +* (gazelle) Gazelle now resolves dependencies for `py_proto_library` + module-level imports, i.e. `import some.package.foo_pb2`. Imports of + messages/enums/services inside modules are not yet supported. {#v0-0-0-removed} ### Removed diff --git a/gazelle/README.md b/gazelle/README.md index 222c1171ab..26a9f1fbac 100644 --- a/gazelle/README.md +++ b/gazelle/README.md @@ -288,7 +288,7 @@ py_proto_library( The default naming convention is `$proto_name$_pb2_py`, so by default in the above example Gazelle would generate `foo_pb2_py`. Any pre-existing rules are left in place and not renamed. -Note that the Python library will always be imported as `foo_pb2` in Python code, regardless of the naming convention. Also note that Gazelle is currently not able to map said imports, e.g. `import foo_pb2`, to fill in `py_proto_library` targets as dependencies of other rules. See [this issue](https://github.com/bazel-contrib/rules_python/issues/1703). +Note that the Python library will always be imported as `foo_pb2` in Python code, regardless of the naming convention. #### Directive: `python_default_visibility`: From 706809c35d92cc6909cc3825866149357398eb1e Mon Sep 17 00:00:00 2001 From: Charles Guo Date: Sun, 20 Jul 2025 19:59:20 -0400 Subject: [PATCH 7/9] Write a test to ensure that a multi-src proto_library will have imports generated for it --- .../testdata/resolves_proto_imports/README.md | 3 +-- .../BUILD.in | 0 .../BUILD.out | 8 ++++++++ .../bar.py | 5 +++++ .../foo/BUILD.in | 1 + .../foo/BUILD.out | 19 +++++++++++++++++++ .../foo/bar.proto | 7 +++++++ .../foo/foo.proto | 7 +++++++ 8 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 gazelle/python/testdata/resolves_proto_imports/test4_generates_imports_for_multiple_proto_srcs/BUILD.in create mode 100644 gazelle/python/testdata/resolves_proto_imports/test4_generates_imports_for_multiple_proto_srcs/BUILD.out create mode 100644 gazelle/python/testdata/resolves_proto_imports/test4_generates_imports_for_multiple_proto_srcs/bar.py create mode 100644 gazelle/python/testdata/resolves_proto_imports/test4_generates_imports_for_multiple_proto_srcs/foo/BUILD.in create mode 100644 gazelle/python/testdata/resolves_proto_imports/test4_generates_imports_for_multiple_proto_srcs/foo/BUILD.out create mode 100644 gazelle/python/testdata/resolves_proto_imports/test4_generates_imports_for_multiple_proto_srcs/foo/bar.proto create mode 100644 gazelle/python/testdata/resolves_proto_imports/test4_generates_imports_for_multiple_proto_srcs/foo/foo.proto diff --git a/gazelle/python/testdata/resolves_proto_imports/README.md b/gazelle/python/testdata/resolves_proto_imports/README.md index 6de0bf7452..934980de91 100644 --- a/gazelle/python/testdata/resolves_proto_imports/README.md +++ b/gazelle/python/testdata/resolves_proto_imports/README.md @@ -5,5 +5,4 @@ This test asserts that Gazelle can resolve imports from `py_proto_library` targe 1. Generates a dependency in the default case. 2. Uses `gazelle:resolve` to generate dependencies. 3. Uses `python_proto_naming_convention` to generate dependencies. - -[gh-1703]: https://github.com/bazel-contrib/rules_python/issues/1703 +4. Generates a correct dependency for a proto_library with multiple srcs. diff --git a/gazelle/python/testdata/resolves_proto_imports/test4_generates_imports_for_multiple_proto_srcs/BUILD.in b/gazelle/python/testdata/resolves_proto_imports/test4_generates_imports_for_multiple_proto_srcs/BUILD.in new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gazelle/python/testdata/resolves_proto_imports/test4_generates_imports_for_multiple_proto_srcs/BUILD.out b/gazelle/python/testdata/resolves_proto_imports/test4_generates_imports_for_multiple_proto_srcs/BUILD.out new file mode 100644 index 0000000000..3ea7fe5819 --- /dev/null +++ b/gazelle/python/testdata/resolves_proto_imports/test4_generates_imports_for_multiple_proto_srcs/BUILD.out @@ -0,0 +1,8 @@ +load("@rules_python//python:defs.bzl", "py_library") + +py_library( + name = "test4_generates_imports_for_multiple_proto_srcs", + srcs = ["bar.py"], + visibility = ["//:__subpackages__"], + deps = ["//test4_generates_imports_for_multiple_proto_srcs/foo:test4_generates_imports_for_multiple_proto_srcs_foo_py_pb2"], +) \ No newline at end of file diff --git a/gazelle/python/testdata/resolves_proto_imports/test4_generates_imports_for_multiple_proto_srcs/bar.py b/gazelle/python/testdata/resolves_proto_imports/test4_generates_imports_for_multiple_proto_srcs/bar.py new file mode 100644 index 0000000000..4f04c6dffe --- /dev/null +++ b/gazelle/python/testdata/resolves_proto_imports/test4_generates_imports_for_multiple_proto_srcs/bar.py @@ -0,0 +1,5 @@ +import test4_generates_imports_for_multiple_proto_srcs.foo.foo_pb2 +import test4_generates_imports_for_multiple_proto_srcs.foo.bar_pb2 + +x = foo_pb2.Foo() +y = bar_pb2.Bar() \ No newline at end of file diff --git a/gazelle/python/testdata/resolves_proto_imports/test4_generates_imports_for_multiple_proto_srcs/foo/BUILD.in b/gazelle/python/testdata/resolves_proto_imports/test4_generates_imports_for_multiple_proto_srcs/foo/BUILD.in new file mode 100644 index 0000000000..ce3eec6001 --- /dev/null +++ b/gazelle/python/testdata/resolves_proto_imports/test4_generates_imports_for_multiple_proto_srcs/foo/BUILD.in @@ -0,0 +1 @@ +# gazelle:python_generate_proto true diff --git a/gazelle/python/testdata/resolves_proto_imports/test4_generates_imports_for_multiple_proto_srcs/foo/BUILD.out b/gazelle/python/testdata/resolves_proto_imports/test4_generates_imports_for_multiple_proto_srcs/foo/BUILD.out new file mode 100644 index 0000000000..1f29e469ce --- /dev/null +++ b/gazelle/python/testdata/resolves_proto_imports/test4_generates_imports_for_multiple_proto_srcs/foo/BUILD.out @@ -0,0 +1,19 @@ +load("@rules_proto//proto:defs.bzl", "proto_library") +load("@com_google_protobuf//bazel:py_proto_library.bzl", "py_proto_library") + +# gazelle:python_generate_proto true + +proto_library( + name = "test4_generates_imports_for_multiple_proto_srcs_foo_proto", + srcs = [ + "bar.proto", + "foo.proto", + ], + visibility = ["//visibility:public"], +) + +py_proto_library( + name = "test4_generates_imports_for_multiple_proto_srcs_foo_py_pb2", + visibility = ["//:__subpackages__"], + deps = [":test4_generates_imports_for_multiple_proto_srcs_foo_proto"], +) diff --git a/gazelle/python/testdata/resolves_proto_imports/test4_generates_imports_for_multiple_proto_srcs/foo/bar.proto b/gazelle/python/testdata/resolves_proto_imports/test4_generates_imports_for_multiple_proto_srcs/foo/bar.proto new file mode 100644 index 0000000000..4c60fa1e68 --- /dev/null +++ b/gazelle/python/testdata/resolves_proto_imports/test4_generates_imports_for_multiple_proto_srcs/foo/bar.proto @@ -0,0 +1,7 @@ +syntax = "proto3"; + +package test4_generates_imports_for_multiple_proto_srcs.foo; + +message Bar { + bool bar = 1; +} \ No newline at end of file diff --git a/gazelle/python/testdata/resolves_proto_imports/test4_generates_imports_for_multiple_proto_srcs/foo/foo.proto b/gazelle/python/testdata/resolves_proto_imports/test4_generates_imports_for_multiple_proto_srcs/foo/foo.proto new file mode 100644 index 0000000000..546c2508de --- /dev/null +++ b/gazelle/python/testdata/resolves_proto_imports/test4_generates_imports_for_multiple_proto_srcs/foo/foo.proto @@ -0,0 +1,7 @@ +syntax = "proto3"; + +package test4_generates_imports_for_multiple_proto_srcs.foo; + +message Foo { + bool bar = 1; +} \ No newline at end of file From af8ff347c1218e2aaef00fc4f138bbf5512de1b4 Mon Sep 17 00:00:00 2001 From: Charles Guo Date: Sun, 20 Jul 2025 19:59:50 -0400 Subject: [PATCH 8/9] Generate imports for each proto src, as we should, and update tests accordingly --- gazelle/python/generate.go | 7 +++++-- gazelle/python/resolve.go | 12 ++++++------ .../test1_generates_dependency/bar.py | 4 ++-- .../test2_generates_using_resolve/BUILD.in | 2 +- .../test2_generates_using_resolve/BUILD.out | 2 +- .../test2_generates_using_resolve/baz.py | 4 ++-- .../test3_uses_naming_convention/baz.py | 4 ++-- 7 files changed, 19 insertions(+), 16 deletions(-) diff --git a/gazelle/python/generate.go b/gazelle/python/generate.go index 54adc634cd..bf13ea3433 100644 --- a/gazelle/python/generate.go +++ b/gazelle/python/generate.go @@ -42,8 +42,8 @@ const ( pyTestEntrypointTargetname = "__test__" conftestFilename = "conftest.py" conftestTargetname = "conftest" - protoKey = "_proto_target" protoRelKey = "_proto_rel" + protoSrcsKey = "_proto_srcs" ) var ( @@ -575,6 +575,7 @@ func generateProtoLibraries(args language.GenerateArgs, cfg *pythonconfig.Config // First, enumerate all the proto_library in this package. var protoRuleNames []string protoRel := map[string]string{} + protoSrcs := map[string][]string{} for _, r := range args.OtherGen { if r.Kind() != "proto_library" { @@ -582,6 +583,7 @@ func generateProtoLibraries(args language.GenerateArgs, cfg *pythonconfig.Config } protoRuleNames = append(protoRuleNames, r.Name()) protoRel[r.Name()] = args.Rel + protoSrcs[r.Name()] = r.AttrStrings("srcs") } sort.Strings(protoRuleNames) @@ -614,8 +616,9 @@ func generateProtoLibraries(args language.GenerateArgs, cfg *pythonconfig.Config addVisibility(visibility). addResolvedDependency(":" + protoRuleName). generateImportsAttribute().build() - pyProtoLibrary.SetPrivateAttr(protoKey, protoRuleName) + pyProtoLibrary.SetPrivateAttr(protoRelKey, protoRel[protoRuleName]) + pyProtoLibrary.SetPrivateAttr(protoSrcsKey, protoSrcs[protoRuleName]) res.Gen = append(res.Gen, pyProtoLibrary) res.Imports = append(res.Imports, pyProtoLibrary.PrivateAttr(config.GazelleImportsKey)) diff --git a/gazelle/python/resolve.go b/gazelle/python/resolve.go index fede236a77..011b96779e 100644 --- a/gazelle/python/resolve.go +++ b/gazelle/python/resolve.go @@ -134,17 +134,17 @@ func importsProtoLibrary(cfg *pythonconfig.Config, r *rule.Rule) []resolve.Impor // Determine the root module and emit an import for that, // i.e. for //foo:foo_py_pb2, we'd get foo.foo_pb2 - protoRuleAttr := r.PrivateAttr(protoKey) protoRelAttr := r.PrivateAttr(protoRelKey) - if protoRuleAttr == nil || protoRelAttr == nil { + protoSrcsAttr := r.PrivateAttr(protoSrcsKey) + if protoRelAttr == nil || protoSrcsAttr == nil { return nil } - protoRule := protoRuleAttr.(string) - generatedPbFileName := strings.TrimSuffix(protoRule, "_proto") + "_pb2.py" protoRel := protoRelAttr.(string) - - specs = append(specs, importSpecFromSrc(cfg.PythonProjectRoot(), protoRel, generatedPbFileName)) + for _, protoSrc := range protoSrcsAttr.([]string) { + generatedPbFileName := strings.TrimSuffix(protoSrc, ".proto") + "_pb2.py" + specs = append(specs, importSpecFromSrc(cfg.PythonProjectRoot(), protoRel, generatedPbFileName)) + } return specs } diff --git a/gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/bar.py b/gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/bar.py index 265535ce3e..8c71ea7e95 100644 --- a/gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/bar.py +++ b/gazelle/python/testdata/resolves_proto_imports/test1_generates_dependency/bar.py @@ -1,3 +1,3 @@ -import test1_generates_dependency.foo.test1_generates_dependency_foo_pb2 +import test1_generates_dependency.foo.foo_pb2 -x = test1_generates_dependency_foo_pb2.Foo() \ No newline at end of file +x = foo_pb2.Foo() \ No newline at end of file diff --git a/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/BUILD.in b/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/BUILD.in index 5a471573e1..83b837de36 100644 --- a/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/BUILD.in +++ b/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/BUILD.in @@ -1 +1 @@ -# gazelle:resolve py test2_generates_using_resolve.foo.test2_generates_using_resolve_foo_pb2 //test2_generates_using_resolve/bar:bar_py_pb2 +# gazelle:resolve py test2_generates_using_resolve.bar.bar_pb2 //test2_generates_using_resolve/bar:bar_py_pb2 diff --git a/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/BUILD.out b/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/BUILD.out index a03238c137..f48079d243 100644 --- a/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/BUILD.out +++ b/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/BUILD.out @@ -1,6 +1,6 @@ load("@rules_python//python:defs.bzl", "py_library") -# gazelle:resolve py test2_generates_using_resolve.foo.test2_generates_using_resolve_foo_pb2 //test2_generates_using_resolve/bar:bar_py_pb2 +# gazelle:resolve py test2_generates_using_resolve.bar.bar_pb2 //test2_generates_using_resolve/bar:bar_py_pb2 py_library( name = "test2_generates_using_resolve", diff --git a/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/baz.py b/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/baz.py index e38e1072a8..b1b313af5b 100644 --- a/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/baz.py +++ b/gazelle/python/testdata/resolves_proto_imports/test2_generates_using_resolve/baz.py @@ -1,3 +1,3 @@ -import test2_generates_using_resolve.foo.test2_generates_using_resolve_foo_pb2 +import test2_generates_using_resolve.bar.bar_pb2 -x = test2_generates_using_resolve_foo_pb2.Bar() \ No newline at end of file +x = bar_pb2.Bar() \ No newline at end of file diff --git a/gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/baz.py b/gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/baz.py index 28596403a7..d6597cd37e 100644 --- a/gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/baz.py +++ b/gazelle/python/testdata/resolves_proto_imports/test3_uses_naming_convention/baz.py @@ -1,3 +1,3 @@ -import test3_uses_naming_convention.bar.test3_uses_naming_convention_bar_pb2 +import test3_uses_naming_convention.bar.bar_pb2 -x = test3_uses_naming_convention_bar_pb2.Bar() \ No newline at end of file +x = bar_pb2.Bar() \ No newline at end of file From a7c03c6dc27bb5163caff13b3d6663262d0bfbf0 Mon Sep 17 00:00:00 2001 From: Charles Guo Date: Sun, 20 Jul 2025 20:06:11 -0400 Subject: [PATCH 9/9] Remove some unused stuff --- gazelle/python/resolve.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/gazelle/python/resolve.go b/gazelle/python/resolve.go index 011b96779e..b6b03ffecb 100644 --- a/gazelle/python/resolve.go +++ b/gazelle/python/resolve.go @@ -317,9 +317,6 @@ func (py *Resolver) Resolve( // Check if the imported module is part of the standard library. if isStdModule(Module{Name: moduleName}) { continue MODULES_LOOP - } else if r.Kind() == pyProtoLibraryKind { - // For py_proto_library, fall back to guessing the label based on the proto_library rule name. - matches = py.resolveProtoFallback(cfg) } else if cfg.ValidateImportStatements() { err := fmt.Errorf( "%[1]q, line %[2]d: %[3]q is an invalid dependency: possible solutions:\n"+ @@ -410,11 +407,6 @@ func (py *Resolver) Resolve( } } -func (*Resolver) resolveProtoFallback(c *pythonconfig.Config) []resolve.FindResult { - // TODO - return []resolve.FindResult{} -} - // addResolvedDeps adds the pre-resolved dependencies from the rule's private attributes // to the provided deps set. func addResolvedDeps(