gh-133005: Support tarfile.open(mode="w|xz", preset=...) (GH-133007)

* gh-133005: Support `tarfile.open(mode="w|xz", preset=...)`

Support passing the `preset` option to `tarfile.open` when the file
is open with `mode="w|xz"`.  This aligns the behavior with `"w:xz"`
mode.

* Also raise an error for `compresslevel` or `preset` with wrong mode

Raise an error if `compresslevel` or `preset` argument is specified
for stream mode with incorrect compression. This should reduce the risk
of mistakes and align the stream modes with regular modes, that raise
an implicit TypeError on unsupported arguments.

* Apply suggestions from code review

Co-authored-by: Brian Schubert <brianm.schubert@gmail.com>
This commit is contained in:
Michał Górny
2025-04-28 00:19:59 +02:00
committed by GitHub
parent 146b981f76
commit 019ee49d50
3 changed files with 16 additions and 4 deletions

View File

@@ -112,7 +112,7 @@ Some facts and figures:
``'w|bz2'``, :func:`tarfile.open` accepts the keyword argument
*compresslevel* (default ``9``) to specify the compression level of the file.
For modes ``'w:xz'`` and ``'x:xz'``, :func:`tarfile.open` accepts the
For modes ``'w:xz'``, ``'x:xz'`` and ``'w|xz'``, :func:`tarfile.open` accepts the
keyword argument *preset* to specify the compression level of the file.
For special purposes, there is a second format for *mode*:
@@ -167,6 +167,9 @@ Some facts and figures:
.. versionchanged:: 3.12
The *compresslevel* keyword argument also works for streams.
.. versionchanged:: next
The *preset* keyword argument also works for streams.
.. class:: TarFile
:noindex:

View File

@@ -339,7 +339,7 @@ class _Stream:
"""
def __init__(self, name, mode, comptype, fileobj, bufsize,
compresslevel):
compresslevel, preset):
"""Construct a _Stream object.
"""
self._extfileobj = True
@@ -398,7 +398,7 @@ class _Stream:
self.cmp = lzma.LZMADecompressor()
self.exception = lzma.LZMAError
else:
self.cmp = lzma.LZMACompressor()
self.cmp = lzma.LZMACompressor(preset=preset)
elif comptype != "tar":
raise CompressionError("unknown compression type %r" % comptype)
@@ -1885,10 +1885,17 @@ class TarFile(object):
if filemode not in ("r", "w"):
raise ValueError("mode must be 'r' or 'w'")
if "compresslevel" in kwargs and comptype not in ("gz", "bz2"):
raise ValueError(
"compresslevel is only valid for w|gz and w|bz2 modes"
)
if "preset" in kwargs and comptype not in ("xz",):
raise ValueError("preset is only valid for w|xz mode")
compresslevel = kwargs.pop("compresslevel", 9)
preset = kwargs.pop("preset", None)
stream = _Stream(name, filemode, comptype, fileobj, bufsize,
compresslevel)
compresslevel, preset)
try:
t = cls(name, filemode, stream, **kwargs)
except:

View File

@@ -0,0 +1,2 @@
Support passing ``preset`` option to :func:`tarfile.open` when using ``'w|xz'``
mode.