refactor validation
This commit is contained in:
@ -24,12 +24,12 @@ from tiramisu.setting import undefined
|
||||
# ____________________________________________________________
|
||||
|
||||
|
||||
def carry_out_calculation(option, config, callback, callback_params,
|
||||
def carry_out_calculation(option, context, callback, callback_params,
|
||||
index=undefined):
|
||||
"""a function that carries out a calculation for an option's value
|
||||
|
||||
:param option: the option
|
||||
:param config: the context config in order to have
|
||||
:param context: the context config in order to have
|
||||
the whole options available
|
||||
:param callback: the name of the callback function
|
||||
:type callback: str
|
||||
@ -147,26 +147,26 @@ def carry_out_calculation(option, config, callback, callback_params,
|
||||
for key, callbacks in callback_params.items():
|
||||
for callbk in callbacks:
|
||||
if isinstance(callbk, tuple):
|
||||
if config is undefined:
|
||||
if context is undefined:
|
||||
raise ContextError() # pragma: optional cover
|
||||
if callbk[0] is None: # pragma: optional cover
|
||||
#Not an option, set full context
|
||||
tcparams.setdefault(key, []).append((config, False))
|
||||
tcparams.setdefault(key, []).append((context, False))
|
||||
else:
|
||||
# callbk is something link (opt, True|False)
|
||||
opt, force_permissive = callbk
|
||||
if opt._is_subdyn():
|
||||
root = '.'.join(option.impl_getpath(config).split('.')[:-1])
|
||||
root = '.'.join(option.impl_getpath(context).split('.')[:-1])
|
||||
name = opt.impl_getname() + option.impl_getsuffix()
|
||||
path = root + '.' + name
|
||||
opt = opt._impl_to_dyn(name, path)
|
||||
else:
|
||||
path = config.cfgimpl_get_description(
|
||||
path = context.cfgimpl_get_description(
|
||||
).impl_get_path_by_opt(opt)
|
||||
# get value
|
||||
try:
|
||||
value = config.getattr(path, force_permissive=True,
|
||||
validate=False)
|
||||
value = context.getattr(path, force_permissive=True,
|
||||
validate=False)
|
||||
# convert to list, not modifie this multi
|
||||
if value.__class__.__name__ == 'Multi':
|
||||
value = list(value)
|
||||
|
@ -20,13 +20,16 @@
|
||||
# ____________________________________________________________
|
||||
"options handler global entry point"
|
||||
import weakref
|
||||
from copy import copy
|
||||
|
||||
|
||||
from tiramisu.error import PropertiesOptionError, ConfigError, ConflictError
|
||||
from tiramisu.option import OptionDescription, Option, SymLinkOption, \
|
||||
DynSymLinkOption
|
||||
from tiramisu.option.baseoption import valid_name
|
||||
from tiramisu.setting import groups, Settings, default_encoding, undefined
|
||||
from tiramisu.storage import get_storages, get_storage, set_storage, \
|
||||
_impl_getstate_setting
|
||||
_impl_getstate_setting, get_storages_validation
|
||||
from tiramisu.value import Values, Multi
|
||||
from tiramisu.i18n import _
|
||||
|
||||
@ -595,6 +598,14 @@ class _CommonConfig(SubConfig):
|
||||
self._impl_settings._impl_setstate(storage)
|
||||
self._impl_meta = None
|
||||
|
||||
def _gen_fake_values(self):
|
||||
fake_config = Config(self._impl_descr, persistent=False,
|
||||
force_storages=get_storages_validation())
|
||||
fake_config.cfgimpl_get_values()._p_._values = copy(self.cfgimpl_get_values()._p_.get_modified_values())
|
||||
fake_config.cfgimpl_get_settings()._p_._properties = copy(self.cfgimpl_get_settings()._p_.get_modified_properties())
|
||||
fake_config.cfgimpl_get_settings()._p_._permissives = copy(self.cfgimpl_get_settings()._p_.get_modified_permissives())
|
||||
return fake_config
|
||||
|
||||
|
||||
# ____________________________________________________________
|
||||
class Config(_CommonConfig):
|
||||
@ -602,7 +613,7 @@ class Config(_CommonConfig):
|
||||
__slots__ = ('__weakref__', '_impl_test', '_impl_name')
|
||||
|
||||
def __init__(self, descr, session_id=None, persistent=False,
|
||||
name=undefined):
|
||||
name=undefined, force_storages=None):
|
||||
""" Configuration option management master class
|
||||
|
||||
:param descr: describes the configuration schema
|
||||
@ -615,7 +626,10 @@ class Config(_CommonConfig):
|
||||
:param persistent: if persistent, don't delete storage when leaving
|
||||
:type persistent: `boolean`
|
||||
"""
|
||||
#if force_storages is None:
|
||||
settings, values = get_storages(self, session_id, persistent)
|
||||
#else:
|
||||
# settings, values = force_storages
|
||||
self._impl_settings = Settings(self, settings)
|
||||
self._impl_values = Values(self, values)
|
||||
super(Config, self).__init__(descr, weakref.ref(self))
|
||||
|
@ -135,6 +135,9 @@ class Base(StorageBase):
|
||||
list(set_forbidden_properties)))
|
||||
StorageBase.__init__(self, name, _multi, warnings_only, doc, extra,
|
||||
calc_properties, requires, properties)
|
||||
if multi is not False and default is None:
|
||||
default = []
|
||||
self.impl_validate(default)
|
||||
self._set_default_values(default, default_multi)
|
||||
if callback is not False:
|
||||
self.impl_set_callback(callback, callback_params)
|
||||
@ -507,7 +510,7 @@ class Option(OnlyOption):
|
||||
if current_opt is undefined:
|
||||
current_opt = self
|
||||
|
||||
def val_validator(val):
|
||||
def calculation_validator(val):
|
||||
validator, validator_params = self.impl_get_validator()
|
||||
if validator is not None:
|
||||
if validator_params != {}:
|
||||
@ -524,7 +527,7 @@ class Option(OnlyOption):
|
||||
else:
|
||||
validator_params_ = {'': (val,)}
|
||||
# Raise ValueError if not valid
|
||||
carry_out_calculation(self, config=context,
|
||||
carry_out_calculation(self, context=context,
|
||||
callback=validator,
|
||||
callback_params=validator_params_)
|
||||
|
||||
@ -545,7 +548,7 @@ class Option(OnlyOption):
|
||||
warning = None
|
||||
try:
|
||||
# valid with self._validator
|
||||
val_validator(_value)
|
||||
calculation_validator(_value)
|
||||
# if not context launch consistency validation
|
||||
if context is not undefined:
|
||||
descr._valid_consistency(current_opt, _value, context,
|
||||
@ -721,6 +724,7 @@ class Option(OnlyOption):
|
||||
None, all_cons_opts, warnings_only,
|
||||
transitive)
|
||||
self._add_consistency(func, all_cons_opts, params)
|
||||
#re validate default value when add consistency
|
||||
self.impl_validate(self.impl_getdefault())
|
||||
|
||||
def _cons_not_equal(self, opts, vals, warnings_only):
|
||||
|
@ -208,7 +208,8 @@ class MasterSlaves(object):
|
||||
index=index,
|
||||
setting_properties=setting_properties),
|
||||
setitem=False,
|
||||
force=True)
|
||||
force=True,
|
||||
validate=validate)
|
||||
if validate_properties:
|
||||
context.cfgimpl_get_settings().validate_properties(opt, False,
|
||||
False,
|
||||
|
@ -74,7 +74,7 @@ class ChoiceOption(Option):
|
||||
values_params = self._choice_values_params
|
||||
if values_params is None:
|
||||
values_params = {}
|
||||
values = carry_out_calculation(self, config=context,
|
||||
values = carry_out_calculation(self, context=context,
|
||||
callback=values,
|
||||
callback_params=values_params)
|
||||
if not isinstance(values, list): # pragma: optional cover
|
||||
@ -290,7 +290,7 @@ class PortOption(Option):
|
||||
except ValueError: # pragma: optional cover
|
||||
raise ValueError(_('invalid port'))
|
||||
if not self._get_extra('_min_value') <= val <= self._get_extra('_max_value'): # pragma: optional cover
|
||||
raise ValueError(_('invalid port, must be an between {0} '
|
||||
raise ValueError(_('invalid port, must be an integer between {0} '
|
||||
'and {1}').format(self._get_extra('_min_value'),
|
||||
self._get_extra('_max_value')))
|
||||
|
||||
|
@ -139,7 +139,7 @@ class OptionDescription(BaseOption, StorageOptionDescription):
|
||||
option.impl_validate_options(cache_option)
|
||||
if init:
|
||||
if len(cache_option) != len(set(cache_option)):
|
||||
for idx in xrange(1, len(cache_option)+1):
|
||||
for idx in xrange(1, len(cache_option) + 1):
|
||||
opt = cache_option.pop(0)
|
||||
if opt in cache_option:
|
||||
raise ConflictError(_('duplicate option: {0}').format(opt))
|
||||
@ -255,7 +255,7 @@ class OptionDescription(BaseOption, StorageOptionDescription):
|
||||
|
||||
def _impl_get_suffixes(self, context):
|
||||
callback, callback_params = self.impl_get_callback()
|
||||
values = carry_out_calculation(self, config=context,
|
||||
values = carry_out_calculation(self, context=context,
|
||||
callback=callback,
|
||||
callback_params=callback_params)
|
||||
if len(values) > len(set(values)):
|
||||
|
@ -27,6 +27,7 @@ configurator ``set_storage()``.
|
||||
|
||||
|
||||
from time import time
|
||||
from random import randint
|
||||
import os
|
||||
from tiramisu.error import ConfigError
|
||||
from tiramisu.i18n import _
|
||||
@ -66,6 +67,8 @@ class StorageType(object):
|
||||
|
||||
storage_type = StorageType()
|
||||
storage_option_type = StorageType()
|
||||
storage_validation = StorageType()
|
||||
storage_validation.set('dictionary')
|
||||
|
||||
|
||||
def set_storage(type_, name, **kwargs): # pragma: optional cover
|
||||
@ -105,13 +108,15 @@ def get_storage(type_, session_id, persistent, test): # pragma: optional cover
|
||||
"""
|
||||
if type_ == 'option':
|
||||
return storage_option_type.get().Storage(session_id, persistent, test)
|
||||
else:
|
||||
elif type_ == 'config':
|
||||
return storage_type.get().Storage(session_id, persistent, test)
|
||||
else:
|
||||
return storage_validation.get().Storage(session_id, persistent, test)
|
||||
|
||||
|
||||
def get_storages(context, session_id, persistent):
|
||||
def gen_id(config):
|
||||
return str(id(config)) + str(time())
|
||||
return str(id(config)) + str(time()) + str(randint(0, 500))
|
||||
|
||||
if session_id is None:
|
||||
session_id = gen_id(context)
|
||||
@ -119,10 +124,8 @@ def get_storages(context, session_id, persistent):
|
||||
storage = imp.Storage(session_id, persistent)
|
||||
try:
|
||||
return imp.Settings(storage), imp.Values(storage)
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
raise Exception('rah')
|
||||
except Exception, err:
|
||||
raise Exception(_('unable to get storages:') + str(err))
|
||||
|
||||
|
||||
def get_storages_option(type_):
|
||||
@ -133,6 +136,12 @@ def get_storages_option(type_):
|
||||
return imp.StorageOptionDescription
|
||||
|
||||
|
||||
def get_storages_validation():
|
||||
imp = storage_validation.get()
|
||||
storage = imp.Storage('pouet', persistent=False, test=True)
|
||||
return imp.Settings(storage), imp.Values(storage)
|
||||
|
||||
|
||||
def list_sessions(type_): # pragma: optional cover
|
||||
"""List all available session (persistent or not persistent)
|
||||
"""
|
||||
|
@ -83,9 +83,6 @@ class StorageBase(object):
|
||||
self._opt = opt
|
||||
|
||||
def _set_default_values(self, default, default_multi):
|
||||
if self.impl_is_multi() and default is None:
|
||||
default = []
|
||||
self.impl_validate(default)
|
||||
if ((self.impl_is_multi() and default != tuple()) or
|
||||
(not self.impl_is_multi() and default is not None)):
|
||||
if self.impl_is_multi():
|
||||
|
@ -322,9 +322,6 @@ class _Base(SqlAlchemyBase):
|
||||
_Consistency(func, all_cons_opts, params)
|
||||
|
||||
def _set_default_values(self, default, default_multi):
|
||||
if self.impl_is_multi() and default is None:
|
||||
default = []
|
||||
self.impl_validate(default)
|
||||
self._default = default
|
||||
if self.impl_is_multi() and default_multi is not None:
|
||||
self._validate(default_multi)
|
||||
|
@ -83,7 +83,7 @@ class Values(object):
|
||||
# if value has callback and is not set
|
||||
if opt.impl_has_callback():
|
||||
callback, callback_params = opt.impl_get_callback()
|
||||
value = carry_out_calculation(opt, config=self._getcontext(),
|
||||
value = carry_out_calculation(opt, context=self._getcontext(),
|
||||
callback=callback,
|
||||
callback_params=callback_params,
|
||||
index=index)
|
||||
@ -161,8 +161,12 @@ class Values(object):
|
||||
if self._contains(path):
|
||||
if validate:
|
||||
setting = context.cfgimpl_get_settings()
|
||||
opt.impl_validate(opt.impl_getdefault(),
|
||||
context, 'validator' in setting)
|
||||
fake_context = context._gen_fake_values()
|
||||
setting_properties = setting._getproperties()
|
||||
fake_value = fake_context.cfgimpl_get_values()
|
||||
fake_value.reset(opt, path, validate=False)
|
||||
opt.impl_validate(getattr(fake_context, path),
|
||||
fake_context, 'validator' in setting_properties)
|
||||
context.cfgimpl_reset_cache()
|
||||
if opt.impl_is_master_slaves('master'):
|
||||
opt.impl_get_master_slaves().reset(opt, self)
|
||||
@ -331,8 +335,16 @@ class Values(object):
|
||||
# valid opt
|
||||
context = self._getcontext()
|
||||
setting_properties = context.cfgimpl_get_settings()._getproperties()
|
||||
opt.impl_validate(value, context,
|
||||
'validator' in setting_properties)
|
||||
fake_context = context._gen_fake_values()
|
||||
fake_context.cfgimpl_get_values()._setitem(opt, value, path,
|
||||
force_permissive, is_write,
|
||||
setting_properties)
|
||||
opt.impl_validate(value, fake_context, 'validator' in setting_properties)
|
||||
self._setitem(opt, value, path, force_permissive, is_write,
|
||||
setting_properties)
|
||||
|
||||
def _setitem(self, opt, value, path, force_permissive, is_write,
|
||||
setting_properties):
|
||||
if opt.impl_is_master_slaves():
|
||||
opt.impl_get_master_slaves().setitem(self, opt, value, path)
|
||||
self._setvalue(opt, path, value, force_permissive=force_permissive,
|
||||
@ -607,8 +619,13 @@ class Multi(list):
|
||||
def __setitem__(self, index, value):
|
||||
self._setitem(index, value)
|
||||
|
||||
def _setitem(self, index, value):
|
||||
self._validate(value, index, True)
|
||||
def _setitem(self, index, value, validate=True):
|
||||
if validate:
|
||||
fake_context = self._getcontext()._gen_fake_values()
|
||||
fake_multi = fake_context.cfgimpl_get_values()._get_cached_item(
|
||||
self.opt, path=self.path, validate=False)
|
||||
fake_multi._setitem(index, value, validate=False)
|
||||
self._validate(value, fake_context, index, True)
|
||||
#assume not checking mandatory property
|
||||
super(Multi, self).__setitem__(index, value)
|
||||
self._getcontext().cfgimpl_get_values()._setvalue(self.opt, self.path,
|
||||
@ -626,7 +643,7 @@ class Multi(list):
|
||||
True, False, None, True,
|
||||
index=index)
|
||||
|
||||
def append(self, value=undefined, force=False, setitem=True):
|
||||
def append(self, value=undefined, force=False, setitem=True, validate=True):
|
||||
"""the list value can be updated (appened)
|
||||
only if the option is a master
|
||||
"""
|
||||
@ -639,7 +656,12 @@ class Multi(list):
|
||||
value = self._get_validated_value(index)
|
||||
except IndexError:
|
||||
value = None
|
||||
self._validate(value, index, True)
|
||||
if validate and value not in [None, undefined]:
|
||||
fake_context = self._getcontext()._gen_fake_values()
|
||||
fake_multi = fake_context.cfgimpl_get_values()._get_cached_item(
|
||||
self.opt, path=self.path, validate=False)
|
||||
fake_multi.append(value, validate=False, force=True)
|
||||
self._validate(value, fake_context, index, True)
|
||||
if not '_index' in self.__slots__ and self.opt.impl_is_submulti():
|
||||
if not isinstance(value, SubMulti):
|
||||
value = SubMulti(value, self.context, self.opt, self.path, index)
|
||||
@ -668,16 +690,21 @@ class Multi(list):
|
||||
super(Multi, self).reverse()
|
||||
self._store()
|
||||
|
||||
def insert(self, index, obj):
|
||||
#FIXME obj should be undefined
|
||||
def insert(self, index, value, validate=True):
|
||||
#FIXME value should be undefined
|
||||
if self.opt.impl_is_master_slaves():
|
||||
raise SlaveError(_("cannot insert multi option {0} if master or "
|
||||
"slave").format(self.opt.impl_getname()))
|
||||
self._validate(obj, index, True)
|
||||
super(Multi, self).insert(index, obj)
|
||||
if value is not None and validate:
|
||||
fake_context = self._getcontext()._gen_fake_values()
|
||||
fake_multi = fake_context.cfgimpl_get_values()._get_cached_item(
|
||||
self.opt, path=self.path, validate=False)
|
||||
fake_multi.insert(index, value, validate=False)
|
||||
self._validate(value, fake_context, index, True)
|
||||
super(Multi, self).insert(index, value)
|
||||
self._store()
|
||||
|
||||
def extend(self, iterable):
|
||||
def extend(self, iterable, validate=True):
|
||||
if self.opt.impl_is_master_slaves():
|
||||
raise SlaveError(_("cannot extend multi option {0} if master or "
|
||||
"slave").format(self.opt.impl_getname()))
|
||||
@ -685,14 +712,18 @@ class Multi(list):
|
||||
index = self._index
|
||||
except:
|
||||
index = None
|
||||
self._validate(iterable, index)
|
||||
if validate:
|
||||
fake_context = self._getcontext()._gen_fake_values()
|
||||
fake_multi = fake_context.cfgimpl_get_values()._get_cached_item(
|
||||
self.opt, path=self.path, validate=False)
|
||||
fake_multi.extend(iterable, validate=False)
|
||||
self._validate(iterable, fake_context, index)
|
||||
super(Multi, self).extend(iterable)
|
||||
self._store()
|
||||
|
||||
def _validate(self, value, force_index, submulti=False):
|
||||
if value is not None:
|
||||
self.opt.impl_validate(value, context=self._getcontext(),
|
||||
force_index=force_index)
|
||||
def _validate(self, value, fake_context, force_index, submulti=False):
|
||||
self.opt.impl_validate(value, context=fake_context,
|
||||
force_index=force_index)
|
||||
|
||||
def pop(self, index, force=False):
|
||||
"""the list value can be updated (poped)
|
||||
@ -749,12 +780,13 @@ class SubMulti(Multi):
|
||||
self.path,
|
||||
self.submulti())
|
||||
|
||||
def _validate(self, value, force_index, submulti=False):
|
||||
def _validate(self, value, fake_context, force_index, submulti=False):
|
||||
if value is not None:
|
||||
if submulti is False:
|
||||
super(SubMulti, self)._validate(value, force_index)
|
||||
super(SubMulti, self)._validate(value, fake_context,
|
||||
force_index, submulti)
|
||||
else:
|
||||
self.opt.impl_validate(value, context=self._getcontext(),
|
||||
self.opt.impl_validate(value, context=fake_context,
|
||||
force_index=self._index,
|
||||
force_submulti_index=force_index)
|
||||
|
||||
|
Reference in New Issue
Block a user