From 2e9e5d1dc33837a6b870e6e11759f2a90c24515e Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Wed, 4 Dec 2019 10:25:12 -0800 Subject: [PATCH] Fix an upcoming pytype error in absltest. I'm working on an improvement to pytype's type-checking of function type comments, which exposes an annotation error in absltest. _TempFile._open() was annotated as returning Union[TextIO, BinaryIO] but is used as: def open_text(...) -> ContextManager[TextIO]: ... return self._open(...) which will cause pytype to complain about open_text returning bytes when text is expected. The proper way to fix this issue would be to use typing.overload and typing.Literal to define multiple signatures for _open(), but pytype doesn't fully support Literal yet, so I've added type comments with the right types in open_text() and open_bytes(). This change also fixes a mistake in the return annotation on _open() and alphabetically orders all typing imports. PiperOrigin-RevId: 283783117 Change-Id: I4d78a9eb1c98218e62a9b0662931213f7c5c1668 --- absl/testing/absltest.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/absl/testing/absltest.py b/absl/testing/absltest.py index 39acba19..180f9045 100644 --- a/absl/testing/absltest.py +++ b/absl/testing/absltest.py @@ -70,7 +70,7 @@ try: # pylint: disable=unused-import import typing - from typing import AnyStr, Callable, Text, Optional, ContextManager, TextIO, BinaryIO, Union, Type, Tuple, Any, MutableSequence, Sequence, Mapping, MutableMapping, IO, List + from typing import Any, AnyStr, BinaryIO, Callable, ContextManager, IO, Iterator, List, Mapping, MutableMapping, MutableSequence, Optional, Sequence, Text, TextIO, Tuple, Type, Union # pylint: enable=unused-import except ImportError: pass @@ -484,7 +484,8 @@ def open_text(self, mode='rt', encoding='utf8', errors='strict'): 'file in text mode'.format(mode)) if 't' not in mode: mode += 't' - return self._open(mode, encoding, errors) + cm = self._open(mode, encoding, errors) # type: ContextManager[TextIO] + return cm def open_bytes(self, mode='rb'): # type: (Text) -> ContextManager[BinaryIO] @@ -505,11 +506,15 @@ def open_bytes(self, mode='rb'): 'file in binary mode'.format(mode)) if 'b' not in mode: mode += 'b' - return self._open(mode, encoding=None, errors=None) + cm = self._open(mode, encoding=None, errors=None) # type: ContextManager[BinaryIO] + return cm + # TODO(b/123775699): Once pytype supports typing.Literal, use overload and + # Literal to express more precise return types and remove the type comments in + # open_text and open_bytes. @contextlib.contextmanager def _open(self, mode, encoding='utf8', errors='strict'): - # type: (Text, Text, Text) -> Union[TextIO, BinaryIO] + # type: (Text, Text, Text) -> Iterator[Union[IO[Text], IO[bytes]]] with io.open( self.full_path, mode=mode, encoding=encoding, errors=errors) as fp: yield fp