1import lz4 2import io 3import os 4import builtins 5import sys 6from ._frame import ( # noqa: F401 7 compress, 8 decompress, 9 create_compression_context, 10 compress_begin, 11 compress_chunk, 12 compress_flush, 13 create_decompression_context, 14 reset_decompression_context, 15 decompress_chunk, 16 get_frame_info, 17 BLOCKSIZE_DEFAULT as _BLOCKSIZE_DEFAULT, 18 BLOCKSIZE_MAX64KB as _BLOCKSIZE_MAX64KB, 19 BLOCKSIZE_MAX256KB as _BLOCKSIZE_MAX256KB, 20 BLOCKSIZE_MAX1MB as _BLOCKSIZE_MAX1MB, 21 BLOCKSIZE_MAX4MB as _BLOCKSIZE_MAX4MB, 22 __doc__ as _doc 23) 24 25__doc__ = _doc 26 27try: 28 import _compression # Python 3.6 and later 29except ImportError: 30 from . import _compression 31 32 33BLOCKSIZE_DEFAULT = _BLOCKSIZE_DEFAULT 34"""Specifier for the default block size. 35 36Specifying ``block_size=lz4.frame.BLOCKSIZE_DEFAULT`` will instruct the LZ4 37library to use the default maximum blocksize. This is currently equivalent to 38`lz4.frame.BLOCKSIZE_MAX64KB` 39 40""" 41 42BLOCKSIZE_MAX64KB = _BLOCKSIZE_MAX64KB 43"""Specifier for a maximum block size of 64 kB. 44 45Specifying ``block_size=lz4.frame.BLOCKSIZE_MAX64KB`` will instruct the LZ4 46library to create blocks containing a maximum of 64 kB of uncompressed data. 47 48""" 49 50BLOCKSIZE_MAX256KB = _BLOCKSIZE_MAX256KB 51"""Specifier for a maximum block size of 256 kB. 52 53Specifying ``block_size=lz4.frame.BLOCKSIZE_MAX256KB`` will instruct the LZ4 54library to create blocks containing a maximum of 256 kB of uncompressed data. 55 56""" 57 58BLOCKSIZE_MAX1MB = _BLOCKSIZE_MAX1MB 59"""Specifier for a maximum block size of 1 MB. 60 61Specifying ``block_size=lz4.frame.BLOCKSIZE_MAX1MB`` will instruct the LZ4 62library to create blocks containing a maximum of 1 MB of uncompressed data. 63 64""" 65 66BLOCKSIZE_MAX4MB = _BLOCKSIZE_MAX4MB 67"""Specifier for a maximum block size of 4 MB. 68 69Specifying ``block_size=lz4.frame.BLOCKSIZE_MAX4MB`` will instruct the LZ4 70library to create blocks containing a maximum of 4 MB of uncompressed data. 71 72""" 73 74COMPRESSIONLEVEL_MIN = 0 75"""Specifier for the minimum compression level. 76 77Specifying ``compression_level=lz4.frame.COMPRESSIONLEVEL_MIN`` will 78instruct the LZ4 library to use a compression level of 0 79 80""" 81 82COMPRESSIONLEVEL_MINHC = 3 83"""Specifier for the minimum compression level for high compression mode. 84 85Specifying ``compression_level=lz4.frame.COMPRESSIONLEVEL_MINHC`` will 86instruct the LZ4 library to use a compression level of 3, the minimum for the 87high compression mode. 88 89""" 90 91COMPRESSIONLEVEL_MAX = 16 92"""Specifier for the maximum compression level. 93 94Specifying ``compression_level=lz4.frame.COMPRESSIONLEVEL_MAX`` will 95instruct the LZ4 library to use a compression level of 16, the highest 96compression level available. 97 98""" 99 100 101class LZ4FrameCompressor(object): 102 """Create a LZ4 frame compressor object. 103 104 This object can be used to compress data incrementally. 105 106 Args: 107 block_size (int): Specifies the maximum blocksize to use. 108 Options: 109 110 - `lz4.frame.BLOCKSIZE_DEFAULT`: the lz4 library default 111 - `lz4.frame.BLOCKSIZE_MAX64KB`: 64 kB 112 - `lz4.frame.BLOCKSIZE_MAX256KB`: 256 kB 113 - `lz4.frame.BLOCKSIZE_MAX1MB`: 1 MB 114 - `lz4.frame.BLOCKSIZE_MAX4MB`: 4 MB 115 116 If unspecified, will default to `lz4.frame.BLOCKSIZE_DEFAULT` which 117 is equal to `lz4.frame.BLOCKSIZE_MAX64KB`. 118 block_linked (bool): Specifies whether to use block-linked 119 compression. If ``True``, the compression ratio is improved, 120 especially for small block sizes. If ``False`` the blocks are 121 compressed independently. The default is ``True``. 122 compression_level (int): Specifies the level of compression used. 123 Values between 0-16 are valid, with 0 (default) being the 124 lowest compression (0-2 are the same value), and 16 the highest. 125 Values above 16 will be treated as 16. 126 Values between 4-9 are recommended. 0 is the default. 127 The following module constants are provided as a convenience: 128 129 - `lz4.frame.COMPRESSIONLEVEL_MIN`: Minimum compression (0) 130 - `lz4.frame.COMPRESSIONLEVEL_MINHC`: Minimum high-compression (3) 131 - `lz4.frame.COMPRESSIONLEVEL_MAX`: Maximum compression (16) 132 133 content_checksum (bool): Specifies whether to enable checksumming of 134 the payload content. If ``True``, a checksum of the uncompressed 135 data is stored at the end of the compressed frame which is checked 136 during decompression. The default is ``False``. 137 block_checksum (bool): Specifies whether to enable checksumming of 138 the content of each block. If ``True`` a checksum of the 139 uncompressed data in each block in the frame is stored at the end 140 of each block. If present, these checksums will be used to 141 validate the data during decompression. The default is ``False``, 142 meaning block checksums are not calculated and stored. This 143 functionality is only supported if the underlying LZ4 library has 144 version >= 1.8.0. Attempting to set this value to ``True`` with a 145 version of LZ4 < 1.8.0 will cause a ``RuntimeError`` to be raised. 146 auto_flush (bool): When ``False``, the LZ4 library may buffer data 147 until a block is full. When ``True`` no buffering occurs, and 148 partially full blocks may be returned. The default is ``False``. 149 return_bytearray (bool): When ``False`` a ``bytes`` object is returned 150 from the calls to methods of this class. When ``True`` a 151 ``bytearray`` object will be returned. The default is ``False``. 152 153 """ 154 155 def __init__(self, 156 block_size=BLOCKSIZE_DEFAULT, 157 block_linked=True, 158 compression_level=COMPRESSIONLEVEL_MIN, 159 content_checksum=False, 160 block_checksum=False, 161 auto_flush=False, 162 return_bytearray=False): 163 self.block_size = block_size 164 self.block_linked = block_linked 165 self.compression_level = compression_level 166 self.content_checksum = content_checksum 167 if block_checksum and lz4.library_version_number() < 10800: 168 raise RuntimeError( 169 'Attempt to set block_checksum to True with LZ4 library' 170 'version < 10800' 171 ) 172 self.block_checksum = block_checksum 173 self.auto_flush = auto_flush 174 self.return_bytearray = return_bytearray 175 self._context = None 176 self._started = False 177 178 def __enter__(self): 179 # All necessary initialization is done in __init__ 180 return self 181 182 def __exit__(self, exception_type, exception, traceback): 183 self.block_size = None 184 self.block_linked = None 185 self.compression_level = None 186 self.content_checksum = None 187 self.block_checksum = None 188 self.auto_flush = None 189 self.return_bytearray = None 190 self._context = None 191 self._started = False 192 193 def begin(self, source_size=0): 194 """Begin a compression frame. 195 196 The returned data contains frame header information. The data returned 197 from subsequent calls to ``compress()`` should be concatenated with 198 this header. 199 200 Keyword Args: 201 source_size (int): Optionally specify the total size of the 202 uncompressed data. If specified, will be stored in the 203 compressed frame header as an 8-byte field for later use 204 during decompression. Default is 0 (no size stored). 205 206 Returns: 207 bytes or bytearray: frame header data 208 209 """ 210 211 if self._started is False: 212 self._context = create_compression_context() 213 result = compress_begin( 214 self._context, 215 block_size=self.block_size, 216 block_linked=self.block_linked, 217 compression_level=self.compression_level, 218 content_checksum=self.content_checksum, 219 block_checksum=self.block_checksum, 220 auto_flush=self.auto_flush, 221 return_bytearray=self.return_bytearray, 222 source_size=source_size 223 ) 224 self._started = True 225 return result 226 else: 227 raise RuntimeError( 228 'LZ4FrameCompressor.begin() called after already initialized' 229 ) 230 231 def compress(self, data): # noqa: F811 232 """Compresses data and returns it. 233 234 This compresses ``data`` (a ``bytes`` object), returning a bytes or 235 bytearray object containing compressed data the input. 236 237 If ``auto_flush`` has been set to ``False``, some of ``data`` may be 238 buffered internally, for use in later calls to 239 `LZ4FrameCompressor.compress()` and `LZ4FrameCompressor.flush()`. 240 241 The returned data should be concatenated with the output of any 242 previous calls to `compress()` and a single call to 243 `compress_begin()`. 244 245 Args: 246 data (str, bytes or buffer-compatible object): data to compress 247 248 Returns: 249 bytes or bytearray: compressed data 250 251 """ 252 if self._context is None: 253 raise RuntimeError('compress called after flush()') 254 255 if self._started is False: 256 raise RuntimeError('compress called before compress_begin()') 257 258 result = compress_chunk( 259 self._context, data, 260 return_bytearray=self.return_bytearray 261 ) 262 263 return result 264 265 def flush(self): 266 """Finish the compression process. 267 268 This returns a ``bytes`` or ``bytearray`` object containing any data 269 stored in the compressor's internal buffers and a frame footer. 270 271 The LZ4FrameCompressor instance may be re-used after this method has 272 been called to create a new frame of compressed data. 273 274 Returns: 275 bytes or bytearray: compressed data and frame footer. 276 277 """ 278 result = compress_flush( 279 self._context, 280 end_frame=True, 281 return_bytearray=self.return_bytearray 282 ) 283 self._context = None 284 self._started = False 285 return result 286 287 def reset(self): 288 """Reset the `LZ4FrameCompressor` instance. 289 290 This allows the `LZ4FrameCompression` instance to be re-used after an 291 error. 292 293 """ 294 self._context = None 295 self._started = False 296 297 298class LZ4FrameDecompressor(object): 299 """Create a LZ4 frame decompressor object. 300 301 This can be used to decompress data incrementally. 302 303 For a more convenient way of decompressing an entire compressed frame at 304 once, see `lz4.frame.decompress()`. 305 306 Args: 307 return_bytearray (bool): When ``False`` a bytes object is returned from 308 the calls to methods of this class. When ``True`` a bytearray 309 object will be returned. The default is ``False``. 310 311 Attributes: 312 eof (bool): ``True`` if the end-of-stream marker has been reached. 313 ``False`` otherwise. 314 unused_data (bytes): Data found after the end of the compressed stream. 315 Before the end of the frame is reached, this will be ``b''``. 316 needs_input (bool): ``False`` if the ``decompress()`` method can 317 provide more decompressed data before requiring new uncompressed 318 input. ``True`` otherwise. 319 320 """ 321 322 def __init__(self, return_bytearray=False): 323 self._context = create_decompression_context() 324 self.eof = False 325 self.needs_input = True 326 self.unused_data = None 327 self._unconsumed_data = b'' 328 self._return_bytearray = return_bytearray 329 330 def __enter__(self): 331 # All necessary initialization is done in __init__ 332 return self 333 334 def __exit__(self, exception_type, exception, traceback): 335 self._context = None 336 self.eof = None 337 self.needs_input = None 338 self.unused_data = None 339 self._unconsumed_data = None 340 self._return_bytearray = None 341 342 def reset(self): 343 """Reset the decompressor state. 344 345 This is useful after an error occurs, allowing re-use of the instance. 346 347 """ 348 reset_decompression_context(self._context) 349 self.eof = False 350 self.needs_input = True 351 self.unused_data = None 352 self._unconsumed_data = b'' 353 354 def decompress(self, data, max_length=-1): # noqa: F811 355 """Decompresses part or all of an LZ4 frame of compressed data. 356 357 The returned data should be concatenated with the output of any 358 previous calls to `decompress()`. 359 360 If ``max_length`` is non-negative, returns at most ``max_length`` bytes 361 of decompressed data. If this limit is reached and further output can 362 be produced, the `needs_input` attribute will be set to ``False``. In 363 this case, the next call to `decompress()` may provide data as 364 ``b''`` to obtain more of the output. In all cases, any unconsumed data 365 from previous calls will be prepended to the input data. 366 367 If all of the input ``data`` was decompressed and returned (either 368 because this was less than ``max_length`` bytes, or because 369 ``max_length`` was negative), the `needs_input` attribute will be set 370 to ``True``. 371 372 If an end of frame marker is encountered in the data during 373 decompression, decompression will stop at the end of the frame, and any 374 data after the end of frame is available from the `unused_data` 375 attribute. In this case, the `LZ4FrameDecompressor` instance is reset 376 and can be used for further decompression. 377 378 Args: 379 data (str, bytes or buffer-compatible object): compressed data to 380 decompress 381 382 Keyword Args: 383 max_length (int): If this is non-negative, this method returns at 384 most ``max_length`` bytes of decompressed data. 385 386 Returns: 387 bytes: Uncompressed data 388 389 """ 390 391 if self._unconsumed_data: 392 data = self._unconsumed_data + data 393 394 decompressed, bytes_read, eoframe = decompress_chunk( 395 self._context, 396 data, 397 max_length=max_length, 398 return_bytearray=self._return_bytearray, 399 ) 400 401 if bytes_read < len(data): 402 if eoframe: 403 self.unused_data = data[bytes_read:] 404 else: 405 self._unconsumed_data = data[bytes_read:] 406 self.needs_input = False 407 else: 408 self._unconsumed_data = b'' 409 self.needs_input = True 410 self.unused_data = None 411 412 self.eof = eoframe 413 414 return decompressed 415 416 417_MODE_CLOSED = 0 418_MODE_READ = 1 419# Value 2 no longer used 420_MODE_WRITE = 3 421 422 423class LZ4FrameFile(_compression.BaseStream): 424 """A file object providing transparent LZ4F (de)compression. 425 426 An LZ4FFile can act as a wrapper for an existing file object, or refer 427 directly to a named file on disk. 428 429 Note that LZ4FFile provides a *binary* file interface - data read is 430 returned as bytes, and data to be written must be given as bytes. 431 432 When opening a file for writing, the settings used by the compressor can be 433 specified. The underlying compressor object is 434 `lz4.frame.LZ4FrameCompressor`. See the docstrings for that class for 435 details on compression options. 436 437 Args: 438 filename(str, bytes, PathLike, file object): can be either an actual 439 file name (given as a str, bytes, or 440 PathLike object), in which case the named file is opened, or it 441 can be an existing file object to read from or write to. 442 443 Keyword Args: 444 mode(str): mode can be ``'r'`` for reading (default), ``'w'`` for 445 (over)writing, ``'x'`` for creating exclusively, or ``'a'`` 446 for appending. These can equivalently be given as ``'rb'``, 447 ``'wb'``, ``'xb'`` and ``'ab'`` respectively. 448 return_bytearray (bool): When ``False`` a bytes object is returned from 449 the calls to methods of this class. When ``True`` a ``bytearray`` 450 object will be returned. The default is ``False``. 451 source_size (int): Optionally specify the total size of the 452 uncompressed data. If specified, will be stored in the compressed 453 frame header as an 8-byte field for later use during decompression. 454 Default is ``0`` (no size stored). Only used for writing 455 compressed files. 456 block_size (int): Compressor setting. See 457 `lz4.frame.LZ4FrameCompressor`. 458 block_linked (bool): Compressor setting. See 459 `lz4.frame.LZ4FrameCompressor`. 460 compression_level (int): Compressor setting. See 461 `lz4.frame.LZ4FrameCompressor`. 462 content_checksum (bool): Compressor setting. See 463 `lz4.frame.LZ4FrameCompressor`. 464 block_checksum (bool): Compressor setting. See 465 `lz4.frame.LZ4FrameCompressor`. 466 auto_flush (bool): Compressor setting. See 467 `lz4.frame.LZ4FrameCompressor`. 468 469 """ 470 471 def __init__(self, filename=None, mode='r', 472 block_size=BLOCKSIZE_DEFAULT, 473 block_linked=True, 474 compression_level=COMPRESSIONLEVEL_MIN, 475 content_checksum=False, 476 block_checksum=False, 477 auto_flush=False, 478 return_bytearray=False, 479 source_size=0): 480 481 self._fp = None 482 self._closefp = False 483 self._mode = _MODE_CLOSED 484 485 if mode in ('r', 'rb'): 486 mode_code = _MODE_READ 487 elif mode in ('w', 'wb', 'a', 'ab', 'x', 'xb'): 488 mode_code = _MODE_WRITE 489 self._compressor = LZ4FrameCompressor( 490 block_size=block_size, 491 block_linked=block_linked, 492 compression_level=compression_level, 493 content_checksum=content_checksum, 494 block_checksum=block_checksum, 495 auto_flush=auto_flush, 496 return_bytearray=return_bytearray, 497 ) 498 self._pos = 0 499 else: 500 raise ValueError('Invalid mode: {!r}'.format(mode)) 501 502 if sys.version_info > (3, 6): 503 path_test = isinstance(filename, (str, bytes, os.PathLike)) 504 else: 505 path_test = isinstance(filename, (str, bytes)) 506 507 if path_test is True: 508 if 'b' not in mode: 509 mode += 'b' 510 self._fp = builtins.open(filename, mode) 511 self._closefp = True 512 self._mode = mode_code 513 elif hasattr(filename, 'read') or hasattr(filename, 'write'): 514 self._fp = filename 515 self._mode = mode_code 516 else: 517 raise TypeError( 518 'filename must be a str, bytes, file or PathLike object' 519 ) 520 521 if self._mode == _MODE_READ: 522 raw = _compression.DecompressReader(self._fp, LZ4FrameDecompressor) 523 self._buffer = io.BufferedReader(raw) 524 525 if self._mode == _MODE_WRITE: 526 self._fp.write( 527 self._compressor.begin(source_size=source_size) 528 ) 529 530 def close(self): 531 """Flush and close the file. 532 533 May be called more than once without error. Once the file is 534 closed, any other operation on it will raise a ValueError. 535 """ 536 if self._mode == _MODE_CLOSED: 537 return 538 try: 539 if self._mode == _MODE_READ: 540 self._buffer.close() 541 self._buffer = None 542 elif self._mode == _MODE_WRITE: 543 self._fp.write(self._compressor.flush()) 544 self._compressor = None 545 finally: 546 try: 547 if self._closefp: 548 self._fp.close() 549 finally: 550 self._fp = None 551 self._closefp = False 552 self._mode = _MODE_CLOSED 553 554 @property 555 def closed(self): 556 """Returns ``True`` if this file is closed. 557 558 Returns: 559 bool: ``True`` if the file is closed, ``False`` otherwise. 560 561 """ 562 return self._mode == _MODE_CLOSED 563 564 def fileno(self): 565 """Return the file descriptor for the underlying file. 566 567 Returns: 568 file object: file descriptor for file. 569 570 """ 571 self._check_not_closed() 572 return self._fp.fileno() 573 574 def seekable(self): 575 """Return whether the file supports seeking. 576 577 Returns: 578 bool: ``True`` if the file supports seeking, ``False`` otherwise. 579 580 """ 581 return self.readable() and self._buffer.seekable() 582 583 def readable(self): 584 """Return whether the file was opened for reading. 585 586 Returns: 587 bool: ``True`` if the file was opened for reading, ``False`` 588 otherwise. 589 590 """ 591 self._check_not_closed() 592 return self._mode == _MODE_READ 593 594 def writable(self): 595 """Return whether the file was opened for writing. 596 597 Returns: 598 bool: ``True`` if the file was opened for writing, ``False`` 599 otherwise. 600 601 """ 602 self._check_not_closed() 603 return self._mode == _MODE_WRITE 604 605 def peek(self, size=-1): 606 """Return buffered data without advancing the file position. 607 608 Always returns at least one byte of data, unless at EOF. The exact 609 number of bytes returned is unspecified. 610 611 Returns: 612 bytes: uncompressed data 613 614 """ 615 self._check_can_read() 616 # Relies on the undocumented fact that BufferedReader.peek() always 617 # returns at least one byte (except at EOF) 618 return self._buffer.peek(size) 619 620 def read(self, size=-1): 621 """Read up to ``size`` uncompressed bytes from the file. 622 623 If ``size`` is negative or omitted, read until ``EOF`` is reached. 624 Returns ``b''`` if the file is already at ``EOF``. 625 626 Args: 627 size(int): If non-negative, specifies the maximum number of 628 uncompressed bytes to return. 629 630 Returns: 631 bytes: uncompressed data 632 633 """ 634 self._check_can_read() 635 return self._buffer.read(size) 636 637 def read1(self, size=-1): 638 """Read up to ``size`` uncompressed bytes. 639 640 This method tries to avoid making multiple reads from the underlying 641 stream. 642 643 This method reads up to a buffer's worth of data if ``size`` is 644 negative. 645 646 Returns ``b''`` if the file is at EOF. 647 648 Args: 649 size(int): If non-negative, specifies the maximum number of 650 uncompressed bytes to return. 651 652 Returns: 653 bytes: uncompressed data 654 655 """ 656 self._check_can_read() 657 if size < 0: 658 size = io.DEFAULT_BUFFER_SIZE 659 return self._buffer.read1(size) 660 661 def readline(self, size=-1): 662 """Read a line of uncompressed bytes from the file. 663 664 The terminating newline (if present) is retained. If size is 665 non-negative, no more than size bytes will be read (in which case the 666 line may be incomplete). Returns b'' if already at EOF. 667 668 Args: 669 size(int): If non-negative, specifies the maximum number of 670 uncompressed bytes to return. 671 672 Returns: 673 bytes: uncompressed data 674 675 """ 676 self._check_can_read() 677 return self._buffer.readline(size) 678 679 def write(self, data): 680 """Write a bytes object to the file. 681 682 Returns the number of uncompressed bytes written, which is always 683 ``len(data)``. Note that due to buffering, the file on disk may not 684 reflect the data written until close() is called. 685 686 Args: 687 data(bytes): uncompressed data to compress and write to the file 688 689 Returns: 690 int: the number of uncompressed bytes written to the file 691 692 """ 693 self._check_can_write() 694 compressed = self._compressor.compress(data) 695 self._fp.write(compressed) 696 self._pos += len(data) 697 return len(data) 698 699 def seek(self, offset, whence=io.SEEK_SET): 700 """Change the file position. 701 702 The new position is specified by ``offset``, relative to the position 703 indicated by ``whence``. Possible values for ``whence`` are: 704 705 - ``io.SEEK_SET`` or 0: start of stream (default): offset must not be 706 negative 707 - ``io.SEEK_CUR`` or 1: current stream position 708 - ``io.SEEK_END`` or 2: end of stream; offset must not be positive 709 710 Returns the new file position. 711 712 Note that seeking is emulated, so depending on the parameters, this 713 operation may be extremely slow. 714 715 Args: 716 offset(int): new position in the file 717 whence(int): position with which ``offset`` is measured. Allowed 718 values are 0, 1, 2. The default is 0 (start of stream). 719 720 Returns: 721 int: new file position 722 723 """ 724 self._check_can_seek() 725 return self._buffer.seek(offset, whence) 726 727 def tell(self): 728 """Return the current file position. 729 730 Args: 731 None 732 733 Returns: 734 int: file position 735 736 """ 737 self._check_not_closed() 738 if self._mode == _MODE_READ: 739 return self._buffer.tell() 740 return self._pos 741 742 743def open(filename, mode="rb", 744 encoding=None, 745 errors=None, 746 newline=None, 747 block_size=BLOCKSIZE_DEFAULT, 748 block_linked=True, 749 compression_level=COMPRESSIONLEVEL_MIN, 750 content_checksum=False, 751 block_checksum=False, 752 auto_flush=False, 753 return_bytearray=False, 754 source_size=0): 755 """Open an LZ4Frame-compressed file in binary or text mode. 756 757 ``filename`` can be either an actual file name (given as a str, bytes, or 758 PathLike object), in which case the named file is opened, or it can be an 759 existing file object to read from or write to. 760 761 The ``mode`` argument can be ``'r'``, ``'rb'`` (default), ``'w'``, 762 ``'wb'``, ``'x'``, ``'xb'``, ``'a'``, or ``'ab'`` for binary mode, or 763 ``'rt'``, ``'wt'``, ``'xt'``, or ``'at'`` for text mode. 764 765 For binary mode, this function is equivalent to the `LZ4FrameFile` 766 constructor: `LZ4FrameFile(filename, mode, ...)`. 767 768 For text mode, an `LZ4FrameFile` object is created, and wrapped in an 769 ``io.TextIOWrapper`` instance with the specified encoding, error handling 770 behavior, and line ending(s). 771 772 Args: 773 filename (str, bytes, os.PathLike): file name or file object to open 774 775 Keyword Args: 776 mode (str): mode for opening the file 777 encoding (str): the name of the encoding that will be used for 778 encoding/deconging the stream. It defaults to 779 ``locale.getpreferredencoding(False)``. See ``io.TextIOWrapper`` 780 for further details. 781 errors (str): specifies how encoding and decoding errors are to be 782 handled. See ``io.TextIOWrapper`` for further details. 783 newline (str): controls how line endings are handled. See 784 ``io.TextIOWrapper`` for further details. 785 return_bytearray (bool): When ``False`` a bytes object is returned 786 from the calls to methods of this class. When ``True`` a bytearray 787 object will be returned. The default is ``False``. 788 source_size (int): Optionally specify the total size of the 789 uncompressed data. If specified, will be stored in the compressed 790 frame header as an 8-byte field for later use during decompression. 791 Default is 0 (no size stored). Only used for writing compressed 792 files. 793 block_size (int): Compressor setting. See 794 `lz4.frame.LZ4FrameCompressor`. 795 block_linked (bool): Compressor setting. See 796 `lz4.frame.LZ4FrameCompressor`. 797 compression_level (int): Compressor setting. See 798 `lz4.frame.LZ4FrameCompressor`. 799 content_checksum (bool): Compressor setting. See 800 `lz4.frame.LZ4FrameCompressor`. 801 block_checksum (bool): Compressor setting. See 802 `lz4.frame.LZ4FrameCompressor`. 803 auto_flush (bool): Compressor setting. See 804 `lz4.frame.LZ4FrameCompressor`. 805 806 """ 807 if 't' in mode: 808 if 'b' in mode: 809 raise ValueError('Invalid mode: %r' % (mode,)) 810 else: 811 if encoding is not None: 812 raise ValueError( 813 "Argument 'encoding' not supported in binary mode" 814 ) 815 if errors is not None: 816 raise ValueError("Argument 'errors' not supported in binary mode") 817 if newline is not None: 818 raise ValueError("Argument 'newline' not supported in binary mode") 819 820 _mode = mode.replace('t', '') 821 822 binary_file = LZ4FrameFile( 823 filename, 824 mode=_mode, 825 block_size=block_size, 826 block_linked=block_linked, 827 compression_level=compression_level, 828 content_checksum=content_checksum, 829 block_checksum=block_checksum, 830 auto_flush=auto_flush, 831 return_bytearray=return_bytearray, 832 ) 833 834 if 't' in mode: 835 return io.TextIOWrapper(binary_file, encoding, errors, newline) 836 else: 837 return binary_file 838