Skip to content

Commit 4adc6f1

Browse files
committed
Add autoreset option to Packer.
1 parent 537a2ab commit 4adc6f1

File tree

2 files changed

+51
-12
lines changed

2 files changed

+51
-12
lines changed

msgpack/_msgpack.pyx

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,16 @@ cdef class Packer(object):
5454
packer = Packer()
5555
astream.write(packer.pack(a))
5656
astream.write(packer.pack(b))
57+
58+
Packer's constructor has some keyword arguments:
59+
60+
* *defaut* - Convert user type to builtin type that Packer supports.
61+
See also simplejson's document.
62+
* *encoding* - Convert unicode to bytes with this encoding. (default: 'utf-8')
63+
* *unicode_erros* - Error handler for encoding unicode. (default: 'strict')
64+
* *use_single_float* - Use single precision float type for float. (default: False)
65+
* *autoreset* - Reset buffer after each pack and return it's content as `bytes`. (default: True).
66+
If set this to false, use `bytes()` to get content and `.reset()` to clear buffer.
5767
"""
5868
cdef msgpack_packer pk
5969
cdef object _default
@@ -62,6 +72,7 @@ cdef class Packer(object):
6272
cdef char *encoding
6373
cdef char *unicode_errors
6474
cdef bool use_float
75+
cdef bint autoreset
6576

6677
def __cinit__(self):
6778
cdef int buf_size = 1024*1024
@@ -71,8 +82,9 @@ cdef class Packer(object):
7182
self.pk.buf_size = buf_size
7283
self.pk.length = 0
7384

74-
def __init__(self, default=None, encoding='utf-8', unicode_errors='strict', use_single_float=False):
85+
def __init__(self, default=None, encoding='utf-8', unicode_errors='strict', use_single_float=False, bint autoreset=1):
7586
self.use_float = use_single_float
87+
self.autoreset = autoreset
7688
if default is not None:
7789
if not PyCallable_Check(default):
7890
raise TypeError("default must be a callable.")
@@ -182,29 +194,32 @@ cdef class Packer(object):
182194
raise MemoryError
183195
elif ret: # should not happen.
184196
raise TypeError
185-
buf = PyBytes_FromStringAndSize(self.pk.buf, self.pk.length)
186-
self.pk.length = 0
187-
return buf
197+
if self.autoreset:
198+
buf = PyBytes_FromStringAndSize(self.pk.buf, self.pk.length)
199+
self.pk.length = 0
200+
return buf
188201

189202
def pack_array_header(self, size_t size):
190203
cdef int ret = msgpack_pack_array(&self.pk, size)
191204
if ret == -1:
192205
raise MemoryError
193206
elif ret: # should not happen
194207
raise TypeError
195-
buf = PyBytes_FromStringAndSize(self.pk.buf, self.pk.length)
196-
self.pk.length = 0
197-
return buf
208+
if self.autoreset:
209+
buf = PyBytes_FromStringAndSize(self.pk.buf, self.pk.length)
210+
self.pk.length = 0
211+
return buf
198212

199213
def pack_map_header(self, size_t size):
200214
cdef int ret = msgpack_pack_map(&self.pk, size)
201215
if ret == -1:
202216
raise MemoryError
203217
elif ret: # should not happen
204218
raise TypeError
205-
buf = PyBytes_FromStringAndSize(self.pk.buf, self.pk.length)
206-
self.pk.length = 0
207-
return buf
219+
if self.autoreset:
220+
buf = PyBytes_FromStringAndSize(self.pk.buf, self.pk.length)
221+
self.pk.length = 0
222+
return buf
208223

209224
def pack_map_pairs(self, object pairs):
210225
"""
@@ -224,9 +239,18 @@ cdef class Packer(object):
224239
raise MemoryError
225240
elif ret: # should not happen
226241
raise TypeError
227-
buf = PyBytes_FromStringAndSize(self.pk.buf, self.pk.length)
242+
if self.autoreset:
243+
buf = PyBytes_FromStringAndSize(self.pk.buf, self.pk.length)
244+
self.pk.length = 0
245+
return buf
246+
247+
def reset(self):
248+
"""Clear internal buffer."""
228249
self.pk.length = 0
229-
return buf
250+
251+
def bytes(self):
252+
"""Return buffer content."""
253+
return PyBytes_FromStringAndSize(self.pk.buf, self.pk.length)
230254

231255

232256
def pack(object o, object stream, default=None, encoding='utf-8', unicode_errors='strict'):

test/test_pack.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,21 @@ def testArraySize(sizes=[0, 5, 50, 1000]):
103103
for size in sizes:
104104
assert unpacker.unpack() == list(range(size))
105105

106+
def test_manualreset(sizes=[0, 5, 50, 1000]):
107+
packer = Packer(autoreset=False)
108+
for size in sizes:
109+
packer.pack_array_header(size)
110+
for i in range(size):
111+
packer.pack(i)
112+
113+
bio = six.BytesIO(packer.bytes())
114+
unpacker = Unpacker(bio, use_list=1)
115+
for size in sizes:
116+
assert unpacker.unpack() == list(range(size))
117+
118+
packer.reset()
119+
assert packer.bytes() == b''
120+
106121
def testMapSize(sizes=[0, 5, 50, 1000]):
107122
bio = six.BytesIO()
108123
packer = Packer()

0 commit comments

Comments
 (0)