[Python-checkins] cpython: Issue #14099: Restored support of writing ZIP files to tellable but
serhiy.storchaka
python-checkins at python.org
Mon Jan 26 13:02:20 CET 2015
https://hg.python.org/cpython/rev/9cbf9f96920d
changeset: 94315:9cbf9f96920d
user: Serhiy Storchaka <storchaka at gmail.com>
date: Mon Jan 26 14:01:27 2015 +0200
summary:
Issue #14099: Restored support of writing ZIP files to tellable but
non-seekable streams.
files:
Lib/test/test_zipfile.py | 28 ++++++++++++++++++++++++++++
Lib/zipfile.py | 16 +++++++++++++---
Misc/NEWS | 3 +++
3 files changed, 44 insertions(+), 3 deletions(-)
diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py
--- a/Lib/test/test_zipfile.py
+++ b/Lib/test/test_zipfile.py
@@ -1668,6 +1668,34 @@
compression = zipfile.ZIP_LZMA
+# Privide the tell() method but not seek()
+class Tellable:
+ def __init__(self, fp):
+ self.fp = fp
+ self.offset = 0
+
+ def write(self, data):
+ self.offset += self.fp.write(data)
+
+ def tell(self):
+ return self.offset
+
+ def flush(self):
+ pass
+
+class UnseekableTests(unittest.TestCase):
+ def test_writestr_tellable(self):
+ f = io.BytesIO()
+ with zipfile.ZipFile(Tellable(f), 'w', zipfile.ZIP_STORED) as zipfp:
+ zipfp.writestr('ones', b'111')
+ zipfp.writestr('twos', b'222')
+ with zipfile.ZipFile(f, mode='r') as zipf:
+ with zipf.open('ones') as zopen:
+ self.assertEqual(zopen.read(), b'111')
+ with zipf.open('twos') as zopen:
+ self.assertEqual(zopen.read(), b'222')
+
+
@requires_zlib
class TestsWithMultipleOpens(unittest.TestCase):
@classmethod
diff --git a/Lib/zipfile.py b/Lib/zipfile.py
--- a/Lib/zipfile.py
+++ b/Lib/zipfile.py
@@ -1504,7 +1504,14 @@
zinfo.file_size = len(data) # Uncompressed size
with self._lock:
- self.fp.seek(self.start_dir, 0)
+ try:
+ self.fp.seek(self.start_dir)
+ except (AttributeError, io.UnsupportedOperation):
+ # Some file-like objects can provide tell() but not seek()
+ pass
+ zinfo.header_offset = self.fp.tell() # Start of header data
+ if compress_type is not None:
+ zinfo.compress_type = compress_type
zinfo.header_offset = self.fp.tell() # Start of header data
if compress_type is not None:
zinfo.compress_type = compress_type
@@ -1550,7 +1557,11 @@
try:
if self.mode in ("w", "a") and self._didModify: # write ending records
with self._lock:
- self.fp.seek(self.start_dir, 0)
+ try:
+ self.fp.seek(self.start_dir)
+ except (AttributeError, io.UnsupportedOperation):
+ # Some file-like objects can provide tell() but not seek()
+ pass
self._write_end_record()
finally:
fp = self.fp
@@ -1558,7 +1569,6 @@
self._fpclose(fp)
def _write_end_record(self):
- self.fp.seek(self.start_dir, 0)
for zinfo in self.filelist: # write central directory
dt = zinfo.date_time
dosdate = (dt[0] - 1980) << 9 | dt[1] << 5 | dt[2]
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -218,6 +218,9 @@
Library
-------
+- Issue #14099: Restored support of writing ZIP files to tellable but
+ non-seekable streams.
+
- Issue #14099: Writing to ZipFile and reading multiple ZipExtFiles is
threadsafe now.
--
Repository URL: https://hg.python.org/cpython
More information about the Python-checkins
mailing list