]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-133005: Support `tarfile.open(mode="w|xz", preset=...)` (GH-133007)
authorMichał Górny <mgorny@gentoo.org>
Sun, 27 Apr 2025 22:19:59 +0000 (00:19 +0200)
committerGitHub <noreply@github.com>
Sun, 27 Apr 2025 22:19:59 +0000 (22:19 +0000)
* 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>
Doc/library/tarfile.rst
Lib/tarfile.py
Misc/NEWS.d/next/Library/2025-04-26-14-44-21.gh-issue-133005.y4SRfk.rst [new file with mode: 0644]

index c9d69cf5094095454b7856b79b77f7eabeae360e..8e9775ddbc691592d5936e004b30e5d96ab90c3e 100644 (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:
index a0fab46b24e24924aec8081c1fb07f2cc520752d..82c5f6704cbd24f4c814932f8cc6c01591df738d 100644 (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:
diff --git a/Misc/NEWS.d/next/Library/2025-04-26-14-44-21.gh-issue-133005.y4SRfk.rst b/Misc/NEWS.d/next/Library/2025-04-26-14-44-21.gh-issue-133005.y4SRfk.rst
new file mode 100644 (file)
index 0000000..cb3ad48
--- /dev/null
@@ -0,0 +1,2 @@
+Support passing ``preset`` option to :func:`tarfile.open` when using ``'w|xz'``
+mode.