Handle lower msgpack versions which can't handle OrderedDict's. Fixes #5017.

Dictionary subclasses were only added to msgpack after 0.2.0(inclusive).
Since `isinstance(OrderedDict(), dict)` returns true, of course, msgpack's custom type handling cannot be used.
The solution is to iterate through the data and convert `OrderedDict`'s to `dict`'s since that's what msgpack also does.
For now, the iteration is a top level one, ie, only first child descendants are evaluated. We won't go deeper unless we get the same failure a little deeper in the nested data.
This commit is contained in:
Pedro Algarvio 2013-05-17 11:51:54 +01:00
parent 16042592ee
commit f68b3ace7d

View File

@ -12,6 +12,7 @@ import salt.log
import salt.crypt
from salt.exceptions import SaltReqTimeoutError
from salt._compat import pickle
from salt.utils.odict import OrderedDict
# Import third party libs
import zmq
@ -106,7 +107,33 @@ class Serial(object):
if self.serial == 'pickle':
return pickle.dumps(msg)
else:
return msgpack.dumps(msg)
try:
return msgpack.dumps(msg)
except TypeError:
if msgpack.version >= (0, 2, 0):
# Should support OrderedDict serialization, so, let's
# raise the exception
raise
# msgpack is < 0.2.0, let's make it's life easier
# Since OrderedDict is identified as a dictionary, we can't
# make use of msgpack custom types, we will need to convert by
# hand.
# This means iterating through all elements of a dictionary or
# list/tuple
def odict_encoder(obj):
if isinstance(obj, OrderedDict):
return dict(obj)
return obj
if isinstance(msg, dict):
for k, v in msg.copy().iteritems():
msg[k] = odict_encoder(v)
elif isinstance(msg, (list, tuple)):
msg = list(msg)
for idx, entry in enumerate(msg):
msg[idx] = odict_encoder(entry)
return msgpack.dumps(msg)
def dump(self, msg, fn_):
'''