aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Levasseur <rlevasseur@google.com>2019-04-11 10:49:00 -0700
committerCopybara-Service <copybara-worker@google.com>2019-04-11 10:49:35 -0700
commit31ee376969da6f95b227f80d4f84e4bbb1aa369c (patch)
tree9467a5891c7d76afeaf05f81c916c4490869204d
parentdcdec971f1541a0453eba8885c273cef217f2ecb (diff)
downloadabsl-py-31ee376969da6f95b227f80d4f84e4bbb1aa369c.tar.gz
Make absl tests pass under new Bazel Python version transition logic.
This makes the absl tests pass when --incompatible_allow_python_version_transitions=true is set. Many tests use subprocesses to verify behavior and were relying on how the subprocess's Python version would match the test's Python version. Since this stickiness is going away, to keep the test and subprocess using the same Python version, the binaries have to be defined twice, one for each Python version, and a select() used with the test to select the matchiing binary. NOTE: Under bazel and Python 3, --python_version=PY3 flag must be specified so that bazel knows how to properly resolve selects. PiperOrigin-RevId: 243099319
-rw-r--r--absl/BUILD10
-rw-r--r--absl/build_defs.bzl37
-rw-r--r--absl/flags/tests/argparse_flags_test.py6
-rw-r--r--absl/logging/BUILD4
-rwxr-xr-xabsl/logging/tests/logging_functional_test.py7
-rw-r--r--absl/testing/BUILD30
-rw-r--r--absl/testing/_bazel_selected_py3.py2
-rw-r--r--absl/testing/_bazelize_command.py14
-rw-r--r--absl/testing/tests/absltest_test.py11
-rwxr-xr-xabsl/testing/tests/xml_reporter_test.py14
-rw-r--r--absl/tests/app_test.py12
11 files changed, 119 insertions, 28 deletions
diff --git a/absl/BUILD b/absl/BUILD
index b6fca88..ea93b60 100644
--- a/absl/BUILD
+++ b/absl/BUILD
@@ -2,6 +2,8 @@ licenses(["notice"]) # Apache 2.0
exports_files(["LICENSE"])
+load(":build_defs.bzl", "py2py3_test_binary")
+
py_library(
name = "app",
srcs = [
@@ -34,6 +36,12 @@ config_setting(
visibility = [":__subpackages__"],
)
+config_setting(
+ name = "py2_mode",
+ flag_values = {"@bazel_tools//tools/python:python_version": "PY2"},
+ visibility = [":__subpackages__"],
+)
+
py_library(
name = "_enum_module",
srcs = ["_enum_module.py"],
@@ -60,7 +68,7 @@ py_library(
],
)
-py_binary(
+py2py3_test_binary(
name = "tests/app_test_helper_pure_python",
testonly = 1,
srcs = ["tests/app_test_helper.py"],
diff --git a/absl/build_defs.bzl b/absl/build_defs.bzl
new file mode 100644
index 0000000..edfb0fb
--- /dev/null
+++ b/absl/build_defs.bzl
@@ -0,0 +1,37 @@
+"""Helpers for absl build rules."""
+
+def py2py3_test_binary(name, **kwargs):
+ """Create the same binary with different python versions for testing.
+
+ Given `name`, `${name}_py2` and `${name}_py3` targets are created with
+ `python_version` set to `PY2` and `PY3`, respectively. An alias named
+ `name` is also created that uses a `select()` between the two underlying
+ targets; this makes it easier to reference the binaries in consuming rules.
+
+ Args:
+ name: base name of the binaries. "_py2" and "_py3" suffixed targets
+ will be created from it.
+ **kwargs: additional args to pass onto py_binary.
+ """
+ kwargs["testonly"] = 1
+ kwargs["srcs_version"] = "PY2AND3"
+ if not kwargs.get("main"):
+ if len(kwargs.get("srcs", [])) != 1:
+ fail("py2py3_test_binary requires main or len(srcs)==1")
+ kwargs["main"] = kwargs["srcs"][0]
+
+ native.alias(name = name, actual = select({
+ "//absl:py3_mode": name + "_py3",
+ "//absl:py2_mode": name + "_py2",
+ }))
+
+ native.py_binary(
+ name = name + "_py2",
+ python_version = "PY2",
+ **kwargs
+ )
+ native.py_binary(
+ name = name + "_py3",
+ python_version = "PY3",
+ **kwargs
+ )
diff --git a/absl/flags/tests/argparse_flags_test.py b/absl/flags/tests/argparse_flags_test.py
index 244f977..51ed7fa 100644
--- a/absl/flags/tests/argparse_flags_test.py
+++ b/absl/flags/tests/argparse_flags_test.py
@@ -419,11 +419,11 @@ class ArgparseWithAppRunTest(parameterized.TestCase):
env = os.environ.copy()
env['MAIN_FUNC'] = main_func_name
env['FLAGS_PARSER_FUNC'] = flags_parser_func_name
- helper = 'absl/flags/tests/argparse_flags_test_helper'
+ helper = _bazelize_command.get_executable_path(
+ 'absl/flags/tests/argparse_flags_test_helper', add_version_suffix=False)
try:
stdout = subprocess.check_output(
- [_bazelize_command.get_executable_path(helper)] + args, env=env,
- universal_newlines=True)
+ [helper] + args, env=env, universal_newlines=True)
except subprocess.CalledProcessError as e:
error_info = ('ERROR: argparse_helper failed\n'
'Command: {}\n'
diff --git a/absl/logging/BUILD b/absl/logging/BUILD
index 1177fea..8f32874 100644
--- a/absl/logging/BUILD
+++ b/absl/logging/BUILD
@@ -2,6 +2,8 @@ licenses(["notice"]) # Apache 2.0
exports_files(["LICENSE"])
+load("//absl:build_defs.bzl", "py2py3_test_binary")
+
py_library(
name = "logging",
srcs = ["__init__.py"],
@@ -72,7 +74,7 @@ py_test(
],
)
-py_binary(
+py2py3_test_binary(
name = "tests/logging_functional_test_helper",
testonly = 1,
srcs = ["tests/logging_functional_test_helper.py"],
diff --git a/absl/logging/tests/logging_functional_test.py b/absl/logging/tests/logging_functional_test.py
index 5458e35..dd7e711 100755
--- a/absl/logging/tests/logging_functional_test.py
+++ b/absl/logging/tests/logging_functional_test.py
@@ -33,10 +33,8 @@ from absl.testing import absltest
from absl.testing import parameterized
import six
-
FLAGS = flags.FLAGS
-
_PY_VLOG3_LOG_MESSAGE = """\
I1231 23:59:59.000000 12345 logging_functional_test_helper.py:62] This line is VLOG level 3
"""
@@ -290,8 +288,9 @@ class FunctionalTest(parameterized.TestCase):
"""Functional tests using the logging_functional_test_helper script."""
def _get_helper(self):
- return _bazelize_command.get_executable_path(
- 'absl/logging/tests/logging_functional_test_helper')
+ helper_name = 'absl/logging/tests/logging_functional_test_helper'
+ return _bazelize_command.get_executable_path(helper_name)
+
def _get_logs(self,
verbosity,
include_info_prefix=True):
diff --git a/absl/testing/BUILD b/absl/testing/BUILD
index 191371d..d1d04b4 100644
--- a/absl/testing/BUILD
+++ b/absl/testing/BUILD
@@ -2,6 +2,8 @@ licenses(["notice"]) # Apache 2.0
exports_files(["LICENSE"])
+load("//absl:build_defs.bzl", "py2py3_test_binary")
+
py_library(
name = "absltest",
srcs = ["absltest.py"],
@@ -59,7 +61,20 @@ py_library(
srcs = ["_bazelize_command.py"],
srcs_version = "PY2AND3",
visibility = ["//:__subpackages__"],
- deps = ["//absl/flags"],
+ deps = [
+ ":_bazel_selected_py3", # buildcleaner: keep
+ "//absl/flags",
+ ],
+)
+
+py_library(
+ name = "_bazel_selected_py3",
+ testonly = 1,
+ srcs = select({
+ "//absl:py3_mode": ["_bazel_selected_py3.py"],
+ "//absl:py2_mode": [],
+ }),
+ srcs_version = "PY2AND3",
)
py_library(
@@ -82,10 +97,11 @@ py_test(
":absltest",
":parameterized",
"//absl/logging",
+ "@six_archive//:six",
],
)
-py_binary(
+py2py3_test_binary(
name = "tests/absltest_filtering_test_helper",
testonly = 1,
srcs = ["tests/absltest_filtering_test_helper.py"],
@@ -104,10 +120,11 @@ py_test(
":absltest",
":parameterized",
"//absl/flags",
+ "@six_archive//:six",
],
)
-py_binary(
+py2py3_test_binary(
name = "tests/absltest_randomization_testcase",
testonly = 1,
srcs = ["tests/absltest_randomization_testcase.py"],
@@ -127,10 +144,11 @@ py_test(
":_bazelize_command",
":absltest",
"//absl/flags",
+ "@six_archive//:six",
],
)
-py_binary(
+py2py3_test_binary(
name = "tests/absltest_sharding_test_helper",
testonly = 1,
srcs = ["tests/absltest_sharding_test_helper.py"],
@@ -153,7 +171,7 @@ py_test(
],
)
-py_binary(
+py2py3_test_binary(
name = "tests/absltest_test_helper",
testonly = 1,
srcs = ["tests/absltest_test_helper.py"],
@@ -203,7 +221,7 @@ py_test(
],
)
-py_binary(
+py2py3_test_binary(
name = "tests/xml_reporter_helper_test",
testonly = 1,
srcs = ["tests/xml_reporter_helper_test.py"],
diff --git a/absl/testing/_bazel_selected_py3.py b/absl/testing/_bazel_selected_py3.py
new file mode 100644
index 0000000..ea0306e
--- /dev/null
+++ b/absl/testing/_bazel_selected_py3.py
@@ -0,0 +1,2 @@
+# The presence of this module means, at build time, Bazel used Python 3
+# when resolving select() calls based on Python version.
diff --git a/absl/testing/_bazelize_command.py b/absl/testing/_bazelize_command.py
index 1be0163..a86a281 100644
--- a/absl/testing/_bazelize_command.py
+++ b/absl/testing/_bazelize_command.py
@@ -22,10 +22,15 @@ import os
from absl import flags
+try:
+ from absl.testing import _bazel_selected_py3
+except ImportError:
+ _bazel_selected_py3 = None
+
FLAGS = flags.FLAGS
-def get_executable_path(py_binary_name):
+def get_executable_path(py_binary_name, add_version_suffix=True):
"""Returns the executable path of a py_binary.
This returns the executable path of a py_binary that is in another Bazel
@@ -38,10 +43,17 @@ def get_executable_path(py_binary_name):
Args:
py_binary_name: string, the name of a py_binary that is in another Bazel
target's data dependencies.
+ add_version_suffix: bool, whether to add a Python version specific suffix
+ to `py_binary_name` when locating the file.
Raises:
RuntimeError: Raised when it cannot locate the executable path.
"""
+ if add_version_suffix:
+ root, ext = os.path.splitext(py_binary_name)
+ suffix = 'py3' if _bazel_selected_py3 else 'py2'
+ py_binary_name = '{}_{}{}'.format(root, suffix, ext)
+
if os.name == 'nt':
py_binary_name += '.exe'
manifest_file = os.path.join(FLAGS.test_srcdir, 'MANIFEST')
diff --git a/absl/testing/tests/absltest_test.py b/absl/testing/tests/absltest_test.py
index eb4631b..8dd696f 100644
--- a/absl/testing/tests/absltest_test.py
+++ b/absl/testing/tests/absltest_test.py
@@ -41,8 +41,11 @@ FLAGS = flags.FLAGS
class HelperMixin(object):
- def run_helper(self, test_id, args, env_overrides, expect_success):
+ def _get_helper_exec_path(self):
helper = 'absl/testing/tests/absltest_test_helper'
+ return _bazelize_command.get_executable_path(helper)
+
+ def run_helper(self, test_id, args, env_overrides, expect_success):
env = os.environ.copy()
for key, value in six.iteritems(env_overrides):
if value is None:
@@ -50,7 +53,8 @@ class HelperMixin(object):
del env[key]
else:
env[key] = value
- command = [_bazelize_command.get_executable_path(helper),
+
+ command = [self._get_helper_exec_path(),
'--test_id={}'.format(test_id)] + args
process = subprocess.Popen(
command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env,
@@ -162,6 +166,7 @@ class TestCaseTest(absltest.TestCase, HelperMixin):
def test_xml_output_file_from_test_xmloutputdir_env(self):
xml_output_dir = tempfile.mkdtemp(dir=FLAGS.test_tmpdir)
+ expected_xml_file = 'absltest_test_helper.xml'
self.run_helper(
6,
[],
@@ -169,7 +174,7 @@ class TestCaseTest(absltest.TestCase, HelperMixin):
'RUNNING_UNDER_TEST_DAEMON': None,
'TEST_XMLOUTPUTDIR': xml_output_dir,
'ABSLTEST_TEST_HELPER_EXPECTED_XML_OUTPUT_FILE': os.path.join(
- xml_output_dir, 'absltest_test_helper.xml'),
+ xml_output_dir, expected_xml_file),
},
expect_success=True)
diff --git a/absl/testing/tests/xml_reporter_test.py b/absl/testing/tests/xml_reporter_test.py
index da7e399..5e50fa2 100755
--- a/absl/testing/tests/xml_reporter_test.py
+++ b/absl/testing/tests/xml_reporter_test.py
@@ -838,6 +838,10 @@ class XMLTest(absltest.TestCase):
class XmlReporterFixtureTest(absltest.TestCase):
+ def _get_helper(self):
+ binary_name = 'absl/testing/tests/xml_reporter_helper_test'
+ return _bazelize_command.get_executable_path(binary_name)
+
def _run_test_and_get_xml(self, flag):
"""Runs xml_reporter_helper_test and returns an Element instance.
@@ -856,9 +860,8 @@ class XmlReporterFixtureTest(absltest.TestCase):
os.close(xml_fhandle)
try:
- binary_name = 'absl/testing/tests/xml_reporter_helper_test'
- args = [_bazelize_command.get_executable_path(binary_name),
- flag, '--xml_output_file=%s' % xml_fname]
+ binary = self._get_helper()
+ args = [binary, flag, '--xml_output_file=%s' % xml_fname]
ret = subprocess.call(args)
self.assertNotEqual(ret, 0)
@@ -873,9 +876,8 @@ class XmlReporterFixtureTest(absltest.TestCase):
os.close(xml_fhandle)
try:
- binary_name = 'absl/testing/tests/xml_reporter_helper_test'
- args = [_bazelize_command.get_executable_path(binary_name),
- flag, '--xml_output_file=%s' % xml_fname]
+ binary = self._get_helper()
+ args = [binary, flag, '--xml_output_file=%s' % xml_fname]
ret = subprocess.call(args)
self.assertNotEqual(ret, 0)
diff --git a/absl/tests/app_test.py b/absl/tests/app_test.py
index ef39c3a..d5435d2 100644
--- a/absl/tests/app_test.py
+++ b/absl/tests/app_test.py
@@ -153,6 +153,7 @@ class FunctionalTests(absltest.TestCase):
env['PYTHONIOENCODING'] = 'utf8'
if env_overrides:
env.update(env_overrides)
+
helper = 'absl/tests/app_test_helper_{}'.format(self.helper_type)
process = subprocess.Popen(
[_bazelize_command.get_executable_path(helper)] + list(arguments),
@@ -207,9 +208,14 @@ class FunctionalTests(absltest.TestCase):
expected_stdout_substring='str_flag_with_unicode_args')
self.assertIn(u'smile:\U0001F604', stdout)
- # Default values get repr'd, which causes unicode strings to incorrectly
- # render with their escaped values.
- self.assertIn(repr(u'thumb:\U0001F44D'), stdout)
+
+ if six.PY2:
+ # Default values get repr'd, which causes unicode strings to incorrectly
+ # render with their escaped values.
+ self.assertIn(repr(u'thumb:\U0001F44D'), stdout)
+ else:
+ # In Python 3, the repr() of a unicode string isn't escaped.
+ self.assertIn(u'thumb:\U0001F44D', stdout)
def test_helpshort(self):
_, _, stderr = self.run_helper(