xref: /aosp_15_r20/prebuilts/build-tools/common/py3-stdlib/bz2.py (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
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