Accurate return types for ZipFile.open() and zipfile.Path.open()#13069
Accurate return types for ZipFile.open() and zipfile.Path.open()#13069AT0myks wants to merge 4 commits into
ZipFile.open() and zipfile.Path.open()#13069Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Sorry for the late reply. I've noticed that there are unnecessary version_info branches both in |
|
Diff from mypy_primer, showing the effect of this PR on open source code: static-frame (https://github.com/static-frame/static-frame)
+ static_frame/core/archive_npy.py:349: error: Argument 1 to "to_npy" of "NPYConverter" has incompatible type "_ZipWriteFile | IO[bytes]"; expected "IO[bytes]" [arg-type]
+ static_frame/core/archive_npy.py:356: error: Argument 1 to "from_npy" of "NPYConverter" has incompatible type "ZipExtFile | IO[bytes]"; expected "IO[bytes]" [arg-type]
+ static_frame/core/archive_npy.py:367: error: Argument 1 to "header_from_npy" of "NPYConverter" has incompatible type "ZipExtFile | IO[bytes]"; expected "IO[bytes]" [arg-type]
+ static_frame/core/archive_npy.py:552: error: Argument 1 to "to_npy" of "NPYConverter" has incompatible type "_ZipWriteFile"; expected "IO[bytes]" [arg-type]
+ static_frame/core/archive_npy.py:560: error: Argument 1 to "from_npy" of "NPYConverter" has incompatible type "ZipExtFile"; expected "IO[bytes]" [arg-type]
+ static_frame/core/archive_npy.py:572: error: Argument 1 to "header_from_npy" of "NPYConverter" has incompatible type "ZipExtFile"; expected "IO[bytes]" [arg-type]
|
srittau
left a comment
There was a problem hiding this comment.
Thanks, as I'm on a personal crusade to eliminate IO from typeshed, I very much welcome any PR working towards this goal. Comments below.
| @overload | ||
| def open( | ||
| self, name: str | ZipInfo, mode: Literal["w"] = ..., pwd: bytes | None = None, *, force_zip64: bool = False |
There was a problem hiding this comment.
This would imply that this overload would also apply if no mode argument is given, which obviously isn't true. Also, since pwd is only allowed when reading files:
| @overload | |
| def open( | |
| self, name: str | ZipInfo, mode: Literal["w"] = ..., pwd: bytes | None = None, *, force_zip64: bool = False | |
| @overload | |
| def open( | |
| self, name: str | ZipInfo, mode: Literal["w"], pwd: None = None, *, force_zip64: bool = False |
| @overload | ||
| def open( | ||
| self, name: str | ZipInfo, mode: _ReadWriteMode = "r", pwd: bytes | None = None, *, force_zip64: bool = False | ||
| self, name: str | ZipInfo, mode: _ReadWriteMode, pwd: bytes | None = None, *, force_zip64: bool = False | ||
| ) -> IO[bytes]: ... |
There was a problem hiding this comment.
I suggest to leave out this "fallback" overload. If this causes too much trouble, mypy_primer in our CI should warn us.
| @overload | ||
| def open(self, mode: _ReadWriteMode, pwd: bytes | None = None, *, force_zip64: bool = False) -> IO[bytes]: ... |
There was a problem hiding this comment.
See above: I would skip this overload.
| @overload | ||
| def open(self, mode: Literal["w"] = ..., pwd: bytes | None = None, *, force_zip64: bool = False) -> _ZipWriteFile: ... |
There was a problem hiding this comment.
As above:
| @overload | |
| def open(self, mode: Literal["w"] = ..., pwd: bytes | None = None, *, force_zip64: bool = False) -> _ZipWriteFile: ... | |
| @overload | |
| def open(self, mode: Literal["w"], pwd: None = None, *, force_zip64: bool = False) -> _ZipWriteFile: ... |
| def open(self, mode: Literal["rb", "wb"], *, pwd: bytes | None = None) -> IO[bytes]: ... | ||
| def open(self, mode: Literal["rb"], *, pwd: bytes | None = None) -> ZipExtFile: ... | ||
| @overload | ||
| def open(self, mode: Literal["wb"], *, pwd: bytes | None = None) -> _ZipWriteFile: ... |
There was a problem hiding this comment.
As above:
| def open(self, mode: Literal["wb"], *, pwd: bytes | None = None) -> _ZipWriteFile: ... | |
| def open(self, mode: Literal["wb"], *, pwd: None = None) -> _ZipWriteFile: ... |
| def open(self, mode: Literal["rb", "wb"], *, pwd: bytes | None = None) -> IO[bytes]: ... | ||
| def open(self, mode: Literal["rb"], *, pwd: bytes | None = None) -> ZipExtFile: ... | ||
| @overload | ||
| def open(self, mode: Literal["wb"], *, pwd: bytes | None = None) -> _ZipWriteFile: ... |
There was a problem hiding this comment.
| def open(self, mode: Literal["wb"], *, pwd: bytes | None = None) -> _ZipWriteFile: ... | |
| def open(self, mode: Literal["wb"], *, pwd: None = None) -> _ZipWriteFile: ... |
An attempt to close #13051. Initially I used
SizedBufferfordatain_ZipWriteFile.write()but this resulted in LSP violations.For Python 3.8
_ReadWriteBinaryModeis replaced by_ReadWriteModeinzipfile.Path.open()because it did not yet accept modesrbandwb.If I understand correctly, tests are failing because
zipfile.Path.open(mode="rb")which now returnsZipExtFiledoes not comply anymore withimportlib.abc.Traversable.open(mode="rb")which returnsIO[bytes]and I'm not sure how this should be addressed.