From 96886ce29914ef8424e2d86aef03650c1dc5b8db Mon Sep 17 00:00:00 2001 From: Sirushti Murugesan Date: Fri, 25 Sep 2015 12:28:26 +0530 Subject: [PATCH] Also check for the existence of `items` in to_primitive() Change-Id: If4636566a642ddf2e6e13cc014abca4ad68d1977 --- oslo_serialization/jsonutils.py | 3 ++ oslo_serialization/tests/test_jsonutils.py | 46 ++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/oslo_serialization/jsonutils.py b/oslo_serialization/jsonutils.py index 2677574..9fb5483 100644 --- a/oslo_serialization/jsonutils.py +++ b/oslo_serialization/jsonutils.py @@ -153,6 +153,9 @@ def to_primitive(value, convert_instances=False, convert_datetime=True, for k, v in six.iteritems(value)) elif hasattr(value, 'iteritems'): return recursive(dict(value.iteritems()), level=level + 1) + # Python 3 does not have iteritems + elif hasattr(value, 'items'): + return recursive(dict(value.items()), level=level + 1) elif hasattr(value, '__iter__'): return list(map(recursive, value)) elif convert_instances and hasattr(value, '__dict__'): diff --git a/oslo_serialization/tests/test_jsonutils.py b/oslo_serialization/tests/test_jsonutils.py index e2c618b..5dc21c5 100644 --- a/oslo_serialization/tests/test_jsonutils.py +++ b/oslo_serialization/tests/test_jsonutils.py @@ -198,6 +198,52 @@ class ToPrimitiveTestCase(test_base.BaseTestCase): # an exception due to excessive recursion depth. jsonutils.to_primitive(x) + def test_items(self): + # Use items() when iteritems() is not available. + class ItemsClass(object): + def __init__(self): + self.data = dict(a=1, b=2, c=3) + + def items(self): + return self.data.items() + + x = ItemsClass() + p = jsonutils.to_primitive(x) + self.assertEqual(p, {'a': 1, 'b': 2, 'c': 3}) + + def test_precedence_items_iteritems(self): + class ItemsIterItemsClass(object): + def items(self): + return {'items': 'items'} + + def iteritems(self): + return {'iteritems': 'iteritems'} + + x = ItemsIterItemsClass() + p = jsonutils.to_primitive(x) + # Prefer iteritems over items + self.assertEqual(p, {'iteritems': 'iteritems'}) + + def test_mapping(self): + # Make sure collections.Mapping is converted to a dict + # and not a list. + class MappingClass(collections.Mapping): + def __init__(self): + self.data = dict(a=1, b=2, c=3) + + def __getitem__(self, val): + return self.data[val] + + def __iter__(self): + return iter(self.data) + + def __len__(self): + return len(self.data) + + x = MappingClass() + p = jsonutils.to_primitive(x) + self.assertEqual(p, {'a': 1, 'b': 2, 'c': 3}) + def test_instance(self): class MysteryClass(object): a = 10