[openstack-dev] [oslo][nova]Accessing nullable, not set versioned object field

Jay Pipes jaypipes at gmail.com
Fri Dec 16 15:02:06 UTC 2016


On 12/16/2016 07:42 AM, Balázs Gibizer wrote:
> Hi,
>
> What is the expected behavior of accessing a nullable and
> not set versioned object field?
> See the following example code:
>
> from oslo_versionedobjects import base
> from oslo_versionedobjects import fields
>
>
> @base.VersionedObjectRegistry.register
> class MyObject(base.VersionedObject):
>
>     VERSION = '1.0'
>     fields = {
>         'nullable_string': fields.StringField(nullable=True),
>     }
>
>
> my_obj = MyObject()
> my_obj.nullable_string
>
> #EOF
>
> My naïve expectation would be that the value of my_obj.nullable_string
> is None but the actual behavior is an exception:
>
> Traceback (most recent call last):
>   File "ovo_nullable_test.py", line 15, in <module>
>     my_obj.nullable_string
>   File ".tox/functional/local/lib/python2.7/site-packages/oslo_versionedobjects/base.py", line 67, in getter
>     self.obj_load_attr(name)
>   File ".tox/functional/local/lib/python2.7/site-packages/oslo_versionedobjects/base.py", line 603, in obj_load_attr
>     _("Cannot load '%s' in the base class") % attrname)
> NotImplementedError: Cannot load 'nullable_string' in the base class
>
> Is this the correct behavior?

Yes, that's the expected behaviour.

> Then what is the expected behavior if the field is also defaulted to None?
>
>     fields = {
>         'nullable_string': fields.StringField(nullable=True, default=None),
>     }
>
> The actual behavior is still the same exception above. Is it the correct behavior?

Yes. So, what the default=None does is describe the behaviour of the 
field when obj_set_defaults() is called. It does *not* describe what is 
returned if the field *value* is accessed before being populated.

What you're looking for is the obj_attr_is_set() method:

if MyObject.obj_attr_is_set('nullable_string'):
     print my_obj.nullable_string

In addition to the obj_attr_is_set() method, use the obj_set_defaults() 
method to manually set all fields that have a default=XXX value to XXX 
if those fields have not yet been manually set:

class MyObject(ovo.VersionedObjectBase):
     def create(self):
         self.obj_set_defaults()
         # Now you can access your nullable_string field.

The reason this was done was to allow us to differentiate between fields 
that had not had their value set and fields that HAD had their attribute 
set, but to None.

Best,
-jay



More information about the OpenStack-dev mailing list