Skip to content

gh-51067: add ZipFile.remove() #103033

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
No more allow mode 'w'/'x'
- File is not truncated in mode 'w'/'x', which results non-shrinked file.
- This cannot be simply resolved by adding truncation for mode 'w'/'x', which may be used on an unseekable file buffer and truncation is not allowed.
  • Loading branch information
danny0838 committed Jun 19, 2025
commit bb90f48f60ddf8244097fc8b274cc5ebde052f94
2 changes: 1 addition & 1 deletion Doc/library/zipfile.rst
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,7 @@ ZipFile Objects
Removes a member from the archive. *zinfo_or_arcname* is either the full
path of the member, or a :class:`ZipInfo` instance.

The archive must be opened with mode ``'w'``, ``'x'`` or ``'a'``.
The archive must be opened with mode ``'a'``.

Calling :meth:`remove` on a closed ZipFile will raise a :exc:`ValueError`.

Expand Down
32 changes: 17 additions & 15 deletions Lib/test/test_zipfile/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1503,6 +1503,23 @@ def test_verify(self):
zh.remove(file)
mock_fn.assert_not_called()

# mode 'w': error and do nothing
with zipfile.ZipFile(TESTFN, 'w', self.compression) as zh:
zh.writestr(file, data)
with mock.patch('zipfile.ZipFile._remove_members') as mock_fn:
with self.assertRaises(ValueError):
zh.remove(file)
mock_fn.assert_not_called()

# mode 'x': error and do nothing
os.remove(TESTFN)
with zipfile.ZipFile(TESTFN, 'x', self.compression) as zh:
zh.writestr(file, data)
with mock.patch('zipfile.ZipFile._remove_members') as mock_fn:
with self.assertRaises(ValueError):
zh.remove(file)
mock_fn.assert_not_called()

# mode 'a': the most general use case
with zipfile.ZipFile(TESTFN, 'w', self.compression) as zh:
zh.writestr(file, data)
Expand Down Expand Up @@ -1531,21 +1548,6 @@ def test_verify(self):
zh.remove(zinfo)
mock_fn.assert_not_called()

# mode 'w': like 'a'; allows removing a just written member
with zipfile.ZipFile(TESTFN, 'w', self.compression) as zh:
zh.writestr(file, data)
with mock.patch('zipfile.ZipFile._remove_members') as mock_fn:
zh.remove(file)
mock_fn.assert_called_once_with({zh.getinfo(file)})

# mode 'x': like 'w'
os.remove(TESTFN)
with zipfile.ZipFile(TESTFN, 'x', self.compression) as zh:
zh.writestr(file, data)
with mock.patch('zipfile.ZipFile._remove_members') as mock_fn:
zh.remove(file)
mock_fn.assert_called_once_with({zh.getinfo(file)})

def test_zip64(self):
"""Test if members use zip64."""
file = 'datafile.txt'
Expand Down
9 changes: 6 additions & 3 deletions Lib/zipfile/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1867,10 +1867,13 @@ def extractall(self, path=None, members=None, pwd=None):
self._extract_member(zipinfo, path, pwd)

def remove(self, zinfo_or_arcname):
"""Remove a member from the archive."""
"""Remove a member from the archive.

if self.mode not in ('w', 'x', 'a'):
raise ValueError("remove() requires mode 'w', 'x', or 'a'")
The archive must be open with mode 'a', since mode 'w'/'x' may be used
on an unseekable file buffer, which disallows truncation."""

if self.mode != 'a':
raise ValueError("remove() requires mode 'a'")
if not self.fp:
raise ValueError(
"Attempt to write to ZIP archive that was already closed")
Expand Down
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy