diff --git a/tests/test_leadership.py b/tests/test_leadership.py index 3f8c34a..f2a8f9b 100644 --- a/tests/test_leadership.py +++ b/tests/test_leadership.py @@ -388,7 +388,28 @@ async def test_groups_with_leader_hidden_in_config(): await cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() with pytest.raises(PropertiesOptionError): await cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() - await cfg.value.dict(leader_to_list=True) == {'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': '192.168.1.1'}]} + assert await cfg.value.dict() == {} + assert await cfg.value.dict(leader_to_list=True) == {} + assert not await list_sessions() + + +async def test_groups_with_leader_hidden_in_config2(): + ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True) + netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, properties=('hidden',)) + interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + od = OptionDescription('root', '', [interface1]) + async with await Config(od) as cfg: + await cfg.property.read_write() + await cfg.permissive.add('hidden') + assert await cfg.forcepermissive.option('ip_admin_eth0.ip_admin_eth0').value.get() == [] + await cfg.forcepermissive.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.1']) + assert await cfg.forcepermissive.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None + with pytest.raises(PropertiesOptionError): + await cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() + with pytest.raises(PropertiesOptionError): + await cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() + assert await cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': ['192.168.1.1']} + assert await cfg.value.dict(leader_to_list=True) == {'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': '192.168.1.1'}]} assert not await list_sessions() diff --git a/tiramisu/config.py b/tiramisu/config.py index cd793d9..c9a34a9 100644 --- a/tiramisu/config.py +++ b/tiramisu/config.py @@ -111,19 +111,12 @@ class SubConfig: for woption in option_bag.option._get_dependencies(self.cfgimpl_get_description()): option = woption() if option.impl_is_dynoptiondescription(): - subpath = option.impl_getpath().rsplit('.', 1)[0] + path = option.impl_getpath() + if '.' in path: + subpath = option.impl_getpath().rsplit('.', 1)[0] + else: + subpath = '' for suffix in await option.get_suffixes(option_bag.config_bag): - doption = option.to_dynoption(subpath, - suffix, - option) - doption_bag = OptionBag() - doption_bag.set_option(doption, - option_bag.index, - option_bag.config_bag) - doption_bag.properties = await self.cfgimpl_get_settings().getproperties(doption_bag) - await self.reset_one_option_cache(desc, - resetted_opts, - doption_bag) async for coption in self.cfgimpl_get_description().get_children_recursively(None, None, option_bag.config_bag): @@ -131,11 +124,20 @@ class SubConfig: coption_bag.set_option(coption, option_bag.index, option_bag.config_bag) - coption_bag.properties = await self.cfgimpl_get_settings().getproperties(coption_bag) await self.reset_one_option_cache(option, resetted_opts, coption_bag, ) + doption = option.to_dynoption(subpath, + suffix, + option) + doption_bag = OptionBag() + doption_bag.set_option(doption, + option_bag.index, + option_bag.config_bag) + await self.reset_one_option_cache(desc, + resetted_opts, + doption_bag) elif option.issubdyn(): # it's an option in dynoptiondescription, remove cache for all generated option dynopt = option.getsubdyn() @@ -151,7 +153,7 @@ class SubConfig: doption_bag.set_option(doption, option_bag.index, option_bag.config_bag) - doption_bag.properties = await self.cfgimpl_get_settings().getproperties(doption_bag) + #doption_bag.properties = await self.cfgimpl_get_settings().getproperties(doption_bag) await self.reset_one_option_cache(desc, resetted_opts, doption_bag) @@ -180,9 +182,16 @@ class SubConfig: context = self.cfgimpl_get_context() desc = context.cfgimpl_get_description() if option_bag is not None: + if 'cache' in option_bag.config_bag.properties: + has_cache = True + option_bag.config_bag.properties = option_bag.config_bag.properties - {'cache'} + else: + has_cache = False await self.reset_one_option_cache(desc, resetted_opts, option_bag) + if has_cache: + option_bag.config_bag.properties = option_bag.config_bag.properties | {'cache'} else: context._impl_values_cache.reset_all_cache() context._impl_properties_cache.reset_all_cache() @@ -435,6 +444,18 @@ class SubConfig: for opt in await self.cfgimpl_get_description().get_children(config_bag): if leader_to_list and opt.impl_is_optiondescription() and opt.impl_is_leadership(): # leader + try: + loption_bag = OptionBag() + loption_bag.set_option(opt, + None, + config_bag) + loption_bag.properties = await self.cfgimpl_get_settings().getproperties(loption_bag) + await self.cfgimpl_get_settings().validate_properties(loption_bag, + need_help=False) + except PropertiesOptionError as err: + if err.proptype in (['mandatory'], ['empty']): + raise err + continue children = await opt.get_children(config_bag) leader = children[0] loption_bag = OptionBag() diff --git a/tiramisu/option/optiondescription.py b/tiramisu/option/optiondescription.py index 10d1af9..c66fb57 100644 --- a/tiramisu/option/optiondescription.py +++ b/tiramisu/option/optiondescription.py @@ -187,7 +187,8 @@ class OptionDescriptionWalk(CacheOptionDescription): async def get_children(self, config_bag: Union[ConfigBag, Undefined], - dyn: bool=True) -> Union[BaseOption, SynDynOptionDescription]: + dyn: bool=True, + ) -> Union[BaseOption, SynDynOptionDescription]: if not dyn or config_bag is undefined or \ config_bag.context.cfgimpl_get_description() == self: subpath = ''