Skip to content

Commit c93e1f5

Browse files
authored
python: Provide python rules via CrossResolve. (#316)
This allows rules_python's gazelle plugin to find python rules generated by rules_proto allowing for a fully gazelle'ified experience working with protos with Python.
1 parent 9fffedb commit c93e1f5

File tree

4 files changed

+69
-1
lines changed

4 files changed

+69
-1
lines changed

pkg/plugin/grpc/grpc/BUILD.bazel

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ go_library(
1414

1515
go_test(
1616
name = "grpc_test",
17-
srcs = ["protoc-gen-grpc-python_test.go"],
17+
srcs = [
18+
"grpc_test.go",
19+
"protoc-gen-grpc-python_test.go",
20+
],
1821
data = [
1922
":protoc",
2023
":protoc-gen-grpc-python",

pkg/rule/rules_python/py_library.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,25 @@ func (s *PyLibrary) Rule(otherGen ...*rule.Rule) *rule.Rule {
121121
return newRule
122122
}
123123

124+
func pyFilenameToImport(s string) string {
125+
if strings.HasSuffix(s, ".py") {
126+
return strings.ReplaceAll(s[:len(s)-3], "/", ".")
127+
}
128+
return s
129+
}
130+
124131
// Imports implements part of the RuleProvider interface.
125132
func (s *PyLibrary) Imports(c *config.Config, r *rule.Rule, file *rule.File) []resolve.ImportSpec {
126133
if lib, ok := r.PrivateAttr(protoc.ProtoLibraryKey).(protoc.ProtoLibrary); ok {
127134
specs := protoc.ProtoLibraryImportSpecsForKind(r.Kind(), lib)
128135
specs = maybeStripImportPrefix(specs, lib.StripImportPrefix())
136+
from := label.New("", file.Pkg, r.Name())
137+
for _, o := range s.Outputs {
138+
pyImp := pyFilenameToImport(o)
139+
protoc.GlobalResolver().Provide("py", "py", pyImp, from)
140+
specs = append(specs, resolve.ImportSpec{Lang: "py", Imp: pyImp})
141+
}
142+
129143
return specs
130144
}
131145
return nil

pkg/rule/rules_python/py_library_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package rules_python
22

33
import (
4+
"fmt"
5+
"path"
46
"testing"
57

68
"github.com/bazelbuild/bazel-gazelle/resolve"
9+
"github.com/bazelbuild/bazel-gazelle/rule"
710
"github.com/google/go-cmp/cmp"
11+
"github.com/stackb/rules_proto/pkg/protoc"
812
)
913

1014
func TestMaybeStripImportPrefix(t *testing.T) {
@@ -49,3 +53,46 @@ func TestMaybeStripImportPrefix(t *testing.T) {
4953
})
5054
}
5155
}
56+
57+
func TestImports(t *testing.T) {
58+
kind := "mykind"
59+
suffix := "_suffix"
60+
pkg := "mypkg"
61+
protoName := "test"
62+
cases := []struct {
63+
Name string
64+
Outputs []string
65+
WantImports []resolve.ImportSpec
66+
}{{
67+
Name: "Empty",
68+
// If for some reason, no python files were output...
69+
Outputs: []string{},
70+
// Always include the output from the proto_library
71+
WantImports: []resolve.ImportSpec{{Lang: kind, Imp: fmt.Sprintf("%s/%s", pkg, protoName)}},
72+
}, {
73+
Name: "One output",
74+
Outputs: []string{path.Join(pkg, "test_pb2.py")},
75+
WantImports: []resolve.ImportSpec{
76+
{Lang: kind, Imp: fmt.Sprintf("%s/%s", pkg, protoName)},
77+
{Lang: "py", Imp: fmt.Sprintf("%s.%s_pb2", pkg, protoName)},
78+
},
79+
}}
80+
81+
for _, c := range cases {
82+
t.Run(c.Name, func(t *testing.T) {
83+
py := &PyLibrary{
84+
KindName: kind,
85+
RuleNameSuffix: suffix,
86+
Outputs: c.Outputs,
87+
Resolver: protoc.ResolveDepsAttr("deps", true),
88+
}
89+
protoLib := protoc.NewOtherProtoLibrary(&rule.File{}, rule.NewRule("proto_library", protoName+"_proto"), protoc.NewFile(pkg, protoName))
90+
r := rule.NewRule(kind, "test"+suffix)
91+
r.SetPrivateAttr(protoc.ProtoLibraryKey, protoLib)
92+
imps := py.Imports(nil, r, &rule.File{Pkg: pkg})
93+
if diff := cmp.Diff(imps, c.WantImports); diff != "" {
94+
t.Fatalf("import mismatch: (-got, +want): %s", diff)
95+
}
96+
})
97+
}
98+
}

rules/private/proto_repository_tools_srcs.bzl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ PROTO_REPOSITORY_TOOLS_SRCS = [
6666
"@build_stack_rules_proto//pkg/language/protobuf:resolve.go",
6767
"@build_stack_rules_proto//pkg/plugin/akka/akka_grpc:BUILD.bazel",
6868
"@build_stack_rules_proto//pkg/plugin/akka/akka_grpc:protoc_gen_akka_grpc.go",
69+
"@build_stack_rules_proto//pkg/plugin/bufbuild:BUILD.bazel",
70+
"@build_stack_rules_proto//pkg/plugin/bufbuild:connect_es_plugin.go",
71+
"@build_stack_rules_proto//pkg/plugin/bufbuild:es_plugin.go",
6972
"@build_stack_rules_proto//pkg/plugin/builtin:BUILD.bazel",
7073
"@build_stack_rules_proto//pkg/plugin/builtin:cpp_plugin.go",
7174
"@build_stack_rules_proto//pkg/plugin/builtin:csharp_plugin.go",
@@ -165,6 +168,7 @@ PROTO_REPOSITORY_TOOLS_SRCS = [
165168
"@build_stack_rules_proto//pkg/rule/rules_scala:scala_proto_library.go",
166169
"@build_stack_rules_proto//plugin:BUILD.bazel",
167170
"@build_stack_rules_proto//plugin/akka/akka-grpc:BUILD.bazel",
171+
"@build_stack_rules_proto//plugin/bufbuild:BUILD.bazel",
168172
"@build_stack_rules_proto//plugin/builtin:BUILD.bazel",
169173
"@build_stack_rules_proto//plugin/gogo/protobuf:BUILD.bazel",
170174
"@build_stack_rules_proto//plugin/golang/protobuf:BUILD.bazel",

0 commit comments

Comments
 (0)