aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYilei Yang (杨一磊) <yileiyang@google.com>2022-03-29 18:54:58 +0000
committerYilei Yang (杨一磊) <yileiyang@google.com>2022-03-29 18:54:58 +0000
commitbb7e02c301813d6543a590eebe46dc65d0e6136c (patch)
treed026deb8daab98f63787cc22986026643e59251d
parent3e4749af698201224165a98930c6845d8c102e0d (diff)
parentf6122a6f743fcc0402a9f7a27ae5d9ccb5e45c4e (diff)
downloadabsl-py-bb7e02c301813d6543a590eebe46dc65d0e6136c.tar.gz
Merge commit for internal changes.
-rw-r--r--CHANGELOG.md4
-rw-r--r--WORKSPACE17
-rw-r--r--absl/BUILD1
-rw-r--r--absl/flags/BUILD3
-rw-r--r--absl/flags/_defines.py2
-rw-r--r--absl/flags/_flag.py4
-rw-r--r--absl/flags/_flagvalues.py8
-rw-r--r--absl/flags/tests/_flag_test.py16
-rw-r--r--absl/flags/tests/flags_helpxml_test.py4
-rw-r--r--absl/flags/tests/flags_numeric_bounds_test.py6
-rw-r--r--absl/flags/tests/flags_test.py29
-rw-r--r--absl/logging/BUILD4
-rw-r--r--absl/logging/__init__.py61
-rw-r--r--absl/logging/converter.py4
-rw-r--r--absl/logging/tests/log_before_import_test.py6
-rw-r--r--absl/logging/tests/logging_functional_test.py4
-rw-r--r--absl/logging/tests/logging_functional_test_helper.py3
-rw-r--r--absl/logging/tests/logging_test.py46
-rw-r--r--absl/testing/BUILD5
-rw-r--r--absl/testing/absltest.py209
-rw-r--r--absl/testing/parameterized.py24
-rw-r--r--absl/testing/xml_reporter.py18
-rw-r--r--absl/tests/command_name_test.py6
-rw-r--r--third_party/mock.BUILD13
24 files changed, 211 insertions, 286 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0cdfa92..7b41a67 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,7 +6,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com).
## Unreleased
-Nothing notable unreleased.
+* `Flag` instances now raise an error if used in a bool context. This prevents
+ the occasional mistake of testing an instance for truthiness rather than
+ testing `flag.value`.
## 1.0.0 (2021-11-09)
diff --git a/WORKSPACE b/WORKSPACE
index 5397414..1370aae 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -17,22 +17,11 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "six_archive",
- urls = [
- "http://mirror.bazel.build/pypi.python.org/packages/source/s/six/six-1.10.0.tar.gz",
- "https://pypi.python.org/packages/source/s/six/six-1.10.0.tar.gz",
- ],
+ build_file = "@//third_party:six.BUILD",
sha256 = "105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a",
strip_prefix = "six-1.10.0",
- build_file = "@//third_party:six.BUILD",
-)
-
-http_archive(
- name = "mock_archive",
urls = [
- "http://mirror.bazel.build/pypi.python.org/packages/a2/52/7edcd94f0afb721a2d559a5b9aae8af4f8f2c79bc63fdbe8a8a6c9b23bbe/mock-1.0.1.tar.gz",
- "https://pypi.python.org/packages/a2/52/7edcd94f0afb721a2d559a5b9aae8af4f8f2c79bc63fdbe8a8a6c9b23bbe/mock-1.0.1.tar.gz",
+ "http://mirror.bazel.build/pypi.python.org/packages/source/s/six/six-1.10.0.tar.gz",
+ "https://pypi.python.org/packages/source/s/six/six-1.10.0.tar.gz",
],
- sha256 = "b839dd2d9c117c701430c149956918a423a9863b48b09c90e30a6013e7d2f44f",
- strip_prefix = "mock-1.0.1",
- build_file = "@//third_party:mock.BUILD",
)
diff --git a/absl/BUILD b/absl/BUILD
index c83ab28..496b0e3 100644
--- a/absl/BUILD
+++ b/absl/BUILD
@@ -76,7 +76,6 @@ py_test(
deps = [
":command_name",
"//absl/testing:absltest",
- "@mock_archive//:mock",
],
)
diff --git a/absl/flags/BUILD b/absl/flags/BUILD
index d54af1d..c180599 100644
--- a/absl/flags/BUILD
+++ b/absl/flags/BUILD
@@ -1,4 +1,4 @@
-licenses(["notice"]) # Apache 2.0
+licenses(["notice"])
py_library(
name = "flags",
@@ -256,7 +256,6 @@ py_test(
":_validators",
":flags",
"//absl/testing:absltest",
- "@mock_archive//:mock",
],
)
diff --git a/absl/flags/_defines.py b/absl/flags/_defines.py
index f655714..4494c3b 100644
--- a/absl/flags/_defines.py
+++ b/absl/flags/_defines.py
@@ -798,7 +798,7 @@ def DEFINE_multi_enum( # pylint: disable=invalid-name,redefined-builtin
serializer,
name,
default,
- help,
+ '<%s>: %s' % ('|'.join(enum_values), help),
flag_values,
required=required,
**args)
diff --git a/absl/flags/_flag.py b/absl/flags/_flag.py
index a893b22..a1c53ff 100644
--- a/absl/flags/_flag.py
+++ b/absl/flags/_flag.py
@@ -128,6 +128,10 @@ class Flag(object):
return id(self) < id(other)
return NotImplemented
+ def __bool__(self):
+ raise TypeError('A Flag instance would always be True. '
+ 'Did you mean to test the `.value` attribute?')
+
def __getstate__(self):
raise TypeError("can't pickle Flag objects")
diff --git a/absl/flags/_flagvalues.py b/absl/flags/_flagvalues.py
index dab6091..c9be720 100644
--- a/absl/flags/_flagvalues.py
+++ b/absl/flags/_flagvalues.py
@@ -774,7 +774,7 @@ class FlagValues(object):
continue
flag = flag_dict.get(name)
- if flag:
+ if flag is not None:
if flag.boolean and value is None:
value = 'true'
else:
@@ -782,13 +782,13 @@ class FlagValues(object):
elif name.startswith('no') and len(name) > 2:
# Boolean flags can take the form of --noflag, with no value.
noflag = flag_dict.get(name[2:])
- if noflag and noflag.boolean:
+ if noflag is not None and noflag.boolean:
if value is not None:
raise ValueError(arg + ' does not take an argument')
flag = noflag
value = 'false'
- if retired_flag_func and not flag:
+ if retired_flag_func and flag is None:
is_retired, is_bool = retired_flag_func(name)
# If we didn't recognize that flag, but it starts with
@@ -808,7 +808,7 @@ class FlagValues(object):
'be specified. See go/totw/90.', name)
continue
- if flag:
+ if flag is not None:
flag.parse(value)
flag.using_default_value = False
else:
diff --git a/absl/flags/tests/_flag_test.py b/absl/flags/tests/_flag_test.py
index 800a00c..492f117 100644
--- a/absl/flags/tests/_flag_test.py
+++ b/absl/flags/tests/_flag_test.py
@@ -35,6 +35,7 @@ from absl.testing import parameterized
class FlagTest(absltest.TestCase):
def setUp(self):
+ super().setUp()
self.flag = _flag.Flag(
_argument_parser.ArgumentParser(),
_argument_parser.ArgumentSerializer(),
@@ -59,6 +60,11 @@ class FlagTest(absltest.TestCase):
'number', 1, 'help')
self.assertEqual(1, flag.default_unparsed)
+ def test_no_truthiness(self):
+ with self.assertRaises(TypeError):
+ if self.flag:
+ self.fail('Flag instances must raise rather than be truthy.')
+
def test_set_default_overrides_current_value(self):
self.assertEqual('apple', self.flag.value)
self.flag._set_default('orange')
@@ -71,14 +77,14 @@ class FlagTest(absltest.TestCase):
self.assertEqual('apple', self.flag.value)
def test_pickle(self):
- with self.assertRaisesRegexp(TypeError, "can't pickle Flag objects"):
+ with self.assertRaisesRegex(TypeError, "can't pickle Flag objects"):
pickle.dumps(self.flag)
def test_copy(self):
self.flag.value = 'orange'
- with self.assertRaisesRegexp(
- TypeError, 'Flag does not support shallow copies'):
+ with self.assertRaisesRegex(TypeError,
+ 'Flag does not support shallow copies'):
copy.copy(self.flag)
flag2 = copy.deepcopy(self.flag)
@@ -172,10 +178,10 @@ class EnumClassFlagTest(parameterized.TestCase):
class MultiEnumClassFlagTest(parameterized.TestCase):
@parameterized.named_parameters(
- ('NoHelpSupplied', '', '<apple|orange>: (no help available);\n '
+ ('NoHelpSupplied', '', '<apple|orange>: (no help available);\n ' +
'repeat this option to specify a list of values', False),
('WithHelpSupplied', 'Type of fruit.',
- '<APPLE|ORANGE>: Type of fruit.;\n '
+ '<APPLE|ORANGE>: Type of fruit.;\n ' +
'repeat this option to specify a list of values', True))
def test_help_text(self, helptext_input, helptext_output, case_sensitive):
f = _flag.MultiEnumClassFlag(
diff --git a/absl/flags/tests/flags_helpxml_test.py b/absl/flags/tests/flags_helpxml_test.py
index 424c3dd..e2168ac 100644
--- a/absl/flags/tests/flags_helpxml_test.py
+++ b/absl/flags/tests/flags_helpxml_test.py
@@ -340,7 +340,7 @@ class FlagCreateXMLDOMElement(absltest.TestCase):
'<flag>\n'
' <file>tool</file>\n'
' <name>flavours</name>\n'
- ' <meaning>Compilation flavour.;\n'
+ ' <meaning>&lt;APPLE|BANANA|CHERRY&gt;: Compilation flavour.;\n'
' repeat this option to specify a list of values</meaning>\n'
' <default>[\'APPLE\', \'BANANA\']</default>\n'
' <current>[\'APPLE\', \'BANANA\']</current>\n'
@@ -474,7 +474,7 @@ EXPECTED_HELP_XML_FOR_FLAGS_FROM_MAIN_MODULE = """\
<key>yes</key>
<file>%(main_module_name)s</file>
<name>flavours</name>
- <meaning>Compilation flavour.;
+ <meaning>&lt;APPLE|BANANA|CHERRY&gt;: Compilation flavour.;
repeat this option to specify a list of values</meaning>
<default>['APPLE', 'BANANA']</default>
<current>['APPLE', 'BANANA']</current>
diff --git a/absl/flags/tests/flags_numeric_bounds_test.py b/absl/flags/tests/flags_numeric_bounds_test.py
index 5743258..d3c2a95 100644
--- a/absl/flags/tests/flags_numeric_bounds_test.py
+++ b/absl/flags/tests/flags_numeric_bounds_test.py
@@ -14,14 +14,10 @@
"""Tests for lower/upper bounds validators for numeric flags."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
+from unittest import mock
from absl import flags
from absl.flags import _validators
from absl.testing import absltest
-import mock
class NumericFlagBoundsTest(absltest.TestCase):
diff --git a/absl/flags/tests/flags_test.py b/absl/flags/tests/flags_test.py
index 75a61d5..8a42bc9 100644
--- a/absl/flags/tests/flags_test.py
+++ b/absl/flags/tests/flags_test.py
@@ -1511,6 +1511,20 @@ class MultiEnumFlagsTest(absltest.TestCase):
fv(argv)
self.assertListEqual(fv.get_flag_value('m_enum', None), ['WHOOSH', 'FOO'])
+ def test_help_text(self):
+ """Test multi_enum flag's help text."""
+ fv = flags.FlagValues()
+
+ flags.DEFINE_multi_enum(
+ 'm_enum',
+ None, ['FOO', 'BAR'],
+ 'Enum option that can occur multiple times',
+ flag_values=fv)
+ self.assertRegex(
+ fv['m_enum'].help,
+ r'<FOO\|BAR>: Enum option that can occur multiple times;\s+'
+ 'repeat this option to specify a list of values')
+
def test_single_value_default(self):
"""Test multi_enum flags with a single default value."""
fv = flags.FlagValues()
@@ -1590,6 +1604,21 @@ class MultiEnumClassFlagsTest(absltest.TestCase):
self.assertIsNone(fv.fruit)
+ def test_help_text(self):
+ fv = flags.FlagValues()
+ enum_defaults = None
+ flags.DEFINE_multi_enum_class(
+ 'fruit',
+ enum_defaults,
+ Fruit,
+ 'Enum option that can occur multiple times',
+ flag_values=fv)
+
+ self.assertRegex(
+ fv['fruit'].help,
+ r'<apple\|orange>: Enum option that can occur multiple times;\s+'
+ 'repeat this option to specify a list of values')
+
def test_define_results_in_registered_flag_with_string(self):
fv = flags.FlagValues()
enum_defaults = 'apple'
diff --git a/absl/logging/BUILD b/absl/logging/BUILD
index d83a2b6..e666d7a 100644
--- a/absl/logging/BUILD
+++ b/absl/logging/BUILD
@@ -1,4 +1,4 @@
-licenses(["notice"]) # Apache 2.0
+licenses(["notice"])
py_library(
name = "logging",
@@ -9,7 +9,6 @@ py_library(
":converter",
"//absl:_collections_abc",
"//absl/flags",
- "@six_archive//:six",
],
)
@@ -57,7 +56,6 @@ py_test(
deps = [
":logging",
"//absl/testing:absltest",
- "@mock_archive//:mock",
],
)
diff --git a/absl/logging/__init__.py b/absl/logging/__init__.py
index c79643f..a475bd5 100644
--- a/absl/logging/__init__.py
+++ b/absl/logging/__init__.py
@@ -71,10 +71,6 @@ program.
The differences in behavior are historical and unfortunate.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
import collections
import getpass
import io
@@ -84,6 +80,7 @@ import os
import socket
import struct
import sys
+import threading
import time
import timeit
import traceback
@@ -93,12 +90,6 @@ import warnings
from absl import flags
from absl._collections_abc import abc
from absl.logging import converter
-import six
-
-if six.PY2:
- import thread as _thread_lib # For .get_ident().
-else:
- import threading as _thread_lib # For .get_ident().
try:
from typing import NoReturn
@@ -257,7 +248,7 @@ class _LoggerLevelsSerializer(object):
"""Serializer for --logger_levels flag."""
def serialize(self, value):
- if isinstance(value, six.string_types):
+ if isinstance(value, str):
return value
return ','.join(
'{}:{}'.format(name, level) for name, level in value.items())
@@ -399,15 +390,11 @@ def warning(msg, *args, **kwargs):
log(WARNING, msg, *args, **kwargs)
-if six.PY2:
- warn = warning # Deprecated function.
-else:
-
- def warn(msg, *args, **kwargs):
- """Deprecated, use 'warning' instead."""
- warnings.warn("The 'warn' function is deprecated, use 'warning' instead",
- DeprecationWarning, 2)
- log(WARNING, msg, *args, **kwargs)
+def warn(msg, *args, **kwargs):
+ """Deprecated, use 'warning' instead."""
+ warnings.warn("The 'warn' function is deprecated, use 'warning' instead",
+ DeprecationWarning, 2)
+ log(WARNING, msg, *args, **kwargs)
def info(msg, *args, **kwargs):
@@ -729,8 +716,7 @@ def find_log_dir(log_dir=None):
for d in dirs:
if os.path.isdir(d) and os.access(d, os.W_OK):
return d
- exception_class = OSError if six.PY2 else FileNotFoundError
- raise exception_class(
+ raise FileNotFoundError(
"Can't find a writable directory for logs, tried %s" % dirs)
@@ -795,7 +781,7 @@ def skip_log_prefix(func):
file_name = func_code.co_filename
func_name = func_code.co_name
func_lineno = func_code.co_firstlineno
- elif isinstance(func, six.string_types):
+ elif isinstance(func, str):
file_name = get_absl_logger().findCaller()[0]
func_name = func
func_lineno = None
@@ -839,10 +825,7 @@ class PythonHandler(logging.StreamHandler):
os.getpid())
filename = os.path.join(actual_log_dir, basename)
- if six.PY2:
- self.stream = open(filename, 'a')
- else:
- self.stream = open(filename, 'a', encoding='utf-8')
+ self.stream = open(filename, 'a', encoding='utf-8')
# os.symlink is not available on Windows Python 2.
if getattr(os, 'symlink', None):
@@ -1072,16 +1055,13 @@ class ABSLLogger(logging.getLoggerClass()):
(code.co_filename, code.co_name,
code.co_firstlineno) not in f_to_skip and
(code.co_filename, code.co_name) not in f_to_skip):
- if six.PY2 and not stack_info:
- return (code.co_filename, frame.f_lineno, code.co_name)
- else:
- sinfo = None
- if stack_info:
- out = io.StringIO()
- out.write(u'Stack (most recent call last):\n')
- traceback.print_stack(frame, file=out)
- sinfo = out.getvalue().rstrip(u'\n')
- return (code.co_filename, frame.f_lineno, code.co_name, sinfo)
+ sinfo = None
+ if stack_info:
+ out = io.StringIO()
+ out.write(u'Stack (most recent call last):\n')
+ traceback.print_stack(frame, file=out)
+ sinfo = out.getvalue().rstrip(u'\n')
+ return (code.co_filename, frame.f_lineno, code.co_name, sinfo)
frame = frame.f_back
def critical(self, msg, *args, **kwargs):
@@ -1098,9 +1078,8 @@ class ABSLLogger(logging.getLoggerClass()):
def warn(self, msg, *args, **kwargs):
"""Logs 'msg % args' with severity 'WARN'."""
- if six.PY3:
- warnings.warn("The 'warn' method is deprecated, use 'warning' instead",
- DeprecationWarning, 2)
+ warnings.warn("The 'warn' method is deprecated, use 'warning' instead",
+ DeprecationWarning, 2)
self.log(logging.WARN, msg, *args, **kwargs)
def warning(self, msg, *args, **kwargs):
@@ -1183,7 +1162,7 @@ def _get_thread_id():
Returns:
Thread ID unique to this process (unsigned)
"""
- thread_id = _thread_lib.get_ident()
+ thread_id = threading.get_ident()
return thread_id & _THREAD_ID_MASK
diff --git a/absl/logging/converter.py b/absl/logging/converter.py
index 87f4324..53dd46d 100644
--- a/absl/logging/converter.py
+++ b/absl/logging/converter.py
@@ -43,10 +43,6 @@ representation, before manipulating the levels, and then only to cpp
or absl if those level schemes are absolutely necessary.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
import logging
STANDARD_CRITICAL = logging.CRITICAL
diff --git a/absl/logging/tests/log_before_import_test.py b/absl/logging/tests/log_before_import_test.py
index d1ba61f..903af16 100644
--- a/absl/logging/tests/log_before_import_test.py
+++ b/absl/logging/tests/log_before_import_test.py
@@ -14,20 +14,16 @@
"""Test of logging behavior before app.run(), aka flag and logging init()."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
import contextlib
import io
import os
import re
import sys
import tempfile
+from unittest import mock
from absl import logging
from absl.testing import absltest
-import mock
logging.get_verbosity() # Access --verbosity before flag parsing.
# Access --logtostderr before flag parsing.
diff --git a/absl/logging/tests/logging_functional_test.py b/absl/logging/tests/logging_functional_test.py
index faa0de4..98a2fab 100644
--- a/absl/logging/tests/logging_functional_test.py
+++ b/absl/logging/tests/logging_functional_test.py
@@ -324,6 +324,7 @@ class FunctionalTest(parameterized.TestCase):
pass_logtostderr=False,
use_absl_log_file=False,
show_info_prefix=1,
+ call_dict_config=False,
extra_args=()):
"""Execute the helper script and verify its output.
@@ -343,6 +344,8 @@ class FunctionalTest(parameterized.TestCase):
logging.get_absl_handler().use_absl_log_file() before test_fn in
logging_functional_test_helper.
show_info_prefix: --showprefixforinfo value passed to the helper script.
+ call_dict_config: True if helper script should call
+ logging.config.dictConfig.
extra_args: Iterable of str (optional, defaults to ()) - extra arguments
to pass to the helper script.
@@ -361,6 +364,7 @@ class FunctionalTest(parameterized.TestCase):
env.update({
'TEST_NAME': test_name,
'USE_ABSL_LOG_FILE': '%d' % (use_absl_log_file,),
+ 'CALL_DICT_CONFIG': '%d' % (call_dict_config,),
})
cmd = [self._get_helper()] + args
diff --git a/absl/logging/tests/logging_functional_test_helper.py b/absl/logging/tests/logging_functional_test_helper.py
index 0eccc74..b95647b 100644
--- a/absl/logging/tests/logging_functional_test_helper.py
+++ b/absl/logging/tests/logging_functional_test_helper.py
@@ -15,6 +15,7 @@
"""Helper script for logging_functional_test."""
import logging as std_logging
+import logging.config as std_logging_config
import os
import sys
import threading
@@ -306,4 +307,6 @@ def main(argv):
if __name__ == '__main__':
sys.argv[0] = 'py_argv_0'
+ if os.environ.get('CALL_DICT_CONFIG') == '1':
+ std_logging_config.dictConfig({'version': 1})
app.run(main)
diff --git a/absl/logging/tests/logging_test.py b/absl/logging/tests/logging_test.py
index c399f37..e5c4fcc 100644
--- a/absl/logging/tests/logging_test.py
+++ b/absl/logging/tests/logging_test.py
@@ -366,6 +366,7 @@ class PythonHandlerTest(absltest.TestCase):
class ABSLHandlerTest(absltest.TestCase):
def setUp(self):
+ super().setUp()
formatter = logging.PythonFormatter()
self.absl_handler = logging.ABSLHandler(formatter)
@@ -438,12 +439,14 @@ class ABSLLoggerTest(absltest.TestCase):
sys._getframe.return_value = mock_frame_0
def setUp(self):
+ super().setUp()
self.message = 'Hello Nurse'
self.logger = logging.ABSLLogger('')
def tearDown(self):
mock.patch.stopall()
self.logger._frames_to_skip.clear()
+ super().tearDown()
def test_constructor_without_level(self):
self.logger = logging.ABSLLogger('')
@@ -579,6 +582,7 @@ class ABSLLoggerTest(absltest.TestCase):
class ABSLLogPrefixTest(parameterized.TestCase):
def setUp(self):
+ super().setUp()
self.record = std_logging.LogRecord(
'name', std_logging.INFO, 'path/to/source.py', 13, 'log message',
None, None)
@@ -804,28 +808,28 @@ class LoggingTest(absltest.TestCase):
old_level = logging.get_verbosity()
logging.set_verbosity(logging.DEBUG)
- self.assertEquals(logging.get_verbosity(), logging.DEBUG)
+ self.assertEqual(logging.get_verbosity(), logging.DEBUG)
self.assertTrue(logging.level_debug())
self.assertTrue(logging.level_info())
self.assertTrue(logging.level_warning())
self.assertTrue(logging.level_error())
logging.set_verbosity(logging.INFO)
- self.assertEquals(logging.get_verbosity(), logging.INFO)
+ self.assertEqual(logging.get_verbosity(), logging.INFO)
self.assertFalse(logging.level_debug())
self.assertTrue(logging.level_info())
self.assertTrue(logging.level_warning())
self.assertTrue(logging.level_error())
logging.set_verbosity(logging.WARNING)
- self.assertEquals(logging.get_verbosity(), logging.WARNING)
+ self.assertEqual(logging.get_verbosity(), logging.WARNING)
self.assertFalse(logging.level_debug())
self.assertFalse(logging.level_info())
self.assertTrue(logging.level_warning())
self.assertTrue(logging.level_error())
logging.set_verbosity(logging.ERROR)
- self.assertEquals(logging.get_verbosity(), logging.ERROR)
+ self.assertEqual(logging.get_verbosity(), logging.ERROR)
self.assertFalse(logging.level_debug())
self.assertFalse(logging.level_info())
self.assertTrue(logging.level_error())
@@ -837,43 +841,43 @@ class LoggingTest(absltest.TestCase):
# Lowercase names.
logging.set_verbosity('debug')
- self.assertEquals(logging.get_verbosity(), logging.DEBUG)
+ self.assertEqual(logging.get_verbosity(), logging.DEBUG)
logging.set_verbosity('info')
- self.assertEquals(logging.get_verbosity(), logging.INFO)
+ self.assertEqual(logging.get_verbosity(), logging.INFO)
logging.set_verbosity('warning')
- self.assertEquals(logging.get_verbosity(), logging.WARNING)
+ self.assertEqual(logging.get_verbosity(), logging.WARNING)
logging.set_verbosity('warn')
- self.assertEquals(logging.get_verbosity(), logging.WARNING)
+ self.assertEqual(logging.get_verbosity(), logging.WARNING)
logging.set_verbosity('error')
- self.assertEquals(logging.get_verbosity(), logging.ERROR)
+ self.assertEqual(logging.get_verbosity(), logging.ERROR)
logging.set_verbosity('fatal')
# Uppercase names.
- self.assertEquals(logging.get_verbosity(), logging.FATAL)
+ self.assertEqual(logging.get_verbosity(), logging.FATAL)
logging.set_verbosity('DEBUG')
- self.assertEquals(logging.get_verbosity(), logging.DEBUG)
+ self.assertEqual(logging.get_verbosity(), logging.DEBUG)
logging.set_verbosity('INFO')
- self.assertEquals(logging.get_verbosity(), logging.INFO)
+ self.assertEqual(logging.get_verbosity(), logging.INFO)
logging.set_verbosity('WARNING')
- self.assertEquals(logging.get_verbosity(), logging.WARNING)
+ self.assertEqual(logging.get_verbosity(), logging.WARNING)
logging.set_verbosity('WARN')
- self.assertEquals(logging.get_verbosity(), logging.WARNING)
+ self.assertEqual(logging.get_verbosity(), logging.WARNING)
logging.set_verbosity('ERROR')
- self.assertEquals(logging.get_verbosity(), logging.ERROR)
+ self.assertEqual(logging.get_verbosity(), logging.ERROR)
logging.set_verbosity('FATAL')
- self.assertEquals(logging.get_verbosity(), logging.FATAL)
+ self.assertEqual(logging.get_verbosity(), logging.FATAL)
# Integers as strings.
logging.set_verbosity(str(logging.DEBUG))
- self.assertEquals(logging.get_verbosity(), logging.DEBUG)
+ self.assertEqual(logging.get_verbosity(), logging.DEBUG)
logging.set_verbosity(str(logging.INFO))
- self.assertEquals(logging.get_verbosity(), logging.INFO)
+ self.assertEqual(logging.get_verbosity(), logging.INFO)
logging.set_verbosity(str(logging.WARNING))
- self.assertEquals(logging.get_verbosity(), logging.WARNING)
+ self.assertEqual(logging.get_verbosity(), logging.WARNING)
logging.set_verbosity(str(logging.ERROR))
- self.assertEquals(logging.get_verbosity(), logging.ERROR)
+ self.assertEqual(logging.get_verbosity(), logging.ERROR)
logging.set_verbosity(str(logging.FATAL))
- self.assertEquals(logging.get_verbosity(), logging.FATAL)
+ self.assertEqual(logging.get_verbosity(), logging.FATAL)
logging.set_verbosity(old_level)
diff --git a/absl/testing/BUILD b/absl/testing/BUILD
index de77bcc..6dbbaea 100644
--- a/absl/testing/BUILD
+++ b/absl/testing/BUILD
@@ -1,4 +1,4 @@
-licenses(["notice"]) # Apache 2.0
+licenses(["notice"])
py_library(
name = "absltest",
@@ -12,7 +12,6 @@ py_library(
"//absl:app",
"//absl/flags",
"//absl/logging",
- "@six_archive//:six",
],
)
@@ -36,7 +35,6 @@ py_library(
deps = [
":absltest",
"//absl:_collections_abc",
- "@six_archive//:six",
],
)
@@ -47,7 +45,6 @@ py_library(
visibility = ["//visibility:public"],
deps = [
":_pretty_print_reporter",
- "@six_archive//:six",
],
)
diff --git a/absl/testing/absltest.py b/absl/testing/absltest.py
index 1ade38e..1303fd4 100644
--- a/absl/testing/absltest.py
+++ b/absl/testing/absltest.py
@@ -18,10 +18,6 @@ This module contains base classes and high-level functions for Abseil-style
tests.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
import contextlib
import difflib
import enum
@@ -43,6 +39,8 @@ import sys
import tempfile
import textwrap
import unittest
+from unittest import mock # pylint: disable=unused-import Allow absltest.mock.
+from urllib import parse
try:
# The faulthandler module isn't always available, and pytype doesn't
@@ -60,9 +58,6 @@ from absl import logging
from absl._collections_abc import abc
from absl.testing import _pretty_print_reporter
from absl.testing import xml_reporter
-import six
-from six.moves import urllib
-from six.moves import xrange # pylint: disable=redefined-builtin
# Make typing an optional import to avoid it being a required dependency
# in Python 2. Type checkers will still understand the imports.
@@ -84,14 +79,6 @@ else:
_OutcomeType = unittest.case._Outcome # pytype: disable=module-attr
-if six.PY3:
- from unittest import mock # pylint: disable=unused-import
-else:
- try:
- import mock # type: ignore
- except ImportError:
- mock = None
-
# Re-export a bunch of unittest functions we support so that people don't
# have to import unittest to get them
@@ -107,7 +94,7 @@ expectedFailure = unittest.expectedFailure
FLAGS = flags.FLAGS
-_TEXT_OR_BINARY_TYPES = (six.text_type, six.binary_type)
+_TEXT_OR_BINARY_TYPES = (str, bytes)
# Suppress surplus entries in AssertionError stack traces.
__unittest = True # pylint: disable=invalid-name
@@ -296,8 +283,8 @@ def _open(filepath, mode, _open_func=open):
# type: (Text, Text, Callable[..., IO]) -> IO
"""Opens a file.
- Like open(), but compatible with Python 2 and 3. Also ensures that we can open
- real files even if tests stub out open().
+ Like open(), but ensure that we can open real files even if tests stub out
+ open().
Args:
filepath: A filepath.
@@ -307,10 +294,7 @@ def _open(filepath, mode, _open_func=open):
Returns:
The opened file object.
"""
- if six.PY2:
- return _open_func(filepath, mode)
- else:
- return _open_func(filepath, mode, encoding='utf-8')
+ return _open_func(filepath, mode, encoding='utf-8')
class _TempDir(object):
@@ -390,7 +374,7 @@ class _TempDir(object):
# Note: there's no need to clear the directory since the containing
# dir was cleared by the tempdir() function.
- _makedirs_exist_ok(path)
+ os.makedirs(path, exist_ok=True)
return _TempDir(path)
@@ -418,14 +402,14 @@ class _TempFile(object):
if file_path:
cleanup_path = os.path.join(base_path, _get_first_part(file_path))
path = os.path.join(base_path, file_path)
- _makedirs_exist_ok(os.path.dirname(path))
+ os.makedirs(os.path.dirname(path), exist_ok=True)
# The file may already exist, in which case, ensure it's writable so that
# it can be truncated.
if os.path.exists(path) and not os.access(path, os.W_OK):
stat_info = os.stat(path)
os.chmod(path, stat_info.st_mode | stat.S_IWUSR)
else:
- _makedirs_exist_ok(base_path)
+ os.makedirs(base_path, exist_ok=True)
fd, path = tempfile.mkstemp(dir=str(base_path))
os.close(fd)
cleanup_path = path
@@ -433,7 +417,7 @@ class _TempFile(object):
tf = cls(path)
if content:
- if isinstance(content, six.text_type):
+ if isinstance(content, str):
tf.write_text(content, mode=mode, encoding=encoding, errors=errors)
else:
tf.write_bytes(content, mode)
@@ -482,8 +466,6 @@ class _TempFile(object):
encoding: The encoding to use when writing the text to the file.
errors: The error handling strategy to use when converting text to bytes.
"""
- if six.PY2 and isinstance(text, bytes):
- text = text.decode(encoding, errors)
with self.open_text(mode, encoding=encoding, errors=errors) as fp:
fp.write(text)
@@ -673,12 +655,12 @@ class TestCase(unittest.TestCase):
path = os.path.join(test_path, name)
cleanup_path = os.path.join(test_path, _get_first_part(name))
else:
- _makedirs_exist_ok(test_path)
+ os.makedirs(test_path, exist_ok=True)
path = tempfile.mkdtemp(dir=test_path)
cleanup_path = path
_rmtree_ignore_errors(cleanup_path)
- _makedirs_exist_ok(path)
+ os.makedirs(path, exist_ok=True)
self._maybe_add_temp_path_cleanup(cleanup_path, cleanup)
@@ -783,7 +765,8 @@ class TestCase(unittest.TestCase):
@classmethod
def _get_tempdir_path_cls(cls):
# type: () -> Text
- return os.path.join(TEST_TMPDIR.value, _get_qualname(cls))
+ return os.path.join(TEST_TMPDIR.value,
+ cls.__qualname__.replace('__main__.', ''))
def _get_tempdir_path_test(self):
# type: () -> Text
@@ -1053,51 +1036,14 @@ class TestCase(unittest.TestCase):
def assertItemsEqual(self, expected_seq, actual_seq, msg=None):
"""Deprecated, please use assertCountEqual instead.
- This is equivalent to assertCountEqual in Python 3. An implementation of
- assertCountEqual is also provided by absltest.TestCase for Python 2.
+ This is equivalent to assertCountEqual.
Args:
expected_seq: A sequence containing elements we are expecting.
actual_seq: The sequence that we are testing.
msg: The message to be printed if the test fails.
"""
- if six.PY3:
- # The assertItemsEqual method was renamed assertCountEqual in Python 3.2
- super(TestCase, self).assertCountEqual(expected_seq, actual_seq, msg)
- else:
- super(TestCase, self).assertItemsEqual(expected_seq, actual_seq, msg)
-
- # Only override assertCountEqual in Python 2 to avoid unnecessary calls.
- if six.PY2:
-
- def assertCountEqual(self, expected_seq, actual_seq, msg=None):
- """Tests two sequences have the same elements regardless of order.
-
- It tests that the first sequence contains the same elements as the
- second, regardless of their order. When they don't, an error message
- listing the differences between the sequences will be generated.
-
- Duplicate elements are not ignored when comparing first and second.
- It verifies whether each element has the same count in both sequences.
- Equivalent to:
-
- self.assertEqual(Counter(list(expected_seq)),
- Counter(list(actual_seq)))
-
- but works with sequences of unhashable objects as well.
-
- Example:
- - [0, 1, 1] and [1, 0, 1] compare equal.
- - [0, 0, 1] and [0, 1] compare unequal.
-
- Args:
- expected_seq: A sequence containing elements we are expecting.
- actual_seq: The sequence that we are testing.
- msg: The message to be printed if the test fails.
-
- """
- # Only call super's method to avoid potential infinite recursions.
- super(TestCase, self).assertItemsEqual(expected_seq, actual_seq, msg)
+ super().assertCountEqual(expected_seq, actual_seq, msg)
def assertSameElements(self, expected_seq, actual_seq, msg=None):
"""Asserts that two sequences have the same elements (in any order).
@@ -1157,10 +1103,10 @@ class TestCase(unittest.TestCase):
# has a different error format. However, I find this slightly more readable.
def assertMultiLineEqual(self, first, second, msg=None, **kwargs):
"""Asserts that two multi-line strings are equal."""
- assert isinstance(first, six.string_types), (
- 'First argument is not a string: %r' % (first,))
- assert isinstance(second, six.string_types), (
- 'Second argument is not a string: %r' % (second,))
+ assert isinstance(first,
+ str), ('First argument is not a string: %r' % (first,))
+ assert isinstance(second,
+ str), ('Second argument is not a string: %r' % (second,))
line_limit = kwargs.pop('line_limit', 0)
if kwargs:
raise TypeError('Unexpected keyword args {}'.format(tuple(kwargs)))
@@ -1237,14 +1183,14 @@ class TestCase(unittest.TestCase):
if type(regex) is not regex_type: # pylint: disable=unidiomatic-typecheck
self.fail('regexes list must all be the same type.', message)
- if regex_type is bytes and isinstance(actual_str, six.text_type):
+ if regex_type is bytes and isinstance(actual_str, str):
regexes = [regex.decode('utf-8') for regex in regexes]
- regex_type = six.text_type
- elif regex_type is six.text_type and isinstance(actual_str, bytes):
+ regex_type = str
+ elif regex_type is str and isinstance(actual_str, bytes):
regexes = [regex.encode('utf-8') for regex in regexes]
regex_type = bytes
- if regex_type is six.text_type:
+ if regex_type is str:
regex = u'(?:%s)' % u')|(?:'.join(regexes)
elif regex_type is bytes:
regex = b'(?:' + (b')|(?:'.join(regexes)) + b')'
@@ -1276,7 +1222,7 @@ class TestCase(unittest.TestCase):
# We need bytes regexes here because `err` is bytes.
# Accommodate code which listed their output regexes w/o the b'' prefix by
# converting them to bytes for the user.
- if isinstance(regexes[0], six.text_type):
+ if isinstance(regexes[0], str):
regexes = [regex.encode('utf-8') for regex in regexes]
command_string = get_command_string(command)
@@ -1322,7 +1268,7 @@ class TestCase(unittest.TestCase):
# We need bytes regexes here because `err` is bytes.
# Accommodate code which listed their output regexes w/o the b'' prefix by
# converting them to bytes for the user.
- if isinstance(regexes[0], six.text_type):
+ if isinstance(regexes[0], str):
regexes = [regex.encode('utf-8') for regex in regexes]
command_string = get_command_string(command)
@@ -1364,6 +1310,21 @@ class TestCase(unittest.TestCase):
self.test_func(exc_value)
return True
+ @typing.overload
+ def assertRaisesWithPredicateMatch(
+ self, expected_exception, predicate) -> _AssertRaisesContext:
+ # The purpose of this return statement is to work around
+ # https://github.com/PyCQA/pylint/issues/5273; it is otherwise ignored.
+ return self._AssertRaisesContext(None, None, None)
+
+ @typing.overload
+ def assertRaisesWithPredicateMatch(
+ self, expected_exception, predicate, callable_obj: Callable[..., Any],
+ *args, **kwargs) -> None:
+ # The purpose of this return statement is to work around
+ # https://github.com/PyCQA/pylint/issues/5273; it is otherwise ignored.
+ return self._AssertRaisesContext(None, None, None)
+
def assertRaisesWithPredicateMatch(self, expected_exception, predicate,
callable_obj=None, *args, **kwargs):
"""Asserts that exception is thrown and predicate(exception) is true.
@@ -1392,6 +1353,22 @@ class TestCase(unittest.TestCase):
with context:
callable_obj(*args, **kwargs)
+ @typing.overload
+ def assertRaisesWithLiteralMatch(
+ self, expected_exception, expected_exception_message
+ ) -> _AssertRaisesContext:
+ # The purpose of this return statement is to work around
+ # https://github.com/PyCQA/pylint/issues/5273; it is otherwise ignored.
+ return self._AssertRaisesContext(None, None, None)
+
+ @typing.overload
+ def assertRaisesWithLiteralMatch(
+ self, expected_exception, expected_exception_message,
+ callable_obj: Callable[..., Any], *args, **kwargs) -> None:
+ # The purpose of this return statement is to work around
+ # https://github.com/PyCQA/pylint/issues/5273; it is otherwise ignored.
+ return self._AssertRaisesContext(None, None, None)
+
def assertRaisesWithLiteralMatch(self, expected_exception,
expected_exception_message,
callable_obj=None, *args, **kwargs):
@@ -1502,7 +1479,7 @@ class TestCase(unittest.TestCase):
subsequence = list(subsequence)
longest_match = 0
- for start in xrange(1 + len(container) - len(subsequence)):
+ for start in range(1 + len(container) - len(subsequence)):
if longest_match == len(subsequence):
break
index = 0
@@ -1666,8 +1643,8 @@ class TestCase(unittest.TestCase):
if a == b:
return
- a_items = Sorted(list(six.iteritems(a)))
- b_items = Sorted(list(six.iteritems(b)))
+ a_items = Sorted(list(a.items()))
+ b_items = Sorted(list(b.items()))
unexpected = []
missing = []
@@ -1679,8 +1656,7 @@ class TestCase(unittest.TestCase):
"""Deterministic repr for dict."""
# Sort the entries based on their repr, not based on their sort order,
# which will be non-deterministic across executions, for many types.
- entries = sorted((safe_repr(k), safe_repr(v))
- for k, v in six.iteritems(dikt))
+ entries = sorted((safe_repr(k), safe_repr(v)) for k, v in dikt.items())
return '{%s}' % (', '.join('%s: %s' % pair for pair in entries))
message = ['%s != %s%s' % (Repr(a), Repr(b), ' (%s)' % msg if msg else '')]
@@ -1718,8 +1694,8 @@ class TestCase(unittest.TestCase):
def assertUrlEqual(self, a, b, msg=None):
"""Asserts that urls are equal, ignoring ordering of query params."""
- parsed_a = urllib.parse.urlparse(a)
- parsed_b = urllib.parse.urlparse(b)
+ parsed_a = parse.urlparse(a)
+ parsed_b = parse.urlparse(b)
self.assertEqual(parsed_a.scheme, parsed_b.scheme, msg)
self.assertEqual(parsed_a.netloc, parsed_b.netloc, msg)
self.assertEqual(parsed_a.path, parsed_b.path, msg)
@@ -1727,8 +1703,8 @@ class TestCase(unittest.TestCase):
self.assertEqual(sorted(parsed_a.params.split(';')),
sorted(parsed_b.params.split(';')), msg)
self.assertDictEqual(
- urllib.parse.parse_qs(parsed_a.query, keep_blank_values=True),
- urllib.parse.parse_qs(parsed_b.query, keep_blank_values=True), msg)
+ parse.parse_qs(parsed_a.query, keep_blank_values=True),
+ parse.parse_qs(parsed_b.query, keep_blank_values=True), msg)
def assertSameStructure(self, a, b, aname='a', bname='b', msg=None):
"""Asserts that two values contain the same structural content.
@@ -1866,7 +1842,7 @@ def _sorted_list_difference(expected, actual):
def _are_both_of_integer_type(a, b):
# type: (object, object) -> bool
- return isinstance(a, six.integer_types) and isinstance(b, six.integer_types)
+ return isinstance(a, int) and isinstance(b, int)
def _are_both_of_sequence_type(a, b):
@@ -1930,14 +1906,14 @@ def _walk_structure_for_problems(a, b, aname, bname, problem_list):
elif (isinstance(a, abc.Sequence) and
not isinstance(a, _TEXT_OR_BINARY_TYPES)):
minlen = min(len(a), len(b))
- for i in xrange(minlen):
+ for i in range(minlen):
_walk_structure_for_problems(
a[i], b[i], '%s[%d]' % (aname, i), '%s[%d]' % (bname, i),
problem_list)
- for i in xrange(minlen, len(a)):
+ for i in range(minlen, len(a)):
problem_list.append('%s has [%i] with value %r but %s does not' %
(aname, i, a[i], bname))
- for i in xrange(minlen, len(b)):
+ for i in range(minlen, len(b)):
problem_list.append('%s lacks [%i] but %s has it with value %r' %
(aname, i, bname, b[i]))
@@ -1954,7 +1930,7 @@ def get_command_string(command):
Returns:
A string suitable for use as a shell command.
"""
- if isinstance(command, six.string_types):
+ if isinstance(command, str):
return command
else:
if os.name == 'nt':
@@ -1989,7 +1965,7 @@ def get_command_stderr(command, env=None, close_fds=True):
# standard handles.
close_fds = False
- use_shell = isinstance(command, six.string_types)
+ use_shell = isinstance(command, str)
process = subprocess.Popen(
command,
close_fds=close_fds,
@@ -2054,7 +2030,7 @@ def _is_in_app_main():
"""Returns True iff app.run is active."""
f = sys._getframe().f_back # pylint: disable=protected-access
while f:
- if f.f_code == six.get_function_code(app.run): # pytype: disable=wrong-arg-types
+ if f.f_code == app.run.__code__:
return True
f = f.f_back
return False
@@ -2150,7 +2126,7 @@ def _run_in_app(function, args, kwargs):
# after the command-line has been parsed. So we have the for loop below
# to change back flags to their old values.
argv = FLAGS(sys.argv)
- for saved_flag in six.itervalues(saved_flags):
+ for saved_flag in saved_flags.values():
saved_flag.restore_flag()
function(argv, args, kwargs)
@@ -2172,15 +2148,10 @@ def _is_suspicious_attribute(testCaseClass, name):
if name.startswith('Test') and len(name) > 4 and name[4].isupper():
attr = getattr(testCaseClass, name)
if inspect.isfunction(attr) or inspect.ismethod(attr):
- if six.PY2:
- args = inspect.getargspec(attr)
- return (len(args.args) == 1 and args.args[0] == 'self'
- and args.varargs is None and args.keywords is None)
- else:
- args = inspect.getfullargspec(attr)
- return (len(args.args) == 1 and args.args[0] == 'self'
- and args.varargs is None and args.varkw is None and
- not args.kwonlyargs)
+ args = inspect.getfullargspec(attr)
+ return (len(args.args) == 1 and args.args[0] == 'self' and
+ args.varargs is None and args.varkw is None and
+ not args.kwonlyargs)
return False
@@ -2418,7 +2389,7 @@ def _setup_sharding(custom_loader=None):
# the test case names for this shard.
delegate_get_names = base_loader.getTestCaseNames
- bucket_iterator = itertools.cycle(xrange(total_shards))
+ bucket_iterator = itertools.cycle(range(total_shards))
def getShardedTestCaseNames(testCaseClass):
filtered_names = []
@@ -2491,7 +2462,7 @@ def _run_and_get_tests_result(argv, args, kwargs, xml_test_runner_class):
# Use an in-memory buffer (not backed by the actual file) to store the XML
# report, because some tools modify the file (e.g., create a placeholder
# with partial information, in case the test process crashes).
- xml_buffer = six.StringIO()
+ xml_buffer = io.StringIO()
kwargs['testRunner'].set_default_xml_stream(xml_buffer) # pytype: disable=attribute-error
# If we've used a seed to randomize test case ordering, we want to record it
@@ -2566,15 +2537,6 @@ def run_tests(argv, args, kwargs): # pylint: disable=line-too-long
sys.exit(not result.wasSuccessful())
-def _get_qualname(cls):
- # type: (Type) -> Text
- if six.PY3:
- name = cls.__qualname__
- else:
- name = '{}.{}'.format(cls.__module__, cls.__name__)
- return name.replace('__main__.', '')
-
-
def _rmtree_ignore_errors(path):
# type: (Text) -> None
if os.path.isfile(path):
@@ -2586,19 +2548,6 @@ def _rmtree_ignore_errors(path):
shutil.rmtree(path, ignore_errors=True)
-def _makedirs_exist_ok(dir_name):
- # type: (Text) -> None
- if six.PY3:
- os.makedirs(dir_name, exist_ok=True) # pylint: disable=unexpected-keyword-arg
- else:
- # Python 2 doesn't have the exist_ok arg, so we roll it ourselves
- try:
- os.makedirs(dir_name)
- except OSError as e:
- if e.errno != errno.EEXIST:
- raise
-
-
def _get_first_part(path):
# type: (Text) -> Text
parts = path.split(os.sep, 1)
diff --git a/absl/testing/parameterized.py b/absl/testing/parameterized.py
index 4d02c4e..f318b98 100644
--- a/absl/testing/parameterized.py
+++ b/absl/testing/parameterized.py
@@ -217,7 +217,6 @@ import unittest
from absl._collections_abc import abc
from absl.testing import absltest
-import six
_ADDR_RE = re.compile(r'\<([a-zA-Z0-9_\-\.]+) object at 0x[a-fA-F0-9]+\>')
@@ -247,15 +246,14 @@ def _clean_repr(obj):
def _non_string_or_bytes_iterable(obj):
- return (isinstance(obj, abc.Iterable) and
- not isinstance(obj, six.text_type) and
- not isinstance(obj, six.binary_type))
+ return (isinstance(obj, abc.Iterable) and not isinstance(obj, str) and
+ not isinstance(obj, bytes))
def _format_parameter_list(testcase_params):
if isinstance(testcase_params, abc.Mapping):
return ', '.join('%s=%s' % (argname, _clean_repr(value))
- for argname, value in six.iteritems(testcase_params))
+ for argname, value in testcase_params.items())
elif _non_string_or_bytes_iterable(testcase_params):
return ', '.join(map(_clean_repr, testcase_params))
else:
@@ -333,10 +331,11 @@ class _ParameterizedTestIter(object):
'Dict for named tests must contain key "%s"' % _NAMED_DICT_KEY)
# Create a new dict to avoid modifying the supplied testcase_params.
testcase_name = testcase_params[_NAMED_DICT_KEY]
- testcase_params = {k: v for k, v in six.iteritems(testcase_params)
- if k != _NAMED_DICT_KEY}
+ testcase_params = {
+ k: v for k, v in testcase_params.items() if k != _NAMED_DICT_KEY
+ }
elif _non_string_or_bytes_iterable(testcase_params):
- if not isinstance(testcase_params[0], six.string_types):
+ if not isinstance(testcase_params[0], str):
raise RuntimeError(
'The first element of named test parameters is the test name '
'suffix and must be a string')
@@ -388,7 +387,7 @@ def _modify_class(class_object, testcases, naming_type):
# NOTE: _test_params_repr is private to parameterized.TestCase and it's
# metaclass; do not use it outside of those classes.
class_object._test_params_reprs = test_params_reprs = {}
- for name, obj in six.iteritems(class_object.__dict__.copy()):
+ for name, obj in class_object.__dict__.copy().items():
if (name.startswith(unittest.TestLoader.testMethodPrefix)
and isinstance(obj, types.FunctionType)):
delattr(class_object, name)
@@ -396,7 +395,7 @@ def _modify_class(class_object, testcases, naming_type):
_update_class_dict_for_param_test_case(
class_object.__name__, methods, test_params_reprs, name,
_ParameterizedTestIter(obj, testcases, naming_type, name))
- for meth_name, meth in six.iteritems(methods):
+ for meth_name, meth in methods.items():
setattr(class_object, meth_name, meth)
@@ -554,7 +553,7 @@ class TestGeneratorMetaclass(type):
# NOTE: _test_params_repr is private to parameterized.TestCase and it's
# metaclass; do not use it outside of those classes.
test_params_reprs = dct.setdefault('_test_params_reprs', {})
- for name, obj in six.iteritems(dct.copy()):
+ for name, obj in dct.copy().items():
if (name.startswith(unittest.TestLoader.testMethodPrefix) and
_non_string_or_bytes_iterable(obj)):
# NOTE: `obj` might not be a _ParameterizedTestIter in two cases:
@@ -637,8 +636,7 @@ def _update_class_dict_for_param_test_case(
test_params_reprs[new_name] = getattr(func, '__x_params_repr__', '')
-@six.add_metaclass(TestGeneratorMetaclass)
-class TestCase(absltest.TestCase):
+class TestCase(absltest.TestCase, metaclass=TestGeneratorMetaclass):
"""Base class for test cases using the parameters decorator."""
# visibility: private; do not call outside this class.
diff --git a/absl/testing/xml_reporter.py b/absl/testing/xml_reporter.py
index 103827b..da56e39 100644
--- a/absl/testing/xml_reporter.py
+++ b/absl/testing/xml_reporter.py
@@ -27,7 +27,6 @@ import traceback
import unittest
from xml.sax import saxutils
from absl.testing import _pretty_print_reporter
-import six
# See http://www.w3.org/TR/REC-xml/#NT-Char
@@ -74,7 +73,7 @@ def _escape_cdata(s):
Returns:
An escaped version of the input string.
"""
- for char, escaped in six.iteritems(_control_character_conversions):
+ for char, escaped in _control_character_conversions.items():
s = s.replace(char, escaped)
return s.replace(']]>', ']] >')
@@ -90,13 +89,8 @@ def _iso8601_timestamp(timestamp):
"""
if timestamp is None or timestamp < 0:
return None
- # Use utcfromtimestamp in PY2 because it doesn't have a built-in UTC object
- if six.PY2:
- return '%s+00:00' % datetime.datetime.utcfromtimestamp(
- timestamp).isoformat()
- else:
- return datetime.datetime.fromtimestamp(
- timestamp, tz=datetime.timezone.utc).isoformat()
+ return datetime.datetime.fromtimestamp(
+ timestamp, tz=datetime.timezone.utc).isoformat()
def _print_xml_element_header(element, attributes, stream, indentation=''):
@@ -110,8 +104,8 @@ def _print_xml_element_header(element, attributes, stream, indentation=''):
"""
stream.write('%s<%s' % (indentation, element))
for attribute in attributes:
- if len(attribute) == 2 \
- and attribute[0] is not None and attribute[1] is not None:
+ if (len(attribute) == 2 and attribute[0] is not None and
+ attribute[1] is not None):
stream.write(' %s="%s"' % (attribute[0], attribute[1]))
stream.write('>\n')
@@ -279,7 +273,7 @@ class _TestSuiteResult(object):
_print_xml_element_header('testsuites', overall_attributes, stream)
if self._testsuites_properties:
stream.write(' <properties>\n')
- for name, value in sorted(six.iteritems(self._testsuites_properties)):
+ for name, value in sorted(self._testsuites_properties.items()):
stream.write(' <property name="%s" value="%s"></property>\n' %
(_escape_xml_attr(name), _escape_xml_attr(str(value))))
stream.write(' </properties>\n')
diff --git a/absl/tests/command_name_test.py b/absl/tests/command_name_test.py
index 61af1bb..2679521 100644
--- a/absl/tests/command_name_test.py
+++ b/absl/tests/command_name_test.py
@@ -15,18 +15,14 @@
"""Tests for absl.command_name."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
import ctypes
import errno
import os
import unittest
+from unittest import mock
from absl import command_name
from absl.testing import absltest
-import mock
def _get_kernel_process_name():
diff --git a/third_party/mock.BUILD b/third_party/mock.BUILD
deleted file mode 100644
index 534ff65..0000000
--- a/third_party/mock.BUILD
+++ /dev/null
@@ -1,13 +0,0 @@
-# Description:
-# mock is a library for testing in Python.
-
-licenses(["notice"]) # BSD
-
-exports_files(["LICENSE.txt"])
-
-py_library(
- name = "mock",
- srcs = ["mock.py"],
- srcs_version = "PY2AND3",
- visibility = ["//visibility:public"],
-)