Author: Julian Berman <[email protected]>
Branch: zlib-copying
Changeset: r95835:51b646896e26
Date: 2019-02-05 13:46 +0100
http://bitbucket.org/pypy/pypy/changeset/51b646896e26/
Log: Now implement decompressobj.copy at the language level.
Something seems likely to be broken still because the contents of
unused_data and unconsumed_tail aren't passed along to the copy...
But we can come back and fix that in a minute, no tests are
currently failing.
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
@@ -241,7 +241,14 @@
Wrapper around zlib's z_stream structure which provides convenient
decompression functionality.
"""
- def __init__(self, space, wbits=rzlib.MAX_WBITS):
+ def __init__(
+ self,
+ space,
+ wbits=rzlib.MAX_WBITS,
+ stream=None,
+ unused_data="",
+ unconsumed_tail="",
+ ):
"""
Initialize a new decompression object.
@@ -251,14 +258,18 @@
inflateInit2.
"""
ZLibObject.__init__(self, space)
- self.unused_data = ''
- self.unconsumed_tail = ''
- try:
- self.stream = rzlib.inflateInit(wbits)
- except rzlib.RZlibError as e:
- raise zlib_error(space, e.msg)
- except ValueError:
- raise oefmt(space.w_ValueError, "Invalid initialization option")
+
+ if stream is None:
+ try:
+ stream = rzlib.inflateInit(wbits)
+ except rzlib.RZlibError as e:
+ raise zlib_error(space, e.msg)
+ except ValueError:
+ raise oefmt(space.w_ValueError, "Invalid initialization
option")
+ self.space = space
+ self.stream = stream
+ self.unused_data = unused_data
+ self.unconsumed_tail = unconsumed_tail
self.register_finalizer(space)
def _finalize_(self):
@@ -305,6 +316,19 @@
self._save_unconsumed_input(data, finished, unused_len)
return space.newbytes(string)
+ def copy(self, space):
+ try:
+ copied = rzlib.inflateCopy(self.stream)
+ except rzlib.RZlibError as e:
+ raise zlib_error(space, e.msg)
+
+ return Decompress(
+ space=self.space,
+ stream=copied,
+ # unused_data=self.unused_data,
+ # unconsumed_tail=self.unconsumed_tail,
+ )
+
def flush(self, space, w_length=None):
"""
flush( [length] ) -- This is kept for backward compatibility,
@@ -345,6 +369,7 @@
Decompress.typedef = TypeDef(
'Decompress',
__new__ = interp2app(Decompress___new__),
+ copy = interp2app(Decompress.copy),
decompress = interp2app(Decompress.decompress),
flush = interp2app(Decompress.flush),
unused_data = interp_attrproperty('unused_data', Decompress,
wrapfn="newbytes"),
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
@@ -8,8 +8,10 @@
except ImportError:
import py; py.test.skip("no zlib module on this host Python")
+from pypy.interpreter.gateway import interp2app
try:
from pypy.module.zlib import interp_zlib
+ from rpython.rlib import rzlib
except ImportError:
import py; py.test.skip("no zlib C library on this machine")
@@ -38,6 +40,22 @@
cls.w_expanded = cls.space.wrap(expanded)
cls.w_compressed = cls.space.wrap(zlib.compress(expanded))
+ def intentionally_break_a_z_stream(space, w_zobj):
+ """
+ Intentionally break the z_stream associated with a
+ compressobj or decompressobj in a way that causes their copy
+ methods to raise RZlibErrors.
+ """
+ from rpython.rtyper.lltypesystem import rffi, lltype
+ w_zobj.stream.c_zalloc = rffi.cast(
+ lltype.typeOf(w_zobj.stream.c_zalloc),
+ rzlib.Z_NULL,
+ )
+
+ cls.w_intentionally_break_a_z_stream = cls.space.wrap(
+ interp2app(intentionally_break_a_z_stream),
+ )
+
def test_error(self):
"""
zlib.error should be an exception class.
@@ -276,3 +294,20 @@
assert dco.flush(1) == input1[1:]
assert dco.unused_data == b''
assert dco.unconsumed_tail == b''
+
+ def test_decompress_copy(self):
+ decompressor = self.zlib.decompressobj()
+ d1 = decompressor.decompress(self.compressed[:10])
+ assert d1
+
+ copied = decompressor.copy()
+
+ from_copy = copied.decompress(self.compressed[10:])
+ from_decompressor = decompressor.decompress(self.compressed[10:])
+
+ assert (d1 + from_copy) == (d1 + from_decompressor)
+
+ def test_unsuccessful_decompress_copy(self):
+ decompressor = self.zlib.decompressobj()
+ self.intentionally_break_a_z_stream(zobj=decompressor)
+ raises(self.zlib.error, decompressor.copy)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit