can convert suffix to build path for dynoptiondescription
This commit is contained in:
parent
0cb69f7a85
commit
76e7fd93b2
9 changed files with 195 additions and 43 deletions
|
@ -14,6 +14,12 @@ from tiramisu.error import PropertiesOptionError, ConfigError, ConflictError
|
|||
from tiramisu.storage import list_sessions
|
||||
|
||||
|
||||
class ConvertDynOptionDescription(DynOptionDescription):
|
||||
def convert_suffix_to_path(self, suffix):
|
||||
# remove dot with is illegal
|
||||
return suffix.replace('.', '')
|
||||
|
||||
|
||||
def teardown_function(function):
|
||||
assert list_sessions() == [], 'session list is not empty when leaving "{}"'.format(function.__name__)
|
||||
|
||||
|
@ -39,6 +45,10 @@ def return_list(val=None, suffix=None):
|
|||
return ['val1', 'val2']
|
||||
|
||||
|
||||
def return_list_dot(val=None, suffix=None):
|
||||
return ['val.1', 'val.2']
|
||||
|
||||
|
||||
def return_same_list(*args, **kwargs):
|
||||
return ['val1', 'val1']
|
||||
|
||||
|
@ -911,6 +921,7 @@ def test_leadership_default_multi_dyndescription():
|
|||
assert api.option('od.stval1.st1val1.st2val1', 0).owner.isdefault()
|
||||
assert api.option('od.stval2.st1val2.st1val2').owner.isdefault()
|
||||
|
||||
|
||||
def test_leadership_dyndescription_param():
|
||||
val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
||||
odval = OptionDescription('odval1', '', [val1])
|
||||
|
@ -1344,3 +1355,107 @@ def test_invalid_name_dyndescription():
|
|||
od1 = OptionDescription('od', '', [dod])
|
||||
cfg = Config(od1)
|
||||
raises(ValueError, "cfg.value.dict()")
|
||||
|
||||
|
||||
def test_leadership_dyndescription_convert():
|
||||
st1 = StrOption('st1', "", multi=True)
|
||||
st2 = StrOption('st2', "", multi=True)
|
||||
stm = Leadership('st1', '', [st1, st2])
|
||||
st = ConvertDynOptionDescription('st', '', [stm], suffixes=Calculation(return_list_dot))
|
||||
od = OptionDescription('od', '', [st])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
api = Config(od2)
|
||||
owner = api.owner.get()
|
||||
#
|
||||
assert api.value.dict() == {'od.stval1.st1val1.st2val1': [], 'od.stval2.st1val2.st2val2': [], 'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': []}
|
||||
assert api.option('od.stval1.st1val1.st1val1').value.get() == []
|
||||
assert api.option('od.stval2.st1val2.st1val2').value.get() == []
|
||||
assert api.option('od.stval1.st1val1.st1val1').owner.isdefault()
|
||||
assert api.option('od.stval2.st1val2.st1val2').owner.isdefault()
|
||||
#
|
||||
api.option('od.stval1.st1val1.st1val1').value.set(['yes'])
|
||||
assert api.value.dict() == {'od.stval1.st1val1.st2val1': [None], 'od.stval2.st1val2.st2val2': [], 'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': ['yes']}
|
||||
assert api.option('od.stval1.st1val1.st1val1').value.get() == ['yes']
|
||||
assert api.option('od.stval1.st1val1.st2val1', 0).value.get() == None
|
||||
assert api.option('od.stval2.st1val2.st1val2').value.get() == []
|
||||
assert api.option('od.stval1.st1val1.st1val1').owner.get() == owner
|
||||
assert api.option('od.stval1.st1val1.st2val1', 0).owner.isdefault()
|
||||
assert api.option('od.stval2.st1val2.st1val2').owner.isdefault()
|
||||
#
|
||||
api.option('od.stval1.st1val1.st2val1', 0).value.set('no')
|
||||
assert api.option('od.stval1.st1val1.st1val1').value.get() == ['yes']
|
||||
assert api.option('od.stval1.st1val1.st2val1', 0).value.get() == 'no'
|
||||
assert api.option('od.stval2.st1val2.st1val2').value.get() == []
|
||||
assert api.option('od.stval1.st1val1.st1val1').owner.get() == owner
|
||||
assert api.option('od.stval1.st1val1.st2val1', 0).owner.get() == owner
|
||||
assert api.option('od.stval2.st1val2.st1val2').owner.isdefault()
|
||||
#
|
||||
api.option('od.stval1.st1val1.st1val1').value.pop(0)
|
||||
assert api.option('od.stval1.st1val1.st1val1').value.get() == []
|
||||
assert api.option('od.stval2.st1val2.st1val2').value.get() == []
|
||||
assert api.option('od.stval1.st1val1.st1val1').owner.get() == owner
|
||||
assert api.option('od.stval2.st1val2.st1val2').owner.isdefault()
|
||||
#
|
||||
api.option('od.stval1.st1val1.st1val1').value.set(['yes'])
|
||||
api.option('od.stval1.st1val1.st2val1', 0).value.set('yes')
|
||||
assert api.option('od.stval1.st1val1.st1val1').owner.get() == owner
|
||||
assert api.option('od.stval1.st1val1.st2val1', 0).owner.get() == owner
|
||||
assert api.option('od.stval2.st1val2.st1val2').owner.isdefault()
|
||||
assert api.option('od.stval1.st1val1.st1val1').owner.get() == owner
|
||||
api.option('od.stval1.st1val1.st2val1', 0).value.reset()
|
||||
assert api.option('od.stval1.st1val1.st1val1').owner.get() == owner
|
||||
assert api.option('od.stval1.st1val1.st2val1', 0).owner.isdefault()
|
||||
#
|
||||
api.option('od.stval1.st1val1.st1val1').value.set(['yes'])
|
||||
api.option('od.stval1.st1val1.st2val1', 0).value.set('yes')
|
||||
api.option('od.stval1.st1val1.st1val1').value.reset()
|
||||
assert api.option('od.stval1.st1val1.st1val1').value.get() == []
|
||||
assert api.option('od.stval2.st1val2.st1val2').value.get() == []
|
||||
assert api.option('od.stval1.st1val1.st1val1').owner.isdefault()
|
||||
assert api.option('od.stval2.st1val2.st1val2').owner.isdefault()
|
||||
|
||||
|
||||
def test_leadership_callback_samegroup_dyndescription_convert():
|
||||
st1 = StrOption('st1', "", multi=True)
|
||||
st2 = StrOption('st2', "", multi=True)
|
||||
st3 = StrOption('st3', "", Calculation(return_dynval, Params(ParamOption(st2))), multi=True)
|
||||
stm = Leadership('st1', '', [st1, st2, st3])
|
||||
stt = ConvertDynOptionDescription('st', '', [stm], suffixes=Calculation(return_list_dot))
|
||||
od1 = OptionDescription('od', '', [stt])
|
||||
od2 = OptionDescription('od', '', [od1])
|
||||
api = Config(od2)
|
||||
owner = api.owner.get()
|
||||
assert api.value.dict() == {'od.stval1.st1val1.st1val1': [],
|
||||
'od.stval1.st1val1.st2val1': [],
|
||||
'od.stval1.st1val1.st3val1': [],
|
||||
'od.stval2.st1val2.st1val2': [],
|
||||
'od.stval2.st1val2.st2val2': [],
|
||||
'od.stval2.st1val2.st3val2': []}
|
||||
assert api.option('od.stval1.st1val1.st1val1').value.get() == []
|
||||
assert api.option('od.stval2.st1val2.st1val2').value.get() == []
|
||||
assert api.option('od.stval1.st1val1.st1val1').owner.isdefault()
|
||||
assert api.option('od.stval2.st1val2.st1val2').owner.isdefault()
|
||||
#
|
||||
api.option('od.stval1.st1val1.st1val1').value.set(['yes'])
|
||||
assert api.value.dict() == {'od.stval1.st1val1.st1val1': ['yes'],
|
||||
'od.stval1.st1val1.st2val1': [None],
|
||||
'od.stval1.st1val1.st3val1': [None],
|
||||
'od.stval2.st1val2.st1val2': [],
|
||||
'od.stval2.st1val2.st2val2': [],
|
||||
'od.stval2.st1val2.st3val2': []}
|
||||
assert api.option('od.stval1.st1val1.st1val1').owner.get() == owner
|
||||
assert api.option('od.stval1.st1val1.st2val1', 0).owner.isdefault()
|
||||
assert api.option('od.stval1.st1val1.st3val1', 0).owner.isdefault()
|
||||
assert api.option('od.stval2.st1val2.st1val2').owner.isdefault()
|
||||
#
|
||||
api.option('od.stval1.st1val1.st2val1', 0).value.set('yes')
|
||||
assert api.value.dict() == {'od.stval1.st1val1.st1val1': ['yes'],
|
||||
'od.stval1.st1val1.st2val1': ['yes'],
|
||||
'od.stval1.st1val1.st3val1': ['yes'],
|
||||
'od.stval2.st1val2.st1val2': [],
|
||||
'od.stval2.st1val2.st2val2': [],
|
||||
'od.stval2.st1val2.st3val2': []}
|
||||
assert api.option('od.stval1.st1val1.st1val1').owner.get() == owner
|
||||
assert api.option('od.stval1.st1val1.st2val1', 0).owner.get() == owner
|
||||
assert api.option('od.stval1.st1val1.st3val1', 0).owner.isdefault()
|
||||
assert api.option('od.stval2.st1val2.st1val2').owner.isdefault()
|
||||
|
|
|
@ -279,7 +279,8 @@ def manager_callback(callbk: Union[ParamOption, ParamValue],
|
|||
callbk_option = callbk.option
|
||||
if callbk_option.issubdyn():
|
||||
callbk_option = callbk_option.to_dynoption(option.rootpath,
|
||||
option.impl_getsuffix())
|
||||
option.impl_getsuffix(),
|
||||
callbk_option.getsubdyn())
|
||||
if leadership_must_have_index and callbk_option.impl_get_leadership() and index is None:
|
||||
raise Break()
|
||||
if config_bag is undefined:
|
||||
|
|
|
@ -110,10 +110,11 @@ class SubConfig(object):
|
|||
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]
|
||||
# it's a dynoptiondescription remove cache for all generated optiondescription
|
||||
for suffix in option.get_suffixes(option_bag.config_bag):
|
||||
doption = option.to_dynoption(subpath,
|
||||
suffix)
|
||||
doption = option.to_dynoption(desc.impl_getpath(),
|
||||
suffix,
|
||||
option)
|
||||
doption_path = doption.impl_getpath()
|
||||
doption_bag = OptionBag()
|
||||
doption_bag.set_option(doption,
|
||||
|
@ -124,13 +125,16 @@ class SubConfig(object):
|
|||
resetted_opts,
|
||||
doption_bag)
|
||||
elif option.issubdyn():
|
||||
# it's an option in dynoptiondescription, remove cache for all generated option
|
||||
dynopt = option.getsubdyn()
|
||||
rootpath = dynopt.impl_getpath()
|
||||
subpaths = [rootpath] + option.impl_getpath()[len(rootpath) + 1:].split('.')[:-1]
|
||||
for suffix in dynopt.get_suffixes(option_bag.config_bag):
|
||||
subpath = '.'.join([subp + suffix for subp in subpaths])
|
||||
path_suffix = dynopt.convert_suffix_to_path(suffix)
|
||||
subpath = '.'.join([subp + path_suffix for subp in subpaths])
|
||||
doption = option.to_dynoption(subpath,
|
||||
suffix)
|
||||
suffix,
|
||||
dynopt)
|
||||
doption_path = doption.impl_getpath()
|
||||
doption_bag = OptionBag()
|
||||
doption_bag.set_option(doption,
|
||||
|
|
|
@ -63,6 +63,10 @@ class DynOptionDescription(OptionDescription):
|
|||
if __debug__ and isinstance(suffixes, Calculation):
|
||||
self._suffixes = suffixes
|
||||
|
||||
def convert_suffix_to_path(self,
|
||||
suffix):
|
||||
return suffix
|
||||
|
||||
def get_suffixes(self,
|
||||
config_bag: ConfigBag) -> List[str]:
|
||||
|
||||
|
@ -78,6 +82,7 @@ class DynOptionDescription(OptionDescription):
|
|||
'').format(self.impl_get_display_name(), values))
|
||||
values_ = []
|
||||
for val in values:
|
||||
val = self.convert_suffix_to_path(val)
|
||||
if not isinstance(val, str) or re.match(NAME_REGEXP, val) is None:
|
||||
if val is not None:
|
||||
raise ValueError(_('invalid suffix "{}" for option "{}"'
|
||||
|
|
|
@ -219,7 +219,9 @@ class Leadership(OptionDescription):
|
|||
|
||||
def to_dynoption(self,
|
||||
rootpath: str,
|
||||
suffix: str) -> SynDynLeadership:
|
||||
suffix: str,
|
||||
ori_dyn) -> SynDynLeadership:
|
||||
return SynDynLeadership(self,
|
||||
rootpath,
|
||||
suffix)
|
||||
suffix,
|
||||
ori_dyn)
|
||||
|
|
|
@ -429,7 +429,9 @@ class Option(BaseOption):
|
|||
|
||||
def to_dynoption(self,
|
||||
rootpath: str,
|
||||
suffix: str) -> SynDynOption:
|
||||
suffix: str,
|
||||
ori_dyn) -> SynDynOption:
|
||||
return SynDynOption(self,
|
||||
rootpath,
|
||||
suffix)
|
||||
suffix,
|
||||
ori_dyn)
|
||||
|
|
|
@ -175,9 +175,10 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
|||
cname = child.impl_getname()
|
||||
if name.startswith(cname):
|
||||
for suffix in child.get_suffixes(config_bag):
|
||||
if name == cname + suffix:
|
||||
if name == cname + child.convert_suffix_to_path(suffix):
|
||||
return child.to_dynoption(subpath,
|
||||
suffix)
|
||||
suffix,
|
||||
child)
|
||||
if self.impl_get_group_type() == groups.root:
|
||||
raise AttributeError(_('unknown option "{0}" '
|
||||
'in root optiondescription'
|
||||
|
@ -199,7 +200,8 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
|||
if dyn and child.impl_is_dynoptiondescription():
|
||||
for suffix in child.get_suffixes(config_bag):
|
||||
yield child.to_dynoption(subpath,
|
||||
suffix)
|
||||
suffix,
|
||||
child)
|
||||
else:
|
||||
yield child
|
||||
|
||||
|
@ -305,7 +307,9 @@ class OptionDescription(OptionDescriptionWalk):
|
|||
|
||||
def to_dynoption(self,
|
||||
rootpath: str,
|
||||
suffix: str) -> SynDynOptionDescription:
|
||||
suffix: str,
|
||||
ori_dyn) -> SynDynOptionDescription:
|
||||
return SynDynOptionDescription(self,
|
||||
rootpath,
|
||||
suffix)
|
||||
suffix,
|
||||
ori_dyn)
|
||||
|
|
|
@ -29,15 +29,18 @@ class SynDynOption:
|
|||
__slots__ = ('rootpath',
|
||||
'opt',
|
||||
'suffix',
|
||||
'ori_dyn',
|
||||
'__weakref__')
|
||||
|
||||
def __init__(self,
|
||||
opt: BaseOption,
|
||||
rootpath: str,
|
||||
suffix: str) -> None:
|
||||
suffix: str,
|
||||
ori_dyn) -> None:
|
||||
self.opt = opt
|
||||
self.rootpath = rootpath
|
||||
self.suffix = suffix
|
||||
self.ori_dyn = ori_dyn
|
||||
|
||||
def __getattr__(self,
|
||||
name: str) -> Any:
|
||||
|
@ -71,4 +74,5 @@ class SynDynOption:
|
|||
leadership = self.opt.impl_get_leadership()
|
||||
if leadership:
|
||||
return leadership.to_dynoption(self.rootpath,
|
||||
self.suffix)
|
||||
self.suffix,
|
||||
self.ori_dyn)
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
# the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/
|
||||
# the whole pypy projet is under MIT licence
|
||||
# ____________________________________________________________
|
||||
from typing import Optional, Iterator, Union, Any, List
|
||||
from typing import Optional, Iterator, Any, List
|
||||
|
||||
|
||||
from ..i18n import _
|
||||
|
@ -31,18 +31,24 @@ from .syndynoption import SynDynOption
|
|||
class SynDynOptionDescription:
|
||||
__slots__ = ('_opt',
|
||||
'_subpath',
|
||||
'_suffix')
|
||||
'_suffix',
|
||||
'ori_dyn')
|
||||
|
||||
def __init__(self,
|
||||
opt: BaseOption,
|
||||
subpath: str,
|
||||
suffix: str) -> None:
|
||||
suffix: str,
|
||||
ori_dyn) -> None:
|
||||
if opt.__class__.__name__.startswith('L') and ori_dyn is None:
|
||||
raise Exception()
|
||||
self._opt = opt
|
||||
if subpath is None:
|
||||
subpath = ''
|
||||
assert isinstance(subpath, str), 'subpath must be a string, not {}'.format(type(subpath))
|
||||
self._subpath = subpath
|
||||
self._suffix = suffix
|
||||
# For a Leadership inside a DynOptionDescription
|
||||
self.ori_dyn = ori_dyn
|
||||
|
||||
def __getattr__(self,
|
||||
name: str) -> Any:
|
||||
|
@ -57,7 +63,6 @@ class SynDynOptionDescription:
|
|||
name: str,
|
||||
config_bag: ConfigBag,
|
||||
subpath: str) -> BaseOption:
|
||||
#FIXME -> Union[BaseOption, SynDynOptionDescription]:
|
||||
if name.endswith(self._suffix):
|
||||
oname = name[:-len(self._suffix)]
|
||||
try:
|
||||
|
@ -67,12 +72,20 @@ class SynDynOptionDescription:
|
|||
pass
|
||||
else:
|
||||
return child.to_dynoption(subpath,
|
||||
self._suffix)
|
||||
self._suffix,
|
||||
self._opt)
|
||||
raise AttributeError(_('unknown option "{0}" '
|
||||
'in dynamic optiondescription "{1}"'
|
||||
'').format(name, self.impl_get_display_name()))
|
||||
|
||||
def impl_getname(self) -> str:
|
||||
def impl_getname(self,
|
||||
for_path=False) -> str:
|
||||
if for_path == 'toto':
|
||||
if self.ori_dyn:
|
||||
opt = self.ori_dyn
|
||||
else:
|
||||
opt = self._opt
|
||||
return self._opt.impl_getname() + opt.convert_suffix_to_path(self._suffix)
|
||||
return self._opt.impl_getname() + self._suffix
|
||||
|
||||
def impl_is_dynoptiondescription(self) -> bool:
|
||||
|
@ -84,14 +97,14 @@ class SynDynOptionDescription:
|
|||
subpath = self.impl_getpath()
|
||||
for child in self._opt.get_children(config_bag):
|
||||
yield child.to_dynoption(subpath,
|
||||
self._suffix)
|
||||
self._suffix,
|
||||
self._opt)
|
||||
|
||||
def get_children_recursively(self,
|
||||
bytype: Optional[BaseOption],
|
||||
byname: Optional[str],
|
||||
config_bag: ConfigBag,
|
||||
self_opt: BaseOption=None) -> BaseOption:
|
||||
# FIXME -> Iterator[Union[BaseOption, SynDynOptionDescription]]:
|
||||
return self._opt.get_children_recursively(bytype,
|
||||
byname,
|
||||
config_bag,
|
||||
|
@ -101,7 +114,7 @@ class SynDynOptionDescription:
|
|||
subpath = self._subpath
|
||||
if subpath != '':
|
||||
subpath += '.'
|
||||
return subpath + self.impl_getname()
|
||||
return subpath + self.impl_getname(for_path=True)
|
||||
|
||||
def impl_get_display_name(self) -> str:
|
||||
return self._opt.impl_get_display_name() + self._suffix
|
||||
|
@ -110,13 +123,15 @@ class SynDynOptionDescription:
|
|||
class SynDynLeadership(SynDynOptionDescription):
|
||||
def get_leader(self) -> SynDynOption:
|
||||
return self._opt.get_leader().to_dynoption(self.impl_getpath(),
|
||||
self._suffix)
|
||||
self._suffix,
|
||||
self.ori_dyn)
|
||||
|
||||
def get_followers(self) -> Iterator[SynDynOption]:
|
||||
subpath = self.impl_getpath()
|
||||
for follower in self._opt.get_followers():
|
||||
yield follower.to_dynoption(subpath,
|
||||
self._suffix)
|
||||
self._suffix,
|
||||
self.ori_dyn)
|
||||
|
||||
def reset_cache(self,
|
||||
path: str,
|
||||
|
|
Loading…
Reference in a new issue