Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Doc/library/tarfile.rst
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ Some facts and figures:
a Zstandard dictionary used to improve compression of smaller amounts of
data.

For modes ``'r:zst'`` and ``'r|zst'``, :func:`tarfile.open` accepts the keyword
arguments *options* and *zstd_dict* as well.

For special purposes, there is a second format for *mode*:
``'filemode|[compression]'``. :func:`tarfile.open` will return a :class:`TarFile`
object that processes its data as a stream of blocks. No random seeking will
Expand Down
18 changes: 14 additions & 4 deletions Lib/tarfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ class _Stream:
"""

def __init__(self, name, mode, comptype, fileobj, bufsize,
compresslevel, preset):
compresslevel, preset, level, options, zstd_dict):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be cleaner at this point to take **kwargs in _Stream and pop items per-(de)compressor. Having stream take every possible argument doesn't seem like a great idea for readability purposes since many of the arguments will be unused. I believe because this was up in the air and also how to treat compressLevel vs level, we intentionally didn't include this in 3.14 before the beta cutoff.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I see. Thanks for the explanation.
I'll rewrite it.

"""Construct a _Stream object.
"""
self._extfileobj = True
Expand Down Expand Up @@ -405,10 +405,10 @@ def __init__(self, name, mode, comptype, fileobj, bufsize,
raise CompressionError("compression.zstd module is not available") from None
if mode == "r":
self.dbuf = b""
self.cmp = zstd.ZstdDecompressor()
self.cmp = zstd.ZstdDecompressor(zstd_dict, options)
self.exception = zstd.ZstdError
else:
self.cmp = zstd.ZstdCompressor()
self.cmp = zstd.ZstdCompressor(level, options, zstd_dict)
elif comptype != "tar":
raise CompressionError("unknown compression type %r" % comptype)

Expand Down Expand Up @@ -1929,10 +1929,20 @@ def not_compressed(comptype):
if "preset" in kwargs and comptype not in ("xz",):
raise ValueError("preset is only valid for w|xz mode")

if comptype not in ("zst",):
for arg in ("level", "options", "zstd_dict"):
if arg in kwargs:
raise ValueError(
f"{arg} is only valid for zstd compression"
)

compresslevel = kwargs.pop("compresslevel", 6)
preset = kwargs.pop("preset", None)
level = kwargs.pop("level", None)
options = kwargs.pop("options", None)
zstd_dict = kwargs.pop("zstd_dict", None)
stream = _Stream(name, filemode, comptype, fileobj, bufsize,
compresslevel, preset)
compresslevel, preset, level, options, zstd_dict)
try:
t = cls(name, filemode, stream, **kwargs)
except:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Make ``tarfile.open`` correctly forward keyword arguments for zstd in stream mode.
Loading