Enhance dict compat of VersionedObjectDictCompat

Add more dictionary methods to VersionedObjectDictCompat:

 * __iter__()
 * keys(), iterkeys()
 * values(), itervalues()

Thanks to new methods, dict constructor now accepts
VersionedObjectDictCompat: it's possible to write directly dict(obj)
instead of having to write dict(obj.iteritems()).

On Python 3, items() now returns an iterator instead of a list, to
respect Python 3 dictionary API, as the new keys() and values() methods.

Keep iterkeys(), itervalues() and iteritems() on Python 3, even if
Python 3 dictionaries don't have these methods, just to ease the
transition from Python 2 to Python 3 in Nova.

Change-Id: I4c52d44c7ba49f98b1bbd123209fce7b70ade98d
This commit is contained in:
Victor Stinner
2015-05-13 16:06:52 +02:00
parent 1ff9ef63a9
commit 3ae09aebff
2 changed files with 47 additions and 8 deletions

View File

@@ -645,13 +645,38 @@ class VersionedObjectDictCompat(object):
attribute access.
"""
def iteritems(self):
def __iter__(self):
for name in self.obj_fields:
if (self.obj_attr_is_set(name) or
name in self.obj_extra_fields):
yield name, getattr(self, name)
yield name
items = lambda self: list(self.iteritems())
iterkeys = __iter__
def itervalues(self):
for name in self:
yield getattr(self, name)
def iteritems(self):
for name in self:
yield name, getattr(self, name)
if six.PY3:
# NOTE(haypo): Python 3 dictionaries don't have iterkeys(),
# itervalues() or iteritems() methods. These methods are provided to
# ease the transition from Python 2 to Python 3.
keys = iterkeys
values = itervalues
items = iteritems
else:
def keys(self):
return list(self.iterkeys())
def values(self):
return list(self.itervalues())
def items(self):
return list(self.iteritems())
def __getitem__(self, name):
return getattr(self, name)

View File

@@ -645,12 +645,26 @@ class _TestObject(object):
self.assertRaises(ValueError, fail)
def test_object_dict_syntax(self):
obj = MyObj(foo=123, bar='bar')
obj = MyObj(foo=123, bar=u'text')
self.assertEqual(obj['foo'], 123)
self.assertEqual(sorted(obj.items(), key=lambda x: x[0]),
[('bar', 'bar'), ('foo', 123)])
self.assertEqual(sorted(list(obj.iteritems()), key=lambda x: x[0]),
[('bar', 'bar'), ('foo', 123)])
self.assertIn('bar', obj)
self.assertNotIn('missing', obj)
self.assertEqual(sorted(iter(obj)),
['bar', 'foo'])
self.assertEqual(sorted(obj.keys()),
['bar', 'foo'])
self.assertEqual(sorted(obj.iterkeys()),
['bar', 'foo'])
self.assertEqual(sorted(obj.values(), key=str),
[123, u'text'])
self.assertEqual(sorted(obj.itervalues(), key=str),
[123, u'text'])
self.assertEqual(sorted(obj.items()),
[('bar', u'text'), ('foo', 123)])
self.assertEqual(sorted(list(obj.iteritems())),
[('bar', u'text'), ('foo', 123)])
self.assertEqual(dict(obj),
{'foo': 123, 'bar': u'text'})
def test_load(self):
obj = MyObj()