diff --git a/nova/objects/base.py b/nova/objects/base.py index 22f8565fdc0..2b83ec2e6c8 100644 --- a/nova/objects/base.py +++ b/nova/objects/base.py @@ -341,20 +341,23 @@ def obj_attr_is_set(self, attrname): False if not. Raises AttributeError if attrname is not a valid attribute for this object. """ - if (attrname not in self.fields and - attrname not in self.obj_extra_fields): + if attrname not in self.obj_fields: raise AttributeError( _("%(objname)s object has no attribute '%(attrname)s'") % {'objname': self.obj_name(), 'attrname': attrname}) return hasattr(self, get_attrname(attrname)) + @property + def obj_fields(self): + return self.fields.keys() + self.obj_extra_fields + # dictish syntactic sugar def iteritems(self): """For backwards-compatibility with dict-based objects. NOTE(danms): May be removed in the future. """ - for name in self.fields.keys() + self.obj_extra_fields: + 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) @@ -390,7 +393,7 @@ def get(self, key, value=NotSpecifiedSentinel): NOTE(danms): May be removed in the future. """ - if key not in self.fields: + if key not in self.obj_fields: raise AttributeError("'%s' object has no attribute '%s'" % ( self.__class__, key)) if value != NotSpecifiedSentinel and not self.obj_attr_is_set(key): diff --git a/nova/tests/objects/test_objects.py b/nova/tests/objects/test_objects.py index 98deb62580f..6b52b5d13e6 100644 --- a/nova/tests/objects/test_objects.py +++ b/nova/tests/objects/test_objects.py @@ -599,6 +599,18 @@ def test_get_changes(self): obj.obj_reset_changes() self.assertEqual({}, obj.obj_get_changes()) + def test_obj_fields(self): + class TestObj(base.NovaObject): + fields = {'foo': int} + obj_extra_fields = ['bar'] + + @property + def bar(self): + return 'this is bar' + + obj = TestObj() + self.assertEqual(['foo', 'bar'], obj.obj_fields) + class TestObject(_LocalTest, _TestObject): pass