made the whole instance handling thing optional
This commit is contained in:
@@ -82,7 +82,7 @@ def notify(publisher_id, event_type, priority, payload):
|
|||||||
_('%s not in valid priorities' % priority))
|
_('%s not in valid priorities' % priority))
|
||||||
|
|
||||||
# Ensure everything is JSON serializable.
|
# Ensure everything is JSON serializable.
|
||||||
payload = utils.to_primitive(payload)
|
payload = utils.to_primitive(payload, convert_instances=True)
|
||||||
|
|
||||||
driver = utils.import_object(FLAGS.notification_driver)
|
driver = utils.import_object(FLAGS.notification_driver)
|
||||||
msg = dict(message_id=str(uuid.uuid4()),
|
msg = dict(message_id=str(uuid.uuid4()),
|
||||||
|
|||||||
@@ -504,28 +504,61 @@ def utf8(value):
|
|||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
def to_primitive(value):
|
def to_primitive(value, convert_instances=False, level=0):
|
||||||
if type(value) is type([]) or type(value) is type((None,)):
|
"""Convert a complex object into primitives.
|
||||||
o = []
|
|
||||||
for v in value:
|
Handy for JSON serialization. We can optionally handle instances,
|
||||||
o.append(to_primitive(v))
|
but since this is a recursive function, we could have cyclical
|
||||||
return o
|
data structures.
|
||||||
elif type(value) is type({}):
|
|
||||||
o = {}
|
To handle cyclical data structures we could track the actual objects
|
||||||
for k, v in value.iteritems():
|
visited in a set, but not all objects are hashable. Instead we just
|
||||||
o[k] = to_primitive(v)
|
track the depth of the object inspections and don't go too deep.
|
||||||
return o
|
|
||||||
elif isinstance(value, datetime.datetime):
|
Therefore, convert_instances=True is lossy ... be aware.
|
||||||
return str(value)
|
|
||||||
elif hasattr(value, 'iteritems'):
|
"""
|
||||||
return to_primitive(dict(value.iteritems()))
|
if inspect.isclass(value):
|
||||||
elif hasattr(value, '__iter__'):
|
return unicode(value)
|
||||||
return to_primitive(list(value))
|
|
||||||
elif hasattr(value, '__dict__'):
|
if level > 3:
|
||||||
# Class member variables not supported.
|
return []
|
||||||
return to_primitive(value.__dict__)
|
|
||||||
else:
|
# The try block may not be necessary after the class check above,
|
||||||
return value
|
# but just in case ...
|
||||||
|
try:
|
||||||
|
if type(value) is type([]) or type(value) is type((None,)):
|
||||||
|
o = []
|
||||||
|
for v in value:
|
||||||
|
o.append(to_primitive(v, convert_instances=convert_instances,
|
||||||
|
level=level))
|
||||||
|
return o
|
||||||
|
elif type(value) is type({}):
|
||||||
|
o = {}
|
||||||
|
for k, v in value.iteritems():
|
||||||
|
o[k] = to_primitive(v, convert_instances=convert_instances,
|
||||||
|
level=level)
|
||||||
|
return o
|
||||||
|
elif isinstance(value, datetime.datetime):
|
||||||
|
return str(value)
|
||||||
|
elif hasattr(value, 'iteritems'):
|
||||||
|
return to_primitive(dict(value.iteritems()),
|
||||||
|
convert_instances=convert_instances,
|
||||||
|
level=level)
|
||||||
|
elif hasattr(value, '__iter__'):
|
||||||
|
return to_primitive(list(value), level)
|
||||||
|
elif convert_instances and hasattr(value, '__dict__'):
|
||||||
|
# Likely an instance of something. Watch for cycles.
|
||||||
|
# Ignore class member vars.
|
||||||
|
return to_primitive(value.__dict__,
|
||||||
|
convert_instances=convert_instances,
|
||||||
|
level=level + 1)
|
||||||
|
else:
|
||||||
|
return value
|
||||||
|
except TypeError, e:
|
||||||
|
# Class objects are tricky since they may define something like
|
||||||
|
# __iter__ defined but it isn't callable as list().
|
||||||
|
return unicode(value)
|
||||||
|
|
||||||
|
|
||||||
def dumps(value):
|
def dumps(value):
|
||||||
|
|||||||
Reference in New Issue
Block a user