[gRPC] Enable Python 3 for Bazel to Run Tests#17644
Conversation
|
@gnossen @ericgribkoff PTAL. The behavior is similar to our internal tool, except the Python 3 version is no longer pinned, but depend on which version your machine's |
gnossen
left a comment
There was a problem hiding this comment.
Awesome stuff, @lidizheng !
| # always fail. | ||
| def _assert_sequence_of_proto_equal(self, x, y): | ||
| self.assertSequenceEqual( | ||
| list(map(lambda x: x.SerializeToString(), x)), |
There was a problem hiding this comment.
Do you think we should file a bug against the python protobuf compiler for this?
There was a problem hiding this comment.
I attempt several times to make a minimum reproducible example without gRPC package involved, but no luck yet.
There was a problem hiding this comment.
This test appears to pass for me locally, without this change. Is bazel+python3 run as part of our CI with this PR?
There was a problem hiding this comment.
It disappears after I do bazel clean --expunge. I have reverted this hack.
It maybe introduced by mixing the artifacts of Python 2 and Python 3 on my local machine... Further more, since I added force_python=PY3, the generated artifacts in latest version of this PR will not be mixed but separated in different folders. I presume it might not happen again...
There was a problem hiding this comment.
Also, I enabled Python 3 Bazel test for future PRs.
There was a problem hiding this comment.
From discussion offline this override here is still necessary. Please file an issue and change the NOTE(lidiz) to TODO(issue link). If I remember correctly we can't reproduce without gRPC involved, so the issue should just go on our repo for now.
* Reverted hack in _reflection_servicer_test.py * To see if Kokoro is happy about it
|
Blocking Bazel Issues:
They are all pointing to the Python namespace package handling of Bazel Python rules. There are several hacks, but haven't found one that can fix ours. |
ericgribkoff
left a comment
There was a problem hiding this comment.
@lidizheng If I understand correctly, there are two blockers here: (aside: one of the four blocking bazel issues you linked to is marked closed. Are all of those actually blocking, or just related?)
-
The equality failure in
_reflection_servier_test.py. I believe when we discussed this offline that you thought the error may be to due to bazel making a change in the namespace of one of the proto libraries, so that the equality check in the test failed - but I don't see this detail here, and AFAIK there's not already a tracking bug for this. This shouldn't block merging of this PR, so if there's not a known issue that maps 1:1 with the failure here, please create a tracking issue on our repo (since we can't repro without gRPC yet, so the fault may be ours), link to it with a TODO on_assert_sequence_of_proto_equal, and self-assign it before merging this PR. -
The import ordering errors still showing on Kokoro, which is tracked by the issue you filed earlier, bazelbuild/bazel#6844. If that is the problem here, please ping the issue on the bazel repo and say this is blocking our use of Bazel with Python 3 on Kokoro.... however, that issue wasn't specific to Python 3, so is that really the same thing that's happening here?
I'm approving the PR (as everything looks good) but let's hold off on merging this until there's a solution for (2) that gets the tests passing on Python 3. Disabling the failing tests for bazel + Python 3 (with an appropriate issue on our repo linked to in a TODO) qualifies as an acceptable solution for now as well.
|
@ericgribkoff Thanks for reviewing, I agree we should solve the blockers before merging. I hope the bug can be solved, and it can be a competent replacement for The "closed" issue Bazel breaks python import with init.py doesn't introduce a solid solution to the override of About the failure in About the import ordering, I presume the bazelbuild/bazel#6844 and this issue share the same root cause. The |
jtattermusch
left a comment
There was a problem hiding this comment.
LGTM after tests pass.
|
Known failure #17729 |
|
@ericgribkoff @gnossen PTAL. Here is the brief of the root cause: The Bazel Python rules will create symbolic links of packages and add them to # Content of "protobuf-3.6.1-py2.7-nspkg.pth"
import sys, types, os;has_mfs = sys.version_info > (3, 5);p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('google',));importlib = has_mfs and __import__('importlib.util');has_mfs and __import__('importlib.machinery');m = has_mfs and sys.modules.setdefault('google', importlib.util.module_from_spec(importlib.machinery.PathFinder.find_spec('google', [os.path.dirname(p)])));m = m or sys.modules.setdefault('google', types.ModuleType('google'));mp = (m or []) and m.__dict__.setdefault('__path__',[]);(p not in mp) and mp.append(p)The So, my workaround for this is explicitly call a def bazel_patch():
"""Add valid sys.path item to site directory to parse the .pth files."""
for item in sys.path:
if os.path.exists(item):
site.addsitedir(item) |
| if python_bin != None: | ||
| return python_bin | ||
| python_bin_path = repository_ctx.which("python") | ||
| python_bin = repository_ctx.os.environ.get(_PYTHON_BIN_PATH, 'python') |
There was a problem hiding this comment.
Why is this changing the semantics of the PYTHON_BIN_PATH environment variable?
There was a problem hiding this comment.
This library is forked from TensorFlow's repo. The main purpose of this package is locating the CPython header files to help Cython compile. In its original logic, to use Python 3, we need to set PYTHON_BIN_PATH to a absolute path like /usr/bin/python3 or /usr/local/bin/python3. It's not very adaptive across environments. So, in the new logic, even if the PYTHON_BIN_PATH is not given an absolute path, it can try to find the correct path using which.
Also, it doesn't break backward compatibility, developers who used this flag should observe no behavior change, because which command will return the exact same path as input if the input is an absolute path.
There was a problem hiding this comment.
which does not allow slashes, so providing an absolute (or relative, for that matter) path causes this script to fail. At master, the following command works:
PYTHON_BIN_PATH='/usr/bin/python' bazel test --test_output=errors //src/python/grpcio_tests/tests/...
On this PR, it fails with an error.
File ".../grpc/third_party/py/python_configure.bzl", line 142, in _get_python_bin
repository_ctx.which(python_bin)
Program argument of which() may not contains a / or a \ ('/usr/bin/python' given) and referenced by '//src/python/grpcio/grpc/_cython:cygrpc.so'
Can you clarify why you are even changing this code? I don't see the burden of requiring an absolute path here (which does indeed seem to be the existing behavior, although it's not documented as such anywhere I could find).
There was a problem hiding this comment.
I see that this is used by the build:python3 --action_env=PYTHON_BIN_PATH=python3 addition in tools/bazel.rc. If the error reported above is indeed valid, I would suggest instead adding a new environment variable (PYTHON_BIN_NAME, or something similar, which defaults to python) that can be set in bazel.rc to python3, and pass this value to the existing which query.
| srcs = ["bazel_patch.py"], | ||
| visibility = ["//visibility:public"], | ||
| data=[ | ||
| "//src/python/grpcio_tests/tests/unit/credentials", |
There was a problem hiding this comment.
This doesn't seem needed
| if python_bin != None: | ||
| return python_bin | ||
| python_bin_path = repository_ctx.which("python") | ||
| python_bin = repository_ctx.os.environ.get(_PYTHON_BIN_PATH, 'python') |
There was a problem hiding this comment.
I see that this is used by the build:python3 --action_env=PYTHON_BIN_PATH=python3 addition in tools/bazel.rc. If the error reported above is indeed valid, I would suggest instead adding a new environment variable (PYTHON_BIN_NAME, or something similar, which defaults to python) that can be set in bazel.rc to python3, and pass this value to the existing which query.
| @@ -0,0 +1,8 @@ | |||
| py_library( | |||
| name = "bazel_patch", | |||
There was a problem hiding this comment.
This needs a scarier-sounding name, something like bazel_namespace_package_hack
| # Python process to parse the .pth file in the sys.path to resolve namespace | ||
| # package in the right place. | ||
| # Analysis in depth: https://github.com/bazelbuild/rules_python/issues/55 | ||
| def bazel_patch(): |
There was a problem hiding this comment.
This should also sound scarier than patch, e.g., sys_path_to_site_dir_hack or similar
| py_library( | ||
| name = "bazel_patch", | ||
| srcs = ["bazel_patch.py"], | ||
| visibility = ["//visibility:public"], |
There was a problem hiding this comment.
Please keep this visibility restricted to a whitelist of specific tests that need it.
| # always fail. | ||
| def _assert_sequence_of_proto_equal(self, x, y): | ||
| self.assertSequenceEqual( | ||
| list(map(lambda x: x.SerializeToString(), x)), |
There was a problem hiding this comment.
From discussion offline this override here is still necessary. Please file an issue and change the NOTE(lidiz) to TODO(issue link). If I remember correctly we can't reproduce without gRPC involved, so the issue should just go on our repo for now.
|
@ericgribkoff PTAL. All of your comments are resolved, and the new issue is filed at #17844. |
|
Be more careful when checking test results on a PR next time. This PR introduces a breakage and it could have been prevented if test results were checked carefully (#17850 filed). |
Revert "Merge pull request #17644 from lidizheng/bzl-py3"
This reverts commit 7da0aac.
Related: #17622
With this PR, gRPC developers should be able to use
--config=python3to switch the Bazel Python interpreter to Python 3.