Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Doc/library/zipfile.rst
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,9 @@ ZipFile objects
strict_descriptor=True[, chunk_size])

Rewrites the archive to remove unreferenced local file entries, shrinking
its file size. The archive must be opened with mode ``'a'``.
its file size. The archive must be opened with mode ``'a'``, and any file
object returned by :meth:`ZipFile.open` must be closed first, since
repacking moves the member data those objects read from.

If *removed* is provided, it must be a sequence of :class:`ZipInfo` objects
representing the recently removed members, and only their corresponding
Expand Down
12 changes: 12 additions & 0 deletions Lib/test/test_zipfile/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2382,6 +2382,18 @@ def test_repack_writing(self, m_repack):
zh.repack()
m_repack.assert_not_called()

@mock.patch.object(zipfile, '_ZipRepacker')
def test_repack_reading(self, m_repack):
self._prepare_zip_from_test_files(TESTFN, self.test_files)
with zipfile.ZipFile(TESTFN, 'a') as zh:
with zh.open(self.test_files[0][0]):
with self.assertRaises(ValueError):
zh.repack()
m_repack.assert_not_called()
# Allowed once the reading handle is closed.
zh.repack()
m_repack.assert_called_once()

@mock.patch.object(zipfile, '_ZipRepacker')
def test_repack_mode_r(self, m_repack):
self._prepare_zip_from_test_files(TESTFN, self.test_files)
Expand Down
5 changes: 5 additions & 0 deletions Lib/zipfile/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2404,6 +2404,11 @@ def repack(self, removed=None, *, strict_descriptor=True,
raise ValueError(
"Can't write to ZIP archive while an open writing handle exists"
)
if self._fileRefCnt > 1:
raise ValueError(
"Can't repack the ZIP archive while an open reading handle "
"exists. Close the reading handle before repacking."
)

with self._lock:
self._writing = True
Expand Down
Loading