[3.14] gh-136170: Revert adding ZipFile.data_offset (GH-136950) (#136955)

gh-136170: Revert adding `ZipFile.data_offset` (GH-136950)

* Revert "gh-84481: Make ZipFile.data_offset more robust (GH-132178)"

This reverts commit 6cd1d6c6b1.

* Revert "gh-84481: Add ZipFile.data_offset attribute (GH-132165)"

This reverts commit 0788948dcb.

---------
(cherry picked from commit 6bf1c0ab34)

Co-authored-by: Emma Smith <emma@emmatyping.dev>
Co-authored-by: Gregory P. Smith <greg@krypto.org>
This commit is contained in:
Miss Islington (bot) 2025-07-22 05:35:41 +02:00 committed by GitHub
parent 4af1b72b31
commit caef946a25
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 3 additions and 75 deletions

View file

@ -558,14 +558,6 @@ The following data attributes are also available:
it should be no longer than 65535 bytes. Comments longer than this will be it should be no longer than 65535 bytes. Comments longer than this will be
truncated. truncated.
.. attribute:: ZipFile.data_offset
The offset to the start of ZIP data from the beginning of the file. When the
:class:`ZipFile` is opened in either mode ``'w'`` or ``'x'`` and the
underlying file does not support ``tell()``, the value will be ``None``
instead.
.. versionadded:: 3.14
.. _path-objects: .. _path-objects:

View file

@ -3470,60 +3470,6 @@ class TestExecutablePrependedZip(unittest.TestCase):
self.assertIn(b'number in executable: 5', output) self.assertIn(b'number in executable: 5', output)
class TestDataOffsetPrependedZip(unittest.TestCase):
"""Test .data_offset on reading zip files with an executable prepended."""
def setUp(self):
self.exe_zip = findfile('exe_with_zip', subdir='archivetestdata')
self.exe_zip64 = findfile('exe_with_z64', subdir='archivetestdata')
def _test_data_offset(self, name):
with zipfile.ZipFile(name) as zipfp:
self.assertEqual(zipfp.data_offset, 713)
def test_data_offset_with_exe_prepended(self):
self._test_data_offset(self.exe_zip)
def test_data_offset_with_exe_prepended_zip64(self):
self._test_data_offset(self.exe_zip64)
class TestDataOffsetZipWrite(unittest.TestCase):
"""Test .data_offset for ZipFile opened in write mode."""
def setUp(self):
os.mkdir(TESTFNDIR)
self.addCleanup(rmtree, TESTFNDIR)
self.test_path = os.path.join(TESTFNDIR, 'testoffset.zip')
def test_data_offset_write_no_prefix(self):
with io.BytesIO() as fp:
with zipfile.ZipFile(fp, "w") as zipfp:
self.assertEqual(zipfp.data_offset, 0)
def test_data_offset_write_with_prefix(self):
with io.BytesIO() as fp:
fp.write(b"this is a prefix")
with zipfile.ZipFile(fp, "w") as zipfp:
self.assertEqual(zipfp.data_offset, 16)
def test_data_offset_append_with_bad_zip(self):
with io.BytesIO() as fp:
fp.write(b"this is a prefix")
with zipfile.ZipFile(fp, "a") as zipfp:
self.assertEqual(zipfp.data_offset, 16)
def test_data_offset_write_no_tell(self):
# The initializer in ZipFile checks if tell raises AttributeError or
# OSError when creating a file in write mode when deducing the offset
# of the beginning of zip data
class NoTellBytesIO(io.BytesIO):
def tell(self):
raise OSError("Unimplemented!")
with NoTellBytesIO() as fp:
with zipfile.ZipFile(fp, "w") as zipfp:
self.assertIsNone(zipfp.data_offset)
class EncodedMetadataTests(unittest.TestCase): class EncodedMetadataTests(unittest.TestCase):
file_names = ['\u4e00', '\u4e8c', '\u4e09'] # Han 'one', 'two', 'three' file_names = ['\u4e00', '\u4e8c', '\u4e09'] # Han 'one', 'two', 'three'
file_content = [ file_content = [

View file

@ -1452,7 +1452,6 @@ class ZipFile:
self._lock = threading.RLock() self._lock = threading.RLock()
self._seekable = True self._seekable = True
self._writing = False self._writing = False
self._data_offset = None
try: try:
if mode == 'r': if mode == 'r':
@ -1463,7 +1462,6 @@ class ZipFile:
self._didModify = True self._didModify = True
try: try:
self.start_dir = self.fp.tell() self.start_dir = self.fp.tell()
self._data_offset = self.start_dir
except (AttributeError, OSError): except (AttributeError, OSError):
self.fp = _Tellable(self.fp) self.fp = _Tellable(self.fp)
self.start_dir = 0 self.start_dir = 0
@ -1488,7 +1486,6 @@ class ZipFile:
# even if no files are added to the archive # even if no files are added to the archive
self._didModify = True self._didModify = True
self.start_dir = self.fp.tell() self.start_dir = self.fp.tell()
self._data_offset = self.start_dir
else: else:
raise ValueError("Mode must be 'r', 'w', 'x', or 'a'") raise ValueError("Mode must be 'r', 'w', 'x', or 'a'")
except: except:
@ -1535,10 +1532,6 @@ class ZipFile:
# self.start_dir: Position of start of central directory # self.start_dir: Position of start of central directory
self.start_dir = offset_cd + concat self.start_dir = offset_cd + concat
# store the offset to the beginning of data for the
# .data_offset property
self._data_offset = concat
if self.start_dir < 0: if self.start_dir < 0:
raise BadZipFile("Bad offset for central directory") raise BadZipFile("Bad offset for central directory")
fp.seek(self.start_dir, 0) fp.seek(self.start_dir, 0)
@ -1599,12 +1592,6 @@ class ZipFile:
zinfo._end_offset = end_offset zinfo._end_offset = end_offset
end_offset = zinfo.header_offset end_offset = zinfo.header_offset
@property
def data_offset(self):
"""The offset to the start of zip data in the file or None if
unavailable."""
return self._data_offset
def namelist(self): def namelist(self):
"""Return a list of file names in the archive.""" """Return a list of file names in the archive."""
return [data.filename for data in self.filelist] return [data.filename for data in self.filelist]

View file

@ -0,0 +1,3 @@
Removed the unreleased ``zipfile.ZipFile.data_offset`` property added in 3.14.0a7
as it wasn't fully clear which behavior it should have in some situations so
the result was not always what a user might expect.