44
from nova.openstack.common.gettextutils import _
42
45
from nova.openstack.common import timeutils
45
def to_primitive(value, convert_instances=False, level=0):
47
LOG = logging.getLogger(__name__)
50
def to_primitive(value, convert_instances=False, convert_datetime=True,
51
level=0, max_depth=3):
46
52
"""Convert a complex object into primitives.
48
54
Handy for JSON serialization. We can optionally handle instances,
78
84
if getattr(value, '__module__', None) == 'mox':
88
LOG.error(_('Max serialization depth exceeded on object: %d %s'),
84
92
# The try block may not be necessary after the class check above,
85
93
# but just in case ...
95
recursive = functools.partial(to_primitive,
96
convert_instances=convert_instances,
97
convert_datetime=convert_datetime,
87
100
# It's not clear why xmlrpclib created their own DateTime type, but
88
101
# for our purposes, make it a datetime type which is explicitly
91
104
value = datetime.datetime(*tuple(value.timetuple())[:6])
93
106
if isinstance(value, (list, tuple)):
96
o.append(to_primitive(v, convert_instances=convert_instances,
107
return [recursive(v) for v in value]
99
108
elif isinstance(value, dict):
101
for k, v in value.iteritems():
102
o[k] = to_primitive(v, convert_instances=convert_instances,
105
elif isinstance(value, datetime.datetime):
109
return dict((k, recursive(v)) for k, v in value.iteritems())
110
elif convert_datetime and isinstance(value, datetime.datetime):
106
111
return timeutils.strtime(value)
107
112
elif hasattr(value, 'iteritems'):
108
return to_primitive(dict(value.iteritems()),
109
convert_instances=convert_instances,
113
return recursive(dict(value.iteritems()), level=level + 1)
111
114
elif hasattr(value, '__iter__'):
112
return to_primitive(list(value),
113
convert_instances=convert_instances,
115
return recursive(list(value))
115
116
elif convert_instances and hasattr(value, '__dict__'):
116
117
# Likely an instance of something. Watch for cycles.
117
118
# Ignore class member vars.
118
return to_primitive(value.__dict__,
119
convert_instances=convert_instances,
119
return recursive(value.__dict__, level=level + 1)
124
123
# Class objects are tricky since they may define something like
125
124
# __iter__ defined but it isn't callable as list().
126
125
return unicode(value)