reorganise consistencies

This commit is contained in:
Emmanuel Garette 2017-12-23 10:55:06 +01:00
parent 7ab479f628
commit a9fed78af0
2 changed files with 153 additions and 149 deletions

View File

@ -801,18 +801,18 @@ def test_consistency_warnings_error():
assert w == [] assert w == []
#def test_consistency_network_netmask_mandatory(): def test_consistency_network_netmask_mandatory():
# a = NetworkOption('a', '', multi=True, properties=('mandatory',), default=[u'0.0.0.0']) a = NetworkOption('a', '', multi=True, properties=('mandatory',), default=[u'0.0.0.0'])
# b = NetmaskOption('b', '', multi=True, properties=('mandatory',), default_multi=u'0.0.0.0') b = NetmaskOption('b', '', multi=True, properties=('mandatory',), default_multi=u'0.0.0.0')
# od = MasterSlaves('a', '', [a, b]) od = MasterSlaves('a', '', [a, b])
# b.impl_add_consistency('network_netmask', a) b.impl_add_consistency('network_netmask', a)
# od2 = OptionDescription('od2', '', [od]) od2 = OptionDescription('od2', '', [od])
# api = getapi(Config(od2)) api = getapi(Config(od2))
# api.property.read_only() api.property.read_only()
# api.property.pop('mandatory') api.property.pop('mandatory')
# api.option.make_dict() api.option.make_dict()
#
#
def test_consistency_has_dependency(): def test_consistency_has_dependency():
a = IPOption('a', '') a = IPOption('a', '')
b = NetmaskOption('b', '') b = NetmaskOption('b', '')

View File

@ -170,142 +170,6 @@ class Option(OnlyOption):
**kwargs): **kwargs):
pass pass
def _launch_consistency(self,
current_opt,
func,
cons_id,
option,
value,
context,
index,
opts,
warnings_only,
transitive,
config_bag):
"""Launch consistency now
:param func: function name, this name should start with _cons_
:type func: `str`
:param option: option that value is changing
:type option: `tiramisu.option.Option`
:param value: new value of this opion
:param context: Config's context, if None, check default value instead
:type context: `tiramisu.config.Config`
:param index: only for multi option, consistency should be launch for
specified index
:type index: `int`
:param opts: all options concerne by this consistency
:type opts: `list` of `tiramisu.option.Option`
:param warnings_only: specific raise error for warning
:type warnings_only: `boolean`
:param transitive: propertyerror is transitive
:type transitive: `boolean`
"""
if context is not undefined:
descr = context.cfgimpl_get_description()
if config_bag is not undefined and cons_id in config_bag.fromconsistency:
return
all_cons_vals = []
all_cons_opts = []
length = None
for opt in opts:
if isinstance(opt, weakref.ReferenceType):
opt = opt()
if option == opt:
# option is current option
# we have already value, so use it
opt_value = value
elif context is undefined:
opt_value = opt.impl_getdefault()
else:
#if context, calculate value, otherwise get default value
sconfig_bag = config_bag.copy('nooption')
sconfig_bag.option = opt
sconfig_bag.fromconsistency.append(cons_id)
sconfig_bag.force_permissive = True
path = opt.impl_getpath(context)
if opt.impl_is_master_slaves('slave'):
index_ = index
else:
index_ = None
try:
opt_value = context.getattr(path,
index_,
sconfig_bag,
iter_slave=True)
except PropertiesOptionError as err:
if debug: # pragma: no cover
log.debug('propertyerror in _launch_consistency: {0}'.format(err))
if transitive:
err.set_orig_opt(option)
raise err
opt_value = None
if not option == opt and opt_value is not None and index is not None and \
(context is undefined or \
not opt.impl_is_master_slaves('slave')):
if len(opt_value) <= index:
opt_value = opt.impl_getdefault_multi()
else:
opt_value = opt_value[index]
if opt.impl_is_multi() and index is None and func not in ALLOWED_CONST_LIST:
if length is not None and length != len(opt_value):
raise ValueError(_('unexpected length of "{}" in constency "{}", should be "{}"'
'').format(len(opt_value),
opt.impl_get_display_name(),
length))
else:
length = len(opt_value)
is_multi = True
else:
is_multi = False
if isinstance(opt_value, list) and func in ALLOWED_CONST_LIST:
for value_ in opt_value:
if isinstance(value_, list):
for val in value_:
all_cons_vals.append((False, val))
all_cons_opts.append(opt)
else:
all_cons_vals.append((False, value_))
all_cons_opts.append(opt)
else:
all_cons_vals.append((is_multi, opt_value))
all_cons_opts.append(opt)
else:
try:
all_values = []
if length is None:
all_value = []
for is_multi, values in all_cons_vals:
all_value.append(values)
all_values = [all_value]
else:
for idx in range(length):
all_value = []
for is_multi, values in all_cons_vals:
if not is_multi:
all_value.append(values)
else:
all_value.append(values[idx])
all_values.append(all_value)
for values in all_values:
getattr(self, func)(current_opt,
all_cons_opts,
values,
warnings_only)
except ValueError as err:
if warnings_only:
msg = _('attention, "{0}" could be an invalid {1} for "{2}", {3}'
'').format(value,
self._display_name,
current_opt.impl_get_display_name(),
err)
warnings.warn_explicit(ValueWarning(msg, self),
ValueWarning,
self.__class__.__name__, 0)
else:
raise err
def impl_is_unique(self): def impl_is_unique(self):
return getattr(self, '_unique', False) return getattr(self, '_unique', False)
@ -615,14 +479,16 @@ class Option(OnlyOption):
config_bag): config_bag):
if context is not undefined: if context is not undefined:
descr = context.cfgimpl_get_description() descr = context.cfgimpl_get_description()
# no consistency found at all
if descr._cache_consistencies is None: if descr._cache_consistencies is None:
return return
#consistencies is something like [('_cons_not_equal', (opt1, opt2))] # get consistencies for this option
if isinstance(option, DynSymLinkOption): if isinstance(option, DynSymLinkOption):
consistencies = descr._cache_consistencies.get(option.impl_getopt()) consistencies = descr._cache_consistencies.get(option.impl_getopt())
else: else:
consistencies = descr._cache_consistencies.get(option) consistencies = descr._cache_consistencies.get(option)
else: else:
# is no context, get consistencies in option
consistencies = option._get_consistencies() consistencies = option._get_consistencies()
if consistencies is not None: if consistencies is not None:
for cons_id, func, all_cons_opts, params in consistencies: for cons_id, func, all_cons_opts, params in consistencies:
@ -652,6 +518,144 @@ class Option(OnlyOption):
transitive, transitive,
config_bag) config_bag)
def _launch_consistency(self,
current_opt,
func,
cons_id,
option,
value,
context,
index,
opts,
warnings_only,
transitive,
config_bag):
"""Launch consistency now
:param func: function name, this name should start with _cons_
:type func: `str`
:param option: option that value is changing
:type option: `tiramisu.option.Option`
:param value: new value of this opion
:param context: Config's context, if None, check default value instead
:type context: `tiramisu.config.Config`
:param index: only for multi option, consistency should be launch for
specified index
:type index: `int`
:param opts: all options concerne by this consistency
:type opts: `list` of `tiramisu.option.Option`
:param warnings_only: specific raise error for warning
:type warnings_only: `boolean`
:param transitive: propertyerror is transitive
:type transitive: `boolean`
"""
if context is not undefined:
descr = context.cfgimpl_get_description()
if config_bag is not undefined and cons_id in config_bag.fromconsistency:
return
all_cons_vals = []
all_cons_opts = []
length = None
for opt in opts:
if isinstance(opt, weakref.ReferenceType):
opt = opt()
if option == opt:
# option is current option
# we have already value, so use it
opt_value = value
elif context is undefined:
opt_value = opt.impl_getdefault()
else:
#if context, calculate value, otherwise get default value
sconfig_bag = config_bag.copy('nooption')
sconfig_bag.option = opt
sconfig_bag.fromconsistency.append(cons_id)
sconfig_bag.force_permissive = True
path = opt.impl_getpath(context)
if opt.impl_is_master_slaves('slave'):
index_ = index
else:
index_ = None
try:
opt_value = context.getattr(path,
index_,
sconfig_bag,
iter_slave=True)
except PropertiesOptionError as err:
if debug: # pragma: no cover
log.debug('propertyerror in _launch_consistency: {0}'.format(err))
if transitive:
err.set_orig_opt(option)
raise err
opt_value = None
if not option == opt and opt_value is not None and index is not None and \
(context is undefined or \
not opt.impl_is_master_slaves('slave')):
if len(opt_value) <= index:
opt_value = opt.impl_getdefault_multi()
else:
opt_value = opt_value[index]
if opt_value is not None and opt.impl_is_multi() and index is None and func not in ALLOWED_CONST_LIST:
if length is not None and length != len(opt_value):
if context is undefined:
return
raise ValueError(_('unexpected length of "{}" in constency "{}", should be "{}"'
'').format(len(opt_value),
opt.impl_get_display_name(),
length))
else:
length = len(opt_value)
is_multi = True
else:
is_multi = False
if isinstance(opt_value, list) and func in ALLOWED_CONST_LIST:
for value_ in opt_value:
if isinstance(value_, list):
for val in value_:
all_cons_vals.append((False, val))
all_cons_opts.append(opt)
else:
all_cons_vals.append((False, value_))
all_cons_opts.append(opt)
else:
all_cons_vals.append((is_multi, opt_value))
all_cons_opts.append(opt)
else:
try:
all_values = []
if length is None:
all_value = []
for is_multi, values in all_cons_vals:
all_value.append(values)
all_values = [all_value]
else:
for idx in range(length):
all_value = []
for is_multi, values in all_cons_vals:
if not is_multi:
all_value.append(values)
else:
all_value.append(values[idx])
all_values.append(all_value)
for values in all_values:
getattr(self, func)(current_opt,
all_cons_opts,
values,
warnings_only)
except ValueError as err:
if warnings_only:
msg = _('attention, "{0}" could be an invalid {1} for "{2}", {3}'
'').format(value,
self._display_name,
current_opt.impl_get_display_name(),
err)
warnings.warn_explicit(ValueWarning(msg, self),
ValueWarning,
self.__class__.__name__, 0)
else:
raise err
def _cons_not_equal(self, def _cons_not_equal(self,
current_opt, current_opt,
opts, opts,