"""Internal classes used by the gzip, lzma and bz2 modules"""import ioBUFFER_SIZE = io.DEFAULT_BUFFER_SIZE # Compressed data read chunk sizeclass BaseStream(io.BufferedIOBase):"""Mode-checking helper functions."""def _check_not_closed(self):if self.closed:raise ValueError("I/O operation on closed file")def _check_can_read(self):if not self.readable():raise io.UnsupportedOperation("File not open for reading")def _check_can_write(self):if not self.writable():raise io.UnsupportedOperation("File not open for writing")def _check_can_seek(self):if not self.readable():raise io.UnsupportedOperation("Seeking is only supported ""on files open for reading")if not self.seekable():raise io.UnsupportedOperation("The underlying file object ""does not support seeking")class DecompressReader(io.RawIOBase):"""Adapts the decompressor API to a RawIOBase reader API"""def readable(self):return Truedef __init__(self, fp, decomp_factory, trailing_error=(), **decomp_args):self._fp = fpself._eof = Falseself._pos = 0 # Current offset in decompressed stream# Set to size of decompressed stream once it is known, for SEEK_ENDself._size = -1# Save the decompressor factory and arguments.# If the file contains multiple compressed streams, each# stream will need a separate decompressor object. A new decompressor# object is also needed when implementing a backwards seek().self._decomp_factory = decomp_factoryself._decomp_args = decomp_argsself._decompressor = self._decomp_factory(**self._decomp_args)# Exception class to catch from decompressor signifying invalid# trailing data to ignoreself._trailing_error = trailing_errordef close(self):self._decompressor = Nonereturn super().close()def seekable(self):return self._fp.seekable()def readinto(self, b):with memoryview(b) as view, view.cast("B") as byte_view:data = self.read(len(byte_view))byte_view[:len(data)] = datareturn len(data)def read(self, size=-1):if size < 0:return self.readall()if not size or self._eof:return b""data = None # Default if EOF is encountered# Depending on the input data, our call to the decompressor may not# return any data. In this case, try again after reading another block.while True:if self._decompressor.eof:rawblock = (self._decompressor.unused_data orself._fp.read(BUFFER_SIZE))if not rawblock:break# Continue to next stream.self._decompressor = self._decomp_factory(**self._decomp_args)try:data = self._decompressor.decompress(rawblock, size)except self._trailing_error:# Trailing data isn't a valid compressed stream; ignore it.breakelse:if self._decompressor.needs_input:rawblock = self._fp.read(BUFFER_SIZE)if not rawblock:raise EOFError("Compressed file ended before the ""end-of-stream marker was reached")else:rawblock = b""data = self._decompressor.decompress(rawblock, size)if data:breakif not data:self._eof = Trueself._size = self._posreturn b""self._pos += len(data)return data# Rewind the file to the beginning of the data stream.def _rewind(self):self._fp.seek(0)self._eof = Falseself._pos = 0self._decompressor = self._decomp_factory(**self._decomp_args)def seek(self, offset, whence=io.SEEK_SET):# Recalculate offset as an absolute file position.if whence == io.SEEK_SET:passelif whence == io.SEEK_CUR:offset = self._pos + offsetelif whence == io.SEEK_END:# Seeking relative to EOF - we need to know the file's size.if self._size < 0:while self.read(io.DEFAULT_BUFFER_SIZE):passoffset = self._size + offsetelse:raise ValueError("Invalid value for whence: {}".format(whence))# Make it so that offset is the number of bytes to skip forward.if offset < self._pos:self._rewind()else:offset -= self._pos# Read and discard data until we reach the desired position.while offset > 0:data = self.read(min(io.DEFAULT_BUFFER_SIZE, offset))if not data:breakoffset -= len(data)return self._posdef tell(self):"""Return the current file position."""return self._pos
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。