Commit d2cbfffc authored by Zackery Spytz's avatar Zackery Spytz Committed by Serhiy Storchaka

bpo-25007: Add copy protocol support to zlib compressors and decompressors (GH-7940)

parent fbd71723
...@@ -231,6 +231,11 @@ Compression objects support the following methods: ...@@ -231,6 +231,11 @@ Compression objects support the following methods:
compress a set of data that share a common initial prefix. compress a set of data that share a common initial prefix.
.. versionchanged:: 3.8
Added :func:`copy.copy` and :func:`copy.deepcopy` support to compression
objects.
Decompression objects support the following methods and attributes: Decompression objects support the following methods and attributes:
...@@ -298,6 +303,11 @@ Decompression objects support the following methods and attributes: ...@@ -298,6 +303,11 @@ Decompression objects support the following methods and attributes:
seeks into the stream at a future point. seeks into the stream at a future point.
.. versionchanged:: 3.8
Added :func:`copy.copy` and :func:`copy.deepcopy` support to decompression
objects.
Information about the version of the zlib library in use is available through Information about the version of the zlib library in use is available through
the following constants: the following constants:
......
import unittest import unittest
from test import support from test import support
import binascii import binascii
import copy
import pickle import pickle
import random import random
import sys import sys
...@@ -626,23 +627,24 @@ class CompressObjectTestCase(BaseCompressTestCase, unittest.TestCase): ...@@ -626,23 +627,24 @@ class CompressObjectTestCase(BaseCompressTestCase, unittest.TestCase):
# Test copying a compression object # Test copying a compression object
data0 = HAMLET_SCENE data0 = HAMLET_SCENE
data1 = bytes(str(HAMLET_SCENE, "ascii").swapcase(), "ascii") data1 = bytes(str(HAMLET_SCENE, "ascii").swapcase(), "ascii")
c0 = zlib.compressobj(zlib.Z_BEST_COMPRESSION) for func in lambda c: c.copy(), copy.copy, copy.deepcopy:
bufs0 = [] c0 = zlib.compressobj(zlib.Z_BEST_COMPRESSION)
bufs0.append(c0.compress(data0)) bufs0 = []
bufs0.append(c0.compress(data0))
c1 = c0.copy() c1 = func(c0)
bufs1 = bufs0[:] bufs1 = bufs0[:]
bufs0.append(c0.compress(data0)) bufs0.append(c0.compress(data0))
bufs0.append(c0.flush()) bufs0.append(c0.flush())
s0 = b''.join(bufs0) s0 = b''.join(bufs0)
bufs1.append(c1.compress(data1)) bufs1.append(c1.compress(data1))
bufs1.append(c1.flush()) bufs1.append(c1.flush())
s1 = b''.join(bufs1) s1 = b''.join(bufs1)
self.assertEqual(zlib.decompress(s0),data0+data0) self.assertEqual(zlib.decompress(s0),data0+data0)
self.assertEqual(zlib.decompress(s1),data0+data1) self.assertEqual(zlib.decompress(s1),data0+data1)
@requires_Compress_copy @requires_Compress_copy
def test_badcompresscopy(self): def test_badcompresscopy(self):
...@@ -651,6 +653,8 @@ class CompressObjectTestCase(BaseCompressTestCase, unittest.TestCase): ...@@ -651,6 +653,8 @@ class CompressObjectTestCase(BaseCompressTestCase, unittest.TestCase):
c.compress(HAMLET_SCENE) c.compress(HAMLET_SCENE)
c.flush() c.flush()
self.assertRaises(ValueError, c.copy) self.assertRaises(ValueError, c.copy)
self.assertRaises(ValueError, copy.copy, c)
self.assertRaises(ValueError, copy.deepcopy, c)
@requires_Decompress_copy @requires_Decompress_copy
def test_decompresscopy(self): def test_decompresscopy(self):
...@@ -660,21 +664,22 @@ class CompressObjectTestCase(BaseCompressTestCase, unittest.TestCase): ...@@ -660,21 +664,22 @@ class CompressObjectTestCase(BaseCompressTestCase, unittest.TestCase):
# Test type of return value # Test type of return value
self.assertIsInstance(comp, bytes) self.assertIsInstance(comp, bytes)
d0 = zlib.decompressobj() for func in lambda c: c.copy(), copy.copy, copy.deepcopy:
bufs0 = [] d0 = zlib.decompressobj()
bufs0.append(d0.decompress(comp[:32])) bufs0 = []
bufs0.append(d0.decompress(comp[:32]))
d1 = d0.copy() d1 = func(d0)
bufs1 = bufs0[:] bufs1 = bufs0[:]
bufs0.append(d0.decompress(comp[32:])) bufs0.append(d0.decompress(comp[32:]))
s0 = b''.join(bufs0) s0 = b''.join(bufs0)
bufs1.append(d1.decompress(comp[32:])) bufs1.append(d1.decompress(comp[32:]))
s1 = b''.join(bufs1) s1 = b''.join(bufs1)
self.assertEqual(s0,s1) self.assertEqual(s0,s1)
self.assertEqual(s0,data) self.assertEqual(s0,data)
@requires_Decompress_copy @requires_Decompress_copy
def test_baddecompresscopy(self): def test_baddecompresscopy(self):
...@@ -684,6 +689,8 @@ class CompressObjectTestCase(BaseCompressTestCase, unittest.TestCase): ...@@ -684,6 +689,8 @@ class CompressObjectTestCase(BaseCompressTestCase, unittest.TestCase):
d.decompress(data) d.decompress(data)
d.flush() d.flush()
self.assertRaises(ValueError, d.copy) self.assertRaises(ValueError, d.copy)
self.assertRaises(ValueError, copy.copy, d)
self.assertRaises(ValueError, copy.deepcopy, d)
def test_compresspickle(self): def test_compresspickle(self):
for proto in range(pickle.HIGHEST_PROTOCOL + 1): for proto in range(pickle.HIGHEST_PROTOCOL + 1):
......
Add :func:`copy.copy` and :func:`copy.deepcopy` support to zlib compressors
and decompressors. Patch by Zackery Spytz.
...@@ -335,6 +335,39 @@ zlib_Compress_copy(compobject *self, PyObject *Py_UNUSED(ignored)) ...@@ -335,6 +335,39 @@ zlib_Compress_copy(compobject *self, PyObject *Py_UNUSED(ignored))
#if defined(HAVE_ZLIB_COPY) #if defined(HAVE_ZLIB_COPY)
PyDoc_STRVAR(zlib_Compress___copy____doc__,
"__copy__($self, /)\n"
"--\n"
"\n");
#define ZLIB_COMPRESS___COPY___METHODDEF \
{"__copy__", (PyCFunction)zlib_Compress___copy__, METH_NOARGS, zlib_Compress___copy____doc__},
static PyObject *
zlib_Compress___copy___impl(compobject *self);
static PyObject *
zlib_Compress___copy__(compobject *self, PyObject *Py_UNUSED(ignored))
{
return zlib_Compress___copy___impl(self);
}
#endif /* defined(HAVE_ZLIB_COPY) */
#if defined(HAVE_ZLIB_COPY)
PyDoc_STRVAR(zlib_Compress___deepcopy____doc__,
"__deepcopy__($self, memo, /)\n"
"--\n"
"\n");
#define ZLIB_COMPRESS___DEEPCOPY___METHODDEF \
{"__deepcopy__", (PyCFunction)zlib_Compress___deepcopy__, METH_O, zlib_Compress___deepcopy____doc__},
#endif /* defined(HAVE_ZLIB_COPY) */
#if defined(HAVE_ZLIB_COPY)
PyDoc_STRVAR(zlib_Decompress_copy__doc__, PyDoc_STRVAR(zlib_Decompress_copy__doc__,
"copy($self, /)\n" "copy($self, /)\n"
"--\n" "--\n"
...@@ -355,6 +388,39 @@ zlib_Decompress_copy(compobject *self, PyObject *Py_UNUSED(ignored)) ...@@ -355,6 +388,39 @@ zlib_Decompress_copy(compobject *self, PyObject *Py_UNUSED(ignored))
#endif /* defined(HAVE_ZLIB_COPY) */ #endif /* defined(HAVE_ZLIB_COPY) */
#if defined(HAVE_ZLIB_COPY)
PyDoc_STRVAR(zlib_Decompress___copy____doc__,
"__copy__($self, /)\n"
"--\n"
"\n");
#define ZLIB_DECOMPRESS___COPY___METHODDEF \
{"__copy__", (PyCFunction)zlib_Decompress___copy__, METH_NOARGS, zlib_Decompress___copy____doc__},
static PyObject *
zlib_Decompress___copy___impl(compobject *self);
static PyObject *
zlib_Decompress___copy__(compobject *self, PyObject *Py_UNUSED(ignored))
{
return zlib_Decompress___copy___impl(self);
}
#endif /* defined(HAVE_ZLIB_COPY) */
#if defined(HAVE_ZLIB_COPY)
PyDoc_STRVAR(zlib_Decompress___deepcopy____doc__,
"__deepcopy__($self, memo, /)\n"
"--\n"
"\n");
#define ZLIB_DECOMPRESS___DEEPCOPY___METHODDEF \
{"__deepcopy__", (PyCFunction)zlib_Decompress___deepcopy__, METH_O, zlib_Decompress___deepcopy____doc__},
#endif /* defined(HAVE_ZLIB_COPY) */
PyDoc_STRVAR(zlib_Decompress_flush__doc__, PyDoc_STRVAR(zlib_Decompress_flush__doc__,
"flush($self, length=zlib.DEF_BUF_SIZE, /)\n" "flush($self, length=zlib.DEF_BUF_SIZE, /)\n"
"--\n" "--\n"
...@@ -468,7 +534,23 @@ exit: ...@@ -468,7 +534,23 @@ exit:
#define ZLIB_COMPRESS_COPY_METHODDEF #define ZLIB_COMPRESS_COPY_METHODDEF
#endif /* !defined(ZLIB_COMPRESS_COPY_METHODDEF) */ #endif /* !defined(ZLIB_COMPRESS_COPY_METHODDEF) */
#ifndef ZLIB_COMPRESS___COPY___METHODDEF
#define ZLIB_COMPRESS___COPY___METHODDEF
#endif /* !defined(ZLIB_COMPRESS___COPY___METHODDEF) */
#ifndef ZLIB_COMPRESS___DEEPCOPY___METHODDEF
#define ZLIB_COMPRESS___DEEPCOPY___METHODDEF
#endif /* !defined(ZLIB_COMPRESS___DEEPCOPY___METHODDEF) */
#ifndef ZLIB_DECOMPRESS_COPY_METHODDEF #ifndef ZLIB_DECOMPRESS_COPY_METHODDEF
#define ZLIB_DECOMPRESS_COPY_METHODDEF #define ZLIB_DECOMPRESS_COPY_METHODDEF
#endif /* !defined(ZLIB_DECOMPRESS_COPY_METHODDEF) */ #endif /* !defined(ZLIB_DECOMPRESS_COPY_METHODDEF) */
/*[clinic end generated code: output=43dd29b8977765f9 input=a9049054013a1b77]*/
#ifndef ZLIB_DECOMPRESS___COPY___METHODDEF
#define ZLIB_DECOMPRESS___COPY___METHODDEF
#endif /* !defined(ZLIB_DECOMPRESS___COPY___METHODDEF) */
#ifndef ZLIB_DECOMPRESS___DEEPCOPY___METHODDEF
#define ZLIB_DECOMPRESS___DEEPCOPY___METHODDEF
#endif /* !defined(ZLIB_DECOMPRESS___DEEPCOPY___METHODDEF) */
/*[clinic end generated code: output=d46c646770146ade input=a9049054013a1b77]*/
...@@ -984,6 +984,32 @@ error: ...@@ -984,6 +984,32 @@ error:
return NULL; return NULL;
} }
/*[clinic input]
zlib.Compress.__copy__
[clinic start generated code]*/
static PyObject *
zlib_Compress___copy___impl(compobject *self)
/*[clinic end generated code: output=1875e6791975442e input=be97a05a788dfd83]*/
{
return zlib_Compress_copy_impl(self);
}
/*[clinic input]
zlib.Compress.__deepcopy__
memo: object
/
[clinic start generated code]*/
static PyObject *
zlib_Compress___deepcopy__(compobject *self, PyObject *memo)
/*[clinic end generated code: output=f47a2213282c9eb0 input=a9a8b0b40d83388e]*/
{
return zlib_Compress_copy_impl(self);
}
/*[clinic input] /*[clinic input]
zlib.Decompress.copy zlib.Decompress.copy
...@@ -1039,6 +1065,33 @@ error: ...@@ -1039,6 +1065,33 @@ error:
Py_XDECREF(retval); Py_XDECREF(retval);
return NULL; return NULL;
} }
/*[clinic input]
zlib.Decompress.__copy__
[clinic start generated code]*/
static PyObject *
zlib_Decompress___copy___impl(compobject *self)
/*[clinic end generated code: output=80bae8bc43498ad4 input=efcb98b5472c13d2]*/
{
return zlib_Decompress_copy_impl(self);
}
/*[clinic input]
zlib.Decompress.__deepcopy__
memo: object
/
[clinic start generated code]*/
static PyObject *
zlib_Decompress___deepcopy__(compobject *self, PyObject *memo)
/*[clinic end generated code: output=1f77286ab490124b input=6e99bd0ac4b9cd8b]*/
{
return zlib_Decompress_copy_impl(self);
}
#endif #endif
/*[clinic input] /*[clinic input]
...@@ -1139,6 +1192,8 @@ static PyMethodDef comp_methods[] = ...@@ -1139,6 +1192,8 @@ static PyMethodDef comp_methods[] =
ZLIB_COMPRESS_COMPRESS_METHODDEF ZLIB_COMPRESS_COMPRESS_METHODDEF
ZLIB_COMPRESS_FLUSH_METHODDEF ZLIB_COMPRESS_FLUSH_METHODDEF
ZLIB_COMPRESS_COPY_METHODDEF ZLIB_COMPRESS_COPY_METHODDEF
ZLIB_COMPRESS___COPY___METHODDEF
ZLIB_COMPRESS___DEEPCOPY___METHODDEF
{NULL, NULL} {NULL, NULL}
}; };
...@@ -1147,6 +1202,8 @@ static PyMethodDef Decomp_methods[] = ...@@ -1147,6 +1202,8 @@ static PyMethodDef Decomp_methods[] =
ZLIB_DECOMPRESS_DECOMPRESS_METHODDEF ZLIB_DECOMPRESS_DECOMPRESS_METHODDEF
ZLIB_DECOMPRESS_FLUSH_METHODDEF ZLIB_DECOMPRESS_FLUSH_METHODDEF
ZLIB_DECOMPRESS_COPY_METHODDEF ZLIB_DECOMPRESS_COPY_METHODDEF
ZLIB_DECOMPRESS___COPY___METHODDEF
ZLIB_DECOMPRESS___DEEPCOPY___METHODDEF
{NULL, NULL} {NULL, NULL}
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment