diff --git a/tests/test_config.py b/tests/test_config.py index 4b8c2e3..7efb323 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -446,7 +446,7 @@ def test_config_od_name(config_type): cfg = get_config(cfg, config_type) assert cfg.option('val.i').name() == 'i' assert cfg.option('val.s').name() == 's' - assert cfg.option('val.s').type() == _('integer') + assert cfg.option('val.s').type() == 'integer' assert cfg.option('val').type() == 'optiondescription' # assert not list_sessions() @@ -458,7 +458,7 @@ def test_config_od_type(config_type): cfg = Config(o2) cfg = get_config(cfg, config_type) assert cfg.option('val').type() == 'optiondescription' - assert cfg.option('val.i').type() == _('integer') + assert cfg.option('val.i').type() == 'integer' # assert not list_sessions() diff --git a/tests/test_option_setting.py b/tests/test_option_setting.py index 0fda79d..884915b 100644 --- a/tests/test_option_setting.py +++ b/tests/test_option_setting.py @@ -626,25 +626,195 @@ def test_reset_properties_force_store_value(): gcgroup = OptionDescription('gc', '', [gcdummy]) od1 = OptionDescription('tiramisu', '', [gcgroup]) cfg = Config(od1) - assert cfg.property.exportation() == {None: {None: frozenset({'validator', 'warnings', 'cache'})}} + assert cfg.property.exportation() == {'properties': {None: {None: frozenset({'cache', + 'validator', + 'warnings'})}}, + 'ro_append': frozenset({'disabled', + 'empty', + 'everything_frozen', + 'force_store_value', + 'frozen', + 'mandatory', + 'validator'}), + 'ro_remove': frozenset({'hidden', + 'permissive'}), + 'rw_append': frozenset({'disabled', + 'force_store_value', + 'frozen', + 'hidden', + 'validator'}), + 'rw_remove': frozenset({'empty', + 'everything_frozen', + 'mandatory', + 'permissive'}), + } + cfg.property.add('frozen') assert cfg.property.exportation() == \ - {None: {None: set(('frozen', 'cache', 'validator', 'warnings'))}} + { + 'properties': {None: {None: frozenset({'cache', + 'frozen', + 'validator', + 'warnings'})}}, + 'ro_append': frozenset({'disabled', + 'empty', + 'everything_frozen', + 'force_store_value', + 'frozen', + 'mandatory', + 'validator'}), + 'ro_remove': frozenset({'hidden', + 'permissive'}), + 'rw_append': frozenset({'disabled', + 'force_store_value', + 'frozen', + 'hidden', + 'validator'}), + 'rw_remove': frozenset({'empty', + 'everything_frozen', + 'mandatory', + 'permissive'}), + } cfg.property.reset() - assert cfg.property.exportation() == {None: {}} + assert cfg.property.exportation() == {'properties': {None: {}}, + 'ro_append': frozenset({'disabled', + 'empty', + 'everything_frozen', + 'force_store_value', + 'frozen', + 'mandatory', + 'validator'}), + 'ro_remove': frozenset({'hidden', + 'permissive'}), + 'rw_append': frozenset({'disabled', + 'force_store_value', + 'frozen', + 'hidden', + 'validator'}), + 'rw_remove': frozenset({'empty', + 'everything_frozen', + 'mandatory', + 'permissive'}), + } + cfg.option('gc.dummy').property.add('test') - assert cfg.property.exportation() == {None: {}, 'gc.dummy': {None: frozenset({'test'})}} + assert cfg.property.exportation() == { + 'properties': {None: {}, + 'gc.dummy': {None: frozenset({'test'})}}, + 'ro_append': frozenset({'disabled', + 'empty', + 'everything_frozen', + 'force_store_value', + 'frozen', + 'mandatory', + 'validator'}), + 'ro_remove': frozenset({'hidden', + 'permissive'}), + 'rw_append': frozenset({'disabled', + 'force_store_value', + 'frozen', + 'hidden', + 'validator'}), + 'rw_remove': frozenset({'empty', + 'everything_frozen', + 'mandatory', + 'permissive'}), + } + cfg.property.reset() - assert cfg.property.exportation() == {None: {}, 'gc.dummy': {None: frozenset({'test'})}} + assert cfg.property.exportation() == { + 'properties': {None: {}, + 'gc.dummy': {None: frozenset({'test'})}}, + 'ro_append': frozenset({'disabled', + 'empty', + 'everything_frozen', + 'force_store_value', + 'frozen', + 'mandatory', + 'validator'}), + 'ro_remove': frozenset({'hidden', + 'permissive'}), + 'rw_append': frozenset({'disabled', + 'force_store_value', + 'frozen', + 'hidden', + 'validator'}), + 'rw_remove': frozenset({'empty', + 'everything_frozen', + 'mandatory', + 'permissive'}), + } + cfg.property.add('frozen') assert cfg.property.exportation() == \ - {None: {None: frozenset({'frozen'})}, 'gc.dummy': {None: frozenset({'test'})}} + { + 'properties': {None: {None: frozenset({'frozen'})}, + 'gc.dummy': {None: frozenset({'test'})}}, + 'ro_append': frozenset({'disabled', + 'empty', + 'everything_frozen', + 'force_store_value', + 'frozen', + 'mandatory', + 'validator'}), + 'ro_remove': frozenset({'hidden', + 'permissive'}), + 'rw_append': frozenset({'disabled', + 'force_store_value', + 'frozen', + 'hidden', + 'validator'}), + 'rw_remove': frozenset({'empty', + 'everything_frozen', + 'mandatory', + 'permissive'}), + } cfg.property.add('frozen') assert cfg.property.exportation() == \ - {None: {None: frozenset({'frozen'})}, 'gc.dummy': {None: frozenset({'test'})}} + { + 'properties': {None: {None: frozenset({'frozen'})}, 'gc.dummy': {None: frozenset({'test'})}}, + 'ro_append': frozenset({'disabled', + 'empty', + 'everything_frozen', + 'force_store_value', + 'frozen', + 'mandatory', + 'validator'}), + 'ro_remove': frozenset({'hidden', + 'permissive'}), + 'rw_append': frozenset({'disabled', + 'force_store_value', + 'frozen', + 'hidden', + 'validator'}), + 'rw_remove': frozenset({'empty', + 'everything_frozen', + 'mandatory', + 'permissive'}), + } cfg.option('gc.dummy').property.add('test') assert cfg.property.exportation() == \ - {None: {None: frozenset({'frozen'})}, 'gc.dummy': {None: frozenset({'test'})}} + { + 'properties': {None: {None: frozenset({'frozen'})}, 'gc.dummy': {None: frozenset({'test'})}}, + 'ro_append': frozenset({'disabled', + 'empty', + 'everything_frozen', + 'force_store_value', + 'frozen', + 'mandatory', + 'validator'}), + 'ro_remove': frozenset({'hidden', + 'permissive'}), + 'rw_append': frozenset({'disabled', + 'force_store_value', + 'frozen', + 'hidden', + 'validator'}), + 'rw_remove': frozenset({'empty', + 'everything_frozen', + 'mandatory', + 'permissive'}), + } # assert not list_sessions() @@ -674,10 +844,79 @@ def test_set_modified_value(): gcgroup = OptionDescription('gc', '', [gcdummy]) od1 = OptionDescription('tiramisu', '', [gcgroup]) cfg = Config(od1) - assert cfg.property.exportation() == {None: {None: frozenset({'warnings', 'validator', 'cache'})}} - cfg.property.importation({None: {None: set(('frozen', 'cache', 'validator', 'warnings'))}}) + assert cfg.property.exportation() == { + 'properties': {None: {None: frozenset({'cache', + 'validator', + 'warnings'})}}, + 'ro_append': frozenset({'disabled', + 'empty', + 'everything_frozen', + 'force_store_value', + 'frozen', + 'mandatory', + 'validator'}), + 'ro_remove': frozenset({'hidden', + 'permissive'}), + 'rw_append': frozenset({'disabled', + 'force_store_value', + 'frozen', + 'hidden', + 'validator'}), + 'rw_remove': frozenset({'empty', + 'everything_frozen', + 'mandatory', + 'permissive'}), + } + + cfg.property.importation({ + 'properties': {None: {None: frozenset({'cache', + 'frozen', + 'validator', + 'warnings'})}}, + 'ro_append': frozenset({'disabled', + 'empty', + 'everything_frozen', + 'force_store_value', + 'frozen', + 'mandatory', + 'validator'}), + 'ro_remove': frozenset({'hidden', + 'permissive'}), + 'rw_append': frozenset({'disabled', + 'force_store_value', + 'frozen', + 'hidden', + 'validator'}), + 'rw_remove': frozenset({'empty', + 'everything_frozen', + 'mandatory', + 'permissive'}), + }) assert cfg.property.exportation() == \ - {None: {None: set(('frozen', 'cache', 'validator', 'warnings'))}} + { + 'properties': {None: {None: frozenset({'cache', + 'frozen', + 'validator', + 'warnings'})}}, + 'ro_append': frozenset({'disabled', + 'empty', + 'everything_frozen', + 'force_store_value', + 'frozen', + 'mandatory', + 'validator'}), + 'ro_remove': frozenset({'hidden', + 'permissive'}), + 'rw_append': frozenset({'disabled', + 'force_store_value', + 'frozen', + 'hidden', + 'validator'}), + 'rw_remove': frozenset({'empty', + 'everything_frozen', + 'mandatory', + 'permissive'}), + } # assert not list_sessions() @@ -749,8 +988,7 @@ def test_pprint(): list_disabled = '"disabled" (' + display_list([msg_is.format('Test int option', '"1"'), msg_is.format('string2', '"string"')], add_quote=False) + ')' list_hidden = '"hidden" (' + msg_is_not.format('Test int option', display_list([2, 3, 4], separator='or', add_quote=True)) + ')' - print('FIXME') -# assert str(err) == _(msg_error.format('option', 'Test string option', properties, display_list([list_disabled, list_hidden], add_quote=False))) + assert str(err) == _(msg_error.format('option', 'Test string option', properties, display_list([list_disabled, list_hidden], add_quote=False))) del err err = None @@ -759,8 +997,7 @@ def test_pprint(): except PropertiesOptionError as error: err = error - print('FIXME') -# assert str(err) == msg_error.format('optiondescription', 'options', prop, '"hidden" (' + msg_is.format('Test int option', '"1"') + ')') + assert str(err) == msg_error.format('optiondescription', 'options', prop, '"hidden" (' + msg_is.format('Test int option', '"1"') + ')') #err = None #try: diff --git a/tests/test_option_validator.py b/tests/test_option_validator.py index 5aaa83d..211f240 100644 --- a/tests/test_option_validator.py +++ b/tests/test_option_validator.py @@ -334,7 +334,7 @@ def test_validator_warning(config_type): assert len(w) == 1 if config_type != 'tiramisu-api': assert w[0].message.opt() == opt2 - assert str(w[0].message) == msg_err.format('val', opt2.get_type(), 'opt2') + ', ' + 'test error return_false' + assert str(w[0].message) == msg_err.format('val', _(opt2.get_type()), 'opt2') + ', ' + 'test error return_false' # with warnings.catch_warnings(record=True) as w: cfg.nowarnings.option('opt2').value.set('val') @@ -352,7 +352,7 @@ def test_validator_warning(config_type): assert len(w) == 1 if config_type != 'tiramisu-api': assert w[0].message.opt() == opt3 - assert str(w[0].message) == msg_err.format('val1', opt3.get_type(), 'opt3') + ', ' + 'test error' + assert str(w[0].message) == msg_err.format('val1', _(opt3.get_type()), 'opt3') + ', ' + 'test error' # with warnings.catch_warnings(record=True) as w: with pytest.raises(ValueError): @@ -365,9 +365,9 @@ def test_validator_warning(config_type): assert len(w) == 2 if config_type != 'tiramisu-api': assert w[0].message.opt() == opt2 - assert str(w[0].message) == msg_err.format('val', opt2.get_type(), 'opt2') + ', ' + 'test error return_false' + assert str(w[0].message) == msg_err.format('val', _(opt2.get_type()), 'opt2') + ', ' + 'test error return_false' assert w[1].message.opt() == opt3 - assert str(w[1].message) == msg_err.format('val1', opt3.get_type(), 'opt3') + ', ' + 'test error' + assert str(w[1].message) == msg_err.format('val1', _(opt3.get_type()), 'opt3') + ', ' + 'test error' # assert not list_sessions() @@ -436,13 +436,13 @@ def test_validator_warning_leadership(config_type): assert len(w) == 1 if config_type != 'tiramisu-api': assert w[0].message.opt() == netmask_admin_eth0 - assert str(w[0].message) == msg_err.format('val1', netmask_admin_eth0.get_type(), display_name_netmask) + ', test error' + assert str(w[0].message) == msg_err.format('val1', _(netmask_admin_eth0.get_type()), display_name_netmask) + ', test error' # with warnings.catch_warnings(record=True) as w: cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val']) if config_type != 'tiramisu-api': assert w and w[0].message.opt() == ip_admin_eth0 - assert str(w[0].message) == msg_err.format('val', ip_admin_eth0.get_type(), display_name_ip) + ', test error return_false' + assert str(w[0].message) == msg_err.format('val', _(ip_admin_eth0.get_type()), display_name_ip) + ', test error return_false' else: assert len(w) == 2 # @@ -450,7 +450,7 @@ def test_validator_warning_leadership(config_type): cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val', 'val1', 'val1']) if config_type != 'tiramisu-api': assert w[0].message.opt() == ip_admin_eth0 - assert str(w[0].message) == msg_err.format('val', ip_admin_eth0.get_type(), display_name_ip) + ', test error return_false' + assert str(w[0].message) == msg_err.format('val', _(ip_admin_eth0.get_type()), display_name_ip) + ', test error return_false' else: assert len(w) == 3 # @@ -458,7 +458,7 @@ def test_validator_warning_leadership(config_type): cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val1', 'val', 'val1']) if config_type != 'tiramisu-api': assert w[0].message.opt() == ip_admin_eth0 - assert str(w[0].message) == msg_err.format('val', ip_admin_eth0.get_type(), display_name_ip) + ', test error return_false' + assert str(w[0].message) == msg_err.format('val', _(ip_admin_eth0.get_type()), display_name_ip) + ', test error return_false' else: assert len(w) == 3 # @@ -467,7 +467,7 @@ def test_validator_warning_leadership(config_type): cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val1', 'val1', 'val']) if config_type != 'tiramisu-api': assert w[0].message.opt() == ip_admin_eth0 - assert str(w[0].message) == msg_err.format('val', ip_admin_eth0.get_type(), display_name_ip) + ', test error return_false' + assert str(w[0].message) == msg_err.format('val', _(ip_admin_eth0.get_type()), display_name_ip) + ', test error return_false' else: assert len(w) == 3 # assert not list_sessions() diff --git a/tests/test_requires.py b/tests/test_requires.py index 7c22931..25c738d 100644 --- a/tests/test_requires.py +++ b/tests/test_requires.py @@ -197,11 +197,9 @@ def test_requires_same_action(config_type): if config_type == 'tiramisu': submsg = '"new" (' + _('the value of "{0}" is {1}').format('activate_service', '"False"') + ')' submsg = '"disabled" (' + str(_('cannot access to {0} "{1}" because has {2} {3}').format('option', 'activate_service_web', _('property'), submsg)) + ')' - print('FIXME') -# assert str(err) == str(_('cannot access to {0} "{1}" because has {2} {3}').format('option', 'ip_address_service_web', _('property'), submsg)) + assert str(err) == str(_('cannot access to {0} "{1}" because has {2} {3}').format('option', 'ip_address_service_web', _('property'), submsg)) #access to cache - print('FIXME') -# assert str(err) == str(_('cannot access to {0} "{1}" because has {2} {3}').format('option', 'ip_address_service_web', _('property'), submsg)) + assert str(err) == str(_('cannot access to {0} "{1}" because has {2} {3}').format('option', 'ip_address_service_web', _('property'), submsg)) else: # FIXME assert str(err) == 'error' @@ -428,9 +426,10 @@ def test_requires_transitive_unrestraint(config_type): # if config_type == 'tiramisu-api': cfg.send() - assert cfg_ori.unrestraint.option('activate_service_web').property.get() == {'disabled'} + assert cfg_ori.option('activate_service_web').property.get() == {'disabled'} print('FIXME') # assert cfg_ori.unrestraint.option('ip_address_service_web').property.get() == {'disabled'} + assert cfg_ori.option('ip_address_service_web').property.get() == {'disabled'} # assert not list_sessions() diff --git a/tests/test_symlink.py b/tests/test_symlink.py index 05c347b..f2fc5ce 100644 --- a/tests/test_symlink.py +++ b/tests/test_symlink.py @@ -297,11 +297,59 @@ def test_symlink_leader(): def test_symlink_followers(): - a = StrOption('a', "", multi=True) ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True) - netmask_admin_eth0 = SymLinkOption('netmask_admin_eth0', a) - with pytest.raises(ValueError): - Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + netmask_admin_eth0 = SymLinkOption('netmask_admin_eth0', ip_admin_eth0) + leader = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + od1 = OptionDescription('opt', '', [leader]) + cfg = Config(od1) + assert parse_od_get(cfg.value.get()) == {'ip_admin_eth0.ip_admin_eth0': []} + cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val1', 'val2']) + assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == 'val2' + assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).owner.get() == 'user' + assert parse_od_get(cfg.value.get()) == { + 'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': 'val1', + 'ip_admin_eth0.netmask_admin_eth0': 'val1'}, + {'ip_admin_eth0.ip_admin_eth0': 'val2', + 'ip_admin_eth0.netmask_admin_eth0': 'val2'}], + } + +def test_symlink_leader_default(): + ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", ['val1', 'val2'], multi=True) + netmask_admin_eth0 = SymLinkOption('netmask_admin_eth0', ip_admin_eth0) + leader = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + od1 = OptionDescription('opt', '', [leader]) + cfg = Config(od1) + assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == 'val2' + assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).owner.isdefault() + assert parse_od_get(cfg.value.get()) == { + 'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': 'val1', + 'ip_admin_eth0.netmask_admin_eth0': 'val1'}, + {'ip_admin_eth0.ip_admin_eth0': 'val2', + 'ip_admin_eth0.netmask_admin_eth0': 'val2'}], + } + + +def test_symlink_followers_2(): + variable1 = StrOption('variable1', "", multi=True) + variable2 = StrOption('variable2', "", multi=True) + variable3 = SymLinkOption('variable3', variable2) + leader = Leadership('variable1', '', [variable1, variable2, variable3]) + od1 = OptionDescription('opt', '', [leader]) + cfg = Config(od1) + assert parse_od_get(cfg.value.get()) == {'variable1.variable1': []} + cfg.option('variable1.variable1').value.set(['val1', 'val2']) + cfg.option('variable1.variable2', 0).value.set('ival1') + cfg.option('variable1.variable2', 1).value.set('ival2') + assert cfg.option('variable1.variable3', 1).owner.get() == 'user' + assert cfg.option('variable1.variable3', 1).value.get() == 'ival2' + assert parse_od_get(cfg.value.get()) == {'variable1.variable1': [{'variable1.variable1': 'val1', + 'variable1.variable2': 'ival1', + 'variable1.variable3': 'ival1'}, + {'variable1.variable1': 'val2', + 'variable1.variable2': 'ival2', + 'variable1.variable3': 'ival2'}], + } + def test_symlink_with_leader(config_type): diff --git a/tiramisu/api.py b/tiramisu/api.py index 610d026..d92c815 100644 --- a/tiramisu/api.py +++ b/tiramisu/api.py @@ -436,6 +436,8 @@ class _TiramisuOptionOption(_TiramisuOptionOptionDescription): need_help=True, validate_properties=self._validate_properties, ) + if isinstance(subconfig, list): + raise ConfigError(_('cannot get option from a follower symlink without index')) subconfig.true_path = subconfig.path return TiramisuOption(subconfig.path, subconfig.index, @@ -1149,8 +1151,8 @@ class TiramisuContextProperty(TiramisuConfig, PropertyPermissive): settings._properties = deepcopy(properties) settings.ro_append = data['ro_append'].copy() settings.ro_remove = data['ro_remove'].copy() - settings.ro_append = data['rw_append'].copy() - settings.ro_remove = data['rw_remove'].copy() + settings.rw_append = data['rw_append'].copy() + settings.rw_remove = data['rw_remove'].copy() context.reset_cache(None, None) self._reset_config_properties(settings) if force_store_value: diff --git a/tiramisu/config.py b/tiramisu/config.py index c61ff4c..5ce7947 100644 --- a/tiramisu/config.py +++ b/tiramisu/config.py @@ -298,7 +298,7 @@ class SubConfig: *, uncalculated: bool=False, ): - if self.option.impl_is_leadership(): + if self.option.impl_is_leadership() and not uncalculated: yield from self.get_leadership_children(validate_properties) else: for child in self.option.get_children(): @@ -357,7 +357,6 @@ class SubConfig: ) if check_index and index is not None: if option.impl_is_optiondescription() or \ - option.impl_is_symlinkoption() or \ not option.impl_is_follower(): raise ConfigError('index must be set only with a follower option') length = self.get_length_leadership() @@ -735,6 +734,7 @@ class _Config(CCache): :return: option's value if name is an option name, OptionDescription otherwise """ + original_index = subconfig.index subconfig = self._get(subconfig, need_help, ) @@ -769,6 +769,8 @@ class _Config(CCache): self.get_settings().validate_mandatory(subconfig, value, ) + if original_index != subconfig.index: + value = value[original_index] return value def _get(self, @@ -787,7 +789,7 @@ class _Config(CCache): true_path=subconfig.path, validate_properties=validate_properties, ) - if suboption.impl_is_follower(): + if suboption.impl_is_follower() and subconfig.index is None: subconfig = self.get_sub_config(subconfig.config_bag, # pylint: disable=no-member suboption.impl_getpath(), None, @@ -805,9 +807,13 @@ class _Config(CCache): )) return ret + if suboption.impl_is_leader(): + index = None + else: + index = subconfig.index s_subconfig = self.get_sub_config(subconfig.config_bag, # pylint: disable=no-member suboption.impl_getpath(), - None, + index, validate_properties=validate_properties, true_path=subconfig.path, ) diff --git a/tiramisu/error.py b/tiramisu/error.py index 34956ba..ad109b2 100644 --- a/tiramisu/error.py +++ b/tiramisu/error.py @@ -181,7 +181,7 @@ class _CommonError: msg = self.prefix except AttributeError: self.prefix = self.tmpl.format(self.val, - self.display_type, + _(self.display_type), self.name) msg = self.prefix if self.err_msg: diff --git a/tiramisu/function.py b/tiramisu/function.py index c02b542..1d487f0 100644 --- a/tiramisu/function.py +++ b/tiramisu/function.py @@ -577,7 +577,7 @@ class CalcValuePropertyHelp(CalcValue): else: calc_values = [calculated_expected] display_value = display_list([str(val) for val in calc_values], - 'or', + separator='or', add_quote=True) msg = self.build_property_message(name, display_value) else: @@ -585,7 +585,7 @@ class CalcValuePropertyHelp(CalcValue): for key, value in calculated_expected.items(): name = self.get_indexed_name(key) msgs.append(self.build_property_message(name, f'"{value}"')) - msg = display_list(msgs, self.condition_operator.lower()) + msg = display_list(msgs, separator=self.condition_operator.lower()) return [(action, f'"{action}" ({msg})')] diff --git a/tiramisu/locale/fr/LC_MESSAGES/tiramisu.po b/tiramisu/locale/fr/LC_MESSAGES/tiramisu.po index 9e9cea3..91316b2 100644 --- a/tiramisu/locale/fr/LC_MESSAGES/tiramisu.po +++ b/tiramisu/locale/fr/LC_MESSAGES/tiramisu.po @@ -606,8 +606,8 @@ msgid "integer" msgstr "nombre" #: tiramisu/option/intoption.py:55 -msgid "value must be greater than \"{0}\"" -msgstr "valeur doit être supérieur à {0}" +msgid "value must be equal or greater than \"{0}\"" +msgstr "valeur doit être supérieur ou égal à {0}" #: tiramisu/option/intoption.py:58 msgid "value must be less than \"{0}\"" diff --git a/tiramisu/option/intoption.py b/tiramisu/option/intoption.py index 9501d2b..2e95fc0 100644 --- a/tiramisu/option/intoption.py +++ b/tiramisu/option/intoption.py @@ -54,9 +54,9 @@ class IntOption(Option): min_number = self.impl_get_extra('min_number') if min_number is not None and value < min_number: if warnings_only: - msg = 'value should be greater than "{0}"' + msg = 'value should be equal or greater than "{0}"' else: - msg = 'value must be greater than "{0}"' + msg = 'value must be equal or greater than "{0}"' raise ValueError(_(msg).format(min_number)) max_number = self.impl_get_extra('max_number') if max_number is not None and value > max_number: diff --git a/tiramisu/option/leadership.py b/tiramisu/option/leadership.py index 18f109d..8398f3e 100644 --- a/tiramisu/option/leadership.py +++ b/tiramisu/option/leadership.py @@ -57,10 +57,9 @@ class Leadership(OptionDescription): if len(children) < 2: raise ValueError(_('a leader and a follower are mandatories in leadership "{}"' '').format(name)) - leader = children[0] for idx, child in enumerate(children): if __debug__: - self._check_child_is_valid(child) + self._check_child_is_valid(child, idx, children) if idx != 0: if __debug__: self._check_default_value(child) @@ -70,14 +69,21 @@ class Leadership(OptionDescription): child._add_dependency(self) child._leadership = weakref.ref(self) if __debug__: + leader = children[0] for prop in leader.impl_getproperties(): if prop not in ALLOWED_LEADER_PROPERTIES and not isinstance(prop, Calculation): raise LeadershipError(_('leader cannot have "{}" property').format(prop)) - def _check_child_is_valid(self, child: BaseOption): + def _check_child_is_valid(self, + child: BaseOption, + index: int, + children: [BaseOption], + ) -> None: if child.impl_is_symlinkoption(): - raise ValueError(_('leadership "{0}" shall not have ' - "a symlinkoption").format(self.impl_get_display_name(None))) + if not index: + raise ValueError(_('leadership "{0}" shall not have ' + "a symlinkoption").format(self.impl_get_display_name(None))) + return if not isinstance(child, Option): raise ValueError(_('leadership "{0}" shall not have ' 'a subgroup').format(self.impl_get_display_name(None))) @@ -88,6 +94,8 @@ class Leadership(OptionDescription): child.impl_get_display_name(None))) def _check_default_value(self, child: BaseOption): + if child.impl_is_symlinkoption(): + return default = child.impl_getdefault() if default != []: if child.impl_is_submulti() and isinstance(default, (list, tuple)): @@ -257,12 +265,3 @@ class Leadership(OptionDescription): def impl_is_leadership(self) -> None: return True -# -# def to_dynoption(self, -# rootpath: str, -# suffixes: Optional[list], -# ) -> SynDynLeadership: -# return SynDynLeadership(self, -# rootpath, -# suffixes, -# ) diff --git a/tiramisu/option/symlinkoption.py b/tiramisu/option/symlinkoption.py index c84482d..8d29bbc 100644 --- a/tiramisu/option/symlinkoption.py +++ b/tiramisu/option/symlinkoption.py @@ -29,7 +29,9 @@ from ..i18n import _ class SymLinkOption(BaseOption): """SymLinkOption link to an other option """ - __slots__ = ('_opt',) + __slots__ = ('_opt', + '_leadership', + ) def __init__(self, name: str, @@ -44,6 +46,7 @@ class SymLinkOption(BaseOption): raise ValueError(_(f'malformed symlink second parameters must be an option for "{name}", not {opt}')) self._name = name self._opt = opt + self._leadership = None opt._add_dependency(self) def __getattr__(self, @@ -63,8 +66,13 @@ class SymLinkOption(BaseOption): def impl_is_leader(self) -> bool: return False - def impl_is_follower(self) -> bool: - return False + def impl_is_follower(self): + """check if option is a leader in a follower + """ + leadership = self._leadership + if leadership is None: + return False + return not leadership().is_leader(self) def impl_getopt(self) -> BaseOption: """get to linked option