diff --git a/tests/test_dyn_optiondescription.py b/tests/test_dyn_optiondescription.py index b20d53f..d287e3f 100644 --- a/tests/test_dyn_optiondescription.py +++ b/tests/test_dyn_optiondescription.py @@ -1851,3 +1851,19 @@ async def test_dyn_leadership_mandatory(): async with await Config(od) as cfg: await cfg.value.mandatory() assert not await list_sessions() + + +@pytest.mark.asyncio +async def test_dyn_symlink(): + remotes = StrOption("remotes", "Remotes", ['a', 'b', 'c'], multi=True) + remote_ip = StrOption("remote_ip_", "Remote IP", Calculation(calc_value, Params(ParamSuffix()))) + dyn_remote = DynOptionDescription("remote_", "Account for ", suffixes=Calculation(calc_value, Params((ParamOption(remotes)))), children=[remote_ip]) + name = SymLinkOption("name", opt=remote_ip) + accounts = OptionDescription(name="accounts", doc="accounts.remote_.remote_ip_", children=[remotes, dyn_remote, name]) + + async with await Config(accounts) as config: + assert await config.option('name').value.get() == ['a', 'b', 'c'] + assert await config.option('name').option.ismulti() == True + assert await config.option('name').option.issubmulti() == False + assert await config.value.dict() == {'remotes': ['a', 'b', 'c'], 'remote_a.remote_ip_a': 'a', 'remote_b.remote_ip_b': 'b', 'remote_c.remote_ip_c': 'c', 'name': ['a', 'b', 'c']} + assert not await list_sessions() diff --git a/tiramisu/config.py b/tiramisu/config.py index 03be2c8..b7796e0 100644 --- a/tiramisu/config.py +++ b/tiramisu/config.py @@ -296,15 +296,41 @@ class SubConfig: option = option_bag.option if option.impl_is_symlinkoption(): + suboption = option.impl_getopt() + if suboption.issubdyn(): + dynopt = suboption.getsubdyn() + rootpath = dynopt.impl_getpath() + subpaths = [rootpath] + suboption.impl_getpath()[len(rootpath) + 1:].split('.')[:-1] + ret = [] + for suffix in await dynopt.get_suffixes(option_bag.config_bag): + path_suffix = dynopt.convert_suffix_to_path(suffix) + subpath = '.'.join([subp + path_suffix for subp in subpaths]) + doption = suboption.to_dynoption(subpath, + suffix, + dynopt) + 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) + doption_bag.ori_option = option + context = self.cfgimpl_get_context() + ret.append(await context.getattr(doption_bag.path, + doption_bag, + )), + return ret soption_bag = OptionBag() - soption_bag.set_option(option.impl_getopt(), + soption_bag.set_option(suboption, option_bag.index, - config_bag) + config_bag, + ) soption_bag.properties = await self.cfgimpl_get_settings().getproperties(soption_bag) soption_bag.ori_option = option context = self.cfgimpl_get_context() return await context.getattr(soption_bag.path, - soption_bag) + soption_bag, + ) #if not from_follower or needs_re_verify_follower_properties: if option.impl_is_follower() and not from_follower: diff --git a/tiramisu/option/symlinkoption.py b/tiramisu/option/symlinkoption.py index 95ff08a..262e903 100644 --- a/tiramisu/option/symlinkoption.py +++ b/tiramisu/option/symlinkoption.py @@ -43,7 +43,8 @@ class SymLinkOption(BaseOption): self._path = None def __getattr__(self, - name: str) -> Any: + name: str, + ) -> Any: return getattr(self._opt, name) def impl_has_dependency(self, @@ -58,3 +59,16 @@ class SymLinkOption(BaseOption): def impl_getopt(self) -> BaseOption: return self._opt + + def issubdyn(self) -> bool: + return False + + def impl_is_multi(self) -> bool: + if self._opt.issubdyn(): + return True + return self._opt.impl_is_multi() + + def impl_is_submulti(self) -> bool: + if self._opt.issubdyn() and self._opt.impl_is_multi(): + return True + return self._opt.impl_is_submulti()