def coerce(self, obj, attr, value): super(StateMachine, self).coerce(obj, attr, value) msg = _("%(object)s's are not allowed transition out of %(value)s " "state") if attr in obj: current_value = getattr(obj, attr) else: return value if current_value in self.ALLOWED_TRANSITIONS: if value in self.ALLOWED_TRANSITIONS[current_value]: return value else: msg = _( "%(object)s's are not allowed to transition out of " "'%(current_value)s' state to '%(value)s' state, choose " "from %(options)r") msg = msg % { 'object': obj.obj_name(), 'current_value': current_value, 'value': value, 'options': [x for x in self.ALLOWED_TRANSITIONS[current_value]] } raise ValueError(msg)
def __init__(self, expected, value): super(KeyTypeError, self).__init__( _('Key %(key)s must be of type %(expected)s not %(actual)s' ) % {'key': repr(value), 'expected': expected.__name__, 'actual': value.__class__.__name__, })
def coerce(obj, attr, value): result = IPAddress.coerce(obj, attr, value) if result.version != 6: raise ValueError(_('Network "%(val)s" is not valid ' 'in field %(attr)s') % {'val': value, 'attr': attr}) return result
def coerce(self, obj, attr, value): try: obj_name = value.obj_name() except AttributeError: obj_name = "" if self._subclasses: obj_names = self._get_all_obj_names(value) else: obj_names = [obj_name] if self._obj_name not in obj_names: if not obj_name: # If we're not dealing with an object, it's probably a # primitive so get it's type for the message below. obj_name = type(value).__name__ obj_mod = '' if hasattr(obj, '__module__'): obj_mod = ''.join([obj.__module__, '.']) val_mod = '' if hasattr(value, '__module__'): val_mod = ''.join([value.__module__, '.']) raise ValueError(_('An object of type %(type)s is required ' 'in field %(attr)s, not a %(valtype)s') % {'type': ''.join([obj_mod, self._obj_name]), 'attr': attr, 'valtype': ''.join([val_mod, obj_name])}) return value
def save(self, context): """Save the changed fields back to the store. This is optional for subclasses, but is presented here in the base class for consistency among those that do. """ raise NotImplementedError(_('Cannot save anything in the base class'))
def obj_load_attr(self, attrname): """Load an additional attribute from the real object. This should load self.$attrname and cache any data that might be useful for future load operations. """ raise NotImplementedError( _("Cannot load '%s' in the base class") % attrname)
def coerce(obj, attr, value): try: versionpredicate.VersionPredicate('check (%s)' % value) except ValueError: raise ValueError(_('Version %(val)s is not a valid predicate in ' 'field %(attr)s') % {'val': value, 'attr': attr}) return value
def coerce(self, obj, attr, value): if not isinstance(value, list): raise ValueError(_('A list is required in field %(attr)s, ' 'not a %(type)s') % {'attr': attr, 'type': type(value).__name__}) for index, element in enumerate(list(value)): value[index] = self._element_type.coerce( obj, '%s[%i]' % (attr, index), element) return value
def convert_version_to_int(version): try: if isinstance(version, six.string_types): version = convert_version_to_tuple(version) if isinstance(version, tuple): return functools.reduce(lambda x, y: (x * 1000) + y, version) except Exception: msg = _("Provided version %s is invalid.") % version raise exception.VersionedObjectsException(msg)
def coerce(self, obj, attr, value): if not isinstance(value, list): raise ValueError(_('A list is required in field %(attr)s, ' 'not a %(type)s') % {'attr': attr, 'type': type(value).__name__}) coerced_list = CoercedList() coerced_list.enable_coercing(self._element_type, obj, attr) coerced_list.extend(value) return coerced_list
def coerce(self, obj, attr, value): if not isinstance(value, set): raise ValueError(_('A set is required in field %(attr)s, ' 'not a %(type)s') % {'attr': attr, 'type': type(value).__name__}) coerced_set = CoercedSet() coerced_set.enable_coercing(self._element_type, obj, attr) coerced_set.update(value) return coerced_set
def __init__(self, expected, key, value): super(ElementTypeError, self).__init__( _('Element %(key)s:%(val)s must be of type %(expected)s' ' not %(actual)s' ) % {'key': key, 'val': repr(value), 'expected': expected, 'actual': value.__class__.__name__, })
def _null(self, obj, attr): if self.nullable: return None elif self._default != UnspecifiedDefault: # NOTE(danms): We coerce the default value each time the field # is set to None as our contract states that we'll let the type # examine the object and attribute name at that time. return self._type.coerce(obj, attr, copy.deepcopy(self._default)) else: raise ValueError(_("Field `%s' cannot be None") % attr)
def coerce(obj, attr, value): # FIXME(danms): We should really try to avoid the need to do this accepted_types = six.integer_types + (float, six.string_types, datetime.datetime) if isinstance(value, accepted_types): return six.text_type(value) else: raise ValueError(_('A string is required in field %(attr)s, ' 'not a %(type)s') % {'attr': attr, 'type': type(value).__name__})
def coerce(self, obj, attr, value): if not isinstance(value, set): raise ValueError(_('A set is required in field %(attr)s, ' 'not a %(type)s') % {'attr': attr, 'type': type(value).__name__}) coerced = set() for element in value: coerced.add(self._element_type.coerce( obj, '%s["%s"]' % (attr, element), element)) return coerced
def obj_attr_is_set(self, attrname): """Test object to see if attrname is present. Returns True if the named attribute has a value set, or False if not. Raises AttributeError if attrname is not a valid attribute for this object. """ 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))
def coerce(self, obj, attr, value): if not isinstance(value, list): raise ValueError( _('A list is required in field %(attr)s, ' 'not a %(type)s') % { 'attr': attr, 'type': type(value).__name__ }) coerced_list = CoercedList() coerced_list.enable_coercing(self._element_type, obj, attr) coerced_list.extend(value) return coerced_list
def coerce(self, obj, attr, value): if not isinstance(value, set): raise ValueError( _('A set is required in field %(attr)s, ' 'not a %(type)s') % { 'attr': attr, 'type': type(value).__name__ }) coerced_set = CoercedSet() coerced_set.enable_coercing(self._element_type, obj, attr) coerced_set.update(value) return coerced_set
def coerce(obj, attr, value): # FIXME(danms): We should really try to avoid the need to do this accepted_types = six.integer_types + (float, six.string_types, datetime.datetime) if isinstance(value, accepted_types): return six.text_type(value) else: raise ValueError( _('A string is required in field %(attr)s, ' 'not a %(type)s') % { 'attr': attr, 'type': type(value).__name__ })
def coerce(self, obj, attr, value): if not isinstance(value, dict): raise ValueError(_('A dict is required in field %(attr)s, ' 'not a %(type)s') % {'attr': attr, 'type': type(value).__name__}) for key, element in value.items(): if not isinstance(key, six.string_types): # NOTE(guohliu) In order to keep compatibility with python3 # we need to use six.string_types rather than basestring here, # since six.string_types is a tuple, so we need to pass the # real type in. raise KeyTypeError(six.string_types[0], key) value[key] = self._element_type.coerce( obj, '%s["%s"]' % (attr, key), element) return value
class VersionedObjectsException(Exception): """Base VersionedObjects Exception To correctly use this class, inherit from it and define a 'msg_fmt' property. That msg_fmt will get printf'd with the keyword arguments provided to the constructor. """ msg_fmt = _("An unknown exception occurred.") code = 500 headers = {} safe = False def __init__(self, message=None, **kwargs): self.kwargs = kwargs if 'code' not in self.kwargs: try: self.kwargs['code'] = self.code except AttributeError: pass if not message: try: message = self.msg_fmt % kwargs except Exception: exc_info = sys.exc_info() # kwargs doesn't match a variable in the message # log the issue and the kwargs LOG.exception(_LE('Exception in string format operation')) for name, value in kwargs.items(): LOG.error("%s: %s" % (name, value)) # noqa if CONF.oslo_versionedobjects.fatal_exception_format_errors: raise six.reraise(*exc_info) else: # at least get the core message out if something happened message = self.msg_fmt super(VersionedObjectsException, self).__init__(message) def format_message(self): # NOTE(mrodden): use the first argument to the python Exception object # which should be our full VersionedObjectsException message, # (see __init__) return self.args[0]
def coerce(self, obj, attr, value): try: obj_name = value.obj_name() except AttributeError: obj_name = "" if self._subclasses: obj_names = self._get_all_obj_names(value) else: obj_names = [obj_name] if self._obj_name not in obj_names: raise ValueError(_('An object of type %(type)s is required ' 'in field %(attr)s, not a %(valtype)s') % {'type': self._obj_name, 'attr': attr, 'valtype': obj_name}) return value
def coerce(self, obj, attr, value): if isinstance(value, six.string_types): # NOTE(danms): Being tolerant of isotime strings here will help us # during our objects transition value = timeutils.parse_isotime(value) elif not isinstance(value, datetime.datetime): raise ValueError(_('A datetime.datetime is required ' 'in field %(attr)s, not a %(type)s') % {'attr': attr, 'type': type(value).__name__}) if value.utcoffset() is None and self.tzinfo_aware: # NOTE(danms): Legacy objects from sqlalchemy are stored in UTC, # but are returned without a timezone attached. # As a transitional aid, assume a tz-naive object is in UTC. value = value.replace(tzinfo=iso8601.iso8601.Utc()) elif not self.tzinfo_aware: value = value.replace(tzinfo=None) return value
def coerce(self, obj, attr, value): try: obj_name = value.obj_name() except AttributeError: obj_name = "" if self._subclasses: obj_names = self._get_all_obj_names(value) else: obj_names = [obj_name] if self._obj_name not in obj_names: if not obj_name: # If we're not dealing with an object, it's probably a # primitive so get it's type for the message below. obj_name = type(value).__name__ raise ValueError(_('An object of type %(type)s is required ' 'in field %(attr)s, not a %(valtype)s') % {'type': self._obj_name, 'attr': attr, 'valtype': obj_name}) return value
def get_schema(self): if hasattr(self, "PATTERN"): return {'type': ['string'], 'pattern': self.PATTERN} else: msg = _("%s has no pattern") % self.__class__.__name__ raise AttributeError(msg)
class UnregisteredSubobject(VersionedObjectsException): msg_fmt = _("%(child_objname)s is referenced by %(parent_objname)s but " "is not registered")
class TargetBeforeSubobjectExistedException(VersionedObjectsException): msg_fmt = _("No subobject existed at version %(target_version)s")
def coerce(self, obj, attr, value): if value not in self._valid_values: msg = _("Field value %s is invalid") % value raise ValueError(msg) return super(Enum, self).coerce(obj, attr, value)
def coerce(obj, attr, value): v = float(value) if v < 0: raise ValueError(_('Value must be >= 0 for field %s') % attr) return v
class EnumRequiresValidValuesError(VersionedObjectsException): msg_fmt = _('Enum fields require a list of valid_values')
class UnsupportedObjectError(VersionedObjectsException): msg_fmt = _('Unsupported object type %(objtype)s')
class IncompatibleObjectVersion(VersionedObjectsException): msg_fmt = _('Version %(objver)s of %(objname)s is not supported, ' 'supported version is %(supported)s')
class OrphanedObjectError(VersionedObjectsException): msg_fmt = _('Cannot call %(method)s on orphaned %(objtype)s object')
class ObjectFieldInvalid(VersionedObjectsException): msg_fmt = _('Field %(field)s of %(objname)s is not an instance of Field')
def coerce(obj, attr, value): if isinstance(value, six.string_types): lowered = value.lower().replace('-', ':') if MACAddress._REGEX.match(lowered): return lowered raise ValueError(_("Malformed MAC %s") % (value, ))
def coerce(obj, attr, value): if isinstance(value, six.string_types): newvalue = value.lower() if PCIAddress._REGEX.match(newvalue): return newvalue raise ValueError(_("Malformed PCI address %s") % (value, ))
class EnumValidValuesInvalidError(VersionedObjectsException): msg_fmt = _('Enum valid values are not valid')
def stringify(self, value): if value not in self._valid_values: msg = _("Field value %s is invalid") % value raise ValueError(msg) return super(Enum, self).stringify(value)
class EnumFieldInvalid(VersionedObjectsException): msg_fmt = _('%(typename)s in %(fieldname)s is not an instance of Enum')
class EnumFieldUnset(VersionedObjectsException): msg_fmt = _('%(fieldname)s missing field type')
class ReadOnlyFieldError(VersionedObjectsException): msg_fmt = _('Cannot modify readonly field %(field)s')
class InvalidTargetVersion(VersionedObjectsException): msg_fmt = _('Invalid target version %(version)s')
class ObjectActionError(VersionedObjectsException): msg_fmt = _('Object action %(action)s failed because: %(reason)s')