-
Notifications
You must be signed in to change notification settings - Fork 256
Make bytearray automatically compatible with bytes? #552
New issue
Have a question about this project? No Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “No Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? No Sign in to your account
Comments
SGTM
|
Sounds reasonable. For completeness, here's some reasoning behind the design decision in mypy. The promotion was implemented due to a combination of factors:
There is at least one somewhat common idiom where the promotion can cause trouble: def question(s: AnyStr) -> AnyStr:
if isinstance(s, bytes):
return s + b'?'
else:
return s + '?'
question(bytearray(b'foo')) # Error This can often be worked around by using |
Perhaps we can also pretend |
Here is a concrete case where it's a problem for import bz2, gzip, lzma, os
from typing import Union
def do_recompression(wfd: int, rfd: int, ext: str) -> None:
"""Decompress data from RFP (which may be in either .gz or .bz2
format) and write recompressed data to WFP. If this process
succeeds, change the file timestamps on WFP to match RFP and
sync WFP to persistent storage.
"""
rfp = os.fdopen(rfd, mode="rb", closefd=False)
rd: Union[gzip.GzipFile, bz2.BZ2File]
if ext == '.gz':
rd = gzip.GzipFile(fileobj=rfp, mode="rb")
elif ext == '.bz2':
rd = bz2.BZ2File(rfp, mode="rb")
else:
# Caller should have ensured that one of the above two cases
# is true.
raise RuntimeError("can't get here")
wfp = os.fdopen(wfd, mode="wb", closefd=False)
wr = lzma.LZMAFile(wfp, mode="wb", format=lzma.FORMAT_XZ,
check=lzma.CHECK_SHA256, preset=9)
# work in 16 megabyte chunks
# wrapping the bytearray in a memoryview allows us to slice
# it without copying
block = memoryview(bytearray(16*1024*1024))
# with-block ensures rd and wr are flushed and closed
# before their file descriptors are
with rd, wr:
while True:
nread = rd.readinto(block)
if nread == 0:
break
wr.write(block[:nread])
st = os.stat(rfd)
os.utime(wfd, ns=(st.st_atime_ns, st.st_mtime_ns))
os.fsync(wfd) mypy objects to both reading and writing into the memoryview, even though this is perfectly acceptable (and documented to work). If I didn't have the memoryview, the
|
What is the status here? https://docs.python.org/3/library/typing.html#typing.ByteString says:
But I see no language in PEP 484. Is there consensus and we just need to update the PEP? (This came up in python/typeshed#4500 (comment)) |
FWIW, typeshed has handled it as described in the docs for as long as I can remember. |
Closing this here. This is at least documented in the typing docs (see above) and this handled correctly by type checkers AFAIK. If there are still issues open surrounding this, please open issues in the corresponding issue trackers. |
mypy 0.910 accepts the test program I posted back in 2019, so I'm satisfied this is resolved. |
mypy automatically promotes bytearray to bytes, which means bytearray objects are accepted for arguments declared as bytes. The motivation in mypy's code is that convenience trumps safety (most function that accept bytes really do accept bytearray) even though the promotion is technically unsafe (https://github.com/python/mypy/blob/41641a021b17cebe5cbd016fb3e5dc1eb552adb8/mypy/semanal.py#L127).
Should we specify in PEP 484 that type checkers should perform this promotion? We already put something similar for float/int (https://www.python.org/dev/peps/pep-0484/#the-numeric-tower) and for int/long and str/unicode in Python 2. If people agree that this promotion should also be standardized, I can make a PR to update the PEP.
I came across this because I realized that I've been relying on the bytearray/bytes promotion in typeshed, but typeshed technically shouldn't rely on this since it's a mypy extension to the standard.
The text was updated successfully, but these errors were encountered: