interface to the liblzma compression library this module provides a class for reading and writing compressed files classes for incremental decompression and convenience functions for oneshot decompression these classes and functions support both the xz and legacy lzma container formats as well as raw compressed data streams value 2 no longer used a file object providing transparent lzma decompression an lzmafile can act as a wrapper for an existing file object or refer directly to a named file on disk note that lzmafile provides a binary file interface data read is returned as bytes and data to be written must be given as bytes open an lzmacompressed file in binary mode filename can be either an actual file name given as a str bytes or pathlike object in which case the named file is opened or it can be an existing file object to read from or write to mode can be r for reading default w for overwriting x for creating exclusively or a for appending these can equivalently be given as rb wb xb and ab respectively format specifies the container format to use for the file if mode is r this defaults to formatauto otherwise the default is formatxz check specifies the integrity check to use this argument can only be used when opening a file for writing for formatxz the default is checkcrc64 formatalone and formatraw do not support integrity checks for these formats check must be omitted or be checknone when opening a file for reading the preset argument is not meaningful and should be omitted the filters argument should also be omitted except when format is formatraw in which case it is required when opening a file for writing the settings used by the compressor can be specified either as a preset compression level with the preset argument or in detail as a custom filter chain with the filters argument for formatxz and formatalone the default is to use the presetdefault preset level for formatraw the caller must always specify a filter chain the raw compressor does not support preset compression levels preset if provided should be an integer in the range 09 optionally ored with the constant presetextreme filters if provided should be a sequence of dicts each dict should have an entry for id indicating id of the filter plus additional entries for options to the filter flush and close the file may be called more than once without error once the file is closed any other operation on it will raise a valueerror true if this file is closed return self mode modeclosed def filenoself return whether the file supports seeking return self readable and self buffer seekable def readableself return whether the file was opened for writing self checknotclosed return self mode modewrite def peekself size1 self checkcanread relies on the undocumented fact that bufferedreader peek always returns at least one byte except at eof return self buffer peeksize def readself size1 self checkcanread return self buffer readsize def read1self size1 self checkcanread if size 0 size io defaultbuffersize return self buffer read1size def readlineself size1 self checkcanread return self buffer readlinesize def writeself data self checkcanwrite if isinstancedata bytes bytearray length lendata else accept any data that supports the buffer protocol data memoryviewdata length data nbytes compressed self compressor compressdata self fp writecompressed self pos length return length def seekself offset whenceio seekset self checkcanseek return self buffer seekoffset whence def tellself open an lzmacompressed file in binary or text mode filename can be either an actual file name given as a str bytes or pathlike object in which case the named file is opened or it can be an existing file object to read from or write to the mode argument can be r rb default w wb x xb a or ab for binary mode or rt wt xt or at for text mode the format check preset and filters arguments specify the compression settings as for lzmacompressor lzmadecompressor and lzmafile for binary mode this function is equivalent to the lzmafile constructor lzmafilefilename mode in this case the encoding errors and newline arguments must not be provided for text mode an lzmafile object is created and wrapped in an io textiowrapper instance with the specified encoding error handling behavior and line endings compress a block of data refer to lzmacompressor s docstring for a description of the optional arguments format check preset and filters for incremental compression use an lzmacompressor instead decompress a block of data refer to lzmadecompressor s docstring for a description of the optional arguments format check and filters for incremental decompression use an lzmadecompressor instead value 2 no longer used a file object providing transparent lzma de compression an lzmafile can act as a wrapper for an existing file object or refer directly to a named file on disk note that lzmafile provides a binary file interface data read is returned as bytes and data to be written must be given as bytes open an lzma compressed file in binary mode filename can be either an actual file name given as a str bytes or pathlike object in which case the named file is opened or it can be an existing file object to read from or write to mode can be r for reading default w for over writing x for creating exclusively or a for appending these can equivalently be given as rb wb xb and ab respectively format specifies the container format to use for the file if mode is r this defaults to format_auto otherwise the default is format_xz check specifies the integrity check to use this argument can only be used when opening a file for writing for format_xz the default is check_crc64 format_alone and format_raw do not support integrity checks for these formats check must be omitted or be check_none when opening a file for reading the preset argument is not meaningful and should be omitted the filters argument should also be omitted except when format is format_raw in which case it is required when opening a file for writing the settings used by the compressor can be specified either as a preset compression level with the preset argument or in detail as a custom filter chain with the filters argument for format_xz and format_alone the default is to use the preset_default preset level for format_raw the caller must always specify a filter chain the raw compressor does not support preset compression levels preset if provided should be an integer in the range 0 9 optionally or ed with the constant preset_extreme filters if provided should be a sequence of dicts each dict should have an entry for id indicating id of the filter plus additional entries for options to the filter flush and close the file may be called more than once without error once the file is closed any other operation on it will raise a valueerror true if this file is closed return the file descriptor for the underlying file return whether the file supports seeking return whether the file was opened for reading return whether the file was opened for writing return buffered data without advancing the file position always returns at least one byte of data unless at eof the exact number of bytes returned is unspecified relies on the undocumented fact that bufferedreader peek always returns at least one byte except at eof read up to size uncompressed bytes from the file if size is negative or omitted read until eof is reached returns b if the file is already at eof read up to size uncompressed bytes while trying to avoid making multiple reads from the underlying stream reads up to a buffer s worth of data if size is negative returns b if the file is at eof read a line of uncompressed bytes from the file the terminating newline if present is retained if size is non negative no more than size bytes will be read in which case the line may be incomplete returns b if already at eof write a bytes object to the file returns the number of uncompressed bytes written which is always the length of data in bytes note that due to buffering the file on disk may not reflect the data written until close is called accept any data that supports the buffer protocol change the file position the new position is specified by offset relative to the position indicated by whence possible values for whence are 0 start of stream default offset must not be negative 1 current stream position 2 end of stream offset must not be positive returns the new file position note that seeking is emulated so depending on the parameters this operation may be extremely slow return the current file position open an lzma compressed file in binary or text mode filename can be either an actual file name given as a str bytes or pathlike object in which case the named file is opened or it can be an existing file object to read from or write to the mode argument can be r rb default w wb x xb a or ab for binary mode or rt wt xt or at for text mode the format check preset and filters arguments specify the compression settings as for lzmacompressor lzmadecompressor and lzmafile for binary mode this function is equivalent to the lzmafile constructor lzmafile filename mode in this case the encoding errors and newline arguments must not be provided for text mode an lzmafile object is created and wrapped in an io textiowrapper instance with the specified encoding error handling behavior and line ending s compress a block of data refer to lzmacompressor s docstring for a description of the optional arguments format check preset and filters for incremental compression use an lzmacompressor instead decompress a block of data refer to lzmadecompressor s docstring for a description of the optional arguments format check and filters for incremental decompression use an lzmadecompressor instead leftover data is not a valid lzma xz stream ignore it error on the first iteration bail out
__all__ = [
    "CHECK_NONE", "CHECK_CRC32", "CHECK_CRC64", "CHECK_SHA256",
    "CHECK_ID_MAX", "CHECK_UNKNOWN",
    "FILTER_LZMA1", "FILTER_LZMA2", "FILTER_DELTA", "FILTER_X86", "FILTER_IA64",
    "FILTER_ARM", "FILTER_ARMTHUMB", "FILTER_POWERPC", "FILTER_SPARC",
    "FORMAT_AUTO", "FORMAT_XZ", "FORMAT_ALONE", "FORMAT_RAW",
    "MF_HC3", "MF_HC4", "MF_BT2", "MF_BT3", "MF_BT4",
    "MODE_FAST", "MODE_NORMAL", "PRESET_DEFAULT", "PRESET_EXTREME",

    "LZMACompressor", "LZMADecompressor", "LZMAFile", "LZMAError",
    "open", "compress", "decompress", "is_check_supported",
]

import builtins
import io
import os
from _lzma import *
from _lzma import _encode_filter_properties, _decode_filter_properties
import _compression


_MODE_CLOSED   = 0
_MODE_READ     = 1

_MODE_WRITE    = 3


class LZMAFile(_compression.BaseStream):

    

    def __init__(self, filename=None, mode="r", *,
                 format=None, check=-1, preset=None, filters=None):
        
        self._fp = None
        self._closefp = False
        self._mode = _MODE_CLOSED

        if mode in ("r", "rb"):
            if check != -1:
                raise ValueError("Cannot specify an integrity check "
                                 "when opening a file for reading")
            if preset is not None:
                raise ValueError("Cannot specify a preset compression "
                                 "level when opening a file for reading")
            if format is None:
                format = FORMAT_AUTO
            mode_code = _MODE_READ
        elif mode in ("w", "wb", "a", "ab", "x", "xb"):
            if format is None:
                format = FORMAT_XZ
            mode_code = _MODE_WRITE
            self._compressor = LZMACompressor(format=format, check=check,
                                              preset=preset, filters=filters)
            self._pos = 0
        else:
            raise ValueError("Invalid mode: {!r}".format(mode))

        if isinstance(filename, (str, bytes, os.PathLike)):
            if "b" not in mode:
                mode += "b"
            self._fp = builtins.open(filename, mode)
            self._closefp = True
            self._mode = mode_code
        elif hasattr(filename, "read") or hasattr(filename, "write"):
            self._fp = filename
            self._mode = mode_code
        else:
            raise TypeError("filename must be a str, bytes, file or PathLike object")

        if self._mode == _MODE_READ:
            raw = _compression.DecompressReader(self._fp, LZMADecompressor,
                trailing_error=LZMAError, format=format, filters=filters)
            self._buffer = io.BufferedReader(raw)

    def close(self):
        
        if self._mode == _MODE_CLOSED:
            return
        try:
            if self._mode == _MODE_READ:
                self._buffer.close()
                self._buffer = None
            elif self._mode == _MODE_WRITE:
                self._fp.write(self._compressor.flush())
                self._compressor = None
        finally:
            try:
                if self._closefp:
                    self._fp.close()
            finally:
                self._fp = None
                self._closefp = False
                self._mode = _MODE_CLOSED

    @property
    def closed(self):
        
        return self._mode == _MODE_CLOSED

    def fileno(self):
        
        self._check_not_closed()
        return self._fp.fileno()

    def seekable(self):
        
        return self.readable() and self._buffer.seekable()

    def readable(self):
        
        self._check_not_closed()
        return self._mode == _MODE_READ

    def writable(self):
        
        self._check_not_closed()
        return self._mode == _MODE_WRITE

    def peek(self, size=-1):
        
        self._check_can_read()
        
        
        return self._buffer.peek(size)

    def read(self, size=-1):
        
        self._check_can_read()
        return self._buffer.read(size)

    def read1(self, size=-1):
        
        self._check_can_read()
        if size < 0:
            size = io.DEFAULT_BUFFER_SIZE
        return self._buffer.read1(size)

    def readline(self, size=-1):
        
        self._check_can_read()
        return self._buffer.readline(size)

    def write(self, data):
        
        self._check_can_write()
        if isinstance(data, (bytes, bytearray)):
            length = len(data)
        else:
            
            data = memoryview(data)
            length = data.nbytes

        compressed = self._compressor.compress(data)
        self._fp.write(compressed)
        self._pos += length
        return length

    def seek(self, offset, whence=io.SEEK_SET):
        
        self._check_can_seek()
        return self._buffer.seek(offset, whence)

    def tell(self):
        
        self._check_not_closed()
        if self._mode == _MODE_READ:
            return self._buffer.tell()
        return self._pos


def open(filename, mode="rb", *,
         format=None, check=-1, preset=None, filters=None,
         encoding=None, errors=None, newline=None):
    
    if "t" in mode:
        if "b" in mode:
            raise ValueError("Invalid mode: %r" % (mode,))
    else:
        if encoding is not None:
            raise ValueError("Argument 'encoding' not supported in binary mode")
        if errors is not None:
            raise ValueError("Argument 'errors' not supported in binary mode")
        if newline is not None:
            raise ValueError("Argument 'newline' not supported in binary mode")

    lz_mode = mode.replace("t", "")
    binary_file = LZMAFile(filename, lz_mode, format=format, check=check,
                           preset=preset, filters=filters)

    if "t" in mode:
        encoding = io.text_encoding(encoding)
        return io.TextIOWrapper(binary_file, encoding, errors, newline)
    else:
        return binary_file


def compress(data, format=FORMAT_XZ, check=-1, preset=None, filters=None):
    
    comp = LZMACompressor(format, check, preset, filters)
    return comp.compress(data) + comp.flush()


def decompress(data, format=FORMAT_AUTO, memlimit=None, filters=None):
    
    results = []
    while True:
        decomp = LZMADecompressor(format, memlimit, filters)
        try:
            res = decomp.decompress(data)
        except LZMAError:
            if results:
                break  
            else:
                raise  
        results.append(res)
        if not decomp.eof:
            raise LZMAError("Compressed data ended before the "
                            "end-of-stream marker was reached")
        data = decomp.unused_data
        if not data:
            break
    return b"".join(results)