From 50cd4b6959568999f5e426e58050ea912a490ac6 Mon Sep 17 00:00:00 2001 From: Yaron de Leeuw Date: Sat, 25 Jun 2022 11:43:54 +0300 Subject: bpo-26253: Add compressionlevel to tarfile stream (GH-2962) `tarfile` already accepts a compressionlevel argument for creating files. This patch adds the same for stream-based tarfile usage. The default is 9, the value that was previously hard-coded. --- Doc/library/tarfile.rst | 7 ++- Lib/tarfile.py | 22 ++++--- Lib/test/test_tarfile.py | 68 ++++++++++++++++++++++ .../2017-07-31-13-35-28.bpo-26253.8v_sCs.rst | 2 + 4 files changed, 88 insertions(+), 11 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2017-07-31-13-35-28.bpo-26253.8v_sCs.rst diff --git a/Doc/library/tarfile.rst b/Doc/library/tarfile.rst index f5c49b0..f9d34de 100644 --- a/Doc/library/tarfile.rst +++ b/Doc/library/tarfile.rst @@ -98,8 +98,8 @@ Some facts and figures: If *fileobj* is specified, it is used as an alternative to a :term:`file object` opened in binary mode for *name*. It is supposed to be at position 0. - For modes ``'w:gz'``, ``'r:gz'``, ``'w:bz2'``, ``'r:bz2'``, ``'x:gz'``, - ``'x:bz2'``, :func:`tarfile.open` accepts the keyword argument + For modes ``'w:gz'``, ``'x:gz'``, ``'w|gz'``, ``'w:bz2'``, ``'x:bz2'``, + ``'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 @@ -152,6 +152,9 @@ Some facts and figures: .. versionchanged:: 3.6 The *name* parameter accepts a :term:`path-like object`. + .. versionchanged:: 3.12 + The *compresslevel* keyword argument also works for streams. + .. class:: TarFile :noindex: diff --git a/Lib/tarfile.py b/Lib/tarfile.py index 169c88d..a08f247 100755 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -336,7 +336,8 @@ class _Stream: _Stream is intended to be used only internally. """ - def __init__(self, name, mode, comptype, fileobj, bufsize): + def __init__(self, name, mode, comptype, fileobj, bufsize, + compresslevel): """Construct a _Stream object. """ self._extfileobj = True @@ -371,7 +372,7 @@ class _Stream: self._init_read_gz() self.exception = zlib.error else: - self._init_write_gz() + self._init_write_gz(compresslevel) elif comptype == "bz2": try: @@ -383,7 +384,7 @@ class _Stream: self.cmp = bz2.BZ2Decompressor() self.exception = OSError else: - self.cmp = bz2.BZ2Compressor() + self.cmp = bz2.BZ2Compressor(compresslevel) elif comptype == "xz": try: @@ -410,13 +411,14 @@ class _Stream: if hasattr(self, "closed") and not self.closed: self.close() - def _init_write_gz(self): + def _init_write_gz(self, compresslevel): """Initialize for writing with gzip compression. """ - self.cmp = self.zlib.compressobj(9, self.zlib.DEFLATED, - -self.zlib.MAX_WBITS, - self.zlib.DEF_MEM_LEVEL, - 0) + self.cmp = self.zlib.compressobj(compresslevel, + self.zlib.DEFLATED, + -self.zlib.MAX_WBITS, + self.zlib.DEF_MEM_LEVEL, + 0) timestamp = struct.pack("