From b9418715f01a1b75548faf26b9fc83fa95e5e6f1 Mon Sep 17 00:00:00 2001 From: Sam Ezeh Date: Sat, 2 Apr 2022 13:44:25 +0100 Subject: [PATCH 1/3] Add ZipInfo.mode property --- Lib/zipfile.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Lib/zipfile.py b/Lib/zipfile.py index 721834aff13a74f..eb61310b6a43a2e 100644 --- a/Lib/zipfile.py +++ b/Lib/zipfile.py @@ -551,6 +551,14 @@ def from_file(cls, filename, arcname=None, *, strict_timestamps=True): return zinfo + @property + def mode(self): + return (self.external_attr >> 16) & (0o777) + + @mode.setter + def mode(self, value): + self.external_attr = (self.external_attr & ~(0o777 << 16)) | (value << 16 ) + def is_dir(self): """Return True if this archive member is a directory.""" return self.filename[-1] == '/' From 232ab1f1a03f1b05a82b0cf175767dba4a552ed5 Mon Sep 17 00:00:00 2001 From: Sam Ezeh Date: Sat, 2 Apr 2022 14:41:21 +0100 Subject: [PATCH 2/3] Add documentation, write tests --- Doc/library/zipfile.rst | 3 +++ Lib/test/test_zipfile.py | 15 +++++++++++++++ Lib/zipfile.py | 4 ++-- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/Doc/library/zipfile.rst b/Doc/library/zipfile.rst index bfcc883de692711..2f02fe4171fa4bc 100644 --- a/Doc/library/zipfile.rst +++ b/Doc/library/zipfile.rst @@ -839,6 +839,9 @@ Instances have the following methods and attributes: Size of the uncompressed file. +.. attribute:: ZipInfo.mode + + The mode of the file (permissions) .. _zipfile-commandline: .. program:: zipfile diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py index 26c40457e62a05a..d8541f77262ab5b 100644 --- a/Lib/test/test_zipfile.py +++ b/Lib/test/test_zipfile.py @@ -1959,6 +1959,21 @@ def test_create_empty_zipinfo_default_attributes(self): self.assertEqual(zi.file_size, 0) self.assertEqual(zi.compress_size, 0) + def test_zipinfo_mode(self): + zinfo = zipfile.ZipInfo() + self.assertEqual(zinfo.mode, 0) + + zinfo.mode = 0o777 + self.assertEqual(zinfo.mode, 0o777) + + zinfo.mode = 0o700 + self.assertEqual(zinfo.mode, 0o700) + + # Setting the file mode should not overwrite the file type + zinfo.mode = 0xFFFF + self.assertLessEqual(zinfo.mode, 0o777) + self.assertEqual(zinfo.external_attr >> 16 >> 9, 0) + def test_zipfile_with_short_extra_field(self): """If an extra field in the header is less than 4 bytes, skip it.""" zipdata = ( diff --git a/Lib/zipfile.py b/Lib/zipfile.py index eb61310b6a43a2e..c464b2482f669df 100644 --- a/Lib/zipfile.py +++ b/Lib/zipfile.py @@ -553,11 +553,11 @@ def from_file(cls, filename, arcname=None, *, strict_timestamps=True): @property def mode(self): - return (self.external_attr >> 16) & (0o777) + return (self.external_attr >> 16) & 0o777 @mode.setter def mode(self, value): - self.external_attr = (self.external_attr & ~(0o777 << 16)) | (value << 16 ) + self.external_attr = self.external_attr & ~(0o777 << 16) | ((value & 0o777) << 16) def is_dir(self): """Return True if this archive member is a directory.""" From a80b34238e68c5d3f14108f20c98a8745c7e8333 Mon Sep 17 00:00:00 2001 From: Sam Ezeh Date: Sat, 2 Apr 2022 14:47:30 +0100 Subject: [PATCH 3/3] Add news entry --- .../NEWS.d/next/Library/2022-04-02-14-47-18.bpo-47200.viCa8l.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2022-04-02-14-47-18.bpo-47200.viCa8l.rst diff --git a/Misc/NEWS.d/next/Library/2022-04-02-14-47-18.bpo-47200.viCa8l.rst b/Misc/NEWS.d/next/Library/2022-04-02-14-47-18.bpo-47200.viCa8l.rst new file mode 100644 index 000000000000000..59183af8f4f4e2b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-04-02-14-47-18.bpo-47200.viCa8l.rst @@ -0,0 +1 @@ +Adds the :attr:`ZipInfo.mode` attribute to get and set the mode of a file