1*cda5da8dSAndroid Build Coastguard Worker"""Interface to the libbzip2 compression library. 2*cda5da8dSAndroid Build Coastguard Worker 3*cda5da8dSAndroid Build Coastguard WorkerThis module provides a file interface, classes for incremental 4*cda5da8dSAndroid Build Coastguard Worker(de)compression, and functions for one-shot (de)compression. 5*cda5da8dSAndroid Build Coastguard Worker""" 6*cda5da8dSAndroid Build Coastguard Worker 7*cda5da8dSAndroid Build Coastguard Worker__all__ = ["BZ2File", "BZ2Compressor", "BZ2Decompressor", 8*cda5da8dSAndroid Build Coastguard Worker "open", "compress", "decompress"] 9*cda5da8dSAndroid Build Coastguard Worker 10*cda5da8dSAndroid Build Coastguard Worker__author__ = "Nadeem Vawda <[email protected]>" 11*cda5da8dSAndroid Build Coastguard Worker 12*cda5da8dSAndroid Build Coastguard Workerfrom builtins import open as _builtin_open 13*cda5da8dSAndroid Build Coastguard Workerimport io 14*cda5da8dSAndroid Build Coastguard Workerimport os 15*cda5da8dSAndroid Build Coastguard Workerimport _compression 16*cda5da8dSAndroid Build Coastguard Worker 17*cda5da8dSAndroid Build Coastguard Workerfrom _bz2 import BZ2Compressor, BZ2Decompressor 18*cda5da8dSAndroid Build Coastguard Worker 19*cda5da8dSAndroid Build Coastguard Worker 20*cda5da8dSAndroid Build Coastguard Worker_MODE_CLOSED = 0 21*cda5da8dSAndroid Build Coastguard Worker_MODE_READ = 1 22*cda5da8dSAndroid Build Coastguard Worker# Value 2 no longer used 23*cda5da8dSAndroid Build Coastguard Worker_MODE_WRITE = 3 24*cda5da8dSAndroid Build Coastguard Worker 25*cda5da8dSAndroid Build Coastguard Worker 26*cda5da8dSAndroid Build Coastguard Workerclass BZ2File(_compression.BaseStream): 27*cda5da8dSAndroid Build Coastguard Worker 28*cda5da8dSAndroid Build Coastguard Worker """A file object providing transparent bzip2 (de)compression. 29*cda5da8dSAndroid Build Coastguard Worker 30*cda5da8dSAndroid Build Coastguard Worker A BZ2File can act as a wrapper for an existing file object, or refer 31*cda5da8dSAndroid Build Coastguard Worker directly to a named file on disk. 32*cda5da8dSAndroid Build Coastguard Worker 33*cda5da8dSAndroid Build Coastguard Worker Note that BZ2File provides a *binary* file interface - data read is 34*cda5da8dSAndroid Build Coastguard Worker returned as bytes, and data to be written should be given as bytes. 35*cda5da8dSAndroid Build Coastguard Worker """ 36*cda5da8dSAndroid Build Coastguard Worker 37*cda5da8dSAndroid Build Coastguard Worker def __init__(self, filename, mode="r", *, compresslevel=9): 38*cda5da8dSAndroid Build Coastguard Worker """Open a bzip2-compressed file. 39*cda5da8dSAndroid Build Coastguard Worker 40*cda5da8dSAndroid Build Coastguard Worker If filename is a str, bytes, or PathLike object, it gives the 41*cda5da8dSAndroid Build Coastguard Worker name of the file to be opened. Otherwise, it should be a file 42*cda5da8dSAndroid Build Coastguard Worker object, which will be used to read or write the compressed data. 43*cda5da8dSAndroid Build Coastguard Worker 44*cda5da8dSAndroid Build Coastguard Worker mode can be 'r' for reading (default), 'w' for (over)writing, 45*cda5da8dSAndroid Build Coastguard Worker 'x' for creating exclusively, or 'a' for appending. These can 46*cda5da8dSAndroid Build Coastguard Worker equivalently be given as 'rb', 'wb', 'xb', and 'ab'. 47*cda5da8dSAndroid Build Coastguard Worker 48*cda5da8dSAndroid Build Coastguard Worker If mode is 'w', 'x' or 'a', compresslevel can be a number between 1 49*cda5da8dSAndroid Build Coastguard Worker and 9 specifying the level of compression: 1 produces the least 50*cda5da8dSAndroid Build Coastguard Worker compression, and 9 (default) produces the most compression. 51*cda5da8dSAndroid Build Coastguard Worker 52*cda5da8dSAndroid Build Coastguard Worker If mode is 'r', the input file may be the concatenation of 53*cda5da8dSAndroid Build Coastguard Worker multiple compressed streams. 54*cda5da8dSAndroid Build Coastguard Worker """ 55*cda5da8dSAndroid Build Coastguard Worker self._fp = None 56*cda5da8dSAndroid Build Coastguard Worker self._closefp = False 57*cda5da8dSAndroid Build Coastguard Worker self._mode = _MODE_CLOSED 58*cda5da8dSAndroid Build Coastguard Worker 59*cda5da8dSAndroid Build Coastguard Worker if not (1 <= compresslevel <= 9): 60*cda5da8dSAndroid Build Coastguard Worker raise ValueError("compresslevel must be between 1 and 9") 61*cda5da8dSAndroid Build Coastguard Worker 62*cda5da8dSAndroid Build Coastguard Worker if mode in ("", "r", "rb"): 63*cda5da8dSAndroid Build Coastguard Worker mode = "rb" 64*cda5da8dSAndroid Build Coastguard Worker mode_code = _MODE_READ 65*cda5da8dSAndroid Build Coastguard Worker elif mode in ("w", "wb"): 66*cda5da8dSAndroid Build Coastguard Worker mode = "wb" 67*cda5da8dSAndroid Build Coastguard Worker mode_code = _MODE_WRITE 68*cda5da8dSAndroid Build Coastguard Worker self._compressor = BZ2Compressor(compresslevel) 69*cda5da8dSAndroid Build Coastguard Worker elif mode in ("x", "xb"): 70*cda5da8dSAndroid Build Coastguard Worker mode = "xb" 71*cda5da8dSAndroid Build Coastguard Worker mode_code = _MODE_WRITE 72*cda5da8dSAndroid Build Coastguard Worker self._compressor = BZ2Compressor(compresslevel) 73*cda5da8dSAndroid Build Coastguard Worker elif mode in ("a", "ab"): 74*cda5da8dSAndroid Build Coastguard Worker mode = "ab" 75*cda5da8dSAndroid Build Coastguard Worker mode_code = _MODE_WRITE 76*cda5da8dSAndroid Build Coastguard Worker self._compressor = BZ2Compressor(compresslevel) 77*cda5da8dSAndroid Build Coastguard Worker else: 78*cda5da8dSAndroid Build Coastguard Worker raise ValueError("Invalid mode: %r" % (mode,)) 79*cda5da8dSAndroid Build Coastguard Worker 80*cda5da8dSAndroid Build Coastguard Worker if isinstance(filename, (str, bytes, os.PathLike)): 81*cda5da8dSAndroid Build Coastguard Worker self._fp = _builtin_open(filename, mode) 82*cda5da8dSAndroid Build Coastguard Worker self._closefp = True 83*cda5da8dSAndroid Build Coastguard Worker self._mode = mode_code 84*cda5da8dSAndroid Build Coastguard Worker elif hasattr(filename, "read") or hasattr(filename, "write"): 85*cda5da8dSAndroid Build Coastguard Worker self._fp = filename 86*cda5da8dSAndroid Build Coastguard Worker self._mode = mode_code 87*cda5da8dSAndroid Build Coastguard Worker else: 88*cda5da8dSAndroid Build Coastguard Worker raise TypeError("filename must be a str, bytes, file or PathLike object") 89*cda5da8dSAndroid Build Coastguard Worker 90*cda5da8dSAndroid Build Coastguard Worker if self._mode == _MODE_READ: 91*cda5da8dSAndroid Build Coastguard Worker raw = _compression.DecompressReader(self._fp, 92*cda5da8dSAndroid Build Coastguard Worker BZ2Decompressor, trailing_error=OSError) 93*cda5da8dSAndroid Build Coastguard Worker self._buffer = io.BufferedReader(raw) 94*cda5da8dSAndroid Build Coastguard Worker else: 95*cda5da8dSAndroid Build Coastguard Worker self._pos = 0 96*cda5da8dSAndroid Build Coastguard Worker 97*cda5da8dSAndroid Build Coastguard Worker def close(self): 98*cda5da8dSAndroid Build Coastguard Worker """Flush and close the file. 99*cda5da8dSAndroid Build Coastguard Worker 100*cda5da8dSAndroid Build Coastguard Worker May be called more than once without error. Once the file is 101*cda5da8dSAndroid Build Coastguard Worker closed, any other operation on it will raise a ValueError. 102*cda5da8dSAndroid Build Coastguard Worker """ 103*cda5da8dSAndroid Build Coastguard Worker if self._mode == _MODE_CLOSED: 104*cda5da8dSAndroid Build Coastguard Worker return 105*cda5da8dSAndroid Build Coastguard Worker try: 106*cda5da8dSAndroid Build Coastguard Worker if self._mode == _MODE_READ: 107*cda5da8dSAndroid Build Coastguard Worker self._buffer.close() 108*cda5da8dSAndroid Build Coastguard Worker elif self._mode == _MODE_WRITE: 109*cda5da8dSAndroid Build Coastguard Worker self._fp.write(self._compressor.flush()) 110*cda5da8dSAndroid Build Coastguard Worker self._compressor = None 111*cda5da8dSAndroid Build Coastguard Worker finally: 112*cda5da8dSAndroid Build Coastguard Worker try: 113*cda5da8dSAndroid Build Coastguard Worker if self._closefp: 114*cda5da8dSAndroid Build Coastguard Worker self._fp.close() 115*cda5da8dSAndroid Build Coastguard Worker finally: 116*cda5da8dSAndroid Build Coastguard Worker self._fp = None 117*cda5da8dSAndroid Build Coastguard Worker self._closefp = False 118*cda5da8dSAndroid Build Coastguard Worker self._mode = _MODE_CLOSED 119*cda5da8dSAndroid Build Coastguard Worker self._buffer = None 120*cda5da8dSAndroid Build Coastguard Worker 121*cda5da8dSAndroid Build Coastguard Worker @property 122*cda5da8dSAndroid Build Coastguard Worker def closed(self): 123*cda5da8dSAndroid Build Coastguard Worker """True if this file is closed.""" 124*cda5da8dSAndroid Build Coastguard Worker return self._mode == _MODE_CLOSED 125*cda5da8dSAndroid Build Coastguard Worker 126*cda5da8dSAndroid Build Coastguard Worker def fileno(self): 127*cda5da8dSAndroid Build Coastguard Worker """Return the file descriptor for the underlying file.""" 128*cda5da8dSAndroid Build Coastguard Worker self._check_not_closed() 129*cda5da8dSAndroid Build Coastguard Worker return self._fp.fileno() 130*cda5da8dSAndroid Build Coastguard Worker 131*cda5da8dSAndroid Build Coastguard Worker def seekable(self): 132*cda5da8dSAndroid Build Coastguard Worker """Return whether the file supports seeking.""" 133*cda5da8dSAndroid Build Coastguard Worker return self.readable() and self._buffer.seekable() 134*cda5da8dSAndroid Build Coastguard Worker 135*cda5da8dSAndroid Build Coastguard Worker def readable(self): 136*cda5da8dSAndroid Build Coastguard Worker """Return whether the file was opened for reading.""" 137*cda5da8dSAndroid Build Coastguard Worker self._check_not_closed() 138*cda5da8dSAndroid Build Coastguard Worker return self._mode == _MODE_READ 139*cda5da8dSAndroid Build Coastguard Worker 140*cda5da8dSAndroid Build Coastguard Worker def writable(self): 141*cda5da8dSAndroid Build Coastguard Worker """Return whether the file was opened for writing.""" 142*cda5da8dSAndroid Build Coastguard Worker self._check_not_closed() 143*cda5da8dSAndroid Build Coastguard Worker return self._mode == _MODE_WRITE 144*cda5da8dSAndroid Build Coastguard Worker 145*cda5da8dSAndroid Build Coastguard Worker def peek(self, n=0): 146*cda5da8dSAndroid Build Coastguard Worker """Return buffered data without advancing the file position. 147*cda5da8dSAndroid Build Coastguard Worker 148*cda5da8dSAndroid Build Coastguard Worker Always returns at least one byte of data, unless at EOF. 149*cda5da8dSAndroid Build Coastguard Worker The exact number of bytes returned is unspecified. 150*cda5da8dSAndroid Build Coastguard Worker """ 151*cda5da8dSAndroid Build Coastguard Worker self._check_can_read() 152*cda5da8dSAndroid Build Coastguard Worker # Relies on the undocumented fact that BufferedReader.peek() 153*cda5da8dSAndroid Build Coastguard Worker # always returns at least one byte (except at EOF), independent 154*cda5da8dSAndroid Build Coastguard Worker # of the value of n 155*cda5da8dSAndroid Build Coastguard Worker return self._buffer.peek(n) 156*cda5da8dSAndroid Build Coastguard Worker 157*cda5da8dSAndroid Build Coastguard Worker def read(self, size=-1): 158*cda5da8dSAndroid Build Coastguard Worker """Read up to size uncompressed bytes from the file. 159*cda5da8dSAndroid Build Coastguard Worker 160*cda5da8dSAndroid Build Coastguard Worker If size is negative or omitted, read until EOF is reached. 161*cda5da8dSAndroid Build Coastguard Worker Returns b'' if the file is already at EOF. 162*cda5da8dSAndroid Build Coastguard Worker """ 163*cda5da8dSAndroid Build Coastguard Worker self._check_can_read() 164*cda5da8dSAndroid Build Coastguard Worker return self._buffer.read(size) 165*cda5da8dSAndroid Build Coastguard Worker 166*cda5da8dSAndroid Build Coastguard Worker def read1(self, size=-1): 167*cda5da8dSAndroid Build Coastguard Worker """Read up to size uncompressed bytes, while trying to avoid 168*cda5da8dSAndroid Build Coastguard Worker making multiple reads from the underlying stream. Reads up to a 169*cda5da8dSAndroid Build Coastguard Worker buffer's worth of data if size is negative. 170*cda5da8dSAndroid Build Coastguard Worker 171*cda5da8dSAndroid Build Coastguard Worker Returns b'' if the file is at EOF. 172*cda5da8dSAndroid Build Coastguard Worker """ 173*cda5da8dSAndroid Build Coastguard Worker self._check_can_read() 174*cda5da8dSAndroid Build Coastguard Worker if size < 0: 175*cda5da8dSAndroid Build Coastguard Worker size = io.DEFAULT_BUFFER_SIZE 176*cda5da8dSAndroid Build Coastguard Worker return self._buffer.read1(size) 177*cda5da8dSAndroid Build Coastguard Worker 178*cda5da8dSAndroid Build Coastguard Worker def readinto(self, b): 179*cda5da8dSAndroid Build Coastguard Worker """Read bytes into b. 180*cda5da8dSAndroid Build Coastguard Worker 181*cda5da8dSAndroid Build Coastguard Worker Returns the number of bytes read (0 for EOF). 182*cda5da8dSAndroid Build Coastguard Worker """ 183*cda5da8dSAndroid Build Coastguard Worker self._check_can_read() 184*cda5da8dSAndroid Build Coastguard Worker return self._buffer.readinto(b) 185*cda5da8dSAndroid Build Coastguard Worker 186*cda5da8dSAndroid Build Coastguard Worker def readline(self, size=-1): 187*cda5da8dSAndroid Build Coastguard Worker """Read a line of uncompressed bytes from the file. 188*cda5da8dSAndroid Build Coastguard Worker 189*cda5da8dSAndroid Build Coastguard Worker The terminating newline (if present) is retained. If size is 190*cda5da8dSAndroid Build Coastguard Worker non-negative, no more than size bytes will be read (in which 191*cda5da8dSAndroid Build Coastguard Worker case the line may be incomplete). Returns b'' if already at EOF. 192*cda5da8dSAndroid Build Coastguard Worker """ 193*cda5da8dSAndroid Build Coastguard Worker if not isinstance(size, int): 194*cda5da8dSAndroid Build Coastguard Worker if not hasattr(size, "__index__"): 195*cda5da8dSAndroid Build Coastguard Worker raise TypeError("Integer argument expected") 196*cda5da8dSAndroid Build Coastguard Worker size = size.__index__() 197*cda5da8dSAndroid Build Coastguard Worker self._check_can_read() 198*cda5da8dSAndroid Build Coastguard Worker return self._buffer.readline(size) 199*cda5da8dSAndroid Build Coastguard Worker 200*cda5da8dSAndroid Build Coastguard Worker def readlines(self, size=-1): 201*cda5da8dSAndroid Build Coastguard Worker """Read a list of lines of uncompressed bytes from the file. 202*cda5da8dSAndroid Build Coastguard Worker 203*cda5da8dSAndroid Build Coastguard Worker size can be specified to control the number of lines read: no 204*cda5da8dSAndroid Build Coastguard Worker further lines will be read once the total size of the lines read 205*cda5da8dSAndroid Build Coastguard Worker so far equals or exceeds size. 206*cda5da8dSAndroid Build Coastguard Worker """ 207*cda5da8dSAndroid Build Coastguard Worker if not isinstance(size, int): 208*cda5da8dSAndroid Build Coastguard Worker if not hasattr(size, "__index__"): 209*cda5da8dSAndroid Build Coastguard Worker raise TypeError("Integer argument expected") 210*cda5da8dSAndroid Build Coastguard Worker size = size.__index__() 211*cda5da8dSAndroid Build Coastguard Worker self._check_can_read() 212*cda5da8dSAndroid Build Coastguard Worker return self._buffer.readlines(size) 213*cda5da8dSAndroid Build Coastguard Worker 214*cda5da8dSAndroid Build Coastguard Worker def write(self, data): 215*cda5da8dSAndroid Build Coastguard Worker """Write a byte string to the file. 216*cda5da8dSAndroid Build Coastguard Worker 217*cda5da8dSAndroid Build Coastguard Worker Returns the number of uncompressed bytes written, which is 218*cda5da8dSAndroid Build Coastguard Worker always the length of data in bytes. Note that due to buffering, 219*cda5da8dSAndroid Build Coastguard Worker the file on disk may not reflect the data written until close() 220*cda5da8dSAndroid Build Coastguard Worker is called. 221*cda5da8dSAndroid Build Coastguard Worker """ 222*cda5da8dSAndroid Build Coastguard Worker self._check_can_write() 223*cda5da8dSAndroid Build Coastguard Worker if isinstance(data, (bytes, bytearray)): 224*cda5da8dSAndroid Build Coastguard Worker length = len(data) 225*cda5da8dSAndroid Build Coastguard Worker else: 226*cda5da8dSAndroid Build Coastguard Worker # accept any data that supports the buffer protocol 227*cda5da8dSAndroid Build Coastguard Worker data = memoryview(data) 228*cda5da8dSAndroid Build Coastguard Worker length = data.nbytes 229*cda5da8dSAndroid Build Coastguard Worker 230*cda5da8dSAndroid Build Coastguard Worker compressed = self._compressor.compress(data) 231*cda5da8dSAndroid Build Coastguard Worker self._fp.write(compressed) 232*cda5da8dSAndroid Build Coastguard Worker self._pos += length 233*cda5da8dSAndroid Build Coastguard Worker return length 234*cda5da8dSAndroid Build Coastguard Worker 235*cda5da8dSAndroid Build Coastguard Worker def writelines(self, seq): 236*cda5da8dSAndroid Build Coastguard Worker """Write a sequence of byte strings to the file. 237*cda5da8dSAndroid Build Coastguard Worker 238*cda5da8dSAndroid Build Coastguard Worker Returns the number of uncompressed bytes written. 239*cda5da8dSAndroid Build Coastguard Worker seq can be any iterable yielding byte strings. 240*cda5da8dSAndroid Build Coastguard Worker 241*cda5da8dSAndroid Build Coastguard Worker Line separators are not added between the written byte strings. 242*cda5da8dSAndroid Build Coastguard Worker """ 243*cda5da8dSAndroid Build Coastguard Worker return _compression.BaseStream.writelines(self, seq) 244*cda5da8dSAndroid Build Coastguard Worker 245*cda5da8dSAndroid Build Coastguard Worker def seek(self, offset, whence=io.SEEK_SET): 246*cda5da8dSAndroid Build Coastguard Worker """Change the file position. 247*cda5da8dSAndroid Build Coastguard Worker 248*cda5da8dSAndroid Build Coastguard Worker The new position is specified by offset, relative to the 249*cda5da8dSAndroid Build Coastguard Worker position indicated by whence. Values for whence are: 250*cda5da8dSAndroid Build Coastguard Worker 251*cda5da8dSAndroid Build Coastguard Worker 0: start of stream (default); offset must not be negative 252*cda5da8dSAndroid Build Coastguard Worker 1: current stream position 253*cda5da8dSAndroid Build Coastguard Worker 2: end of stream; offset must not be positive 254*cda5da8dSAndroid Build Coastguard Worker 255*cda5da8dSAndroid Build Coastguard Worker Returns the new file position. 256*cda5da8dSAndroid Build Coastguard Worker 257*cda5da8dSAndroid Build Coastguard Worker Note that seeking is emulated, so depending on the parameters, 258*cda5da8dSAndroid Build Coastguard Worker this operation may be extremely slow. 259*cda5da8dSAndroid Build Coastguard Worker """ 260*cda5da8dSAndroid Build Coastguard Worker self._check_can_seek() 261*cda5da8dSAndroid Build Coastguard Worker return self._buffer.seek(offset, whence) 262*cda5da8dSAndroid Build Coastguard Worker 263*cda5da8dSAndroid Build Coastguard Worker def tell(self): 264*cda5da8dSAndroid Build Coastguard Worker """Return the current file position.""" 265*cda5da8dSAndroid Build Coastguard Worker self._check_not_closed() 266*cda5da8dSAndroid Build Coastguard Worker if self._mode == _MODE_READ: 267*cda5da8dSAndroid Build Coastguard Worker return self._buffer.tell() 268*cda5da8dSAndroid Build Coastguard Worker return self._pos 269*cda5da8dSAndroid Build Coastguard Worker 270*cda5da8dSAndroid Build Coastguard Worker 271*cda5da8dSAndroid Build Coastguard Workerdef open(filename, mode="rb", compresslevel=9, 272*cda5da8dSAndroid Build Coastguard Worker encoding=None, errors=None, newline=None): 273*cda5da8dSAndroid Build Coastguard Worker """Open a bzip2-compressed file in binary or text mode. 274*cda5da8dSAndroid Build Coastguard Worker 275*cda5da8dSAndroid Build Coastguard Worker The filename argument can be an actual filename (a str, bytes, or 276*cda5da8dSAndroid Build Coastguard Worker PathLike object), or an existing file object to read from or write 277*cda5da8dSAndroid Build Coastguard Worker to. 278*cda5da8dSAndroid Build Coastguard Worker 279*cda5da8dSAndroid Build Coastguard Worker The mode argument can be "r", "rb", "w", "wb", "x", "xb", "a" or 280*cda5da8dSAndroid Build Coastguard Worker "ab" for binary mode, or "rt", "wt", "xt" or "at" for text mode. 281*cda5da8dSAndroid Build Coastguard Worker The default mode is "rb", and the default compresslevel is 9. 282*cda5da8dSAndroid Build Coastguard Worker 283*cda5da8dSAndroid Build Coastguard Worker For binary mode, this function is equivalent to the BZ2File 284*cda5da8dSAndroid Build Coastguard Worker constructor: BZ2File(filename, mode, compresslevel). In this case, 285*cda5da8dSAndroid Build Coastguard Worker the encoding, errors and newline arguments must not be provided. 286*cda5da8dSAndroid Build Coastguard Worker 287*cda5da8dSAndroid Build Coastguard Worker For text mode, a BZ2File object is created, and wrapped in an 288*cda5da8dSAndroid Build Coastguard Worker io.TextIOWrapper instance with the specified encoding, error 289*cda5da8dSAndroid Build Coastguard Worker handling behavior, and line ending(s). 290*cda5da8dSAndroid Build Coastguard Worker 291*cda5da8dSAndroid Build Coastguard Worker """ 292*cda5da8dSAndroid Build Coastguard Worker if "t" in mode: 293*cda5da8dSAndroid Build Coastguard Worker if "b" in mode: 294*cda5da8dSAndroid Build Coastguard Worker raise ValueError("Invalid mode: %r" % (mode,)) 295*cda5da8dSAndroid Build Coastguard Worker else: 296*cda5da8dSAndroid Build Coastguard Worker if encoding is not None: 297*cda5da8dSAndroid Build Coastguard Worker raise ValueError("Argument 'encoding' not supported in binary mode") 298*cda5da8dSAndroid Build Coastguard Worker if errors is not None: 299*cda5da8dSAndroid Build Coastguard Worker raise ValueError("Argument 'errors' not supported in binary mode") 300*cda5da8dSAndroid Build Coastguard Worker if newline is not None: 301*cda5da8dSAndroid Build Coastguard Worker raise ValueError("Argument 'newline' not supported in binary mode") 302*cda5da8dSAndroid Build Coastguard Worker 303*cda5da8dSAndroid Build Coastguard Worker bz_mode = mode.replace("t", "") 304*cda5da8dSAndroid Build Coastguard Worker binary_file = BZ2File(filename, bz_mode, compresslevel=compresslevel) 305*cda5da8dSAndroid Build Coastguard Worker 306*cda5da8dSAndroid Build Coastguard Worker if "t" in mode: 307*cda5da8dSAndroid Build Coastguard Worker encoding = io.text_encoding(encoding) 308*cda5da8dSAndroid Build Coastguard Worker return io.TextIOWrapper(binary_file, encoding, errors, newline) 309*cda5da8dSAndroid Build Coastguard Worker else: 310*cda5da8dSAndroid Build Coastguard Worker return binary_file 311*cda5da8dSAndroid Build Coastguard Worker 312*cda5da8dSAndroid Build Coastguard Worker 313*cda5da8dSAndroid Build Coastguard Workerdef compress(data, compresslevel=9): 314*cda5da8dSAndroid Build Coastguard Worker """Compress a block of data. 315*cda5da8dSAndroid Build Coastguard Worker 316*cda5da8dSAndroid Build Coastguard Worker compresslevel, if given, must be a number between 1 and 9. 317*cda5da8dSAndroid Build Coastguard Worker 318*cda5da8dSAndroid Build Coastguard Worker For incremental compression, use a BZ2Compressor object instead. 319*cda5da8dSAndroid Build Coastguard Worker """ 320*cda5da8dSAndroid Build Coastguard Worker comp = BZ2Compressor(compresslevel) 321*cda5da8dSAndroid Build Coastguard Worker return comp.compress(data) + comp.flush() 322*cda5da8dSAndroid Build Coastguard Worker 323*cda5da8dSAndroid Build Coastguard Worker 324*cda5da8dSAndroid Build Coastguard Workerdef decompress(data): 325*cda5da8dSAndroid Build Coastguard Worker """Decompress a block of data. 326*cda5da8dSAndroid Build Coastguard Worker 327*cda5da8dSAndroid Build Coastguard Worker For incremental decompression, use a BZ2Decompressor object instead. 328*cda5da8dSAndroid Build Coastguard Worker """ 329*cda5da8dSAndroid Build Coastguard Worker results = [] 330*cda5da8dSAndroid Build Coastguard Worker while data: 331*cda5da8dSAndroid Build Coastguard Worker decomp = BZ2Decompressor() 332*cda5da8dSAndroid Build Coastguard Worker try: 333*cda5da8dSAndroid Build Coastguard Worker res = decomp.decompress(data) 334*cda5da8dSAndroid Build Coastguard Worker except OSError: 335*cda5da8dSAndroid Build Coastguard Worker if results: 336*cda5da8dSAndroid Build Coastguard Worker break # Leftover data is not a valid bzip2 stream; ignore it. 337*cda5da8dSAndroid Build Coastguard Worker else: 338*cda5da8dSAndroid Build Coastguard Worker raise # Error on the first iteration; bail out. 339*cda5da8dSAndroid Build Coastguard Worker results.append(res) 340*cda5da8dSAndroid Build Coastguard Worker if not decomp.eof: 341*cda5da8dSAndroid Build Coastguard Worker raise ValueError("Compressed data ended before the " 342*cda5da8dSAndroid Build Coastguard Worker "end-of-stream marker was reached") 343*cda5da8dSAndroid Build Coastguard Worker data = decomp.unused_data 344*cda5da8dSAndroid Build Coastguard Worker return b"".join(results) 345