Description
Using hashlib.file_digest
with a file object obtained via pathlib.Path.open
failed to typecheck with a protocol compatibility error:
src/create_bundles.py:223: error: Argument 1 to "file_digest" has incompatible type "FileIO"; expected "_BytesIOLike | _FileDigestFileObj" [arg-type]
src/create_bundles.py:223: note: Following member(s) of "FileIO" have conflicts:
src/create_bundles.py:223: note: Expected:
src/create_bundles.py:223: note: def readinto(self, bytearray, /) -> int
src/create_bundles.py:223: note: Got:
src/create_bundles.py:223: note: def readinto(self, Buffer, /) -> int | None
I'm reasonably sure this is a typeshed
issue rather than a mypy
issue.
My first thought was that this looks like an internal inconsistency in typeshed
, as _FileDigestFileObj
is declared specifically with bytearray
rather than the more general WriteableBuffer
(hence filing the issue here).
However, my second thought was that this signature declaration is presumably as it is because file_digest
will specifically pass a bytearray
instance to readinto
, and bytearray
is compatible with Buffer
, so mypy
shouldn't be complaining about that. That means the conflict is presumably on the return type rather than on parameter types.
The declared type signature nominally indicates that file_digest
can't cope with readinto
returning None
, and mypy
is correctly flagging that as inconsistent with the way typeshed
declares the file and socket IO types (allowing them to return None
here).
Searching the typeshed code suggests this particular inconsistency exists across several different IO consumer type declarations: https://github.com/search?q=repo%3Apython%2Ftypeshed%20readinto&type=code