def make_class_properties(cls): # NOTE(danms/comstud): Inherit fields from super classes. # mro() returns the current class first and returns 'object' last, so # those can be skipped. Also be careful to not overwrite any fields # that already exist. And make sure each cls has its own copy of # fields and that it is not sharing the dict with a super class. cls.fields = dict(cls.fields) for supercls in cls.mro()[1:-1]: if not hasattr(supercls, 'fields'): continue for name, field in supercls.fields.items(): if name not in cls.fields: cls.fields[name] = field for name, field in cls.fields.iteritems(): if not isinstance(field, fields.Field): raise exception.ObjectFieldInvalid(field=name, objname=cls.obj_name()) def getter(self, name=name): attrname = get_attrname(name) if not hasattr(self, attrname): self.obj_load_attr(name) return getattr(self, attrname) def setter(self, value, name=name, field=field): self._changed_fields.add(name) try: return setattr(self, get_attrname(name), field.coerce(self, name, value)) except Exception: attr = "%s.%s" % (self.obj_name(), name) LOG.exception(_('Error setting %(attr)s') % {'attr': attr}) raise setattr(cls, name, property(getter, setter))
def make_class_properties(cls): # NOTE(danms/comstud): Inherit fields from super classes. # mro() returns the current class first and returns 'object' last, so # those can be skipped. Also be careful to not overwrite any fields # that already exist. And make sure each cls has its own copy of # fields and that it is not sharing the dict with a super class. cls.fields = dict(cls.fields) for supercls in cls.mro()[1:-1]: if not hasattr(supercls, 'fields'): continue for name, field in supercls.fields.items(): if name not in cls.fields: cls.fields[name] = field for name, field in six.iteritems(cls.fields): if not isinstance(field, obj_fields.Field): raise exception.ObjectFieldInvalid( field=name, objname=cls.obj_name()) def getter(self, name=name): attrname = get_attrname(name) if not hasattr(self, attrname): self.obj_load_attr(name) return getattr(self, attrname) def setter(self, value, name=name, field=field): attrname = get_attrname(name) field_value = field.coerce(self, name, value) if field.read_only and hasattr(self, attrname): # Note(yjiang5): _from_db_object() may iterate # every field and write, no exception in such situation. if getattr(self, attrname) != field_value: raise exception.ReadOnlyFieldError(field=name) else: return self._changed_fields.add(name) try: return setattr(self, attrname, field_value) except Exception: attr = "%s.%s" % (self.obj_name(), name) LOG.exception(_LE('Error setting %(attr)s'), {'attr': attr}) raise def deleter(self, name=name): attrname = get_attrname(name) if not hasattr(self, attrname): raise AttributeError('No such attribute `%s' % name) delattr(self, get_attrname(name)) setattr(cls, name, property(getter, setter, deleter))