Merge pull request #161 from jfolz/feature/packbuffers
Support packing memoryview objects
This commit is contained in:
commit
82b3121507
|
@ -10,6 +10,11 @@ from msgpack.exceptions import PackValueError
|
||||||
from msgpack import ExtType
|
from msgpack import ExtType
|
||||||
|
|
||||||
|
|
||||||
|
cdef extern from "Python.h":
|
||||||
|
|
||||||
|
int PyMemoryView_Check(object obj)
|
||||||
|
|
||||||
|
|
||||||
cdef extern from "pack.h":
|
cdef extern from "pack.h":
|
||||||
struct msgpack_packer:
|
struct msgpack_packer:
|
||||||
char* buf
|
char* buf
|
||||||
|
@ -132,6 +137,7 @@ cdef class Packer(object):
|
||||||
cdef size_t L
|
cdef size_t L
|
||||||
cdef int default_used = 0
|
cdef int default_used = 0
|
||||||
cdef bint strict_types = self.strict_types
|
cdef bint strict_types = self.strict_types
|
||||||
|
cdef Py_buffer view
|
||||||
|
|
||||||
if nest_limit < 0:
|
if nest_limit < 0:
|
||||||
raise PackValueError("recursion limit exceeded.")
|
raise PackValueError("recursion limit exceeded.")
|
||||||
|
@ -231,6 +237,17 @@ cdef class Packer(object):
|
||||||
for v in o:
|
for v in o:
|
||||||
ret = self._pack(v, nest_limit-1)
|
ret = self._pack(v, nest_limit-1)
|
||||||
if ret != 0: break
|
if ret != 0: break
|
||||||
|
elif PyMemoryView_Check(o):
|
||||||
|
if PyObject_GetBuffer(o, &view, PyBUF_SIMPLE) != 0:
|
||||||
|
raise ValueError("could not get buffer for memoryview")
|
||||||
|
L = view.len
|
||||||
|
if L > (2**32)-1:
|
||||||
|
PyBuffer_Release(&view);
|
||||||
|
raise ValueError("memoryview is too large")
|
||||||
|
ret = msgpack_pack_bin(&self.pk, L)
|
||||||
|
if ret == 0:
|
||||||
|
ret = msgpack_pack_raw_body(&self.pk, <char*>view.buf, L)
|
||||||
|
PyBuffer_Release(&view);
|
||||||
elif not default_used and self._default:
|
elif not default_used and self._default:
|
||||||
o = self._default(o)
|
o = self._default(o)
|
||||||
default_used = 1
|
default_used = 1
|
||||||
|
|
|
@ -36,6 +36,8 @@ if hasattr(sys, 'pypy_version_info'):
|
||||||
else:
|
else:
|
||||||
self.builder = StringBuilder()
|
self.builder = StringBuilder()
|
||||||
def write(self, s):
|
def write(self, s):
|
||||||
|
if isinstance(s, memoryview):
|
||||||
|
s = s.tobytes()
|
||||||
self.builder.append(s)
|
self.builder.append(s)
|
||||||
def getvalue(self):
|
def getvalue(self):
|
||||||
return self.builder.build()
|
return self.builder.build()
|
||||||
|
@ -682,7 +684,7 @@ class Packer(object):
|
||||||
default_used = True
|
default_used = True
|
||||||
continue
|
continue
|
||||||
raise PackValueError("Integer value out of range")
|
raise PackValueError("Integer value out of range")
|
||||||
if self._use_bin_type and check(obj, bytes):
|
if self._use_bin_type and check(obj, (bytes, memoryview)):
|
||||||
n = len(obj)
|
n = len(obj)
|
||||||
if n <= 0xff:
|
if n <= 0xff:
|
||||||
self._buffer.write(struct.pack('>BB', 0xc4, n))
|
self._buffer.write(struct.pack('>BB', 0xc4, n))
|
||||||
|
@ -693,7 +695,7 @@ class Packer(object):
|
||||||
else:
|
else:
|
||||||
raise PackValueError("Bytes is too large")
|
raise PackValueError("Bytes is too large")
|
||||||
return self._buffer.write(obj)
|
return self._buffer.write(obj)
|
||||||
if check(obj, (Unicode, bytes)):
|
if check(obj, (Unicode, bytes, memoryview)):
|
||||||
if check(obj, Unicode):
|
if check(obj, Unicode):
|
||||||
if self._encoding is None:
|
if self._encoding is None:
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# coding: utf-8
|
||||||
|
|
||||||
|
|
||||||
|
from msgpack import packb, unpackb
|
||||||
|
|
||||||
|
|
||||||
|
def test_pack_memoryview():
|
||||||
|
data = bytearray(range(256))
|
||||||
|
view = memoryview(data)
|
||||||
|
unpacked = unpackb(packb(view))
|
||||||
|
assert data == unpacked
|
Loading…
Reference in New Issue