Author: Brian Kearns <[email protected]>
Branch: stdlib-2.7.6
Changeset: r69632:00860b5ad1a8
Date: 2014-03-03 00:48 -0500
http://bitbucket.org/pypy/pypy/changeset/00860b5ad1a8/
Log: more fixes for zlib
diff --git a/pypy/module/zlib/interp_zlib.py b/pypy/module/zlib/interp_zlib.py
--- a/pypy/module/zlib/interp_zlib.py
+++ b/pypy/module/zlib/interp_zlib.py
@@ -2,7 +2,7 @@
from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.baseobjspace import W_Root
from pypy.interpreter.typedef import TypeDef, interp_attrproperty
-from pypy.interpreter.error import OperationError
+from pypy.interpreter.error import OperationError, oefmt
from rpython.rlib.rarithmetic import intmask, r_uint
from rpython.rlib.objectmodel import keepalive_until_here
@@ -87,7 +87,7 @@
return space.wrap(result)
-@unwrap_spec(string='bufferstr', wbits=int, bufsize=int)
+@unwrap_spec(string='bufferstr', wbits="c_int", bufsize=int)
def decompress(space, string, wbits=rzlib.MAX_WBITS, bufsize=0):
"""
decompress(string[, wbits[, bufsize]]) -- Return decompressed string.
@@ -116,7 +116,6 @@
stream = rzlib.null_stream
def __init__(self, space):
- self.space = space
self._lock = space.allocate_lock()
def lock(self):
@@ -146,7 +145,7 @@
self.stream = rzlib.deflateInit(level, method, wbits,
memLevel, strategy)
except rzlib.RZlibError, e:
- raise zlib_error(self.space, e.msg)
+ raise zlib_error(space, e.msg)
except ValueError:
raise OperationError(space.w_ValueError,
space.wrap("Invalid initialization option"))
@@ -158,7 +157,7 @@
self.stream = rzlib.null_stream
@unwrap_spec(data='bufferstr')
- def compress(self, data):
+ def compress(self, space, data):
"""
compress(data) -- Return a string containing data compressed.
@@ -171,17 +170,17 @@
self.lock()
try:
if not self.stream:
- raise zlib_error(self.space,
+ raise zlib_error(space,
"compressor object already flushed")
result = rzlib.compress(self.stream, data)
finally:
self.unlock()
except rzlib.RZlibError, e:
- raise zlib_error(self.space, e.msg)
- return self.space.wrap(result)
+ raise zlib_error(space, e.msg)
+ return space.wrap(result)
@unwrap_spec(mode="c_int")
- def flush(self, mode=rzlib.Z_FINISH):
+ def flush(self, space, mode=rzlib.Z_FINISH):
"""
flush( [mode] ) -- Return a string containing any remaining compressed
data.
@@ -197,7 +196,7 @@
self.lock()
try:
if not self.stream:
- raise zlib_error(self.space,
+ raise zlib_error(space,
"compressor object already flushed")
result = rzlib.compress(self.stream, '', mode)
if mode == rzlib.Z_FINISH: # release the data structures now
@@ -206,8 +205,8 @@
finally:
self.unlock()
except rzlib.RZlibError, e:
- raise zlib_error(self.space, e.msg)
- return self.space.wrap(result)
+ raise zlib_error(space, e.msg)
+ return space.wrap(result)
@unwrap_spec(level=int, method=int, wbits=int, memLevel=int, strategy=int)
@@ -257,7 +256,7 @@
try:
self.stream = rzlib.inflateInit(wbits)
except rzlib.RZlibError, e:
- raise zlib_error(self.space, e.msg)
+ raise zlib_error(space, e.msg)
except ValueError:
raise OperationError(space.w_ValueError,
space.wrap("Invalid initialization option"))
@@ -278,8 +277,8 @@
else:
self.unconsumed_tail = tail
- @unwrap_spec(data='bufferstr', max_length=int)
- def decompress(self, data, max_length=0):
+ @unwrap_spec(data='bufferstr', max_length="c_int")
+ def decompress(self, space, data, max_length=0):
"""
decompress(data[, max_length]) -- Return a string containing the
decompressed version of the data.
@@ -291,9 +290,8 @@
if max_length == 0:
max_length = sys.maxint
elif max_length < 0:
- raise OperationError(self.space.w_ValueError,
- self.space.wrap("max_length must be "
- "greater than zero"))
+ raise oefmt(space.w_ValueError,
+ "max_length must be greater than zero")
try:
self.lock()
try:
@@ -301,35 +299,36 @@
finally:
self.unlock()
except rzlib.RZlibError, e:
- raise zlib_error(self.space, e.msg)
+ raise zlib_error(space, e.msg)
string, finished, unused_len = result
self._save_unconsumed_input(data, finished, unused_len)
- return self.space.wrap(string)
+ return space.wrap(string)
- @unwrap_spec(mode="c_int")
- def flush(self, mode=rzlib.Z_FINISH):
+ def flush(self, space, w_length=None):
"""
flush( [length] ) -- This is kept for backward compatibility,
because each call to decompress() immediately returns as much
data as possible.
"""
- if mode == rzlib.Z_NO_FLUSH:
- return self.space.wrap("")
-
+ if w_length is not None:
+ length = space.c_int_w(w_length)
+ if length <= 0:
+ raise oefmt(space.w_ValueError,
+ "length must be greater than zero")
data = self.unconsumed_tail
try:
self.lock()
try:
- result = rzlib.decompress(self.stream, data, mode)
+ result = rzlib.decompress(self.stream, data, rzlib.Z_FINISH)
finally:
self.unlock()
- except rzlib.RZlibError, e:
- raise zlib_error(self.space, e.msg)
-
- string, finished, unused_len = result
- self._save_unconsumed_input(data, finished, unused_len)
- return self.space.wrap(string)
+ except rzlib.RZlibError:
+ string = ""
+ else:
+ string, finished, unused_len = result
+ self._save_unconsumed_input(data, finished, unused_len)
+ return space.wrap(string)
@unwrap_spec(wbits=int)
diff --git a/pypy/module/zlib/test/test_zlib.py
b/pypy/module/zlib/test/test_zlib.py
--- a/pypy/module/zlib/test/test_zlib.py
+++ b/pypy/module/zlib/test/test_zlib.py
@@ -33,14 +33,12 @@
cls.w_expanded = cls.space.wrap(expanded)
cls.w_compressed = cls.space.wrap(zlib.compress(expanded))
-
def test_error(self):
"""
zlib.error should be an exception class.
"""
assert issubclass(self.zlib.error, Exception)
-
def test_crc32(self):
"""
When called with a string, zlib.crc32 should compute its CRC32 and
@@ -162,13 +160,46 @@
raises(self.zlib.error, self.zlib.decompress, self.compressed[:-2])
raises(self.zlib.error, self.zlib.decompress, 'foobar')
+ def test_bad_arguments(self):
+ import zlib
+ raises(ValueError, zlib.decompressobj().flush, 0)
+ raises(ValueError, zlib.decompressobj().flush, -1)
+ raises(TypeError, zlib.decompressobj().flush, None)
+ raises(OverflowError, zlib.decompressobj().flush, 2**31)
+ raises(ValueError, zlib.decompressobj().decompress, 'abc', -1)
+ raises(TypeError, zlib.decompressobj().decompress, 'abc', None)
+ raises(OverflowError, zlib.decompressobj().decompress, 'abc', 2**31)
+ raises(TypeError, self.zlib.decompress, self.compressed, None)
+ raises(OverflowError, self.zlib.decompress, self.compressed, 2**31)
+
+ def test_empty_flush(self):
+ import zlib
+ co = zlib.compressobj(zlib.Z_BEST_COMPRESSION)
+ assert co.flush() # Returns a zlib header
+ dco = zlib.decompressobj()
+ assert dco.flush() == ""
+
+ def test_decompress_incomplete_stream(self):
+ import zlib
+ # This is 'foo', deflated
+ x = 'x\x9cK\xcb\xcf\x07\x00\x02\x82\x01E'
+ # For the record
+ assert zlib.decompress(x) == 'foo'
+ raises(zlib.error, zlib.decompress, x[:-5])
+ # Omitting the stream end works with decompressor objects
+ # (see issue #8672).
+ dco = zlib.decompressobj()
+ y = dco.decompress(x[:-5])
+ y += dco.flush()
+ assert y == 'foo'
+
def test_unused_data(self):
"""
Try to feed too much data to zlib.decompress().
It should show up in the unused_data attribute.
"""
d = self.zlib.decompressobj()
- s = d.decompress(self.compressed + 'extrastuff')
+ s = d.decompress(self.compressed + 'extrastuff', 0)
assert s == self.expanded
assert d.unused_data == 'extrastuff'
assert d.flush() == ''
@@ -232,6 +263,6 @@
dco.decompress(data, 1)
del data
data = self.zlib.compress(input2)
- assert dco.flush() == input1[1:]
+ assert dco.flush(1) == input1[1:]
assert dco.unused_data == ''
assert dco.unconsumed_tail == ''
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit