Implement dual testing

pull/20097/head
Richard Belleville 6 years ago
parent 4e317f0b34
commit 426450cd82
  1. 2
      BUILD
  2. 9
      bazel/grpc_python_deps.bzl
  3. 26
      bazel/python_rules.bzl
  4. 4
      src/python/grpcio_tests/tests/unit/BUILD.bazel
  5. 49
      third_party/py/BUILD.tpl
  6. 92
      third_party/py/python_configure.bzl
  7. 10
      third_party/py/remote.BUILD.tpl
  8. 26
      third_party/py/variety.tpl
  9. 4
      tools/bazel.rc

@ -65,7 +65,7 @@ config_setting(
config_setting(
name = "python3",
values = {"python_path": "python3"},
flag_values = {"@bazel_tools//tools/python:python_version": "PY3"},
)
config_setting(

@ -47,6 +47,15 @@ def grpc_python_deps():
remote = "https://github.com/bazelbuild/rules_python.git",
)
if "rules_python" not in native.existing_rules():
http_archive(
name = "rules_python",
url = "https://github.com/bazelbuild/rules_python/archive/9d68f24659e8ce8b736590ba1e4418af06ec2552.zip",
sha256 = "f7402f11691d657161f871e11968a984e5b48b023321935f5a55d7e56cf4758a",
strip_prefix = "rules_python-9d68f24659e8ce8b736590ba1e4418af06ec2552",
)
python_configure(name = "local_config_python")
native.bind(

@ -178,3 +178,29 @@ def py_grpc_library(
deps = [Label("//src/python/grpcio/grpc:grpcio")] + deps,
**kwargs
)
def py2and3_test(name,
py_test = native.py_test,
**kwargs):
if "python_version" in kwargs:
fail("Cannot specify 'python_version' in py2and3_test.")
names = [name + suffix for suffix in (".python2", ".python3")]
python_versions = ["PY2", "PY3"]
for case_name, python_version in zip(names, python_versions):
py_test(
name = case_name,
python_version = python_version,
**kwargs
)
suite_kwargs = {}
if "visibility" in kwargs:
suite_kwargs["visibility"] = kwargs["visibility"]
native.test_suite(
name = name,
tests = names,
**suite_kwargs
)

@ -1,3 +1,5 @@
load("//bazel:python_rules.bzl", "py2and3_test")
package(default_visibility = ["//visibility:public"])
GRPCIO_TESTS_UNIT = [
@ -80,7 +82,7 @@ py_library(
)
[
py_test(
py2and3_test(
name=test_file_name[:-3],
size="small",
srcs=[test_file_name],

@ -2,35 +2,36 @@
package(default_visibility=["//visibility:public"])
# To build Python C/C++ extension on Windows, we need to link to python import library pythonXY.lib
# See https://docs.python.org/3/extending/windows.html
cc_import(
name="python_lib",
interface_library=select({
":windows": ":python_import_lib",
# A placeholder for Unix platforms which makes --no_build happy.
"//conditions:default": "not-existing.lib",
}),
system_provided=1,
)
cc_library(
name="python_headers",
hdrs=[":python_include"],
deps=select({
":windows": [":python_lib"],
"//conditions:default": [],
}),
includes=["python_include"],
)
config_setting(
name="windows",
values={"cpu": "x64_windows"},
visibility=["//visibility:public"],
)
%{PYTHON_INCLUDE_GENRULE}
%{PYTHON_IMPORT_LIB_GENRULE}
config_setting(
name="python2",
flag_values = {"@rules_python//python:python_version": "PY2"}
)
config_setting(
name="python3",
flag_values = {"@rules_python//python:python_version": "PY3"}
)
cc_library(
name = "python_lib",
deps = select({
":python2": ["//_python2:_python2_lib"],
":python3": ["//_python3:_python3_lib"],
"//conditions:default": ["not-existing.lib"],
})
)
cc_library(
name = "python_headers",
deps = select({
":python2": ["//_python2:_python2_headers"],
":python3": ["//_python3:_python3_headers"],
"//conditions:default": ["not-existing.headers"],
})
)

@ -3,14 +3,15 @@
`python_configure` depends on the following environment variables:
* `PYTHON_BIN_PATH`: location of python binary.
* `PYTHON_LIB_PATH`: Location of python libraries.
* `PYTHON2_BIN_PATH`: location of python binary.
* `PYTHON2_LIB_PATH`: Location of python libraries.
"""
_BAZEL_SH = "BAZEL_SH"
_PYTHON_BIN_PATH = "PYTHON_BIN_PATH"
_PYTHON_LIB_PATH = "PYTHON_LIB_PATH"
_PYTHON_CONFIG_REPO = "PYTHON_CONFIG_REPO"
_PYTHON2_BIN_PATH = "PYTHON2_BIN_PATH"
_PYTHON2_LIB_PATH = "PYTHON2_LIB_PATH"
_PYTHON3_BIN_PATH = "PYTHON3_BIN_PATH"
_PYTHON3_LIB_PATH = "PYTHON3_LIB_PATH"
def _tpl(repository_ctx, tpl, substitutions={}, out=None):
@ -136,9 +137,9 @@ def _symlink_genrule_for_dir(repository_ctx,
"\n".join(outs))
def _get_python_bin(repository_ctx):
def _get_python_bin(repository_ctx, bin_path_key, default_bin_path):
"""Gets the python bin path."""
python_bin = repository_ctx.os.environ.get(_PYTHON_BIN_PATH, 'python')
python_bin = repository_ctx.os.environ.get(bin_path_key, default_bin_path)
if not repository_ctx.path(python_bin).exists:
# It's a command, use 'which' to find its path.
python_bin_path = repository_ctx.which(python_bin)
@ -150,7 +151,7 @@ def _get_python_bin(repository_ctx):
_fail("Cannot find python in PATH, please make sure " +
"python is installed and add its directory in PATH, or --define " +
"%s='/something/else'.\nPATH=%s" %
(_PYTHON_BIN_PATH, repository_ctx.os.environ.get("PATH", "")))
(bin_path_key, repository_ctx.os.environ.get("PATH", "")))
def _get_bash_bin(repository_ctx):
@ -170,9 +171,9 @@ def _get_bash_bin(repository_ctx):
(_BAZEL_SH, repository_ctx.os.environ.get("PATH", "")))
def _get_python_lib(repository_ctx, python_bin):
def _get_python_lib(repository_ctx, python_bin, lib_path_key):
"""Gets the python lib path."""
python_lib = repository_ctx.os.environ.get(_PYTHON_LIB_PATH)
python_lib = repository_ctx.os.environ.get(lib_path_key)
if python_lib != None:
return python_lib
print_lib = (
@ -202,13 +203,13 @@ def _check_python_lib(repository_ctx, python_lib):
_fail("Invalid python library path: %s" % python_lib)
def _check_python_bin(repository_ctx, python_bin):
def _check_python_bin(repository_ctx, python_bin, bin_path_key):
"""Checks the python bin path."""
cmd = '[[ -x "%s" ]] && [[ ! -d "%s" ]]' % (python_bin, python_bin)
result = repository_ctx.execute([_get_bash_bin(repository_ctx), "-c", cmd])
if result.return_code == 1:
_fail("--define %s='%s' is not executable. Is it the python binary?" %
(_PYTHON_BIN_PATH, python_bin))
(bin_path_key, python_bin))
def _get_python_include(repository_ctx, python_bin):
@ -222,11 +223,11 @@ def _get_python_include(repository_ctx, python_bin):
error_msg="Problem getting python include path.",
error_details=(
"Is the Python binary path set up right? " + "(See ./configure or "
+ _PYTHON_BIN_PATH + ".) " + "Is distutils installed?"))
+ _PYTHON2_BIN_PATH + ".) " + "Is distutils installed?"))
return result.stdout.splitlines()[0]
def _get_python_import_lib_name(repository_ctx, python_bin):
def _get_python_import_lib_name(repository_ctx, python_bin, bin_path_key):
"""Get Python import library name (pythonXY.lib) on Windows."""
result = _execute(
repository_ctx, [
@ -236,66 +237,77 @@ def _get_python_import_lib_name(repository_ctx, python_bin):
],
error_msg="Problem getting python import library.",
error_details=("Is the Python binary path set up right? " +
"(See ./configure or " + _PYTHON_BIN_PATH + ".) "))
"(See ./configure or " + bin_path_key + ".) "))
return result.stdout.splitlines()[0]
def _create_local_python_repository(repository_ctx):
# TODO(rbellevi): Rename.
def _create_local_python_repository(repository_ctx,
variety_name,
bin_path_key,
default_bin_path,
lib_path_key):
"""Creates the repository containing files set up to build with Python."""
python_bin = _get_python_bin(repository_ctx)
_check_python_bin(repository_ctx, python_bin)
python_lib = _get_python_lib(repository_ctx, python_bin)
python_bin = _get_python_bin(repository_ctx, bin_path_key, default_bin_path)
_check_python_bin(repository_ctx, python_bin, bin_path_key)
python_lib = _get_python_lib(repository_ctx, python_bin, lib_path_key)
_check_python_lib(repository_ctx, python_lib)
python_include = _get_python_include(repository_ctx, python_bin)
python_include_rule = _symlink_genrule_for_dir(
repository_ctx, python_include, 'python_include', 'python_include')
repository_ctx, python_include, '{}_include'.format(variety_name),
'{}_include'.format(variety_name))
python_import_lib_genrule = ""
# To build Python C/C++ extension on Windows, we need to link to python import library pythonXY.lib
# See https://docs.python.org/3/extending/windows.html
if _is_windows(repository_ctx):
python_include = _normalize_path(python_include)
python_import_lib_name = _get_python_import_lib_name(
python_import_lib_name = _get_python_import_lib_name, bin_path_key(
repository_ctx, python_bin)
python_import_lib_src = python_include.rsplit(
'/', 1)[0] + "/libs/" + python_import_lib_name
python_import_lib_genrule = _symlink_genrule_for_dir(
repository_ctx, None, '', 'python_import_lib',
repository_ctx, None, '', '{}_import_lib'.format(variety_name),
[python_import_lib_src], [python_import_lib_name])
_tpl(
repository_ctx, "BUILD", {
repository_ctx, "variety", {
"%{PYTHON_INCLUDE_GENRULE}": python_include_rule,
"%{PYTHON_IMPORT_LIB_GENRULE}": python_import_lib_genrule,
})
def _create_remote_python_repository(repository_ctx, remote_config_repo):
"""Creates pointers to a remotely configured repo set up to build with Python.
"""
_tpl(repository_ctx, "remote.BUILD", {
"%{REMOTE_PYTHON_REPO}": remote_config_repo,
}, "BUILD")
"%{VARIETY_NAME}": variety_name,
},
out="{}/BUILD".format(variety_name))
# TODO(rbellevi): Remove
def _python_autoconf_impl(repository_ctx):
"""Implementation of the python_autoconf repository rule."""
if _PYTHON_CONFIG_REPO in repository_ctx.os.environ:
_create_remote_python_repository(
repository_ctx, repository_ctx.os.environ[_PYTHON_CONFIG_REPO])
else:
_create_local_python_repository(repository_ctx)
_create_local_python_repository(repository_ctx,
"_python2",
_PYTHON2_BIN_PATH,
"python",
_PYTHON2_LIB_PATH)
_create_local_python_repository(repository_ctx,
"_python3",
_PYTHON3_BIN_PATH,
"python3",
_PYTHON3_LIB_PATH)
_tpl(repository_ctx, "BUILD")
python_configure = repository_rule(
implementation=_python_autoconf_impl,
environ=[
_BAZEL_SH,
_PYTHON_BIN_PATH,
_PYTHON_LIB_PATH,
_PYTHON_CONFIG_REPO,
_PYTHON2_BIN_PATH,
_PYTHON2_LIB_PATH,
_PYTHON3_BIN_PATH,
_PYTHON3_LIB_PATH,
],
)
"""Detects and configures the local Python.
It is expected that the system have both a working Python 2 and python 3
installation
Add the following to your WORKSPACE FILE:
```python

@ -1,10 +0,0 @@
# Adapted with modifications from tensorflow/third_party/py/
package(default_visibility=["//visibility:public"])
alias(
name="python_headers",
actual="%{REMOTE_PYTHON_REPO}:python_headers",
)

@ -0,0 +1,26 @@
package(default_visibility=["//visibility:public"])
# To build Python C/C++ extension on Windows, we need to link to python import library pythonXY.lib
# See https://docs.python.org/3/extending/windows.html
cc_import(
name="%{VARIETY_NAME}_lib",
interface_library=select({
"//:windows": ":%{VARIETY_NAME}_import_lib",
# A placeholder for Unix platforms which makes --no_build happy.
"//conditions:default": "not-existing.lib",
}),
system_provided=1,
)
cc_library(
name="%{VARIETY_NAME}_headers",
hdrs=[":%{VARIETY_NAME}_include"],
deps=select({
"//:windows": [":%{VARIETY_NAME}_lib"],
"//conditions:default": [],
}),
includes=["%{VARIETY_NAME}_include"],
)
%{PYTHON_INCLUDE_GENRULE}
%{PYTHON_IMPORT_LIB_GENRULE}

@ -82,7 +82,3 @@ build:basicprof --copt=-DNDEBUG
build:basicprof --copt=-O2
build:basicprof --copt=-DGRPC_BASIC_PROFILER
build:basicprof --copt=-DGRPC_TIMERS_RDTSC
build:python3 --python_path=python3
build:python3 --python_version=PY3
build:python3 --action_env=PYTHON_BIN_PATH=python3

Loading…
Cancel
Save