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