add custom validator
This commit is contained in:
parent
b353c6ba60
commit
5969eaa2d6
2 changed files with 39 additions and 19 deletions
|
@ -40,6 +40,8 @@ class Config(object):
|
|||
#mandatory means: a mandatory option has to have a value that is not None
|
||||
_cfgimpl_mandatory = True
|
||||
_cfgimpl_frozen = True
|
||||
#enables validation function for options if set
|
||||
_cfgimpl_validator = False
|
||||
_cfgimpl_owner = default_owner
|
||||
_cfgimpl_toplevel = None
|
||||
|
||||
|
@ -248,9 +250,9 @@ class Config(object):
|
|||
return value
|
||||
else:
|
||||
return value
|
||||
rootconfig = self._cfgimpl_get_toplevel()
|
||||
try:
|
||||
result = opt_or_descr.getcallback_value(
|
||||
self._cfgimpl_get_toplevel())
|
||||
result = opt_or_descr.getcallback_value(rootconfig)
|
||||
except NoValueReturned, err:
|
||||
pass
|
||||
else:
|
||||
|
@ -264,7 +266,8 @@ class Config(object):
|
|||
raise ConfigError('invalid calculated value returned'
|
||||
' for option {0} : shall not be a list'.format(name))
|
||||
_result = result
|
||||
if _result != None and not opt_or_descr.validate(_result):
|
||||
if _result != None and not opt_or_descr.validate(_result,
|
||||
rootconfig._cfgimpl_validator):
|
||||
raise ConfigError('invalid calculated value returned'
|
||||
' for option {0}'.format(name))
|
||||
self._cfgimpl_values[name] = _result
|
||||
|
@ -455,6 +458,7 @@ class Config(object):
|
|||
rootconfig.cfgimpl_disable_property('hidden')
|
||||
rootconfig.cfgimpl_enable_property('disabled')
|
||||
rootconfig._cfgimpl_mandatory = True
|
||||
rootconfig._cfgimpl_validator = True
|
||||
|
||||
def cfgimpl_read_write(self):
|
||||
"convenience method to freeze, hidde and disable"
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
# the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/
|
||||
# the whole pypy projet is under MIT licence
|
||||
# ____________________________________________________________
|
||||
from types import FunctionType
|
||||
from tiramisu.basetype import HiddenBaseType, DisabledBaseType
|
||||
from tiramisu.error import (ConfigError, ConflictConfigError, NotFoundError,
|
||||
RequiresError, RequirementRecursionError, MandatoryError,
|
||||
|
@ -92,7 +93,7 @@ class Option(HiddenBaseType, DisabledBaseType):
|
|||
_force_default_on_freeze = False
|
||||
def __init__(self, name, doc, default=None, default_multi=None,
|
||||
requires=None, mandatory=False, multi=False, callback=None,
|
||||
callback_params=None):
|
||||
callback_params=None, validator=None, validator_args={}):
|
||||
"""
|
||||
:param default: ['bla', 'bla', 'bla']
|
||||
:param default_multi: 'bla' (used in case of a reset to default only at
|
||||
|
@ -103,6 +104,14 @@ class Option(HiddenBaseType, DisabledBaseType):
|
|||
self._requires = requires
|
||||
self._mandatory = mandatory
|
||||
self.multi = multi
|
||||
self._validator = None
|
||||
self._validator_args = None
|
||||
if validator is not None:
|
||||
if type(validator) != FunctionType:
|
||||
raise TypeError("validator must be a function")
|
||||
self._validator = validator
|
||||
if validator_args is not None:
|
||||
self._validator_args = validator_args
|
||||
if not self.multi and default_multi is not None:
|
||||
raise ConfigError("a default_multi is set whereas multi is False"
|
||||
" in option: {0}".format(name))
|
||||
|
@ -123,17 +132,29 @@ class Option(HiddenBaseType, DisabledBaseType):
|
|||
if self.multi == True:
|
||||
if default == None:
|
||||
default = []
|
||||
if not isinstance(default, list) or not self.validate(default):
|
||||
if not isinstance(default, list):
|
||||
raise ConfigError("invalid default value {0} "
|
||||
"for option {1} : not list type".format(str(default), name))
|
||||
if not self.validate(default, False):
|
||||
raise ConfigError("invalid default value {0} "
|
||||
"for option {1}".format(str(default), name))
|
||||
else:
|
||||
if default != None and not self.validate(default):
|
||||
if default != None and not self.validate(default, False):
|
||||
raise ConfigError("invalid default value {0} "
|
||||
"for option {1}".format(str(default), name))
|
||||
self.default = default
|
||||
self.properties = [] # 'hidden', 'disabled'...
|
||||
|
||||
def validate(self, value):
|
||||
def validate(self, value, validate=True):
|
||||
"""
|
||||
:param value: the option's value
|
||||
:param validate: if true enables ``self._validator`` validation
|
||||
"""
|
||||
# customizing the validator
|
||||
if validate and value is not None and self._validator is not None:
|
||||
if not self._validator(value, **self._validator_args):
|
||||
return False
|
||||
# generic calculation
|
||||
if self.multi == False:
|
||||
# None allows the reset of the value
|
||||
if value != None:
|
||||
|
@ -235,7 +256,8 @@ class Option(HiddenBaseType, DisabledBaseType):
|
|||
:param who : is **not necessarily** a owner because it cannot be a list
|
||||
:type who: string """
|
||||
name = self._name
|
||||
if not self.validate(value):
|
||||
rootconfig = config._cfgimpl_get_toplevel()
|
||||
if not self.validate(value, rootconfig._cfgimpl_validator):
|
||||
raise ConfigError('invalid value %s for option %s' % (value, name))
|
||||
if self.is_mandatory():
|
||||
# value shall not be '' for a mandatory option
|
||||
|
@ -253,7 +275,7 @@ class Option(HiddenBaseType, DisabledBaseType):
|
|||
|
||||
if config.is_frozen() and self.is_frozen():
|
||||
raise TypeError('cannot change the value to %s for '
|
||||
'option %s' % (str(value), name))
|
||||
'option %s this option is frozen' % (str(value), name))
|
||||
apply_requires(self, config)
|
||||
if type(config._cfgimpl_values[name]) == Multi:
|
||||
config._cfgimpl_previous_values[name] = list(config._cfgimpl_values[name])
|
||||
|
@ -283,7 +305,8 @@ class ChoiceOption(Option):
|
|||
|
||||
def __init__(self, name, doc, values, default=None, default_multi=None,
|
||||
requires=None, mandatory=False, multi=False, callback=None,
|
||||
callback_params=None, open_values=False):
|
||||
callback_params=None, open_values=False, validator=None,
|
||||
validator_args={}):
|
||||
self.values = values
|
||||
if open_values not in [True, False]:
|
||||
raise ConfigError('Open_values must be a boolean for '
|
||||
|
@ -292,7 +315,8 @@ class ChoiceOption(Option):
|
|||
super(ChoiceOption, self).__init__(name, doc, default=default,
|
||||
default_multi=default_multi, callback=callback,
|
||||
callback_params=callback_params, requires=requires,
|
||||
multi=multi, mandatory=mandatory)
|
||||
multi=multi, mandatory=mandatory, validator=validator,
|
||||
validator_args=validator_args)
|
||||
|
||||
def _validate(self, value):
|
||||
if not self.open_values:
|
||||
|
@ -306,14 +330,6 @@ class BoolOption(Option):
|
|||
def _validate(self, value):
|
||||
return isinstance(value, bool)
|
||||
|
||||
# config level validator
|
||||
# def setoption(self, config, value, who):
|
||||
# name = self._name
|
||||
# if value and self._validator is not None:
|
||||
# toplevel = config._cfgimpl_get_toplevel()
|
||||
# self._validator(toplevel)
|
||||
# super(BoolOption, self).setoption(config, value, who)
|
||||
|
||||
class IntOption(Option):
|
||||
opt_type = 'int'
|
||||
|
||||
|
|
Loading…
Reference in a new issue