diff options
author | Gregory P. Smith <greg@krypto.org> | 2024-01-12 20:15:05 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-12 20:15:05 (GMT) |
commit | b44b9d99004f096619c962a8b42a19322f6a441b (patch) | |
tree | f9f32f7eeac3ec7da168e23946365dfb024a4c37 | |
parent | ac92527c08d917dffdb9c0a218d06f21114614a2 (diff) | |
download | cpython-b44b9d99004f096619c962a8b42a19322f6a441b.zip cpython-b44b9d99004f096619c962a8b42a19322f6a441b.tar.gz cpython-b44b9d99004f096619c962a8b42a19322f6a441b.tar.bz2 |
gh-113971: Make `zipfile.ZipInfo._compresslevel` public as `.compress_level` (#113969)
Make zipfile.ZipInfo.compress_level public.
A property is used to retain the behavior of the ._compresslevel.
People constructing zipfile.ZipInfo instances to pass into existing APIs to control per-file compression levels already treat this as public, there was never a reason for it not to be.
I used the more modern name compress_level instead of compresslevel as the keyword argument on other ZipFile APIs is called to be consistent with compress_type and a general long term preference of not runningwordstogether without a separator in names.
-rw-r--r-- | Doc/library/zipfile.rst | 5 | ||||
-rw-r--r-- | Lib/test/test_zipfile/test_core.py | 15 | ||||
-rw-r--r-- | Lib/zipfile/__init__.py | 27 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2024-01-11-16-58-10.gh-issue-113971.skJZ4g.rst | 4 |
4 files changed, 40 insertions, 11 deletions
diff --git a/Doc/library/zipfile.rst b/Doc/library/zipfile.rst index a77e49a..c70f2ec 100644 --- a/Doc/library/zipfile.rst +++ b/Doc/library/zipfile.rst @@ -79,6 +79,11 @@ The module defines the following items: of the last modification to the file; the fields are described in section :ref:`zipinfo-objects`. + .. versionadded:: 3.13 + A public ``.compress_level`` attribute has been added to expose the + formerly protected ``._compresslevel``. The older protected name + continues to work as a property for backwards compatibility. + .. function:: is_zipfile(filename) Returns ``True`` if *filename* is a valid ZIP file based on its magic number, diff --git a/Lib/test/test_zipfile/test_core.py b/Lib/test/test_zipfile/test_core.py index f7b6db4..9bdb08a 100644 --- a/Lib/test/test_zipfile/test_core.py +++ b/Lib/test/test_zipfile/test_core.py @@ -315,7 +315,7 @@ class AbstractTestsWithSourceFile: # Compression level follows the constructor. a_info = zipfp.getinfo('a.txt') self.assertEqual(a_info.compress_type, self.compression) - self.assertEqual(a_info._compresslevel, 1) + self.assertEqual(a_info.compress_level, 1) # Compression level is overridden. b_info = zipfp.getinfo('b.txt') @@ -408,7 +408,7 @@ class AbstractTestsWithSourceFile: one_info = zipfp.getinfo('compress_1') nine_info = zipfp.getinfo('compress_9') self.assertEqual(one_info._compresslevel, 1) - self.assertEqual(nine_info._compresslevel, 9) + self.assertEqual(nine_info.compress_level, 9) def test_writing_errors(self): class BrokenFile(io.BytesIO): @@ -3011,6 +3011,17 @@ class ZipInfoTests(unittest.TestCase): self.assertEqual(zi.compress_type, zipfile.ZIP_STORED) self.assertEqual(zi.file_size, 0) + def test_compresslevel_property(self): + zinfo = zipfile.ZipInfo("xxx") + self.assertFalse(zinfo._compresslevel) + self.assertFalse(zinfo.compress_level) + zinfo._compresslevel = 99 # test the legacy @property.setter + self.assertEqual(zinfo.compress_level, 99) + self.assertEqual(zinfo._compresslevel, 99) + zinfo.compress_level = 8 + self.assertEqual(zinfo.compress_level, 8) + self.assertEqual(zinfo._compresslevel, 8) + class CommandLineTest(unittest.TestCase): diff --git a/Lib/zipfile/__init__.py b/Lib/zipfile/__init__.py index 1d8a607..8005b4b 100644 --- a/Lib/zipfile/__init__.py +++ b/Lib/zipfile/__init__.py @@ -371,7 +371,7 @@ def _sanitize_filename(filename): return filename -class ZipInfo (object): +class ZipInfo: """Class with attributes describing each file in the ZIP archive.""" __slots__ = ( @@ -379,7 +379,7 @@ class ZipInfo (object): 'filename', 'date_time', 'compress_type', - '_compresslevel', + 'compress_level', 'comment', 'extra', 'create_system', @@ -413,7 +413,7 @@ class ZipInfo (object): # Standard values: self.compress_type = ZIP_STORED # Type of compression for the file - self._compresslevel = None # Level for the compressor + self.compress_level = None # Level for the compressor self.comment = b"" # Comment for each file self.extra = b"" # ZIP extra data if sys.platform == 'win32': @@ -435,6 +435,15 @@ class ZipInfo (object): # header_offset Byte offset to the file header # CRC CRC-32 of the uncompressed file + # Maintain backward compatibility with the old protected attribute name. + @property + def _compresslevel(self): + return self.compress_level + + @_compresslevel.setter + def _compresslevel(self, value): + self.compress_level = value + def __repr__(self): result = ['<%s filename=%r' % (self.__class__.__name__, self.filename)] if self.compress_type != ZIP_STORED: @@ -1191,7 +1200,7 @@ class _ZipWriteFile(io.BufferedIOBase): self._zip64 = zip64 self._zipfile = zf self._compressor = _get_compressor(zinfo.compress_type, - zinfo._compresslevel) + zinfo.compress_level) self._file_size = 0 self._compress_size = 0 self._crc = 0 @@ -1603,7 +1612,7 @@ class ZipFile: elif mode == 'w': zinfo = ZipInfo(name) zinfo.compress_type = self.compression - zinfo._compresslevel = self.compresslevel + zinfo.compress_level = self.compresslevel else: # Get info object for name zinfo = self.getinfo(name) @@ -1855,9 +1864,9 @@ class ZipFile: zinfo.compress_type = self.compression if compresslevel is not None: - zinfo._compresslevel = compresslevel + zinfo.compress_level = compresslevel else: - zinfo._compresslevel = self.compresslevel + zinfo.compress_level = self.compresslevel with open(filename, "rb") as src, self.open(zinfo, 'w') as dest: shutil.copyfileobj(src, dest, 1024*8) @@ -1875,7 +1884,7 @@ class ZipFile: zinfo = ZipInfo(filename=zinfo_or_arcname, date_time=time.localtime(time.time())[:6]) zinfo.compress_type = self.compression - zinfo._compresslevel = self.compresslevel + zinfo.compress_level = self.compresslevel if zinfo.filename.endswith('/'): zinfo.external_attr = 0o40775 << 16 # drwxrwxr-x zinfo.external_attr |= 0x10 # MS-DOS directory flag @@ -1896,7 +1905,7 @@ class ZipFile: zinfo.compress_type = compress_type if compresslevel is not None: - zinfo._compresslevel = compresslevel + zinfo.compress_level = compresslevel zinfo.file_size = len(data) # Uncompressed size with self._lock: diff --git a/Misc/NEWS.d/next/Library/2024-01-11-16-58-10.gh-issue-113971.skJZ4g.rst b/Misc/NEWS.d/next/Library/2024-01-11-16-58-10.gh-issue-113971.skJZ4g.rst new file mode 100644 index 0000000..aa7a34d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-01-11-16-58-10.gh-issue-113971.skJZ4g.rst @@ -0,0 +1,4 @@ +The :class:`zipfile.ZipInfo` previously protected ``._compresslevel`` +attribute has been made public as ``.compress_level`` with the old +``_compresslevel`` name remaining available as a property to retain +compatibility. |