I wasn't getting any Mypy error with Mypy 0.812.
But after upgrading Mypy to latest (1.14.1) I am getting below error.
error: Argument 1 to "_redirect_stdout" has incompatible type "StringIO"; expected "TextIOWrapper[_WrappedBuffer]" [arg-type]
Please help me to understand
@contextlib.contextmanager
def _redirect_stdout(
new_target: io.TextIOWrapper
) -> Generator[io.TextIOWrapper, None, None]:
old_target = sys.stdout
sys.stdout = new_target
try:
yield new_target
finally:
sys.stdout = old_target
target_stdout = io.StringIO()
with _redirect_stdout(target_stdout):
print(['These', 'are', 'sample', 'strings.'])
Mypy 0.812 is ancient: It was released in February 2021. There have been many, many changes since then. This answer will thus not cover the "exact" change, if there is even such a thing.
The type StringIO
is not assignable to TextIOWrapper
, as they are defined as different classes, and with different bases, to boot:
# https://github.com/python/typeshed/blob/101287091c/stdlib/_io.pyi#L157
class TextIOWrapper(TextIOBase, _TextIOBase, TextIO, Generic[_BufferT_co]):
...
# https://github.com/python/typeshed/blob/101287091c/stdlib/_io.pyi#L191
class StringIO(TextIOBase, _TextIOBase, TextIO):
...
They do, however, share a few base classes. _TextIOBase
is private, as signalled by its name, so it's out of the question. That leaves TextIOBase
and TextIO
:
from io import StringIO, TextIOBase
from typing import TextIO
def a(v: TextIOBase) -> None: ...
def b(v: TextIO) -> None: ...
a(StringIO()) # fine
b(StringIO()) # fine
sys.stdout
has the type TextIO
, so the best choice overall is TextIO
:
# https://github.com/python/typeshed/blob/101287091c/stdlib/sys/__init__.pyi#L67
stdout: TextIO | MaybeNone