[Python-checkins] r46012 - in python/trunk: Doc/lib/libzlib.tex Lib/test/test_zlib.py Misc/NEWS Modules/zlibmodule.c

georg.brandl python-checkins at python.org
Tue May 16 09:38:28 CEST 2006


Author: georg.brandl
Date: Tue May 16 09:38:27 2006
New Revision: 46012

Modified:
   python/trunk/Doc/lib/libzlib.tex
   python/trunk/Lib/test/test_zlib.py
   python/trunk/Misc/NEWS
   python/trunk/Modules/zlibmodule.c
Log:
Patch #1435422: zlib's compress and decompress objects now have a
copy() method.


Modified: python/trunk/Doc/lib/libzlib.tex
==============================================================================
--- python/trunk/Doc/lib/libzlib.tex	(original)
+++ python/trunk/Doc/lib/libzlib.tex	Tue May 16 09:38:27 2006
@@ -123,6 +123,12 @@
 action is to delete the object.  
 \end{methoddesc}
 
+\begin{methoddesc}[Compress]{copy}{}
+Returns a copy of the compression object.  This can be used to efficiently
+compress a set of data that share a common initial prefix.
+\versionadded{2.5}
+\end{methoddesc}
+
 Decompression objects support the following methods, and two attributes:
 
 \begin{memberdesc}{unused_data}
@@ -176,6 +182,13 @@
 output buffer.
 \end{methoddesc}
 
+\begin{methoddesc}[Decompress]{copy}{}
+Returns a copy of the decompression object.  This can be used to save the
+state of the decompressor midway through the data stream in order to speed up
+random seeks into the stream at a future point.
+\versionadded{2.5}
+\end{methoddesc}
+
 \begin{seealso}
   \seemodule{gzip}{Reading and writing \program{gzip}-format files.}
   \seeurl{http://www.zlib.net}{The zlib library home page.}

Modified: python/trunk/Lib/test/test_zlib.py
==============================================================================
--- python/trunk/Lib/test/test_zlib.py	(original)
+++ python/trunk/Lib/test/test_zlib.py	Tue May 16 09:38:27 2006
@@ -302,6 +302,63 @@
         dco = zlib.decompressobj()
         self.assertEqual(dco.flush(), "") # Returns nothing
 
+    def test_compresscopy(self):
+        # Test copying a compression object
+        data0 = HAMLET_SCENE
+        data1 = HAMLET_SCENE.swapcase()
+        c0 = zlib.compressobj(zlib.Z_BEST_COMPRESSION)
+        bufs0 = []
+        bufs0.append(c0.compress(data0))
+
+        c1 = c0.copy()
+        bufs1 = bufs0[:]
+
+        bufs0.append(c0.compress(data0))
+        bufs0.append(c0.flush())
+        s0 = ''.join(bufs0)
+
+        bufs1.append(c1.compress(data1))
+        bufs1.append(c1.flush())
+        s1 = ''.join(bufs1)
+
+        self.assertEqual(zlib.decompress(s0),data0+data0)
+        self.assertEqual(zlib.decompress(s1),data0+data1)
+
+    def test_badcompresscopy(self):
+        # Test copying a compression object in an inconsistent state
+        c = zlib.compressobj()
+        c.compress(HAMLET_SCENE)
+        c.flush()
+        self.assertRaises(ValueError, c.copy)
+
+    def test_decompresscopy(self):
+        # Test copying a decompression object
+        data = HAMLET_SCENE
+        comp = zlib.compress(data)
+
+        d0 = zlib.decompressobj()
+        bufs0 = []
+        bufs0.append(d0.decompress(comp[:32]))
+
+        d1 = d0.copy()
+        bufs1 = bufs0[:]
+
+        bufs0.append(d0.decompress(comp[32:]))
+        s0 = ''.join(bufs0)
+
+        bufs1.append(d1.decompress(comp[32:]))
+        s1 = ''.join(bufs1)
+
+        self.assertEqual(s0,s1)
+        self.assertEqual(s0,data)
+
+    def test_baddecompresscopy(self):
+        # Test copying a compression object in an inconsistent state
+        data = zlib.compress(HAMLET_SCENE)
+        d = zlib.decompressobj()
+        d.decompress(data)
+        d.flush()
+        self.assertRaises(ValueError, d.copy)
 
 def genblock(seed, length, step=1024, generator=random):
     """length-byte stream of random data from a seed (in step-byte blocks)."""

Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS	(original)
+++ python/trunk/Misc/NEWS	Tue May 16 09:38:27 2006
@@ -28,6 +28,9 @@
 Extension Modules
 -----------------
 
+- Patch #1435422: zlib's compress and decompress objects now have a
+  copy() method.
+
 - On Win32, os.listdir now supports arbitrarily-long Unicode path names
   (up to the system limit of 32K characters).
 

Modified: python/trunk/Modules/zlibmodule.c
==============================================================================
--- python/trunk/Modules/zlibmodule.c	(original)
+++ python/trunk/Modules/zlibmodule.c	Tue May 16 09:38:27 2006
@@ -653,6 +653,104 @@
     return RetVal;
 }
 
+PyDoc_STRVAR(comp_copy__doc__,
+"copy() -- Return a copy of the compression object.");
+
+static PyObject *
+PyZlib_copy(compobject *self)
+{
+    compobject *retval = NULL;
+    int err;
+
+    retval = newcompobject(&Comptype);
+    if (!retval) return NULL;
+
+    /* Copy the zstream state
+     * We use ENTER_ZLIB / LEAVE_ZLIB to make this thread-safe
+     */
+    ENTER_ZLIB
+    err = deflateCopy(&retval->zst, &self->zst);
+    switch(err) {
+    case(Z_OK):
+        break;
+    case(Z_STREAM_ERROR):
+        PyErr_SetString(PyExc_ValueError, "Inconsistent stream state");
+        goto error;
+    case(Z_MEM_ERROR):
+        PyErr_SetString(PyExc_MemoryError,
+                        "Can't allocate memory for compression object");
+        goto error;
+    default:
+        zlib_error(self->zst, err, "while copying compression object");
+        goto error;
+    }
+
+    retval->unused_data = self->unused_data;
+    retval->unconsumed_tail = self->unconsumed_tail;
+    Py_INCREF(retval->unused_data);
+    Py_INCREF(retval->unconsumed_tail);
+
+    /* Mark it as being initialized */
+    retval->is_initialised = 1;
+
+    LEAVE_ZLIB
+    return (PyObject *)retval;
+
+error:
+    LEAVE_ZLIB
+    Py_XDECREF(retval);	
+    return NULL;
+}
+
+PyDoc_STRVAR(decomp_copy__doc__,
+"copy() -- Return a copy of the decompression object.");
+
+static PyObject *
+PyZlib_uncopy(compobject *self)
+{
+    compobject *retval = NULL;
+    int err;
+
+    retval = newcompobject(&Decomptype);
+    if (!retval) return NULL;
+
+    /* Copy the zstream state
+     * We use ENTER_ZLIB / LEAVE_ZLIB to make this thread-safe
+     */
+    ENTER_ZLIB
+    err = inflateCopy(&retval->zst, &self->zst);
+    switch(err) {
+    case(Z_OK):
+        break;
+    case(Z_STREAM_ERROR):
+        PyErr_SetString(PyExc_ValueError, "Inconsistent stream state");
+        goto error;
+    case(Z_MEM_ERROR):
+        PyErr_SetString(PyExc_MemoryError,
+                        "Can't allocate memory for decompression object");
+        goto error;
+    default:
+        zlib_error(self->zst, err, "while copying decompression object");
+        goto error;
+    }
+
+    retval->unused_data = self->unused_data;
+    retval->unconsumed_tail = self->unconsumed_tail;
+    Py_INCREF(retval->unused_data);
+    Py_INCREF(retval->unconsumed_tail);
+
+    /* Mark it as being initialized */
+    retval->is_initialised = 1;
+
+    LEAVE_ZLIB
+    return (PyObject *)retval;
+
+error:
+    LEAVE_ZLIB
+    Py_XDECREF(retval);
+    return NULL;
+}
+
 PyDoc_STRVAR(decomp_flush__doc__,
 "flush( [length] ) -- Return a string containing any remaining\n"
 "decompressed data. length, if given, is the initial size of the\n"
@@ -725,6 +823,8 @@
                  comp_compress__doc__},
     {"flush", (binaryfunc)PyZlib_flush, METH_VARARGS,
               comp_flush__doc__},
+    {"copy",  (PyCFunction)PyZlib_copy, METH_NOARGS,
+              comp_copy__doc__},
     {NULL, NULL}
 };
 
@@ -734,6 +834,8 @@
                    decomp_decompress__doc__},
     {"flush", (binaryfunc)PyZlib_unflush, METH_VARARGS,
               decomp_flush__doc__},
+    {"copy",  (PyCFunction)PyZlib_uncopy, METH_NOARGS,
+              decomp_copy__doc__},
     {NULL, NULL}
 };
 


More information about the Python-checkins mailing list