feat: dynamic family can have sub family

This commit is contained in:
egarette@silique.fr 2023-11-19 13:40:55 +01:00
parent 059c5f7407
commit 6b473e63f2
8 changed files with 153 additions and 103 deletions

View file

@ -1434,7 +1434,7 @@ def test_leadership_dyndescription_param_follower():
# assert not list_sessions() # assert not list_sessions()
def test_leadership_default_multi_dyndescription(): def test_leadership_default_multi_dyndescription_sub():
st1 = StrOption('st1', "", multi=True) st1 = StrOption('st1', "", multi=True)
st2 = StrOption('st2', "", multi=True, default_multi='no') st2 = StrOption('st2', "", multi=True, default_multi='no')
stm = Leadership('st1', '', [st1, st2]) stm = Leadership('st1', '', [st1, st2])
@ -1628,12 +1628,46 @@ def test_invalid_conflict_dyndescription():
# assert not list_sessions() # assert not list_sessions()
def test_invalid_subod_dyndescription(): #def test_invalid_subod_dyndescription():
st2 = StrOption('st2', '') # st2 = StrOption('st2', '')
od1 = OptionDescription('od1', '', [st2]) # od1 = OptionDescription('od1', '', [st2])
od1 # od1
with pytest.raises(ConfigError): # with pytest.raises(ConfigError):
DynOptionDescription('dod', '', [od1], suffixes=Calculation(return_list)) # DynOptionDescription('dod', '', [od1], suffixes=Calculation(return_list))
## assert not list_sessions()
#
#
def test_leadership_default_multi_dyndescription():
st1 = StrOption('st1', "", multi=True)
st2 = StrOption('st2', "", multi=True, default_multi='no')
stm = Leadership('st1', '', [st1, st2])
od1 = OptionDescription('od1', '', [stm])
st = DynOptionDescription('st', '', [od1], suffixes=Calculation(return_list))
od = OptionDescription('od', '', [st])
od1 = OptionDescription('od', '', [od])
cfg = Config(od1)
owner = cfg.owner.get()
#
assert cfg.value.get() == {'od.stval1.od1.st1.st1': [],
'od.stval2.od1.st1.st1': [],
}
assert cfg.option('od.stval1.od1.st1.st1').value.get() == []
assert cfg.option('od.stval2.od1.st1.st1').value.get() == []
assert cfg.option('od.stval1.od1.st1.st1').owner.isdefault()
assert cfg.option('od.stval2.od1.st1.st1').owner.isdefault()
#
cfg.option('od.stval1.od1.st1.st1').value.set(['yes'])
assert cfg.option('od.stval1.od1.st1.st1').value.get() == ['yes']
assert cfg.option('od.stval1.od1.st1.st2', 0).value.get() == 'no'
assert cfg.option('od.stval2.od1.st1.st1').value.get() == []
assert cfg.option('od.stval1.od1.st1.st1').owner.get() == owner
assert cfg.option('od.stval1.od1.st1.st2', 0).owner.isdefault()
assert cfg.option('od.stval2.od1.st1.st1').owner.isdefault()
assert cfg.value.get() == {'od.stval1.od1.st1.st1': [],
'od.stval1.od1.st1.st1': [{'od.stval1.od1.st1.st1': 'yes',
'od.stval1.od1.st1.st2': 'no'}],
'od.stval2.od1.st1.st1': [],
}
# assert not list_sessions() # assert not list_sessions()

View file

@ -430,13 +430,11 @@ def manager_callback(callback: Callable,
if callbk_option.issubdyn(): if callbk_option.issubdyn():
found = False found = False
if isinstance(param, ParamDynOption): if isinstance(param, ParamDynOption):
subdyn = param.dynoptiondescription soption_bag = param.dynoptiondescription.get_sub_child(callbk_option,
rootpath = subdyn.impl_getpath() + param.suffix param.suffix,
suffix = param.suffix config_bag,
callbk_option = callbk_option.to_dynoption(rootpath,
suffix,
subdyn,
) )
callbk_option = soption_bag.option
found = True found = True
elif option.impl_is_dynsymlinkoption(): elif option.impl_is_dynsymlinkoption():
rootpath = option.rootpath rootpath = option.rootpath
@ -454,16 +452,11 @@ def manager_callback(callback: Callable,
found = True found = True
if not found: if not found:
callbk_options = [] callbk_options = []
dynopt = callbk_option.getsubdyn() for doption_bag in callbk_option.getsubdyn().get_sub_children(callbk_option,
rootpath = dynopt.impl_getpath() config_bag,
subpaths = [rootpath] + callbk_option.impl_getpath()[len(rootpath) + 1:].split('.')[:-1] None,
for suffix in dynopt.get_suffixes(config_bag): ):
path_suffix = dynopt.convert_suffix_to_path(suffix) callbk_options.append(doption_bag.option)
subpath = '.'.join([subp + path_suffix for subp in subpaths])
doption = callbk_option.to_dynoption(subpath,
suffix,
dynopt)
callbk_options.append(doption)
if callbk_options is None: if callbk_options is None:
callbk_options = [callbk_option] callbk_options = [callbk_option]
values = None values = None

View file

@ -161,23 +161,12 @@ class _SubConfig:
resetted_opts, resetted_opts,
): ):
# reset cache for all chidren # reset cache for all chidren
path = option_bag.option.impl_getpath() for doption_bag in option_bag.option.get_sub_children(option_bag.option,
if '.' in path:
subpath = path.rsplit('.', 1)[0]
else:
subpath = ''
for suffix in option_bag.option.get_suffixes(option_bag.config_bag):
doption = option_bag.option.to_dynoption(subpath,
suffix,
option_bag.option,
)
doption_bag = OptionBag(doption,
option_bag.index,
option_bag.config_bag, option_bag.config_bag,
option_bag.index,
properties=None, properties=None,
) ):
for coption in doption.get_children_recursively(None, for coption in doption_bag.option.get_children_recursively(None,
None, None,
option_bag.config_bag, option_bag.config_bag,
): ):

View file

@ -22,7 +22,7 @@
""" """
import re import re
import weakref import weakref
from typing import List, Any from typing import List, Any, Optional
from itertools import chain from itertools import chain
from ..autolib import ParamOption from ..autolib import ParamOption
@ -125,18 +125,50 @@ class DynOptionDescription(OptionDescription):
index=None, index=None,
properties=undefined, properties=undefined,
): ):
if option == self: rootpath = self.get_root_path(option)
rootpath = self.impl_getpath().rsplit('.', 1)[0] subpath = self.get_sub_path(option)
else:
rootpath = self.impl_getpath()
subpath = option.impl_getpath()[len(rootpath):].rsplit('.', 1)[0]
for suffix in self.get_suffixes(config_bag): for suffix in self.get_suffixes(config_bag):
path_suffix = self.convert_suffix_to_path(suffix) yield self.get_sub_child(option,
suffix,
config_bag,
index=index,
rootpath=rootpath,
subpath=subpath,
properties=properties,
)
def get_root_path(self, option):
path = self.impl_getpath()
rootpath = path.rsplit('.', 1)[0] if '.' in path else ''
if option != self:
if rootpath:
rootpath += '.'
return rootpath
def get_sub_path(self, option):
if option != self:
return option.impl_getpath()[len(self.impl_getpath()):].rsplit('.', 1)[0]
return None
def get_sub_child(self,
option,
suffix,
config_bag,
*,
index: Optional[int]=None,
rootpath: Optional[str]=None,
subpath: Optional[str]=None,
properties: Optional[str]=None,
):
if rootpath is None:
rootpath = self.get_root_path(option)
if option == self: if option == self:
parent_path = rootpath parent_path = rootpath
else: else:
parent_path = rootpath + path_suffix + subpath if subpath is None:
doption_bag = OptionBag(option.to_dynoption(parent_path, subpath = self.get_sub_path(option)
parent_path = rootpath + self.impl_getname(suffix) + subpath
return OptionBag(option.to_dynoption(parent_path,
suffix, suffix,
self, self,
), ),
@ -145,4 +177,18 @@ class DynOptionDescription(OptionDescription):
properties=properties, properties=properties,
ori_option=option ori_option=option
) )
yield doption_bag
def _setsubdyn(self,
subdyn,
) -> None:
raise ConfigError(_('cannot set a dynoptiondescription in a '
'dynoptiondescription'))
def impl_getname(self, suffix=None) -> str:
"""get name
"""
name = super().impl_getname()
if suffix is None:
return name
path_suffix = self.convert_suffix_to_path(suffix)
return name + path_suffix

View file

@ -320,12 +320,6 @@ class OptionDescription(OptionDescriptionWalk):
# the group_type is useful for filtering OptionDescriptions in a config # the group_type is useful for filtering OptionDescriptions in a config
self._group_type = groups.default self._group_type = groups.default
def _setsubdyn(self,
subdyn,
) -> None:
raise ConfigError(_('cannot set optiondescription in a '
'dynoptiondescription'))
def impl_is_optiondescription(self) -> bool: def impl_is_optiondescription(self) -> bool:
"""the option is an option description """the option is an option description
""" """

View file

@ -54,7 +54,6 @@ class SynDynOption:
"""get option name """get option name
""" """
return self.opt.impl_getname() return self.opt.impl_getname()
#return self.opt.impl_getname() + self.dyn_parent.convert_suffix_to_path(self.suffix)
def impl_get_display_name(self) -> str: def impl_get_display_name(self) -> str:
"""get option display name """get option display name

View file

@ -81,9 +81,15 @@ class SynDynOptionDescription:
def impl_getname(self) -> str: def impl_getname(self) -> str:
"""get name """get name
""" """
if isinstance(self, SynDynLeadership): if self.opt.impl_is_dynoptiondescription():
return self.opt.impl_getname(self._suffix)
return self.opt.impl_getname() return self.opt.impl_getname()
return self.opt.impl_getname() + self.ori_dyn.convert_suffix_to_path(self._suffix)
def impl_get_display_name(self) -> str:
"""get display name
"""
if self.opt.impl_is_dynoptiondescription():
return self.opt.impl_get_display_name() + str(self._suffix)
def get_children(self, def get_children(self,
config_bag: ConfigBag, config_bag: ConfigBag,
@ -130,11 +136,6 @@ class SynDynOptionDescription:
path = f'{self.rootpath}.{path}' path = f'{self.rootpath}.{path}'
return path return path
def impl_get_display_name(self) -> str:
"""get display name
"""
return self.opt.impl_get_display_name() + str(self._suffix)
class SynDynLeadership(SynDynOptionDescription): class SynDynLeadership(SynDynOptionDescription):
"""SynDynLeadership internal option, it's an instanciate synoptiondescription """SynDynLeadership internal option, it's an instanciate synoptiondescription

View file

@ -359,14 +359,7 @@ class Values:
force_store_options.append(coption) force_store_options.append(coption)
if not force_store_options: if not force_store_options:
continue continue
rootpath = option.impl_getpath()
for suffix in option.get_suffixes(option_bag.config_bag):
for coption in force_store_options: for coption in force_store_options:
parent_subpath = rootpath + suffix + coption.impl_getpath()[len(rootpath):].rsplit('.', 1)[0]
doption = coption.to_dynoption(parent_subpath,
suffix,
option,
)
if coption.impl_is_follower(): if coption.impl_is_follower():
leader = coption.impl_get_leadership().get_leader() leader = coption.impl_get_leadership().get_leader()
loption_bag = OptionBag(leader, loption_bag = OptionBag(leader,
@ -378,10 +371,11 @@ class Values:
else: else:
indexes = [None] indexes = [None]
for index in indexes: for index in indexes:
coption_bag = OptionBag(doption, for coption_bag in option.get_sub_children(coption,
index,
option_bag.config_bag, option_bag.config_bag,
) index,
properties=frozenset(),
):
default_value = [self.get_value(coption_bag)[0], owners.forced] default_value = [self.get_value(coption_bag)[0], owners.forced]
self._values.setdefault(coption_bag.path, {})[index] = default_value self._values.setdefault(coption_bag.path, {})[index] = default_value