aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Lib/compression/zstd
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/compression/zstd')
-rw-r--r--Lib/compression/zstd/__init__.py136
-rw-r--r--Lib/compression/zstd/_zstdfile.py74
2 files changed, 107 insertions, 103 deletions
diff --git a/Lib/compression/zstd/__init__.py b/Lib/compression/zstd/__init__.py
index 4f734eb07b0..84b25914b0a 100644
--- a/Lib/compression/zstd/__init__.py
+++ b/Lib/compression/zstd/__init__.py
@@ -2,41 +2,48 @@
__all__ = (
# compression.zstd
- "COMPRESSION_LEVEL_DEFAULT",
- "compress",
- "CompressionParameter",
- "decompress",
- "DecompressionParameter",
- "finalize_dict",
- "get_frame_info",
- "Strategy",
- "train_dict",
+ 'COMPRESSION_LEVEL_DEFAULT',
+ 'compress',
+ 'CompressionParameter',
+ 'decompress',
+ 'DecompressionParameter',
+ 'finalize_dict',
+ 'get_frame_info',
+ 'Strategy',
+ 'train_dict',
# compression.zstd._zstdfile
- "open",
- "ZstdFile",
+ 'open',
+ 'ZstdFile',
# _zstd
- "get_frame_size",
- "zstd_version",
- "zstd_version_info",
- "ZstdCompressor",
- "ZstdDecompressor",
- "ZstdDict",
- "ZstdError",
+ 'get_frame_size',
+ 'zstd_version',
+ 'zstd_version_info',
+ 'ZstdCompressor',
+ 'ZstdDecompressor',
+ 'ZstdDict',
+ 'ZstdError',
)
import _zstd
import enum
-from _zstd import *
+from _zstd import (ZstdCompressor, ZstdDecompressor, ZstdDict, ZstdError,
+ get_frame_size, zstd_version)
from compression.zstd._zstdfile import ZstdFile, open, _nbytes
-COMPRESSION_LEVEL_DEFAULT = _zstd._compressionLevel_values[0]
+# zstd_version_number is (MAJOR * 100 * 100 + MINOR * 100 + RELEASE)
+zstd_version_info = (*divmod(_zstd.zstd_version_number // 100, 100),
+ _zstd.zstd_version_number % 100)
+"""Version number of the runtime zstd library as a tuple of integers."""
+
+COMPRESSION_LEVEL_DEFAULT = _zstd.ZSTD_CLEVEL_DEFAULT
"""The default compression level for Zstandard, currently '3'."""
class FrameInfo:
"""Information about a Zstandard frame."""
+
__slots__ = 'decompressed_size', 'dictionary_id'
def __init__(self, decompressed_size, dictionary_id):
@@ -65,7 +72,7 @@ def get_frame_info(frame_buffer):
the frame may or may not need a dictionary to be decoded,
and the ID of such a dictionary is not specified.
"""
- return FrameInfo(*_zstd._get_frame_info(frame_buffer))
+ return FrameInfo(*_zstd.get_frame_info(frame_buffer))
def train_dict(samples, dict_size):
@@ -85,7 +92,7 @@ def train_dict(samples, dict_size):
chunk_sizes = tuple(_nbytes(sample) for sample in samples)
if not chunks:
raise ValueError("samples contained no data; can't train dictionary.")
- dict_content = _zstd._train_dict(chunks, chunk_sizes, dict_size)
+ dict_content = _zstd.train_dict(chunks, chunk_sizes, dict_size)
return ZstdDict(dict_content)
@@ -119,13 +126,13 @@ def finalize_dict(zstd_dict, /, samples, dict_size, level):
chunks = b''.join(samples)
chunk_sizes = tuple(_nbytes(sample) for sample in samples)
if not chunks:
- raise ValueError("The samples are empty content, can't finalize the"
+ raise ValueError("The samples are empty content, can't finalize the "
"dictionary.")
- dict_content = _zstd._finalize_dict(zstd_dict.dict_content,
- chunks, chunk_sizes,
- dict_size, level)
+ dict_content = _zstd.finalize_dict(zstd_dict.dict_content, chunks,
+ chunk_sizes, dict_size, level)
return ZstdDict(dict_content)
+
def compress(data, level=None, options=None, zstd_dict=None):
"""Return Zstandard compressed *data* as bytes.
@@ -141,6 +148,7 @@ def compress(data, level=None, options=None, zstd_dict=None):
comp = ZstdCompressor(level=level, options=options, zstd_dict=zstd_dict)
return comp.compress(data, mode=ZstdCompressor.FLUSH_FRAME)
+
def decompress(data, zstd_dict=None, options=None):
"""Decompress one or more frames of Zstandard compressed *data*.
@@ -156,59 +164,59 @@ def decompress(data, zstd_dict=None, options=None):
decomp = ZstdDecompressor(options=options, zstd_dict=zstd_dict)
results.append(decomp.decompress(data))
if not decomp.eof:
- raise ZstdError("Compressed data ended before the "
- "end-of-stream marker was reached")
+ raise ZstdError('Compressed data ended before the '
+ 'end-of-stream marker was reached')
data = decomp.unused_data
if not data:
break
- return b"".join(results)
+ return b''.join(results)
class CompressionParameter(enum.IntEnum):
"""Compression parameters."""
- compression_level = _zstd._ZSTD_c_compressionLevel
- window_log = _zstd._ZSTD_c_windowLog
- hash_log = _zstd._ZSTD_c_hashLog
- chain_log = _zstd._ZSTD_c_chainLog
- search_log = _zstd._ZSTD_c_searchLog
- min_match = _zstd._ZSTD_c_minMatch
- target_length = _zstd._ZSTD_c_targetLength
- strategy = _zstd._ZSTD_c_strategy
-
- enable_long_distance_matching = _zstd._ZSTD_c_enableLongDistanceMatching
- ldm_hash_log = _zstd._ZSTD_c_ldmHashLog
- ldm_min_match = _zstd._ZSTD_c_ldmMinMatch
- ldm_bucket_size_log = _zstd._ZSTD_c_ldmBucketSizeLog
- ldm_hash_rate_log = _zstd._ZSTD_c_ldmHashRateLog
-
- content_size_flag = _zstd._ZSTD_c_contentSizeFlag
- checksum_flag = _zstd._ZSTD_c_checksumFlag
- dict_id_flag = _zstd._ZSTD_c_dictIDFlag
-
- nb_workers = _zstd._ZSTD_c_nbWorkers
- job_size = _zstd._ZSTD_c_jobSize
- overlap_log = _zstd._ZSTD_c_overlapLog
+ compression_level = _zstd.ZSTD_c_compressionLevel
+ window_log = _zstd.ZSTD_c_windowLog
+ hash_log = _zstd.ZSTD_c_hashLog
+ chain_log = _zstd.ZSTD_c_chainLog
+ search_log = _zstd.ZSTD_c_searchLog
+ min_match = _zstd.ZSTD_c_minMatch
+ target_length = _zstd.ZSTD_c_targetLength
+ strategy = _zstd.ZSTD_c_strategy
+
+ enable_long_distance_matching = _zstd.ZSTD_c_enableLongDistanceMatching
+ ldm_hash_log = _zstd.ZSTD_c_ldmHashLog
+ ldm_min_match = _zstd.ZSTD_c_ldmMinMatch
+ ldm_bucket_size_log = _zstd.ZSTD_c_ldmBucketSizeLog
+ ldm_hash_rate_log = _zstd.ZSTD_c_ldmHashRateLog
+
+ content_size_flag = _zstd.ZSTD_c_contentSizeFlag
+ checksum_flag = _zstd.ZSTD_c_checksumFlag
+ dict_id_flag = _zstd.ZSTD_c_dictIDFlag
+
+ nb_workers = _zstd.ZSTD_c_nbWorkers
+ job_size = _zstd.ZSTD_c_jobSize
+ overlap_log = _zstd.ZSTD_c_overlapLog
def bounds(self):
"""Return the (lower, upper) int bounds of a compression parameter.
Both the lower and upper bounds are inclusive.
"""
- return _zstd._get_param_bounds(self.value, is_compress=True)
+ return _zstd.get_param_bounds(self.value, is_compress=True)
class DecompressionParameter(enum.IntEnum):
"""Decompression parameters."""
- window_log_max = _zstd._ZSTD_d_windowLogMax
+ window_log_max = _zstd.ZSTD_d_windowLogMax
def bounds(self):
"""Return the (lower, upper) int bounds of a decompression parameter.
Both the lower and upper bounds are inclusive.
"""
- return _zstd._get_param_bounds(self.value, is_compress=False)
+ return _zstd.get_param_bounds(self.value, is_compress=False)
class Strategy(enum.IntEnum):
@@ -219,16 +227,16 @@ class Strategy(enum.IntEnum):
the numeric value might change.
"""
- fast = _zstd._ZSTD_fast
- dfast = _zstd._ZSTD_dfast
- greedy = _zstd._ZSTD_greedy
- lazy = _zstd._ZSTD_lazy
- lazy2 = _zstd._ZSTD_lazy2
- btlazy2 = _zstd._ZSTD_btlazy2
- btopt = _zstd._ZSTD_btopt
- btultra = _zstd._ZSTD_btultra
- btultra2 = _zstd._ZSTD_btultra2
+ fast = _zstd.ZSTD_fast
+ dfast = _zstd.ZSTD_dfast
+ greedy = _zstd.ZSTD_greedy
+ lazy = _zstd.ZSTD_lazy
+ lazy2 = _zstd.ZSTD_lazy2
+ btlazy2 = _zstd.ZSTD_btlazy2
+ btopt = _zstd.ZSTD_btopt
+ btultra = _zstd.ZSTD_btultra
+ btultra2 = _zstd.ZSTD_btultra2
# Check validity of the CompressionParameter & DecompressionParameter types
-_zstd._set_parameter_types(CompressionParameter, DecompressionParameter)
+_zstd.set_parameter_types(CompressionParameter, DecompressionParameter)
diff --git a/Lib/compression/zstd/_zstdfile.py b/Lib/compression/zstd/_zstdfile.py
index fbc9e02a733..d709f5efc65 100644
--- a/Lib/compression/zstd/_zstdfile.py
+++ b/Lib/compression/zstd/_zstdfile.py
@@ -1,12 +1,9 @@
import io
from os import PathLike
-from _zstd import (ZstdCompressor, ZstdDecompressor, _ZSTD_DStreamSizes,
- ZstdError)
+from _zstd import ZstdCompressor, ZstdDecompressor, ZSTD_DStreamOutSize
from compression._common import _streams
-__all__ = ("ZstdFile", "open")
-
-_ZSTD_DStreamOutSize = _ZSTD_DStreamSizes[1]
+__all__ = ('ZstdFile', 'open')
_MODE_CLOSED = 0
_MODE_READ = 1
@@ -33,15 +30,15 @@ class ZstdFile(_streams.BaseStream):
FLUSH_BLOCK = ZstdCompressor.FLUSH_BLOCK
FLUSH_FRAME = ZstdCompressor.FLUSH_FRAME
- def __init__(self, file, /, mode="r", *,
+ def __init__(self, file, /, mode='r', *,
level=None, options=None, zstd_dict=None):
"""Open a Zstandard compressed file in binary mode.
*file* can be either an file-like object, or a file name to open.
- *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.
+ *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.
*level* is an optional int specifying the compression level to use,
or COMPRESSION_LEVEL_DEFAULT if not given.
@@ -59,39 +56,38 @@ class ZstdFile(_streams.BaseStream):
self._buffer = None
if not isinstance(mode, str):
- raise ValueError("mode must be a str")
+ raise ValueError('mode must be a str')
if options is not None and not isinstance(options, dict):
- raise TypeError("options must be a dict or None")
- mode = mode.removesuffix("b") # handle rb, wb, xb, ab
- if mode == "r":
+ raise TypeError('options must be a dict or None')
+ mode = mode.removesuffix('b') # handle rb, wb, xb, ab
+ if mode == 'r':
if level is not None:
- raise TypeError("level is illegal in read mode")
+ raise TypeError('level is illegal in read mode')
self._mode = _MODE_READ
- elif mode in {"w", "a", "x"}:
+ elif mode in {'w', 'a', 'x'}:
if level is not None and not isinstance(level, int):
- raise TypeError("level must be int or None")
+ raise TypeError('level must be int or None')
self._mode = _MODE_WRITE
self._compressor = ZstdCompressor(level=level, options=options,
zstd_dict=zstd_dict)
self._pos = 0
else:
- raise ValueError(f"Invalid mode: {mode!r}")
+ raise ValueError(f'Invalid mode: {mode!r}')
if isinstance(file, (str, bytes, PathLike)):
self._fp = io.open(file, f'{mode}b')
self._close_fp = True
- elif ((mode == 'r' and hasattr(file, "read"))
- or (mode != 'r' and hasattr(file, "write"))):
+ elif ((mode == 'r' and hasattr(file, 'read'))
+ or (mode != 'r' and hasattr(file, 'write'))):
self._fp = file
else:
- raise TypeError("file must be a file-like object "
- "or a str, bytes, or PathLike object")
+ raise TypeError('file must be a file-like object '
+ 'or a str, bytes, or PathLike object')
if self._mode == _MODE_READ:
raw = _streams.DecompressReader(
self._fp,
ZstdDecompressor,
- trailing_error=ZstdError,
zstd_dict=zstd_dict,
options=options,
)
@@ -154,22 +150,22 @@ class ZstdFile(_streams.BaseStream):
return
self._check_not_closed()
if mode not in {self.FLUSH_BLOCK, self.FLUSH_FRAME}:
- raise ValueError("Invalid mode argument, expected either "
- "ZstdFile.FLUSH_FRAME or "
- "ZstdFile.FLUSH_BLOCK")
+ raise ValueError('Invalid mode argument, expected either '
+ 'ZstdFile.FLUSH_FRAME or '
+ 'ZstdFile.FLUSH_BLOCK')
if self._compressor.last_mode == mode:
return
# Flush zstd block/frame, and write.
data = self._compressor.flush(mode)
self._fp.write(data)
- if hasattr(self._fp, "flush"):
+ if hasattr(self._fp, 'flush'):
self._fp.flush()
def read(self, size=-1):
"""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.
+ Returns b'' if the file is already at EOF.
"""
if size is None:
size = -1
@@ -181,14 +177,14 @@ class ZstdFile(_streams.BaseStream):
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.
+ Returns b'' if the file is at EOF.
"""
self._check_can_read()
if size < 0:
# Note this should *not* be io.DEFAULT_BUFFER_SIZE.
# ZSTD_DStreamOutSize is the minimum amount to read guaranteeing
# a full block is read.
- size = _ZSTD_DStreamOutSize
+ size = ZSTD_DStreamOutSize
return self._buffer.read1(size)
def readinto(self, b):
@@ -296,7 +292,7 @@ class ZstdFile(_streams.BaseStream):
return self._mode == _MODE_WRITE
-def open(file, /, mode="rb", *, level=None, options=None, zstd_dict=None,
+def open(file, /, mode='rb', *, level=None, options=None, zstd_dict=None,
encoding=None, errors=None, newline=None):
"""Open a Zstandard compressed file in binary or text mode.
@@ -304,8 +300,8 @@ def open(file, /, mode="rb", *, level=None, options=None, zstd_dict=None,
in which case the named file is opened, or it can be an existing file object
to read from or write to.
- The mode parameter can be "r", "rb" (default), "w", "wb", "x", "xb", "a",
- "ab" for binary mode, or "rt", "wt", "xt", "at" for text mode.
+ The mode parameter can be 'r', 'rb' (default), 'w', 'wb', 'x', 'xb', 'a',
+ 'ab' for binary mode, or 'rt', 'wt', 'xt', 'at' for text mode.
The level, options, and zstd_dict parameters specify the settings the same
as ZstdFile.
@@ -326,19 +322,19 @@ def open(file, /, mode="rb", *, level=None, options=None, zstd_dict=None,
behavior, and line ending(s).
"""
- text_mode = "t" in mode
- mode = mode.replace("t", "")
+ text_mode = 't' in mode
+ mode = mode.replace('t', '')
if text_mode:
- if "b" in mode:
- raise ValueError(f"Invalid mode: {mode!r}")
+ if 'b' in mode:
+ raise ValueError(f'Invalid mode: {mode!r}')
else:
if encoding is not None:
- raise ValueError("Argument 'encoding' not supported in binary mode")
+ raise ValueError('Argument "encoding" not supported in binary mode')
if errors is not None:
- raise ValueError("Argument 'errors' not supported in binary mode")
+ raise ValueError('Argument "errors" not supported in binary mode')
if newline is not None:
- raise ValueError("Argument 'newline' not supported in binary mode")
+ raise ValueError('Argument "newline" not supported in binary mode')
binary_file = ZstdFile(file, mode, level=level, options=options,
zstd_dict=zstd_dict)