diff -r 7757e98a9f3b Lib/gzip.py --- a/Lib/gzip.py Tue Mar 17 06:56:11 2015 +0200 +++ b/Lib/gzip.py Fri Mar 20 14:13:11 2015 +0100 @@ -334,17 +334,20 @@ if self.fileobj is None: raise ValueError("write() on closed GzipFile object") - # Convert data type if called by io.BufferedWriter. - if isinstance(data, memoryview): - data = data.tobytes() + if isinstance(data, bytes): + length = len(data) + else: + # accept any data that supports the buffer protocol + data = memoryview(data) + length = data.nbytes - if len(data) > 0: - self.size = self.size + len(data) + if length > 0: + self.fileobj.write( self.compress.compress(data) ) + self.size = self.size + length self.crc = zlib.crc32(data, self.crc) & 0xffffffff - self.fileobj.write( self.compress.compress(data) ) - self.offset += len(data) + self.offset += length - return len(data) + return length def read(self, size=-1): self._check_closed() diff -r 7757e98a9f3b Lib/test/test_gzip.py --- a/Lib/test/test_gzip.py Tue Mar 17 06:56:11 2015 +0200 +++ b/Lib/test/test_gzip.py Fri Mar 20 14:13:11 2015 +0100 @@ -130,6 +130,40 @@ if not ztxt: break self.assertEqual(contents, b'a'*201) + def test_write_memoryview(self): + # Test that write accepts a memoryview instead of bytes + # and that the data written equals memoryview.tobytes(). + m = memoryview(data1 * 50) + with gzip.GzipFile(self.filename, 'wb') as f: + f.write(m) + with gzip.GzipFile(self.filename, 'rb') as f: + self.assertEqual(f.read(), data1 * 50) + m = memoryview(bytes(range(256))) + n = m.cast('B', shape=[8,8,4]) + with gzip.GzipFile(self.filename, 'wb') as f: + f.write(n) + with gzip.GzipFile(self.filename, 'rb') as f: + self.assertEqual(f.read(), m.tobytes()) + + def test_write_misc_data(self): + # Test that any binary sequence type can be written + # and that other types raise TypeError. + with gzip.GzipFile(self.filename, 'wb') as f: + bytes_like_types = { bytes, bytearray } + data = (bytearray(data1), data1.decode('utf-8'), + list(data1), data1) + for d in data: + try: + f.write(d) + except TypeError: + self.assertNotIn(type(d), bytes_like_types) + else: + self.assertIn(type(d), bytes_like_types) + with gzip.GzipFile(self.filename, 'rb') as f: + self.assertEqual(f.read(), + b''.join(bytes(d) for d in data + if type(d) in bytes_like_types)) + def test_exclusive_write(self): with gzip.GzipFile(self.filename, 'xb') as f: f.write(data1 * 50)