Issue #26243: zlib.compress() keyword argument support by Aviv Palivoda

This commit is contained in:
Martin Panter 2016-02-10 10:06:36 +00:00
parent 38418662e0
commit 1fe0d13d12
6 changed files with 44 additions and 25 deletions

View File

@ -46,14 +46,19 @@ The available exception and functions in this module are:
platforms, use ``adler32(data) & 0xffffffff``.
.. function:: compress(data[, level])
.. function:: compress(data, level=-1)
Compresses the bytes in *data*, returning a bytes object containing compressed data.
*level* is an integer from ``0`` to ``9`` controlling the level of compression;
*level* is an integer from ``0`` to ``9`` or ``-1`` controlling the level of compression;
``1`` is fastest and produces the least compression, ``9`` is slowest and
produces the most. ``0`` is no compression. The default value is ``6``.
produces the most. ``0`` is no compression. The default value is ``-1``
(Z_DEFAULT_COMPRESSION). Z_DEFAULT_COMPRESSION represents a default
compromise between speed and compression (currently equivalent to level 6).
Raises the :exc:`error` exception if any error occurs.
.. versionchanged:: 3.6
Keyword arguments are now supported.
.. function:: compressobj(level=-1, method=DEFLATED, wbits=15, memLevel=8, strategy=Z_DEFAULT_STRATEGY[, zdict])

View File

@ -150,6 +150,13 @@ to check if the :class:`~zipfile.ZipInfo` instance represents a directory.
(Contributed by Thomas Kluyver in :issue:`26039`.)
zlib
----
The :func:`~zlib.compress` function now accepts keyword arguments.
(Contributed by Aviv Palivoda in :issue:`26243`.)
Optimizations
=============

View File

@ -162,6 +162,10 @@ class CompressTestCase(BaseCompressTestCase, unittest.TestCase):
x = zlib.compress(HAMLET_SCENE)
self.assertEqual(zlib.decompress(x), HAMLET_SCENE)
def test_keywords(self):
x = zlib.compress(data=HAMLET_SCENE, level=3)
self.assertEqual(zlib.decompress(x), HAMLET_SCENE)
def test_speech128(self):
# compress more data
data = HAMLET_SCENE * 128

View File

@ -175,6 +175,9 @@ Core and Builtins
Library
-------
- Issue #26243: Support keyword arguments to zlib.compress(). Patch by Aviv
Palivoda.
- Issue #26117: The os.scandir() iterator now closes file descriptor not only
when the iteration is finished, but when it was failed with error.

View File

@ -3,38 +3,39 @@ preserve
[clinic start generated code]*/
PyDoc_STRVAR(zlib_compress__doc__,
"compress($module, bytes, level=Z_DEFAULT_COMPRESSION, /)\n"
"compress($module, /, data, level=Z_DEFAULT_COMPRESSION)\n"
"--\n"
"\n"
"Returns a bytes object containing compressed data.\n"
"\n"
" bytes\n"
" data\n"
" Binary data to be compressed.\n"
" level\n"
" Compression level, in 0-9.");
#define ZLIB_COMPRESS_METHODDEF \
{"compress", (PyCFunction)zlib_compress, METH_VARARGS, zlib_compress__doc__},
{"compress", (PyCFunction)zlib_compress, METH_VARARGS|METH_KEYWORDS, zlib_compress__doc__},
static PyObject *
zlib_compress_impl(PyModuleDef *module, Py_buffer *bytes, int level);
zlib_compress_impl(PyModuleDef *module, Py_buffer *data, int level);
static PyObject *
zlib_compress(PyModuleDef *module, PyObject *args)
zlib_compress(PyModuleDef *module, PyObject *args, PyObject *kwargs)
{
PyObject *return_value = NULL;
Py_buffer bytes = {NULL, NULL};
static char *_keywords[] = {"data", "level", NULL};
Py_buffer data = {NULL, NULL};
int level = Z_DEFAULT_COMPRESSION;
if (!PyArg_ParseTuple(args, "y*|i:compress",
&bytes, &level))
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "y*|i:compress", _keywords,
&data, &level))
goto exit;
return_value = zlib_compress_impl(module, &bytes, level);
return_value = zlib_compress_impl(module, &data, level);
exit:
/* Cleanup for bytes */
if (bytes.obj)
PyBuffer_Release(&bytes);
/* Cleanup for data */
if (data.obj)
PyBuffer_Release(&data);
return return_value;
}
@ -439,4 +440,4 @@ exit:
#ifndef ZLIB_COMPRESS_COPY_METHODDEF
#define ZLIB_COMPRESS_COPY_METHODDEF
#endif /* !defined(ZLIB_COMPRESS_COPY_METHODDEF) */
/*[clinic end generated code: output=cf81e1deae3af0ce input=a9049054013a1b77]*/
/*[clinic end generated code: output=3c96b58b923c1273 input=a9049054013a1b77]*/

View File

@ -137,18 +137,17 @@ PyZlib_Free(voidpf ctx, void *ptr)
/*[clinic input]
zlib.compress
bytes: Py_buffer
data: Py_buffer
Binary data to be compressed.
level: int(c_default="Z_DEFAULT_COMPRESSION") = Z_DEFAULT_COMPRESSION
Compression level, in 0-9.
/
Compression level, in 0-9 or -1.
Returns a bytes object containing compressed data.
[clinic start generated code]*/
static PyObject *
zlib_compress_impl(PyModuleDef *module, Py_buffer *bytes, int level)
/*[clinic end generated code: output=5d7dd4588788efd3 input=be3abe9934bda4b3]*/
zlib_compress_impl(PyModuleDef *module, Py_buffer *data, int level)
/*[clinic end generated code: output=1b97589132b203b4 input=671c615a4b2267da]*/
{
PyObject *ReturnVal = NULL;
Byte *input, *output = NULL;
@ -156,13 +155,13 @@ zlib_compress_impl(PyModuleDef *module, Py_buffer *bytes, int level)
int err;
z_stream zst;
if ((size_t)bytes->len > UINT_MAX) {
if ((size_t)data->len > UINT_MAX) {
PyErr_SetString(PyExc_OverflowError,
"Size does not fit in an unsigned int");
goto error;
}
input = bytes->buf;
length = (unsigned int)bytes->len;
input = data->buf;
length = (unsigned int)data->len;
zst.avail_out = length + length/1000 + 12 + 1;
@ -1323,7 +1322,7 @@ PyDoc_STRVAR(zlib_module_documentation,
"zlib library, which is based on GNU zip.\n"
"\n"
"adler32(string[, start]) -- Compute an Adler-32 checksum.\n"
"compress(string[, level]) -- Compress string, with compression level in 0-9.\n"
"compress(data[, level]) -- Compress data, with compression level 0-9 or -1.\n"
"compressobj([level[, ...]]) -- Return a compressor object.\n"
"crc32(string[, start]) -- Compute a CRC-32 checksum.\n"
"decompress(string,[wbits],[bufsize]) -- Decompresses a compressed string.\n"