bpo-37523: Raise ValueError for I/O operations on a closed zipfile.ZipExtFile. (GH-14658)
Raises ValueError when calling the following on a closed zipfile.ZipExtFile: read, readable, seek, seekable, tell.
This commit is contained in:
parent
1df65f7c6c
commit
8d62df60d8
|
@ -571,6 +571,20 @@ class StoredTestsWithSourceFile(AbstractTestsWithSourceFile,
|
||||||
with open(TESTFN, "rb") as f:
|
with open(TESTFN, "rb") as f:
|
||||||
self.assertEqual(zipfp.read(TESTFN), f.read())
|
self.assertEqual(zipfp.read(TESTFN), f.read())
|
||||||
|
|
||||||
|
def test_io_on_closed_zipextfile(self):
|
||||||
|
fname = "somefile.txt"
|
||||||
|
with zipfile.ZipFile(TESTFN2, mode="w") as zipfp:
|
||||||
|
zipfp.writestr(fname, "bogus")
|
||||||
|
|
||||||
|
with zipfile.ZipFile(TESTFN2, mode="r") as zipfp:
|
||||||
|
with zipfp.open(fname) as fid:
|
||||||
|
fid.close()
|
||||||
|
self.assertRaises(ValueError, fid.read)
|
||||||
|
self.assertRaises(ValueError, fid.seek, 0)
|
||||||
|
self.assertRaises(ValueError, fid.tell)
|
||||||
|
self.assertRaises(ValueError, fid.readable)
|
||||||
|
self.assertRaises(ValueError, fid.seekable)
|
||||||
|
|
||||||
def test_write_to_readonly(self):
|
def test_write_to_readonly(self):
|
||||||
"""Check that trying to call write() on a readonly ZipFile object
|
"""Check that trying to call write() on a readonly ZipFile object
|
||||||
raises a ValueError."""
|
raises a ValueError."""
|
||||||
|
|
|
@ -889,12 +889,16 @@ class ZipExtFile(io.BufferedIOBase):
|
||||||
return self._readbuffer[self._offset: self._offset + 512]
|
return self._readbuffer[self._offset: self._offset + 512]
|
||||||
|
|
||||||
def readable(self):
|
def readable(self):
|
||||||
|
if self.closed:
|
||||||
|
raise ValueError("I/O operation on closed file.")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def read(self, n=-1):
|
def read(self, n=-1):
|
||||||
"""Read and return up to n bytes.
|
"""Read and return up to n bytes.
|
||||||
If the argument is omitted, None, or negative, data is read and returned until EOF is reached.
|
If the argument is omitted, None, or negative, data is read and returned until EOF is reached.
|
||||||
"""
|
"""
|
||||||
|
if self.closed:
|
||||||
|
raise ValueError("read from closed file.")
|
||||||
if n is None or n < 0:
|
if n is None or n < 0:
|
||||||
buf = self._readbuffer[self._offset:]
|
buf = self._readbuffer[self._offset:]
|
||||||
self._readbuffer = b''
|
self._readbuffer = b''
|
||||||
|
@ -1031,9 +1035,13 @@ class ZipExtFile(io.BufferedIOBase):
|
||||||
super().close()
|
super().close()
|
||||||
|
|
||||||
def seekable(self):
|
def seekable(self):
|
||||||
|
if self.closed:
|
||||||
|
raise ValueError("I/O operation on closed file.")
|
||||||
return self._seekable
|
return self._seekable
|
||||||
|
|
||||||
def seek(self, offset, whence=0):
|
def seek(self, offset, whence=0):
|
||||||
|
if self.closed:
|
||||||
|
raise ValueError("seek on closed file.")
|
||||||
if not self._seekable:
|
if not self._seekable:
|
||||||
raise io.UnsupportedOperation("underlying stream is not seekable")
|
raise io.UnsupportedOperation("underlying stream is not seekable")
|
||||||
curr_pos = self.tell()
|
curr_pos = self.tell()
|
||||||
|
@ -1082,6 +1090,8 @@ class ZipExtFile(io.BufferedIOBase):
|
||||||
return self.tell()
|
return self.tell()
|
||||||
|
|
||||||
def tell(self):
|
def tell(self):
|
||||||
|
if self.closed:
|
||||||
|
raise ValueError("tell on closed file.")
|
||||||
if not self._seekable:
|
if not self._seekable:
|
||||||
raise io.UnsupportedOperation("underlying stream is not seekable")
|
raise io.UnsupportedOperation("underlying stream is not seekable")
|
||||||
filepos = self._orig_file_size - self._left - len(self._readbuffer) + self._offset
|
filepos = self._orig_file_size - self._left - len(self._readbuffer) + self._offset
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Change :class:`zipfile.ZipExtFile` to raise ``ValueError`` when trying to access the underlying file object after it has been closed. This new behavior is consistent with how accessing closed files is handled in other parts of Python.
|
Loading…
Reference in New Issue