added distinguish_tuple argument to Packer

This will make precise python types serialization possible.
This commit is contained in:
faerot 2014-05-22 11:32:54 +03:00
parent 61bac2f586
commit 3b933f0966
2 changed files with 19 additions and 4 deletions

View file

@ -56,6 +56,10 @@ cdef class Packer(object):
Convert unicode to bytes with this encoding. (default: 'utf-8') Convert unicode to bytes with this encoding. (default: 'utf-8')
:param str unicode_errors: :param str unicode_errors:
Error handler for encoding unicode. (default: 'strict') Error handler for encoding unicode. (default: 'strict')
:param bool distinguish_tuple:
If set to true, tuples will not be serialized as lists
and will be treated as unsupported type. This is useful when trying
to implement accurate serialization for python types.
:param bool use_single_float: :param bool use_single_float:
Use single precision float type for float. (default: False) Use single precision float type for float. (default: False)
:param bool autoreset: :param bool autoreset:
@ -71,6 +75,7 @@ cdef class Packer(object):
cdef object _berrors cdef object _berrors
cdef char *encoding cdef char *encoding
cdef char *unicode_errors cdef char *unicode_errors
cdef bool distinguish_tuple
cdef bool use_float cdef bool use_float
cdef bint autoreset cdef bint autoreset
@ -83,10 +88,12 @@ cdef class Packer(object):
self.pk.length = 0 self.pk.length = 0
def __init__(self, default=None, encoding='utf-8', unicode_errors='strict', def __init__(self, default=None, encoding='utf-8', unicode_errors='strict',
use_single_float=False, bint autoreset=1, bint use_bin_type=0): distinguish_tuple=False, use_single_float=False, bint autoreset=1,
bint use_bin_type=0):
""" """
""" """
self.use_float = use_single_float self.use_float = use_single_float
self.distinguish_tuple = distinguish_tuple
self.autoreset = autoreset self.autoreset = autoreset
self.pk.use_bin_type = use_bin_type self.pk.use_bin_type = use_bin_type
if default is not None: if default is not None:
@ -122,6 +129,7 @@ cdef class Packer(object):
cdef dict d cdef dict d
cdef size_t L cdef size_t L
cdef int default_used = 0 cdef int default_used = 0
cdef bool distinguish_tuple = self.distinguish_tuple
if nest_limit < 0: if nest_limit < 0:
raise PackValueError("recursion limit exceeded.") raise PackValueError("recursion limit exceeded.")
@ -204,7 +212,7 @@ cdef class Packer(object):
raise ValueError("EXT data is too large") raise ValueError("EXT data is too large")
ret = msgpack_pack_ext(&self.pk, longval, L) ret = msgpack_pack_ext(&self.pk, longval, L)
ret = msgpack_pack_raw_body(&self.pk, rawval, L) ret = msgpack_pack_raw_body(&self.pk, rawval, L)
elif PyTuple_Check(o) or PyList_Check(o): elif (PyTuple_Check(o) and not distinguish_tuple) or PyList_Check(o):
L = len(o) L = len(o)
if L > (2**32)-1: if L > (2**32)-1:
raise ValueError("list is too large") raise ValueError("list is too large")

View file

@ -485,6 +485,10 @@ class Packer(object):
Convert unicode to bytes with this encoding. (default: 'utf-8') Convert unicode to bytes with this encoding. (default: 'utf-8')
:param str unicode_errors: :param str unicode_errors:
Error handler for encoding unicode. (default: 'strict') Error handler for encoding unicode. (default: 'strict')
:param bool distinguish_tuple:
If set to true, tuples will not be serialized as lists
and will be treated as unsupported type. This is useful when trying
to implement accurate serialization for python types.
:param bool use_single_float: :param bool use_single_float:
Use single precision float type for float. (default: False) Use single precision float type for float. (default: False)
:param bool autoreset: :param bool autoreset:
@ -495,7 +499,9 @@ class Packer(object):
It also enable str8 type for unicode. It also enable str8 type for unicode.
""" """
def __init__(self, default=None, encoding='utf-8', unicode_errors='strict', def __init__(self, default=None, encoding='utf-8', unicode_errors='strict',
use_single_float=False, autoreset=True, use_bin_type=False): distinguish_tuple=False, use_single_float=False, autoreset=True,
use_bin_type=False):
self._distinguish_tuple = distinguish_tuple
self._use_float = use_single_float self._use_float = use_single_float
self._autoreset = autoreset self._autoreset = autoreset
self._use_bin_type = use_bin_type self._use_bin_type = use_bin_type
@ -509,6 +515,7 @@ class Packer(object):
def _pack(self, obj, nest_limit=DEFAULT_RECURSE_LIMIT, isinstance=isinstance): def _pack(self, obj, nest_limit=DEFAULT_RECURSE_LIMIT, isinstance=isinstance):
default_used = False default_used = False
list_type = list if self._distinguish_tuple else (list, tuple)
while True: while True:
if nest_limit < 0: if nest_limit < 0:
raise PackValueError("recursion limit exceeded") raise PackValueError("recursion limit exceeded")
@ -599,7 +606,7 @@ class Packer(object):
self._buffer.write(struct.pack("b", code)) self._buffer.write(struct.pack("b", code))
self._buffer.write(data) self._buffer.write(data)
return return
if isinstance(obj, (list, tuple)): if isinstance(obj, list_type):
n = len(obj) n = len(obj)
self._fb_pack_array_header(n) self._fb_pack_array_header(n)
for i in xrange(n): for i in xrange(n):