Issue #16764: Support keyword arguments to zlib.decompress(). Patch by

Xiang Zhang.
This commit is contained in:
Serhiy Storchaka 2016-08-15 10:06:16 +03:00
parent eb24988962
commit 15f3228b7c
5 changed files with 61 additions and 25 deletions

View File

@ -129,7 +129,7 @@ The available exception and functions in this module are:
platforms, use ``crc32(data) & 0xffffffff``.
.. function:: decompress(data[, wbits[, bufsize]])
.. function:: decompress(data, wbits=MAX_WBITS, bufsize=DEF_BUF_SIZE)
Decompresses the bytes in *data*, returning a bytes object containing the
uncompressed data. The *wbits* parameter depends on
@ -164,14 +164,16 @@ The available exception and functions in this module are:
When decompressing a stream, the window size must not be smaller
than the size originally used to compress the stream; using a too-small
value may result in an :exc:`error` exception. The default *wbits* value
is 15, which corresponds to the largest window size and requires a zlib
header and trailer to be included.
corresponds to the largest window size and requires a zlib header and
trailer to be included.
*bufsize* is the initial size of the buffer used to hold decompressed data. If
more space is required, the buffer size will be increased as needed, so you
don't have to get this value exactly right; tuning it will only save a few calls
to :c:func:`malloc`. The default size is 16384.
to :c:func:`malloc`.
.. versionchanged:: 3.6
*wbits* and *bufsize* can be used as keyword arguments.
.. function:: decompressobj(wbits=15[, zdict])
@ -257,7 +259,7 @@ Decompression objects support the following methods and attributes:
.. versionadded:: 3.3
.. method:: Decompress.decompress(data[, max_length])
.. method:: Decompress.decompress(data, max_length=0)
Decompress *data*, returning a bytes object containing the uncompressed data
corresponding to at least part of the data in *string*. This data should be
@ -269,9 +271,11 @@ Decompression objects support the following methods and attributes:
no longer than *max_length*. This may mean that not all of the compressed input
can be processed; and unconsumed data will be stored in the attribute
:attr:`unconsumed_tail`. This bytestring must be passed to a subsequent call to
:meth:`decompress` if decompression is to continue. If *max_length* is not
supplied then the whole input is decompressed, and :attr:`unconsumed_tail` is
empty.
:meth:`decompress` if decompression is to continue. If *max_length* is zero
then the whole input is decompressed, and :attr:`unconsumed_tail` is empty.
.. versionchanged:: 3.6
*max_length* can be used as a keyword argument.
.. method:: Decompress.flush([length])

View File

@ -169,6 +169,14 @@ class CompressTestCase(BaseCompressTestCase, unittest.TestCase):
self.assertEqual(zlib.decompress(x), HAMLET_SCENE)
with self.assertRaises(TypeError):
zlib.compress(data=HAMLET_SCENE, level=3)
self.assertEqual(zlib.decompress(x,
wbits=zlib.MAX_WBITS,
bufsize=zlib.DEF_BUF_SIZE),
HAMLET_SCENE)
with self.assertRaises(TypeError):
zlib.decompress(data=x,
wbits=zlib.MAX_WBITS,
bufsize=zlib.DEF_BUF_SIZE)
def test_speech128(self):
# compress more data
@ -240,6 +248,27 @@ class CompressObjectTestCase(BaseCompressTestCase, unittest.TestCase):
self.assertIsInstance(dco.unconsumed_tail, bytes)
self.assertIsInstance(dco.unused_data, bytes)
def test_keywords(self):
level = 2
method = zlib.DEFLATED
wbits = -12
memLevel = 9
strategy = zlib.Z_FILTERED
co = zlib.compressobj(level=level,
method=method,
wbits=wbits,
memLevel=memLevel,
strategy=strategy,
zdict=b"")
do = zlib.decompressobj(wbits=wbits, zdict=b"")
with self.assertRaises(TypeError):
co.compress(data=HAMLET_SCENE)
with self.assertRaises(TypeError):
do.decompress(data=zlib.compress(HAMLET_SCENE))
x = co.compress(HAMLET_SCENE) + co.flush()
y = do.decompress(x, max_length=len(HAMLET_SCENE)) + do.flush()
self.assertEqual(HAMLET_SCENE, y)
def test_compressoptions(self):
# specify lots of options to compressobj()
level = 2
@ -255,10 +284,6 @@ class CompressObjectTestCase(BaseCompressTestCase, unittest.TestCase):
y2 = dco.flush()
self.assertEqual(HAMLET_SCENE, y1 + y2)
# keyword arguments should also be supported
zlib.compressobj(level=level, method=method, wbits=wbits,
memLevel=memLevel, strategy=strategy, zdict=b"")
def test_compressincremental(self):
# compress object in steps, decompress object as one-shot
data = HAMLET_SCENE * 128

View File

@ -10,6 +10,9 @@ What's New in Python 3.6.0 alpha 4
Core and Builtins
-----------------
- Issue #16764: Support keyword arguments to zlib.decompress(). Patch by
Xiang Zhang.
- Issue #27704: Optimized creating bytes and bytearray from byte-like objects
and iterables. Speed up to 3 times for short objects. Original patch by
Naoki Inada.

View File

@ -44,7 +44,7 @@ exit:
}
PyDoc_STRVAR(zlib_decompress__doc__,
"decompress($module, data, wbits=MAX_WBITS, bufsize=DEF_BUF_SIZE, /)\n"
"decompress($module, data, /, wbits=MAX_WBITS, bufsize=DEF_BUF_SIZE)\n"
"--\n"
"\n"
"Returns a bytes object containing the uncompressed data.\n"
@ -57,21 +57,23 @@ PyDoc_STRVAR(zlib_decompress__doc__,
" The initial output buffer size.");
#define ZLIB_DECOMPRESS_METHODDEF \
{"decompress", (PyCFunction)zlib_decompress, METH_VARARGS, zlib_decompress__doc__},
{"decompress", (PyCFunction)zlib_decompress, METH_VARARGS|METH_KEYWORDS, zlib_decompress__doc__},
static PyObject *
zlib_decompress_impl(PyObject *module, Py_buffer *data, int wbits,
Py_ssize_t bufsize);
static PyObject *
zlib_decompress(PyObject *module, PyObject *args)
zlib_decompress(PyObject *module, PyObject *args, PyObject *kwargs)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"", "wbits", "bufsize", NULL};
static _PyArg_Parser _parser = {"y*|iO&:decompress", _keywords, 0};
Py_buffer data = {NULL, NULL};
int wbits = MAX_WBITS;
Py_ssize_t bufsize = DEF_BUF_SIZE;
if (!PyArg_ParseTuple(args, "y*|iO&:decompress",
if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
&data, &wbits, ssize_t_converter, &bufsize)) {
goto exit;
}
@ -228,7 +230,7 @@ exit:
}
PyDoc_STRVAR(zlib_Decompress_decompress__doc__,
"decompress($self, data, max_length=0, /)\n"
"decompress($self, data, /, max_length=0)\n"
"--\n"
"\n"
"Return a bytes object containing the decompressed version of the data.\n"
@ -245,20 +247,22 @@ PyDoc_STRVAR(zlib_Decompress_decompress__doc__,
"Call the flush() method to clear these buffers.");
#define ZLIB_DECOMPRESS_DECOMPRESS_METHODDEF \
{"decompress", (PyCFunction)zlib_Decompress_decompress, METH_VARARGS, zlib_Decompress_decompress__doc__},
{"decompress", (PyCFunction)zlib_Decompress_decompress, METH_VARARGS|METH_KEYWORDS, zlib_Decompress_decompress__doc__},
static PyObject *
zlib_Decompress_decompress_impl(compobject *self, Py_buffer *data,
Py_ssize_t max_length);
static PyObject *
zlib_Decompress_decompress(compobject *self, PyObject *args)
zlib_Decompress_decompress(compobject *self, PyObject *args, PyObject *kwargs)
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"", "max_length", NULL};
static _PyArg_Parser _parser = {"y*|O&:decompress", _keywords, 0};
Py_buffer data = {NULL, NULL};
Py_ssize_t max_length = 0;
if (!PyArg_ParseTuple(args, "y*|O&:decompress",
if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser,
&data, ssize_t_converter, &max_length)) {
goto exit;
}
@ -463,4 +467,4 @@ exit:
#ifndef ZLIB_COMPRESS_COPY_METHODDEF
#define ZLIB_COMPRESS_COPY_METHODDEF
#endif /* !defined(ZLIB_COMPRESS_COPY_METHODDEF) */
/*[clinic end generated code: output=1fed251c15a9bffa input=a9049054013a1b77]*/
/*[clinic end generated code: output=48911ef429b65903 input=a9049054013a1b77]*/

View File

@ -318,11 +318,11 @@ zlib.decompress
data: Py_buffer
Compressed data.
/
wbits: int(c_default="MAX_WBITS") = MAX_WBITS
The window buffer size and container format.
bufsize: ssize_t(c_default="DEF_BUF_SIZE") = DEF_BUF_SIZE
The initial output buffer size.
/
Returns a bytes object containing the uncompressed data.
[clinic start generated code]*/
@ -330,7 +330,7 @@ Returns a bytes object containing the uncompressed data.
static PyObject *
zlib_decompress_impl(PyObject *module, Py_buffer *data, int wbits,
Py_ssize_t bufsize)
/*[clinic end generated code: output=77c7e35111dc8c42 input=c13dd2c5696cd17f]*/
/*[clinic end generated code: output=77c7e35111dc8c42 input=21960936208e9a5b]*/
{
PyObject *RetVal = NULL;
Byte *ibuf;
@ -750,11 +750,11 @@ zlib.Decompress.decompress
data: Py_buffer
The binary data to decompress.
/
max_length: ssize_t = 0
The maximum allowable length of the decompressed data.
Unconsumed input data will be stored in
the unconsumed_tail attribute.
/
Return a bytes object containing the decompressed version of the data.
@ -766,7 +766,7 @@ Call the flush() method to clear these buffers.
static PyObject *
zlib_Decompress_decompress_impl(compobject *self, Py_buffer *data,
Py_ssize_t max_length)
/*[clinic end generated code: output=6e5173c74e710352 input=d6de9b53c4566b8a]*/
/*[clinic end generated code: output=6e5173c74e710352 input=b85a212a012b770a]*/
{
int err = Z_OK;
Py_ssize_t ibuflen, obuflen = DEF_BUF_SIZE, hard_limit;