Consider the following code:
from io import TextIOWrapper
from typing import List
from zipfile import ZipFile
def read_zip_lines(zippath: str, filename: str) -> List[str]:
with ZipFile(zippath) as zf:
with zf.open(filename) as bfp:
with TextIOWrapper(bfp, 'utf-8') as fp:
return fp.readlines()
Running mypy v0.782 on the above code under Python 3.6.9 fails with the following error:
zfopen.py:8: error: Argument 1 to "TextIOWrapper" has incompatible type "IO[bytes]"; expected "BinaryIO"
However, I feel that this code should not be regarded as an error, as ZipFile.open()
returns a binary filehandle, which TextIOWrapper
accepts. Moreover, IO[bytes]
and BinaryIO
are (as far as I understand) effectively the same thing; it's just that BinaryIO
is declared as a subclass of IO[bytes]
. I would naïvely expect IO[bytes]
to be accepted everywhere that BinaryIO
is, except that's not how subclasses work, and I'm not sure how to properly make use of this subclassing when typing.
Who is in error here, and how does the error get fixed?
ZipFile.open()
as IO[bytes]
instead of BinaryIO
?TextIOWrapper
as BinaryIO
instead of IO[bytes]
?typing
module in error for making BinaryIO
a subclass of IO[bytes]
instead of an alias?bfp
?bfp
to be passable to TextIOWrapper
unmodified?This shorter test case with mypy 0.782 gets the same error:
binary_file = io.open('foo.bin', 'rb')
text_file = io.TextIOWrapper(binary_file, encoding='utf-8', newline='')
whether binary_file
is explicitly declared as IO[bytes]
or inferred.
Fix: Use mypy 0.770
or mypy 0.790
.
It was a regression in mypy's typeshed (Issue 4349) and the fix is in mypy 0.790, fixing both zipfile.open()
and io.open()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With