Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit bca63b3

Browse files
Issue #23688: Added support of arbitrary bytes-like objects and avoided
unnecessary copying of memoryview in gzip.GzipFile.write(). Original patch by Wolfgang Maier.
1 parent 77d8997 commit bca63b3

4 files changed

Lines changed: 56 additions & 8 deletions

File tree

Doc/library/gzip.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ The module defines the following items:
137137
.. versionchanged:: 3.4
138138
Added support for the ``'x'`` and ``'xb'`` modes.
139139

140+
.. versionchanged:: 3.5
141+
Added support for writing arbitrary
142+
:term:`bytes-like objects <bytes-like object>`.
143+
140144

141145
.. function:: compress(data, compresslevel=9)
142146

Lib/gzip.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -334,17 +334,20 @@ def write(self,data):
334334
if self.fileobj is None:
335335
raise ValueError("write() on closed GzipFile object")
336336

337-
# Convert data type if called by io.BufferedWriter.
338-
if isinstance(data, memoryview):
339-
data = data.tobytes()
337+
if isinstance(data, bytes):
338+
length = len(data)
339+
else:
340+
# accept any data that supports the buffer protocol
341+
data = memoryview(data)
342+
length = data.nbytes
340343

341-
if len(data) > 0:
342-
self.size = self.size + len(data)
344+
if length > 0:
345+
self.fileobj.write(self.compress.compress(data))
346+
self.size += length
343347
self.crc = zlib.crc32(data, self.crc) & 0xffffffff
344-
self.fileobj.write( self.compress.compress(data) )
345-
self.offset += len(data)
348+
self.offset += length
346349

347-
return len(data)
350+
return length
348351

349352
def read(self, size=-1):
350353
self._check_closed()

Lib/test/test_gzip.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import os
77
import io
88
import struct
9+
import array
910
gzip = support.import_module('gzip')
1011

1112
data1 = b""" int length=DEFAULTALLOC, err = Z_OK;
@@ -43,6 +44,14 @@ def tearDown(self):
4344

4445

4546
class TestGzip(BaseTest):
47+
def write_and_read_back(self, data, mode='b'):
48+
b_data = bytes(data)
49+
with gzip.GzipFile(self.filename, 'w'+mode) as f:
50+
l = f.write(data)
51+
self.assertEqual(l, len(b_data))
52+
with gzip.GzipFile(self.filename, 'r'+mode) as f:
53+
self.assertEqual(f.read(), b_data)
54+
4655
def test_write(self):
4756
with gzip.GzipFile(self.filename, 'wb') as f:
4857
f.write(data1 * 50)
@@ -57,6 +66,34 @@ def test_write(self):
5766
# Test multiple close() calls.
5867
f.close()
5968

69+
# The following test_write_xy methods test that write accepts
70+
# the corresponding bytes-like object type as input
71+
# and that the data written equals bytes(xy) in all cases.
72+
def test_write_memoryview(self):
73+
self.write_and_read_back(memoryview(data1 * 50))
74+
m = memoryview(bytes(range(256)))
75+
data = m.cast('B', shape=[8,8,4])
76+
self.write_and_read_back(data)
77+
78+
def test_write_bytearray(self):
79+
self.write_and_read_back(bytearray(data1 * 50))
80+
81+
def test_write_array(self):
82+
self.write_and_read_back(array.array('I', data1 * 40))
83+
84+
def test_write_incompatible_type(self):
85+
# Test that non-bytes-like types raise TypeError.
86+
# Issue #21560: attempts to write incompatible types
87+
# should not affect the state of the fileobject
88+
with gzip.GzipFile(self.filename, 'wb') as f:
89+
with self.assertRaises(TypeError):
90+
f.write('')
91+
with self.assertRaises(TypeError):
92+
f.write([])
93+
f.write(data1)
94+
with gzip.GzipFile(self.filename, 'rb') as f:
95+
self.assertEqual(f.read(), data1)
96+
6097
def test_read(self):
6198
self.test_write()
6299
# Try reading.

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ Core and Builtins
2323
Library
2424
-------
2525

26+
- Issue #23688: Added support of arbitrary bytes-like objects and avoided
27+
unnecessary copying of memoryview in gzip.GzipFile.write().
28+
Original patch by Wolfgang Maier.
29+
2630
- Issue #23252: Added support for writing ZIP files to unseekable streams.
2731

2832
- Issue #21526: Tkinter now supports new boolean type in Tcl 8.5.

0 commit comments

Comments
 (0)