Merge pull request #195 from yilei/push_up_to_461698919

Push up to 461698919
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3c36751..ab288ff 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,12 @@
 
 Nothing notable unreleased.
 
+## 1.2.0 (2022-07-18)
+
+### Fixed
+
+*   Fixed a crash in Python 3.11 when `TempFileCleanup.SUCCESS` is used.
+
 ## 1.1.0 (2022-06-01)
 
 *   `Flag` instances now raise an error if used in a bool context. This prevents
diff --git a/absl/app.py b/absl/app.py
index 037f75c..196a951 100644
--- a/absl/app.py
+++ b/absl/app.py
@@ -25,10 +25,6 @@
       app.run(main)
 """
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import collections
 import errno
 import os
diff --git a/absl/command_name.py b/absl/command_name.py
index 3bf9fad..1996493 100644
--- a/absl/command_name.py
+++ b/absl/command_name.py
@@ -14,10 +14,6 @@
 
 """A tiny stand alone library to change the kernel process name on Linux."""
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import os
 import sys
 
diff --git a/absl/flags/_defines.py b/absl/flags/_defines.py
index 4494c3b..a102652 100644
--- a/absl/flags/_defines.py
+++ b/absl/flags/_defines.py
@@ -17,10 +17,6 @@
 aliases defined at the package level instead.
 """
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import sys
 import types
 
diff --git a/absl/flags/_defines.pyi b/absl/flags/_defines.pyi
index 1f482a2..0fbe921 100644
--- a/absl/flags/_defines.pyi
+++ b/absl/flags/_defines.pyi
@@ -576,7 +576,23 @@
 @overload
 def DEFINE_multi_enum_class(
     name: Text,
-    default: Union[None, Iterable[_ET], _ET, Text],
+    # This is separate from `Union[None, _ET, Text]` to avoid a Pytype issue
+    # inferring the return value to FlagHolder[List[Union[_ET, enum.Enum]]]
+    # when an iterable of concrete enum subclasses are used.
+    default: Iterable[_ET],
+    enum_class: Type[_ET],
+    help: Text,
+    flag_values: _flagvalues.FlagValues = ...,
+    module_name: Optional[Text] = ...,
+    *,
+    required: Literal[True],
+    **args: Any) -> _flagvalues.FlagHolder[List[_ET]]:
+  ...
+
+@overload
+def DEFINE_multi_enum_class(
+    name: Text,
+    default: Union[None, _ET, Text],
     enum_class: Type[_ET],
     help: Text,
     flag_values: _flagvalues.FlagValues = ...,
@@ -601,7 +617,10 @@
 @overload
 def DEFINE_multi_enum_class(
     name: Text,
-    default: Union[Iterable[_ET], _ET, Text],
+    # This is separate from `Union[None, _ET, Text]` to avoid a Pytype issue
+    # inferring the return value to FlagHolder[List[Union[_ET, enum.Enum]]]
+    # when an iterable of concrete enum subclasses are used.
+    default: Iterable[_ET],
     enum_class: Type[_ET],
     help: Text,
     flag_values: _flagvalues.FlagValues = ...,
@@ -610,6 +629,17 @@
     **args: Any) -> _flagvalues.FlagHolder[List[_ET]]:
   ...
 
+@overload
+def DEFINE_multi_enum_class(
+    name: Text,
+    default: Union[_ET, Text],
+    enum_class: Type[_ET],
+    help: Text,
+    flag_values: _flagvalues.FlagValues = ...,
+    module_name: Optional[Text] = ...,
+    required: bool = ...,
+    **args: Any) -> _flagvalues.FlagHolder[List[_ET]]:
+  ...
 
 
 def DEFINE_alias(
diff --git a/absl/flags/_exceptions.py b/absl/flags/_exceptions.py
index 254eb9b..0ca2777 100644
--- a/absl/flags/_exceptions.py
+++ b/absl/flags/_exceptions.py
@@ -18,10 +18,6 @@
 aliases defined at the package level instead.
 """
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import sys
 
 from absl.flags import _helpers
diff --git a/absl/flags/_helpers.py b/absl/flags/_helpers.py
index 37ae360..96f0a85 100644
--- a/absl/flags/_helpers.py
+++ b/absl/flags/_helpers.py
@@ -14,10 +14,6 @@
 
 """Internal helper functions for Abseil Python flags library."""
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import collections
 import os
 import re
diff --git a/absl/flags/_validators.py b/absl/flags/_validators.py
index af66050..26639c5 100644
--- a/absl/flags/_validators.py
+++ b/absl/flags/_validators.py
@@ -32,10 +32,6 @@
 aliases defined at the package level instead.
 """
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import warnings
 
 from absl.flags import _exceptions
diff --git a/absl/flags/_validators_classes.py b/absl/flags/_validators_classes.py
index d8996e0..2881499 100644
--- a/absl/flags/_validators_classes.py
+++ b/absl/flags/_validators_classes.py
@@ -18,10 +18,6 @@
 private APIs.
 """
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 from absl.flags import _exceptions
 
 
diff --git a/absl/flags/argparse_flags.py b/absl/flags/argparse_flags.py
index 4f78f50..69e4c8a 100644
--- a/absl/flags/argparse_flags.py
+++ b/absl/flags/argparse_flags.py
@@ -88,10 +88,6 @@
    3) argparse_flags supports `-h`; absl.app does not.
 """
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import argparse
 import sys
 
diff --git a/absl/flags/tests/_flag_test.py b/absl/flags/tests/_flag_test.py
index 492f117..1625289 100644
--- a/absl/flags/tests/_flag_test.py
+++ b/absl/flags/tests/_flag_test.py
@@ -17,10 +17,6 @@
 Most of the Flag classes are covered in the flags_test.py.
 """
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import copy
 import enum
 import pickle
diff --git a/absl/flags/tests/_helpers_test.py b/absl/flags/tests/_helpers_test.py
index 4746a79..2697d1c 100644
--- a/absl/flags/tests/_helpers_test.py
+++ b/absl/flags/tests/_helpers_test.py
@@ -14,10 +14,6 @@
 
 """Unittests for helpers module."""
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import sys
 
 from absl.flags import _helpers
diff --git a/absl/flags/tests/_validators_test.py b/absl/flags/tests/_validators_test.py
index f724813..1cccf53 100644
--- a/absl/flags/tests/_validators_test.py
+++ b/absl/flags/tests/_validators_test.py
@@ -18,10 +18,6 @@
 failed validator will throw an exception, etc.
 """
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import warnings
 
 
diff --git a/absl/flags/tests/argparse_flags_test_helper.py b/absl/flags/tests/argparse_flags_test_helper.py
index 8cf42e6..613c896 100644
--- a/absl/flags/tests/argparse_flags_test_helper.py
+++ b/absl/flags/tests/argparse_flags_test_helper.py
@@ -14,10 +14,6 @@
 
 """Test helper for argparse_flags_test."""
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import os
 import random
 
diff --git a/absl/flags/tests/flags_formatting_test.py b/absl/flags/tests/flags_formatting_test.py
index bb547ce..ef55850 100644
--- a/absl/flags/tests/flags_formatting_test.py
+++ b/absl/flags/tests/flags_formatting_test.py
@@ -12,10 +12,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 from absl import flags
 from absl.flags import _helpers
 from absl.testing import absltest
diff --git a/absl/flags/tests/flags_unicode_literals_test.py b/absl/flags/tests/flags_unicode_literals_test.py
index e8ed5bf..1f72f23 100644
--- a/absl/flags/tests/flags_unicode_literals_test.py
+++ b/absl/flags/tests/flags_unicode_literals_test.py
@@ -14,11 +14,6 @@
 
 """Test the use of flags when from __future__ import unicode_literals is on."""
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-from __future__ import unicode_literals
-
 from absl import flags
 from absl.testing import absltest
 
diff --git a/absl/flags/tests/module_bar.py b/absl/flags/tests/module_bar.py
index 8714d2e..51dffa3 100644
--- a/absl/flags/tests/module_bar.py
+++ b/absl/flags/tests/module_bar.py
@@ -18,10 +18,6 @@
 sure the unit tests for flags.py involve more than one module.
 """
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 from absl import flags
 from absl.flags import _helpers
 
diff --git a/absl/flags/tests/module_baz.py b/absl/flags/tests/module_baz.py
index 7199516..9bf03fd 100644
--- a/absl/flags/tests/module_baz.py
+++ b/absl/flags/tests/module_baz.py
@@ -18,10 +18,6 @@
 before main() executes.
 """
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 from absl import flags
 
 FLAGS = flags.FLAGS
diff --git a/absl/flags/tests/module_foo.py b/absl/flags/tests/module_foo.py
index a1a2573..649047c 100644
--- a/absl/flags/tests/module_foo.py
+++ b/absl/flags/tests/module_foo.py
@@ -19,10 +19,6 @@
 for flags.py involve more than one module.
 """
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 from absl import flags
 from absl.flags import _helpers
 from absl.flags.tests import module_bar
diff --git a/absl/logging/tests/converter_test.py b/absl/logging/tests/converter_test.py
index bdc893a..2c95c4f 100644
--- a/absl/logging/tests/converter_test.py
+++ b/absl/logging/tests/converter_test.py
@@ -14,10 +14,6 @@
 
 """Tests for converter.py."""
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import logging
 
 from absl import logging as absl_logging
diff --git a/absl/logging/tests/verbosity_flag_test.py b/absl/logging/tests/verbosity_flag_test.py
index 4609e64..ea9944d 100644
--- a/absl/logging/tests/verbosity_flag_test.py
+++ b/absl/logging/tests/verbosity_flag_test.py
@@ -14,10 +14,6 @@
 
 """Tests -v/--verbosity flag and logging.root level's sync behavior."""
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import logging
 
 assert logging.root.getEffectiveLevel() == logging.WARN, (
diff --git a/absl/testing/BUILD b/absl/testing/BUILD
index b608c8c..d428792 100644
--- a/absl/testing/BUILD
+++ b/absl/testing/BUILD
@@ -199,6 +199,7 @@
     srcs_version = "PY3",
     deps = [
         ":absltest",
+        "//absl:app",
         "//absl/flags",
     ],
 )
diff --git a/absl/testing/_bazelize_command.py b/absl/testing/_bazelize_command.py
index fdf6eb6..9380d27 100644
--- a/absl/testing/_bazelize_command.py
+++ b/absl/testing/_bazelize_command.py
@@ -14,10 +14,6 @@
 
 """Internal helper for running tests on Windows Bazel."""
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import os
 
 from absl import flags
diff --git a/absl/testing/_pretty_print_reporter.py b/absl/testing/_pretty_print_reporter.py
index ef03934..b0dde07 100644
--- a/absl/testing/_pretty_print_reporter.py
+++ b/absl/testing/_pretty_print_reporter.py
@@ -14,10 +14,6 @@
 
 """TestResult implementing default output for test execution status."""
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import unittest
 
 
diff --git a/absl/testing/absltest.py b/absl/testing/absltest.py
index cebb1ca..b7a941b 100644
--- a/absl/testing/absltest.py
+++ b/absl/testing/absltest.py
@@ -531,8 +531,9 @@
   # Literal to express more precise return types. The contained type is
   # currently `Any` to avoid [bad-return-type] errors in the open_* methods.
   @contextlib.contextmanager
-  def _open(self, mode, encoding='utf8', errors='strict'):
-    # type: (Text, Text, Text) -> Iterator[Any]
+  def _open(
+      self, mode: str, encoding: str = 'utf8', errors: str = 'strict'
+  ) -> Iterator[Any]:
     with io.open(
         self.full_path, mode=mode, encoding=encoding, errors=errors) as fp:
       yield fp
@@ -786,24 +787,49 @@
     elif cleanup == TempFileCleanup.ALWAYS:
       self.addCleanup(_rmtree_ignore_errors, path)
     elif cleanup == TempFileCleanup.SUCCESS:
-      self._internal_cleanup_on_success(_rmtree_ignore_errors, path)
+      self._internal_add_cleanup_on_success(_rmtree_ignore_errors, path)
     else:
       raise AssertionError('Unexpected cleanup value: {}'.format(cleanup))
 
-  def _internal_cleanup_on_success(self, function, *args, **kwargs):
-    # type: (Callable[..., object], Any, Any) -> None
+  def _internal_add_cleanup_on_success(
+      self,
+      function: Callable[..., Any],
+      *args: Any,
+      **kwargs: Any,
+  ) -> None:
+    """Adds `function` as cleanup when the test case succeeds."""
+    outcome = self._outcome
+    previous_failure_count = (
+        len(outcome.result.failures)
+        + len(outcome.result.errors)
+        + len(outcome.result.unexpectedSuccesses)
+    )
     def _call_cleaner_on_success(*args, **kwargs):
-      if not self._ran_and_passed():
+      if not self._internal_ran_and_passed_when_called_during_cleanup(
+          previous_failure_count):
         return
       function(*args, **kwargs)
     self.addCleanup(_call_cleaner_on_success, *args, **kwargs)
 
-  def _ran_and_passed(self):
-    # type: () -> bool
+  def _internal_ran_and_passed_when_called_during_cleanup(
+      self,
+      previous_failure_count: int,
+  ) -> bool:
+    """Returns whether test is passed. Expected to be called during cleanup."""
     outcome = self._outcome
-    result = self.defaultTestResult()
-    self._feedErrorsToResult(result, outcome.errors)  # pytype: disable=attribute-error
-    return result.wasSuccessful()
+    if sys.version_info[:2] >= (3, 11):
+      current_failure_count = (
+          len(outcome.result.failures)
+          + len(outcome.result.errors)
+          + len(outcome.result.unexpectedSuccesses)
+      )
+      return current_failure_count == previous_failure_count
+    else:
+      # Before Python 3.11 https://github.com/python/cpython/pull/28180, errors
+      # were bufferred in _Outcome before calling cleanup.
+      result = self.defaultTestResult()
+      self._feedErrorsToResult(result, outcome.errors)  # pytype: disable=attribute-error
+      return result.wasSuccessful()
 
   def shortDescription(self):
     # type: () -> Text
@@ -2036,19 +2062,6 @@
   return False
 
 
-class _SavedFlag(object):
-  """Helper class for saving and restoring a flag value."""
-
-  def __init__(self, flag):
-    self.flag = flag
-    self.value = flag.value
-    self.present = flag.present
-
-  def restore_flag(self):
-    self.flag.value = self.value
-    self.flag.present = self.present
-
-
 def _register_sigterm_with_faulthandler():
   # type: () -> None
   """Have faulthandler dump stacks on SIGTERM.  Useful to diagnose timeouts."""
@@ -2105,29 +2118,30 @@
   if _is_in_app_main():
     _register_sigterm_with_faulthandler()
 
-    # Save command-line flags so the side effects of FLAGS(sys.argv) can be
-    # undone.
-    flag_objects = (FLAGS[name] for name in FLAGS)
-    saved_flags = dict((f.name, _SavedFlag(f)) for f in flag_objects)
-
     # Change the default of alsologtostderr from False to True, so the test
     # programs's stderr will contain all the log messages.
     # If --alsologtostderr=false is specified in the command-line, or user
     # has called FLAGS.alsologtostderr = False before, then the value is kept
     # False.
     FLAGS.set_default('alsologtostderr', True)
-    # Remove it from saved flags so it doesn't get restored later.
-    del saved_flags['alsologtostderr']
 
-    # The call FLAGS(sys.argv) parses sys.argv, returns the arguments
-    # without the flags, and -- as a side effect -- modifies flag values in
-    # FLAGS. We don't want the side effect, because we don't want to
-    # override flag changes the program did (e.g. in __main__.main)
-    # 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 saved_flags.values():
-      saved_flag.restore_flag()
+    # Here we only want to get the `argv` without the flags. To avoid any
+    # side effects of parsing flags, we temporarily stub out the `parse` method
+    stored_parse_methods = {}
+    noop_parse = lambda _: None
+    for name in FLAGS:
+      # Avoid any side effects of parsing flags.
+      stored_parse_methods[name] = FLAGS[name].parse
+    # This must be a separate loop since multiple flag names (short_name=) can
+    # point to the same flag object.
+    for name in FLAGS:
+      FLAGS[name].parse = noop_parse
+    try:
+      argv = FLAGS(sys.argv)
+    finally:
+      for name in FLAGS:
+        FLAGS[name].parse = stored_parse_methods[name]
+      sys.stdout.flush()
 
     function(argv, args, kwargs)
   else:
diff --git a/absl/testing/flagsaver.py b/absl/testing/flagsaver.py
index 7fe95fe..f87dbb1 100644
--- a/absl/testing/flagsaver.py
+++ b/absl/testing/flagsaver.py
@@ -59,10 +59,6 @@
 and then restore flag values, the added flag will be deleted with no errors.
 """
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import functools
 import inspect
 
diff --git a/absl/testing/tests/absltest_fail_fast_test.py b/absl/testing/tests/absltest_fail_fast_test.py
index dc967f9..efde8a0 100644
--- a/absl/testing/tests/absltest_fail_fast_test.py
+++ b/absl/testing/tests/absltest_fail_fast_test.py
@@ -14,10 +14,6 @@
 
 """Tests for test fail fast protocol."""
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import subprocess
 
 from absl import logging
diff --git a/absl/testing/tests/absltest_fail_fast_test_helper.py b/absl/testing/tests/absltest_fail_fast_test_helper.py
index 339a569..a6ffb62 100644
--- a/absl/testing/tests/absltest_fail_fast_test_helper.py
+++ b/absl/testing/tests/absltest_fail_fast_test_helper.py
@@ -14,10 +14,6 @@
 
 """A helper test program for absltest_fail_fast_test."""
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import os
 import sys
 
diff --git a/absl/testing/tests/absltest_filtering_test.py b/absl/testing/tests/absltest_filtering_test.py
index 30a81f6..3bbb219 100644
--- a/absl/testing/tests/absltest_filtering_test.py
+++ b/absl/testing/tests/absltest_filtering_test.py
@@ -13,10 +13,6 @@
 # limitations under the License.
 """Tests for test filtering protocol."""
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import subprocess
 import sys
 
diff --git a/absl/testing/tests/absltest_filtering_test_helper.py b/absl/testing/tests/absltest_filtering_test_helper.py
index 2b741ed..b8bc55f 100644
--- a/absl/testing/tests/absltest_filtering_test_helper.py
+++ b/absl/testing/tests/absltest_filtering_test_helper.py
@@ -14,10 +14,6 @@
 
 """A helper test program for absltest_filtering_test."""
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import os
 import sys
 
diff --git a/absl/testing/tests/absltest_randomization_test.py b/absl/testing/tests/absltest_randomization_test.py
index 75a3868..e73dfce 100644
--- a/absl/testing/tests/absltest_randomization_test.py
+++ b/absl/testing/tests/absltest_randomization_test.py
@@ -14,10 +14,6 @@
 
 """Tests for test randomization."""
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import random
 import subprocess
 
diff --git a/absl/testing/tests/absltest_randomization_testcase.py b/absl/testing/tests/absltest_randomization_testcase.py
index 18b20ff..ac2cea0 100644
--- a/absl/testing/tests/absltest_randomization_testcase.py
+++ b/absl/testing/tests/absltest_randomization_testcase.py
@@ -14,10 +14,6 @@
 
 """Stub tests, only for use in absltest_randomization_test.py."""
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import os
 import sys
 
diff --git a/absl/testing/tests/absltest_sharding_test.py b/absl/testing/tests/absltest_sharding_test.py
index 6411971..9bbb903 100644
--- a/absl/testing/tests/absltest_sharding_test.py
+++ b/absl/testing/tests/absltest_sharding_test.py
@@ -14,10 +14,6 @@
 
 """Tests for test sharding protocol."""
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import os
 import subprocess
 
diff --git a/absl/testing/tests/absltest_sharding_test_helper.py b/absl/testing/tests/absltest_sharding_test_helper.py
index 7b2f20e..57a924c 100644
--- a/absl/testing/tests/absltest_sharding_test_helper.py
+++ b/absl/testing/tests/absltest_sharding_test_helper.py
@@ -14,10 +14,6 @@
 
 """A helper test program for absltest_sharding_test."""
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import sys
 
 from absl.testing import absltest
diff --git a/absl/testing/tests/absltest_test.py b/absl/testing/tests/absltest_test.py
index 48eeca8..43201bd 100644
--- a/absl/testing/tests/absltest_test.py
+++ b/absl/testing/tests/absltest_test.py
@@ -186,6 +186,15 @@
         },
         expect_success=True)
 
+  def test_app_run(self):
+    stdout, _ = self.run_helper(
+        7,
+        ['--name=cat', '--name=dog'],
+        {'ABSLTEST_TEST_HELPER_USE_APP_RUN': '1'},
+        expect_success=True)
+    self.assertIn('Names in main() are: cat dog', stdout)
+    self.assertIn('Names in test_name_flag() are: cat dog', stdout)
+
   def test_assert_in(self):
     animals = {'monkey': 'banana', 'cow': 'grass', 'seal': 'fish'}
 
@@ -2136,6 +2145,11 @@
         'TempFileHelperTest/test_failure',
         'TempFileHelperTest/test_failure/failure',
         'TempFileHelperTest/test_success',
+        'TempFileHelperTest/test_subtest_failure',
+        'TempFileHelperTest/test_subtest_failure/parent',
+        'TempFileHelperTest/test_subtest_failure/successful_child',
+        'TempFileHelperTest/test_subtest_failure/failed_child',
+        'TempFileHelperTest/test_subtest_success',
     }
     self.run_tempfile_helper('SUCCESS', expected)
 
@@ -2144,6 +2158,8 @@
         'TempFileHelperTest',
         'TempFileHelperTest/test_failure',
         'TempFileHelperTest/test_success',
+        'TempFileHelperTest/test_subtest_failure',
+        'TempFileHelperTest/test_subtest_success',
     }
     self.run_tempfile_helper('ALWAYS', expected)
 
@@ -2154,6 +2170,14 @@
         'TempFileHelperTest/test_failure/failure',
         'TempFileHelperTest/test_success',
         'TempFileHelperTest/test_success/success',
+        'TempFileHelperTest/test_subtest_failure',
+        'TempFileHelperTest/test_subtest_failure/parent',
+        'TempFileHelperTest/test_subtest_failure/successful_child',
+        'TempFileHelperTest/test_subtest_failure/failed_child',
+        'TempFileHelperTest/test_subtest_success',
+        'TempFileHelperTest/test_subtest_success/parent',
+        'TempFileHelperTest/test_subtest_success/child0',
+        'TempFileHelperTest/test_subtest_success/child1',
     }
     self.run_tempfile_helper('OFF', expected)
 
@@ -2163,8 +2187,8 @@
   def test_incorrect_decorator_call(self):
     with self.assertRaises(TypeError):
 
-      @absltest.skipThisClass  # pylint: disable=unused-variable
-      class Test(absltest.TestCase):
+      @absltest.skipThisClass
+      class Test(absltest.TestCase):  # pylint: disable=unused-variable
         pass
 
   def test_incorrect_decorator_subclass(self):
diff --git a/absl/testing/tests/absltest_test_helper.py b/absl/testing/tests/absltest_test_helper.py
index c6b2465..89b6721 100644
--- a/absl/testing/tests/absltest_test_helper.py
+++ b/absl/testing/tests/absltest_test_helper.py
@@ -14,26 +14,34 @@
 
 """Helper binary for absltest_test.py."""
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import os
 import tempfile
 import unittest
 
+from absl import app
 from absl import flags
 from absl.testing import absltest
 
 FLAGS = flags.FLAGS
 
-flags.DEFINE_integer('test_id', 0, 'Which test to run.')
+_TEST_ID = flags.DEFINE_integer('test_id', 0, 'Which test to run.')
+_NAME = flags.DEFINE_multi_string('name', [], 'List of names to print.')
+
+
+@flags.validator('name')
+def validate_name(value):
+  # This validator makes sure that the second FLAGS(sys.argv) inside
+  # absltest.main() won't actually trigger side effects of the flag parsing.
+  if len(value) > 2:
+    raise flags.ValidationError(
+        f'No more than two names should be specified, found {len(value)} names')
+  return True
 
 
 class HelperTest(absltest.TestCase):
 
   def test_flags(self):
-    if FLAGS.test_id == 1:
+    if _TEST_ID.value == 1:
       self.assertEqual(FLAGS.test_random_seed, 301)
       if os.name == 'nt':
         # On Windows, it's always in the temp dir, which doesn't start with '/'.
@@ -45,7 +53,7 @@
           '--test_tmpdir={} does not start with {}'.format(
               absltest.TEST_TMPDIR.value, expected_prefix))
       self.assertTrue(os.access(absltest.TEST_TMPDIR.value, os.W_OK))
-    elif FLAGS.test_id == 2:
+    elif _TEST_ID.value == 2:
       self.assertEqual(FLAGS.test_random_seed, 321)
       self.assertEqual(
           absltest.TEST_SRCDIR.value,
@@ -53,7 +61,7 @@
       self.assertEqual(
           absltest.TEST_TMPDIR.value,
           os.environ['ABSLTEST_TEST_HELPER_EXPECTED_TEST_TMPDIR'])
-    elif FLAGS.test_id == 3:
+    elif _TEST_ID.value == 3:
       self.assertEqual(FLAGS.test_random_seed, 123)
       self.assertEqual(
           absltest.TEST_SRCDIR.value,
@@ -61,7 +69,7 @@
       self.assertEqual(
           absltest.TEST_TMPDIR.value,
           os.environ['ABSLTEST_TEST_HELPER_EXPECTED_TEST_TMPDIR'])
-    elif FLAGS.test_id == 4:
+    elif _TEST_ID.value == 4:
       self.assertEqual(FLAGS.test_random_seed, 221)
       self.assertEqual(
           absltest.TEST_SRCDIR.value,
@@ -71,26 +79,35 @@
           os.environ['ABSLTEST_TEST_HELPER_EXPECTED_TEST_TMPDIR'])
     else:
       raise unittest.SkipTest(
-          'Not asked to run: --test_id={}'.format(FLAGS.test_id))
+          'Not asked to run: --test_id={}'.format(_TEST_ID.value))
 
   @unittest.expectedFailure
   def test_expected_failure(self):
-    if FLAGS.test_id == 5:
+    if _TEST_ID.value == 5:
       self.assertEqual(1, 1)  # Expected failure, got success.
     else:
       self.assertEqual(1, 2)  # The expected failure.
 
   def test_xml_env_vars(self):
-    if FLAGS.test_id == 6:
+    if _TEST_ID.value == 6:
       self.assertEqual(
           FLAGS.xml_output_file,
           os.environ['ABSLTEST_TEST_HELPER_EXPECTED_XML_OUTPUT_FILE'])
     else:
       raise unittest.SkipTest(
-          'Not asked to run: --test_id={}'.format(FLAGS.test_id))
+          'Not asked to run: --test_id={}'.format(_TEST_ID.value))
+
+  def test_name_flag(self):
+    if _TEST_ID.value == 7:
+      print('Names in test_name_flag() are:', ' '.join(_NAME.value))
+    else:
+      raise unittest.SkipTest(
+          'Not asked to run: --test_id={}'.format(_TEST_ID.value))
 
 
 class TempFileHelperTest(absltest.TestCase):
+  """Helper test case for tempfile cleanup tests."""
+
   tempfile_cleanup = absltest.TempFileCleanup[os.environ.get(
       'ABSLTEST_TEST_HELPER_TEMPFILE_CLEANUP', 'SUCCESS')]
 
@@ -101,6 +118,29 @@
   def test_success(self):
     self.create_tempfile('success')
 
+  def test_subtest_failure(self):
+    self.create_tempfile('parent')
+    with self.subTest('success'):
+      self.create_tempfile('successful_child')
+    with self.subTest('failure'):
+      self.create_tempfile('failed_child')
+      self.fail('expected failure')
+
+  def test_subtest_success(self):
+    self.create_tempfile('parent')
+    for i in range(2):
+      with self.subTest(f'success{i}'):
+        self.create_tempfile(f'child{i}')
+
+
+def main(argv):
+  del argv  # Unused.
+  print('Names in main() are:', ' '.join(_NAME.value))
+  absltest.main()
+
 
 if __name__ == '__main__':
-  absltest.main()
+  if os.environ.get('ABSLTEST_TEST_HELPER_USE_APP_RUN'):
+    app.run(main)
+  else:
+    absltest.main()
diff --git a/absl/testing/tests/flagsaver_test.py b/absl/testing/tests/flagsaver_test.py
index 3439a32..e98cd06 100644
--- a/absl/testing/tests/flagsaver_test.py
+++ b/absl/testing/tests/flagsaver_test.py
@@ -13,10 +13,6 @@
 # limitations under the License.
 """Tests for flagsaver."""
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 from absl import flags
 from absl.testing import absltest
 from absl.testing import flagsaver
diff --git a/absl/testing/tests/xml_reporter_helper_test.py b/absl/testing/tests/xml_reporter_helper_test.py
index 661bbdc..af3c63d 100644
--- a/absl/testing/tests/xml_reporter_helper_test.py
+++ b/absl/testing/tests/xml_reporter_helper_test.py
@@ -12,10 +12,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import random
 
 from absl import flags
diff --git a/absl/testing/xml_reporter.py b/absl/testing/xml_reporter.py
index da56e39..5996ce2 100644
--- a/absl/testing/xml_reporter.py
+++ b/absl/testing/xml_reporter.py
@@ -14,10 +14,6 @@
 
 """A Python test reporter that generates test reports in JUnit XML format."""
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import datetime
 import re
 import sys
diff --git a/absl/tests/app_test_helper.py b/absl/tests/app_test_helper.py
index 6bd1a89..f9fbdec 100644
--- a/absl/tests/app_test_helper.py
+++ b/absl/tests/app_test_helper.py
@@ -14,10 +14,6 @@
 
 """Helper script used by app_test.py."""
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import os
 import sys
 
diff --git a/setup.py b/setup.py
index 13b2353..23fcac2 100644
--- a/setup.py
+++ b/setup.py
@@ -14,10 +14,6 @@
 
 """Abseil setup configuration."""
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import os
 import sys
 
@@ -47,7 +43,7 @@
 
 setuptools.setup(
     name='absl-py',
-    version='1.1.0',
+    version='1.2.0',
     description=(
         'Abseil Python Common Libraries, '
         'see https://github.com/abseil/abseil-py.'),
@@ -68,6 +64,7 @@
         'Programming Language :: Python :: 3.8',
         'Programming Language :: Python :: 3.9',
         'Programming Language :: Python :: 3.10',
+        'Programming Language :: Python :: 3.11',
         'Intended Audience :: Developers',
         'Topic :: Software Development :: Libraries :: Python Modules',
         'License :: OSI Approved :: Apache Software License',
diff --git a/smoke_tests/sample_app.py b/smoke_tests/sample_app.py
index 532a11e..d45be96 100644
--- a/smoke_tests/sample_app.py
+++ b/smoke_tests/sample_app.py
@@ -14,10 +14,6 @@
 
 """Test helper for smoke_test.sh."""
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 import sys
 
 from absl import app
diff --git a/smoke_tests/sample_test.py b/smoke_tests/sample_test.py
index 713677a..2d3f3e4 100644
--- a/smoke_tests/sample_test.py
+++ b/smoke_tests/sample_test.py
@@ -14,10 +14,6 @@
 
 """Test helper for smoke_test.sh."""
 
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
 from absl.testing import absltest