Skip to content

Commit e3e56c7

Browse files
dwscopybara-github
authored andcommitted
Generate .pyi files in py_proto_library (#10366) (#21567)
We here adjust py_proto_library to produce `.pyi` files along with the `.py` files it already generates. This achieves the same effect as the gRPC py_proto_library. Per reviewer feedback, we here propagate the paths to the `.pyi` files via the `direct_pyi_files` and `transitive_pyi_files` members of `PyInfo` which are available starting in `rules_python` 1.1.0. Since this means that the files are not automatically in the runfiles of the `py_proto_library`, tooling to run mypy will need to be adjusted to add what is needed from these provider fields to the runfiles if that is what is wanted. Closes #10366. Closes #21567 COPYBARA_INTEGRATE_REVIEW=#21567 from dws:py_proto_library-pyi 37fbdc0 PiperOrigin-RevId: 778116905
1 parent ae0129f commit e3e56c7

File tree

1 file changed

+40
-1
lines changed

1 file changed

+40
-1
lines changed

bazel/py_proto_library.bzl

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ _PyProtoInfo = provider(
1717
(depset[File]) Files from the transitive closure implicit proto
1818
dependencies""",
1919
"transitive_sources": """(depset[File]) The Python sources.""",
20+
"direct_pyi_files": """
21+
(depset[File]) Type definition files (usually `.pyi` files)
22+
for the Python modules provided by this target.""",
23+
"transitive_pyi_files": """
24+
(depset[File]) The transitive set of type definition files
25+
(usually `.pyi` files) for the Python modules for this target
26+
and its transitive dependencies.""",
2027
},
2128
)
2229

@@ -61,6 +68,7 @@ def _py_proto_aspect_impl(target, ctx):
6168
api_deps = [proto_lang_toolchain_info.runtime]
6269

6370
generated_sources = []
71+
generated_stubs = []
6472
proto_info = target[ProtoInfo]
6573
proto_root = proto_info.proto_source_root
6674
if proto_info.direct_sources:
@@ -72,6 +80,14 @@ def _py_proto_aspect_impl(target, ctx):
7280
name_mapper = lambda name: name.replace("-", "_").replace(".", "/"),
7381
)
7482

83+
# Generate pyi files
84+
generated_stubs = proto_common.declare_generated_files(
85+
actions = ctx.actions,
86+
proto_info = proto_info,
87+
extension = "_pb2.pyi",
88+
name_mapper = lambda name: name.replace("-", "_").replace(".", "/"),
89+
)
90+
7591
# Handles multiple repository and virtual import cases
7692
if proto_root.startswith(ctx.bin_dir.path):
7793
proto_root = proto_root[len(ctx.bin_dir.path) + 1:]
@@ -84,12 +100,17 @@ def _py_proto_aspect_impl(target, ctx):
84100
else:
85101
proto_root = ctx.workspace_name + "/" + proto_root
86102

103+
additional_args = ctx.actions.args()
104+
if generated_stubs:
105+
additional_args.add(plugin_output, format = "--pyi_out=%s")
106+
87107
proto_common.compile(
88108
actions = ctx.actions,
89109
proto_info = proto_info,
90110
proto_lang_toolchain_info = proto_lang_toolchain_info,
91-
generated_files = generated_sources,
111+
generated_files = generated_sources + generated_stubs,
92112
plugin_output = plugin_output,
113+
additional_args = additional_args,
93114
)
94115

95116
# Generated sources == Python sources
@@ -104,6 +125,13 @@ def _py_proto_aspect_impl(target, ctx):
104125
direct = python_sources,
105126
transitive = [dep.transitive_sources for dep in deps],
106127
)
128+
direct_pyi_files = depset(
129+
direct = generated_stubs,
130+
)
131+
transitive_pyi_files = depset(
132+
direct = generated_stubs,
133+
transitive = [dep.transitive_pyi_files for dep in deps],
134+
)
107135

108136
return [
109137
_PyProtoInfo(
@@ -119,6 +147,8 @@ def _py_proto_aspect_impl(target, ctx):
119147
),
120148
runfiles_from_proto_deps = runfiles_from_proto_deps,
121149
transitive_sources = transitive_sources,
150+
direct_pyi_files = direct_pyi_files,
151+
transitive_pyi_files = transitive_pyi_files,
122152
),
123153
]
124154

@@ -150,6 +180,13 @@ def _py_proto_library_rule(ctx):
150180
default_outputs = depset(
151181
transitive = [info.transitive_sources for info in pyproto_infos],
152182
)
183+
direct_pyi_files = []
184+
for info in pyproto_infos:
185+
direct_pyi_files.extend(info.direct_pyi_files.to_list())
186+
transitive_pyi_files = depset(
187+
direct = direct_pyi_files,
188+
transitive = [info.transitive_pyi_files for info in pyproto_infos],
189+
)
153190

154191
return [
155192
DefaultInfo(
@@ -166,6 +203,8 @@ def _py_proto_library_rule(ctx):
166203
PyInfo(
167204
transitive_sources = default_outputs,
168205
imports = depset(transitive = [info.imports for info in pyproto_infos]),
206+
direct_pyi_files = depset(direct = direct_pyi_files),
207+
transitive_pyi_files = transitive_pyi_files,
169208
# Proto always produces 2- and 3- compatible source files
170209
has_py2_only_sources = False,
171210
has_py3_only_sources = False,

0 commit comments

Comments
 (0)