From 1fe0d13d1246b5d60a4f4fb8c627babd0e94ab87 Mon Sep 17 00:00:00 2001 From: Martin Panter Date: Wed, 10 Feb 2016 10:06:36 +0000 Subject: Issue #26243: zlib.compress() keyword argument support by Aviv Palivoda --- Doc/library/zlib.rst | 11 ++++++++--- Doc/whatsnew/3.6.rst | 7 +++++++ Lib/test/test_zlib.py | 4 ++++ Misc/NEWS | 3 +++ Modules/clinic/zlibmodule.c.h | 27 ++++++++++++++------------- Modules/zlibmodule.c | 17 ++++++++--------- 6 files changed, 44 insertions(+), 25 deletions(-) diff --git a/Doc/library/zlib.rst b/Doc/library/zlib.rst index 1869bb8..09026cb 100644 --- a/Doc/library/zlib.rst +++ b/Doc/library/zlib.rst @@ -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]) diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst index b7cc159..87199df 100644 --- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -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 ============= diff --git a/Lib/test/test_zlib.py b/Lib/test/test_zlib.py index ecdb5a7..ca30116 100644 --- a/Lib/test/test_zlib.py +++ b/Lib/test/test_zlib.py @@ -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 diff --git a/Misc/NEWS b/Misc/NEWS index d308762..6ce7e2d 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -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. diff --git a/Modules/clinic/zlibmodule.c.h b/Modules/clinic/zlibmodule.c.h index 2d75bc9..d92f88b 100644 --- a/Modules/clinic/zlibmodule.c.h +++ b/Modules/clinic/zlibmodule.c.h @@ -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]*/ diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c index 5cdab45..8ddc774 100644 --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -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" -- cgit v0.12