Index: Modules/zlibmodule.c =================================================================== --- Modules/zlibmodule.c (revision 71045) +++ Modules/zlibmodule.c (working copy) @@ -186,25 +186,34 @@ } PyDoc_STRVAR(decompress__doc__, -"decompress(string[, wbits[, bufsize]]) -- Return decompressed string.\n" +"decompress(string[, wbits[, bufsize[, tail]]]) -- Return decompressed string.\n" "\n" "Optional arg wbits is the window buffer size. Optional arg bufsize is\n" -"the initial output buffer size."); +"the initial output buffer size. Optional arg tail, if True, will\n" +"cause the return value to be a tuple, with the second element any\n" +"unused data following the compressed part."); static PyObject * -PyZlib_decompress(PyObject *self, PyObject *args) +PyZlib_decompress(PyObject *self, PyObject *args, PyObject *kw) { PyObject *result_str; Byte *input; int length, err; int wsize=DEF_WBITS; Py_ssize_t r_strlen=DEFAULTALLOC; + PyObject *tailO = Py_False; + int tail = 0; z_stream zst; + char *keywords[] = {"string", "wbits", "bufsize", "tail", 0}; - if (!PyArg_ParseTuple(args, "s#|in:decompress", - &input, &length, &wsize, &r_strlen)) + if (!PyArg_ParseTupleAndKeywords(args, kw, "s#|inO:decompress", keywords, + &input, &length, &wsize, &r_strlen, &tailO)) return NULL; - + if (tailO != Py_False) { + tail = PyObject_IsTrue(tailO); + if (tail < 0) + return NULL; + } if (r_strlen <= 0) r_strlen = 1; @@ -279,6 +288,11 @@ } _PyString_Resize(&result_str, zst.total_out); + if (result_str != NULL && tail) { + PyObject *tail = PyString_FromStringAndSize( + (char *)zst.next_in, zst.avail_in); + return Py_BuildValue("NN", result_str, tail); + } return result_str; error: @@ -941,7 +955,7 @@ compressobj__doc__}, {"crc32", (PyCFunction)PyZlib_crc32, METH_VARARGS, crc32__doc__}, - {"decompress", (PyCFunction)PyZlib_decompress, METH_VARARGS, + {"decompress", (PyCFunction)PyZlib_decompress, METH_KEYWORDS, decompress__doc__}, {"decompressobj", (PyCFunction)PyZlib_decompressobj, METH_VARARGS, decompressobj__doc__},