diff --git a/tiramisu/option.py b/tiramisu/option.py index 94d1aa1..512242a 100644 --- a/tiramisu/option.py +++ b/tiramisu/option.py @@ -140,9 +140,12 @@ class Option(BaseInformation): if not self._multi and default_multi is not None: raise ValueError(_("a default_multi is set whereas multi is False" " in option: {0}").format(name)) - if default_multi is not None and not self._validate(default_multi): - raise ValueError(_("invalid default_multi value {0} " - "for option {1}").format(str(default_multi), name)) + if default_multi is not None: + try: + self._validate(default_multi) + except ValueError, err: + raise ValueError(_("invalid default_multi value {0} " + "for option {1}: {2}").format(str(default_multi), name, err)) if callback is not None and (default is not None or default_multi is not None): raise ValueError(_("defaut values not allowed if option: {0} " "is calculated").format(name)) @@ -253,34 +256,35 @@ class Option(BaseInformation): if not validate: return - def _val_validator(val): - callback_params = deepcopy(self._validator[1]) - callback_params.setdefault('', []).insert(0, val) - return carry_out_calculation(self._name, config=context, - callback=self._validator[0], - callback_params=callback_params) - - def val_validator(): - #add current value has first argument - if self.impl_is_multi(): - for val in value: - if not _val_validator(val): - return False - return True + def val_validator(val): + if self._validator is not None: + callback_params = deepcopy(self._validator[1]) + callback_params.setdefault('', []).insert(0, val) + return carry_out_calculation(self._name, config=context, + callback=self._validator[0], + callback_params=callback_params) else: - return _val_validator(value) + return True + + def do_validation(_value, _index=None): + if _value is None: + return True + if not val_validator(_value): + raise ValueError(_("invalid value {0} for option {1} for object {2}" + "").format(_value, self._name, self.__class__)) + try: + self._validate(_value) + except ValueError, err: + raise ValueError(_("invalid value {0} for option {1}: {2}" + "").format(_value, self._name, err)) + if context is not None: + descr._valid_consistency(self, _value, context, _index) # generic calculation if context is not None: descr = context.cfgimpl_get_description() if not self._multi: - if value is not None and ((self._validator is not None and - not val_validator()) or - not self._validate(value)): - raise ValueError(_("invalid value {0} for option {1} (type {2})" - "").format(value, self._name, self.__class__)) - if context is not None: - descr._valid_consistency(self, value, context, None) + do_validation(value) else: if not isinstance(value, list): raise ValueError(_("invalid value {0} for option {1} " @@ -288,13 +292,7 @@ class Option(BaseInformation): self._name)) for index in range(0, len(value)): val = value[index] - if val is not None and ((self._validator is not None and - not val_validator()) or - not self._validate(val)): - raise ValueError(_("invalid value {0} for option {1}" - "").format(value, self._name)) - if context is not None: - descr._valid_consistency(self, val, context, index) + do_validation(val, index) def impl_getdefault(self, default_multi=False): "accessing the default value" @@ -398,10 +396,9 @@ class ChoiceOption(Option): return self._open_values def _validate(self, value): - if not self._open_values: - return value is None or value in self._values - else: - return True + if not self._open_values and not value in self._values: + raise ValueError(_('value {0} is not permitted, only {1} is allowed' + '').format(value, self._values)) class BoolOption(Option): @@ -410,7 +407,8 @@ class BoolOption(Option): _opt_type = 'bool' def _validate(self, value): - return isinstance(value, bool) + if not isinstance(value, bool): + raise ValueError(_('value must be a boolean')) class IntOption(Option): @@ -419,7 +417,8 @@ class IntOption(Option): _opt_type = 'int' def _validate(self, value): - return isinstance(value, int) + if not isinstance(value, int): + raise ValueError(_('value must be an integer')) class FloatOption(Option): @@ -428,7 +427,8 @@ class FloatOption(Option): _opt_type = 'float' def _validate(self, value): - return isinstance(value, float) + if not isinstance(value, float): + raise ValueError(_('value must be a float')) class StrOption(Option): @@ -437,7 +437,8 @@ class StrOption(Option): _opt_type = 'string' def _validate(self, value): - return isinstance(value, str) + if not isinstance(value, str): + raise ValueError(_('value must be a string')) class UnicodeOption(Option): @@ -447,7 +448,8 @@ class UnicodeOption(Option): _empty = u'' def _validate(self, value): - return isinstance(value, unicode) + if not isinstance(value, unicode): + raise ValueError(_('value must be an unicode')) class SymLinkOption(object): @@ -490,15 +492,11 @@ class IPOption(Option): properties=properties) def _validate(self, value): - try: - ip = IP('{0}/32'.format(value)) - if ip.iptype() == 'RESERVED': - return False - if self._only_private: - return ip.iptype() == 'PRIVATE' - return True - except ValueError: - return False + ip = IP('{0}/32'.format(value)) + if ip.iptype() == 'RESERVED': + raise ValueError(_("IP mustn't not be in reserved class")) + if self._only_private and not ip.iptype() == 'PRIVATE': + raise ValueError(_("IP must be in private class")) class PortOption(Option): @@ -552,23 +550,19 @@ class PortOption(Option): properties=properties) def _validate(self, value): - try: - if self._allow_range and ":" in str(value): - value = str(value).split(':') - if len(value) != 2: - return False - if not value[0] < value[1]: - return False - else: - value = [value] + if self._allow_range and ":" in str(value): + value = str(value).split(':') + if len(value) != 2: + raise ValueError('range must have two values only') + if not value[0] < value[1]: + raise ValueError('first port in range must be smaller than the second one') + else: + value = [value] - for val in value: - if not self._min_value <= int(val) <= self._max_value: - return False - - return True - except ValueError: - return False + for val in value: + if not self._min_value <= int(val) <= self._max_value: + raise ValueError('port must be an between {0} and {1}' + ''.format(self._min_value, self._max_value)) class NetworkOption(Option): @@ -577,13 +571,9 @@ class NetworkOption(Option): _opt_type = 'network' def _validate(self, value): - try: - ip = IP(value) - if ip.iptype() == 'RESERVED': - return False - return True - except ValueError: - return False + ip = IP(value) + if ip.iptype() == 'RESERVED': + raise ValueError(_("network mustn't not be in reserved class")) class NetmaskOption(Option): @@ -592,11 +582,7 @@ class NetmaskOption(Option): _opt_type = 'netmask' def _validate(self, value): - try: - IP('0.0.0.0/{0}'.format(value)) - return True - except ValueError: - return False + IP('0.0.0.0/{0}'.format(value)) def _cons_network_netmask(self, optname, value, value_): #opts must be (netmask, network) options @@ -669,7 +655,7 @@ class DomainnameOption(Option): if self._allow_ip is True: try: IP('{0}/32'.format(value)) - return True + return except ValueError: pass if self._type == 'netbios': @@ -688,7 +674,8 @@ class DomainnameOption(Option): raise ValueError(_("invalid value's length for {0} (max {1})" "").format(self._name, length)) regexp = r'^[a-z]([a-z\d{0}-])*[a-z\d]$'.format(extrachar) - return re.match(regexp, value) is not None + if re.match(regexp, value) is None: + raise ValueError(_('invalid domainname')) class OptionDescription(BaseInformation): @@ -896,6 +883,7 @@ def validate_requires_arg(requires, name): for require in requires: if not type(require) == dict: + print require raise ValueError(_("malformed requirements type for option:" " {0}, must be a dict").format(name)) valid_keys = ('option', 'expected', 'action', 'inverse', 'transitive', @@ -929,14 +917,18 @@ def validate_requires_arg(requires, name): ' same_action must be boolean')) if not isinstance(option, Option): - raise ValueError(_('malformed requirements first argument ' + print option, type(option) + raise ValueError(_('malformed requirements ' 'must be an option in option {0}').format(name)) if option.impl_is_multi(): raise ValueError(_('malformed requirements option {0} ' 'should not be a multi').format(name)) - if expected is not None and not option._validate(expected): - raise ValueError(_('malformed requirements second argument ' - 'must be valid for option {0}').format(name)) + if expected is not None: + try: + option._validate(expected) + except ValueError, err: + raise ValueError(_('malformed requirements second argument ' + 'must be valid for option {0}: {1}').format(name, err)) if action in config_action: if inverse != config_action[action]: raise ValueError(_("inconsistency in action types for option: {0}" diff --git a/tiramisu/value.py b/tiramisu/value.py index 851b340..65a23b1 100644 --- a/tiramisu/value.py +++ b/tiramisu/value.py @@ -361,10 +361,13 @@ class Multi(list): super(Multi, self).extend(iterable) def _validate(self, value): - if value is not None and not self.opt._validate(value): - raise ValueError(_("invalid value {0} " - "for option {1}").format(str(value), - self.opt._name)) + if value is not None: + try: + self.opt._validate(value) + except ValueError, err: + raise ValueError(_("invalid value {0} " + "for option {1}: {2}").format(str(value), + self.opt._name, err)) def pop(self, key, force=False): """the list value can be updated (poped)