From a9fed78af028120348410c3885c0cfb8b5c861e1 Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Sat, 23 Dec 2017 10:55:06 +0100 Subject: [PATCH] reorganise consistencies --- test/new_api/test_option_consistency.py | 24 +- tiramisu/option/option.py | 278 ++++++++++++------------ 2 files changed, 153 insertions(+), 149 deletions(-) diff --git a/test/new_api/test_option_consistency.py b/test/new_api/test_option_consistency.py index 3b77755..0657292 100644 --- a/test/new_api/test_option_consistency.py +++ b/test/new_api/test_option_consistency.py @@ -801,18 +801,18 @@ def test_consistency_warnings_error(): assert w == [] -#def test_consistency_network_netmask_mandatory(): -# 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') -# od = MasterSlaves('a', '', [a, b]) -# b.impl_add_consistency('network_netmask', a) -# od2 = OptionDescription('od2', '', [od]) -# api = getapi(Config(od2)) -# api.property.read_only() -# api.property.pop('mandatory') -# api.option.make_dict() -# -# +def test_consistency_network_netmask_mandatory(): + 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') + od = MasterSlaves('a', '', [a, b]) + b.impl_add_consistency('network_netmask', a) + od2 = OptionDescription('od2', '', [od]) + api = getapi(Config(od2)) + api.property.read_only() + api.property.pop('mandatory') + api.option.make_dict() + + def test_consistency_has_dependency(): a = IPOption('a', '') b = NetmaskOption('b', '') diff --git a/tiramisu/option/option.py b/tiramisu/option/option.py index f5468e1..039c0a1 100644 --- a/tiramisu/option/option.py +++ b/tiramisu/option/option.py @@ -170,142 +170,6 @@ class Option(OnlyOption): **kwargs): 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): return getattr(self, '_unique', False) @@ -615,14 +479,16 @@ class Option(OnlyOption): config_bag): if context is not undefined: descr = context.cfgimpl_get_description() + # no consistency found at all if descr._cache_consistencies is None: return - #consistencies is something like [('_cons_not_equal', (opt1, opt2))] + # get consistencies for this option if isinstance(option, DynSymLinkOption): consistencies = descr._cache_consistencies.get(option.impl_getopt()) else: consistencies = descr._cache_consistencies.get(option) else: + # is no context, get consistencies in option consistencies = option._get_consistencies() if consistencies is not None: for cons_id, func, all_cons_opts, params in consistencies: @@ -652,6 +518,144 @@ class Option(OnlyOption): transitive, 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, current_opt, opts,