@@ -50,6 +50,7 @@ cdef class Packer(object):
5050 cdef object _berrors
5151 cdef char * encoding
5252 cdef char * unicode_errors
53+ cdef bool _canonical
5354
5455 def __cinit__ (self ):
5556 cdef int buf_size = 1024 * 1024
@@ -59,7 +60,8 @@ cdef class Packer(object):
5960 self .pk.buf_size = buf_size
6061 self .pk.length = 0
6162
62- def __init__ (self , default = None , encoding = ' utf-8' , unicode_errors = ' strict' ):
63+ def __init__ (self , default = None , encoding = ' utf-8' , unicode_errors = ' strict' ,
64+ canonical = False ):
6365 if default is not None :
6466 if not PyCallable_Check(default):
6567 raise TypeError (" default must be a callable." )
@@ -79,6 +81,8 @@ cdef class Packer(object):
7981 self ._berrors = unicode_errors
8082 self .unicode_errors = PyBytes_AsString(self ._berrors)
8183
84+ self ._canonical = canonical
85+
8286 def __dealloc__ (self ):
8387 free(self .pk.buf);
8488
@@ -131,11 +135,20 @@ cdef class Packer(object):
131135 d = o
132136 ret = msgpack_pack_map(& self .pk, len (d))
133137 if ret == 0 :
134- for k,v in d.items():
135- ret = self ._pack(k, nest_limit- 1 )
136- if ret != 0 : break
137- ret = self ._pack(v, nest_limit- 1 )
138- if ret != 0 : break
138+ if self ._canonical:
139+ # Unfortunately can't use d.items() because a closure would
140+ # be required
141+ for k in sorted (d.keys()):
142+ ret = self ._pack(k, nest_limit- 1 )
143+ if ret != 0 : break
144+ ret = self ._pack(d[k], nest_limit- 1 )
145+ if ret != 0 : break
146+ else :
147+ for k,v in d.items():
148+ ret = self ._pack(k, nest_limit- 1 )
149+ if ret != 0 : break
150+ ret = self ._pack(v, nest_limit- 1 )
151+ if ret != 0 : break
139152 elif PySequence_Check(o):
140153 ret = msgpack_pack_array(& self .pk, len (o))
141154 if ret == 0 :
@@ -159,16 +172,16 @@ cdef class Packer(object):
159172 return buf
160173
161174
162- def pack (object o , object stream , default = None , encoding = ' utf-8' , unicode_errors = ' strict' ):
175+ def pack (object o , object stream , default = None , encoding = ' utf-8' , unicode_errors = ' strict' , canonical = False ):
163176 """
164177 pack an object `o` and write it to stream)."""
165- packer = Packer(default = default, encoding = encoding, unicode_errors = unicode_errors)
178+ packer = Packer(default = default, encoding = encoding, unicode_errors = unicode_errors, canonical = canonical )
166179 stream.write(packer.pack(o))
167180
168- def packb (object o , default = None , encoding = ' utf-8' , unicode_errors = ' strict' ):
181+ def packb (object o , default = None , encoding = ' utf-8' , unicode_errors = ' strict' , canonical = False ):
169182 """
170183 pack o and return packed bytes."""
171- packer = Packer(default = default, encoding = encoding, unicode_errors = unicode_errors)
184+ packer = Packer(default = default, encoding = encoding, unicode_errors = unicode_errors, canonical = canonical )
172185 return packer.pack(o)
173186
174187
0 commit comments