/Lib/_compression.py (b00f31b400c3f3afc17658951168618dc15df8b1) (5340 bytes) (mode 100644) (type blob)
"""Internal classes used by the gzip, lzma and bz2 modules"""
import io
BUFFER_SIZE = io.DEFAULT_BUFFER_SIZE # Compressed data read chunk size
class 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 True
def __init__(self, fp, decomp_factory, trailing_error=(), **decomp_args):
self._fp = fp
self._eof = False
self._pos = 0 # Current offset in decompressed stream
# Set to size of decompressed stream once it is known, for SEEK_END
self._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_factory
self._decomp_args = decomp_args
self._decompressor = self._decomp_factory(**self._decomp_args)
# Exception class to catch from decompressor signifying invalid
# trailing data to ignore
self._trailing_error = trailing_error
def close(self):
self._decompressor = None
return 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)] = data
return 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 or
self._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.
break
else:
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:
break
if not data:
self._eof = True
self._size = self._pos
return 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 = False
self._pos = 0
self._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:
pass
elif whence == io.SEEK_CUR:
offset = self._pos + offset
elif 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):
pass
offset = self._size + offset
else:
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:
break
offset -= len(data)
return self._pos
def tell(self):
"""Return the current file position."""
return self._pos
Mode |
Type |
Size |
Ref |
File |
100644 |
blob |
582 |
58471109208922c9ee8c4b06135725f03ed16814 |
.bzrignore |
100644 |
blob |
545 |
fcf9df6a7a698e4bd87ed0c1cc4ed70bad8b9887 |
.codecov.yml |
100644 |
blob |
255 |
82694d81f276b2c59a0a93a4f678e1852e625052 |
.gitattributes |
040000 |
tree |
- |
7e849e161267e730810fbbe6a848b14d5d002788 |
.github |
100644 |
blob |
1397 |
8b54c2c4861389f6e8bbfbab5ae0c8b6bbbad041 |
.gitignore |
100644 |
blob |
1060 |
eb19a6c88d28d05588db25d21525ee2e19c22666 |
.hgeol |
100644 |
blob |
1358 |
68c607f2e8d420c8dfd0748efcd3b3b5447def16 |
.hgignore |
100644 |
blob |
8917 |
8f51c2ced49aed46d8b480280b630ea4264c57c3 |
.hgtags |
100644 |
blob |
1328 |
b9be0f11fdb829f16e9de1921257eb7ee45fac57 |
.hgtouch |
100644 |
blob |
248 |
0614a299b6221dc7faedaa9139ae8b034e618a85 |
.mention-bot |
100644 |
blob |
3512 |
e7e8694530ca21a6d7a19da3fab687a3e9d79e9c |
.travis.yml |
040000 |
tree |
- |
ab6ef0c3da91d215c813859260aa9d0724504633 |
Doc |
040000 |
tree |
- |
5dd6fc9dc09374506491247872c868eca111e256 |
Grammar |
040000 |
tree |
- |
df0de9d4359f11311c74fd0dbad471bb2613a2d4 |
Include |
100644 |
blob |
12773 |
f5d0b39a0cdddb91a31a537052b7d8d31a4aa79f |
LICENSE |
040000 |
tree |
- |
35e9c80068a1b6441f6a676002e031d908be567f |
Lib |
040000 |
tree |
- |
1db7415d4375525eaf8d05ddd5b088de3321041c |
Mac |
100644 |
blob |
58983 |
4145634c032d543d02295bd2c28a0c6ce839fa86 |
Makefile.pre.in |
040000 |
tree |
- |
6854ababa88443950a60516508b6994cfd8888db |
Misc |
040000 |
tree |
- |
92e4f07c6b277cc3dae87514f9cebce860ec55ba |
Modules |
040000 |
tree |
- |
cec92311ba9c836d7f68a2d6e24b27e8287ac690 |
Objects |
040000 |
tree |
- |
ed4f35810e9633502c16ae038c2ce697d3987201 |
PC |
040000 |
tree |
- |
37a613ac0022a9cfefaf3f13913fec7debe59259 |
PCbuild |
040000 |
tree |
- |
bfcd1ca2e85b8724b1b7be4e0673b90220a04e7c |
Parser |
040000 |
tree |
- |
3efbcc80237ab7c3d4eb5bf31c893ca6de88e747 |
Programs |
040000 |
tree |
- |
8f832869b53d99ee02d78ea0cc8491d3882222da |
Python |
100644 |
blob |
9325 |
9c95815d9e9d91b8dae8e05d8bbc696fe19f796b |
README.rst |
040000 |
tree |
- |
66b8a7e032e5538a9a2e08422da3716c50e91a4b |
Tools |
100644 |
blob |
10910 |
9a9cc557281571f0d46c506c0e9d1b9fb25e063c |
aclocal.m4 |
100755 |
blob |
42856 |
1f5c50c0d1529d50b94dc3533ca72a47f0fa5849 |
config.guess |
100755 |
blob |
35740 |
d654d03cdcd2226a5d7584890717e674a8122f4f |
config.sub |
100755 |
blob |
485283 |
87504d206837baf5a5781b6e1cc44dcce7138af9 |
configure |
100644 |
blob |
160661 |
f9bd92ce3da29ea7674a32bd5fe511b1fc4c4d0a |
configure.ac |
100755 |
blob |
7122 |
0ec27bcd488da5cad6ead13d70accbdbc40d31ef |
install-sh |
100644 |
blob |
41449 |
21354a5cb84fe5530dd0d460561ba95569abe1d4 |
pyconfig.h.in |
100644 |
blob |
98743 |
3b3d097454211c790c1602d759918bb65a622c97 |
setup.py |
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"
Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/benf_wspdigital/cpython
Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/benf_wspdigital/cpython
Clone this repository using git:
git clone git://git.rocketgit.com/user/benf_wspdigital/cpython
You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a
merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main