Skip to content

[bazel] Auto-generate .pyi files in py_proto_library rule#32872

Merged
gnossen merged 4 commits intogrpc:masterfrom
ferstlf:generate-pyi
Jun 12, 2023
Merged

[bazel] Auto-generate .pyi files in py_proto_library rule#32872
gnossen merged 4 commits intogrpc:masterfrom
ferstlf:generate-pyi

Conversation

@ferstlf
Copy link
Contributor

@ferstlf ferstlf commented Apr 14, 2023

With some delay, this is a PR for #32564 (and previously #31791).

I looked into adding a regular py_test for this change as suggested but I am not aware of any effect that the presence of a .pyi stub file would have at runtime and where some sort of type-checking in a .py script would be affected. Stub files are only for use by type checkers & IDE's. I mean, something like this would work:

import helloworld_pb2
py_file = helloworld_pb2.__file__ 
pyi_file = py_file + 'i’
self.assertTrue(os.path.exists(pyi_file))

But that seems really hacky to me. Instead I created a simple rule test for py_proto_library with Bazel Skylib which tests the declared outputs for an example py_proto_library target. Indirectly, this also tests that the declared output files are actually generated. Please let me know if this is sufficient.

@linux-foundation-easycla
Copy link

linux-foundation-easycla bot commented Apr 14, 2023

CLA Signed

The committers listed above are authorized under a signed CLA.

@ferstlf ferstlf marked this pull request as ready for review April 14, 2023 08:38
@ferstlf
Copy link
Contributor Author

ferstlf commented Apr 25, 2023

Friendly bump!

@ferstlf ferstlf changed the title Auto-generate .pyi files in py_proto_library rule [bazel] Auto-generate .pyi files in py_proto_library rule May 2, 2023
@gnossen gnossen self-assigned this May 3, 2023
@XuanWang-Amos XuanWang-Amos added release notes: no Indicates if PR should not be in release notes kokoro:run labels May 11, 2023
@gnossen
Copy link
Contributor

gnossen commented Jun 6, 2023

Unfortunately, it looks like adding a dependency on Bazel Skylib introduces a thorny issue:

(venv) rbellevi@rbellevi:~/dev/grpc/test/distrib/bazel/python$ tools/bazel test -c dbg //:py_proto_library_provider_contents_test
INFO: Running bazel wrapper (see //tools/bazel for details), bazel version 6.1.2 will be used instead of system-wide bazel installation.
ERROR: /usr/local/google/home/rbellevi/.cache/bazel/_bazel_rbellevi/6b245ae2ccca35fac920f4dfd855cf78/external/bazel_tools/platforms/BUILD:89:6: in alias rule @bazel_tools//platforms:windows: Constraints from @bazel_tools//platforms have been removed. Please use constraints from @platforms repository embedded in Bazel, or preferably declare dependency on https://github.com/bazelbuild/platforms. See https://github.com/bazelbuild/bazel/issues/8622 for details.
ERROR: /usr/local/google/home/rbellevi/.cache/bazel/_bazel_rbellevi/6b245ae2ccca35fac920f4dfd855cf78/external/bazel_tools/platforms/BUILD:89:6: Analysis of target '@bazel_tools//platforms:windows' failed
ERROR: /usr/local/google/home/rbellevi/dev/grpc/test/distrib/bazel/python/BUILD:160:24: While resolving toolchains for target //:py_proto_library_provider_contents_test: invalid registered toolchain '@bazel_skylib//toolchains/unittest:cmd_toolchain': 
ERROR: Analysis of target '//:py_proto_library_provider_contents_test' failed; build aborted: 
INFO: Elapsed time: 0.355s
INFO: 0 processes.
FAILED: Build did NOT complete successfully (0 packages loaded, 2 targets configured)
ERROR: Couldn't start the build. Unable to run tests

This only happens on Bazel 6+, but we need to run these tests against all supported Bazel versions, including 6+. We don't use platform constraints ourself, but several of our dependencies do:

(venv) rbellevi@rbellevi:~/dev/grpc$ grep -rn "bazel_tools//platforms"
third_party/bloaty/third_party/protobuf/third_party/googletest/BUILD.bazel:41:    constraint_values = ["@bazel_tools//platforms:windows"],
third_party/bloaty/third_party/googletest/BUILD.bazel:41:    constraint_values = ["@bazel_tools//platforms:windows"],
third_party/bloaty/third_party/abseil-cpp/absl/BUILD.bazel:47:        "@bazel_tools//platforms:osx",
third_party/bloaty/third_party/abseil-cpp/absl/BUILD.bazel:54:        "@bazel_tools//platforms:ios",
third_party/bloaty/third_party/abseil-cpp/absl/time/internal/cctz/BUILD.bazel:29:        "@bazel_tools//platforms:osx",
third_party/bloaty/third_party/abseil-cpp/absl/time/internal/cctz/BUILD.bazel:36:        "@bazel_tools//platforms:ios",

So fixing that issue would become a big yak shaving exercise.

Instead of using Bazel Skylib, could we do something more end-to-end? How are these .pyi files going to be consumed by you under Bazel builds? Presumably you also have a type checker like pytype or mypy integrated with your Bazel build? Could we just have a smoke check that a simple proto passes type check with this change?

@ferstlf
Copy link
Contributor Author

ferstlf commented Jun 7, 2023

Thanks for the reply, I can reproduce this problem. I was using Bazel 5.4.0 when creating this PR.

Currently we don't consume the .pyi files with Bazel (or a type checker integrated with Bazel) but with Pylance/VS Code to get import resolution and auto-completion. There is a bit more to our setup, but in a nut-shell we add Bazel's output paths such as bazel-bin/external/com_github_grpc_grpc/src/python/grpcio to the analysis paths for Pylance and then, of course, Pylance understands seeing foo.py next to foo.pyi.

I haven't worked with type checkers in Bazel but I could give it a shot. But before I do: would it be an option to simply update to a newer version of Skylib? It seems like Skylib migrated their use of platform constraints in this commit. All we'd need is Skylib version 1.0.3 instead of 1.0.2 in grpc_deps(). I tentatively updated this PR with the newer skylib version - just so you can try it out (if bumping the version is in fact an option). Tested successfully with Bazel 5.4.0 and 6.1.2.

@gnossen
Copy link
Contributor

gnossen commented Jun 7, 2023

would it be an option to simply update to a newer version of Skylib

Sure! As long as it works with all of our versions of Bazel. I just triggered CI so we can find out.

@ferstlf
Copy link
Contributor Author

ferstlf commented Jun 12, 2023

AFAICT the newer Skylib version seems to have solved the issue?!

@gnossen gnossen merged commit fa32eb3 into grpc:master Jun 12, 2023
@copybara-service copybara-service bot added the imported Specifies if the PR has been imported to the internal repository label Jun 12, 2023
mario-vimal pushed a commit to mario-vimal/grpc that referenced this pull request Jun 15, 2023
With some delay, this is a PR for
grpc#32564 (and previously
grpc#31791).

I looked into adding a regular `py_test` for this change [as
suggested](grpc#31791 (comment))
but I am not aware of any effect that the presence of a .pyi stub file
would have at runtime and where some sort of type-checking in a .py
script would be affected. Stub files are only for use by type checkers &
IDE's. I mean, something like this would work:

```
import helloworld_pb2
py_file = helloworld_pb2.__file__ 
pyi_file = py_file + 'i’
self.assertTrue(os.path.exists(pyi_file))
```

But that seems really hacky to me. Instead I created a simple rule test
for `py_proto_library` with Bazel Skylib which tests the declared
outputs for an example `py_proto_library` target. Indirectly, this also
tests that the declared output files are actually generated. Please let
me know if this is sufficient.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bloat/none imported Specifies if the PR has been imported to the internal repository lang/Python per-call-memory/neutral per-channel-memory/neutral release notes: no Indicates if PR should not be in release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants