simplify tiramisu/option/masterslaves.py

This commit is contained in:
Emmanuel Garette 2018-11-15 08:15:55 +01:00
parent 184a086bc1
commit 8b3da4d37b
7 changed files with 101 additions and 114 deletions

View file

@ -1077,7 +1077,7 @@ def autocheck_find(cfg, mcfg, pathread, pathwrite, confread, confwrite, **kwargs
def _getoption(opt): def _getoption(opt):
opt = opt.option.get() opt = opt.option.get()
if opt.impl_is_dynsymlinkoption(): if opt.impl_is_dynsymlinkoption():
opt = opt._opt opt = opt.opt
return opt return opt
def _getoptions(opts): def _getoptions(opts):

View file

@ -217,25 +217,25 @@ def test_groups_with_master():
def test_groups_is_master(): def test_groups_is_master():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True) 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, default_multi='value') netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, default_multi='value')
interface1 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) interface1 = MasterSlaves('masterslaves', '', [ip_admin_eth0, netmask_admin_eth0])
var = StrOption('var', "ip réseau autorisé", multi=True) var = StrOption('var', "ip réseau autorisé", multi=True)
od2 = OptionDescription('od2', '', [var]) od2 = OptionDescription('od2', '', [var])
od1 = OptionDescription('od', '', [interface1, od2]) od1 = OptionDescription('od', '', [interface1, od2])
api = Config(od1) api = Config(od1)
assert not api.option('od2').option.ismasterslaves() assert not api.option('od2').option.ismasterslaves()
assert api.option('ip_admin_eth0').option.ismasterslaves() assert api.option('masterslaves').option.ismasterslaves()
assert not api.option('od2.var').option.ismaster() assert not api.option('od2.var').option.ismaster()
assert not api.option('od2.var').option.isslave() assert not api.option('od2.var').option.isslave()
assert api.option('ip_admin_eth0.ip_admin_eth0').option.ismulti() assert api.option('masterslaves.ip_admin_eth0').option.ismulti()
assert api.option('ip_admin_eth0.netmask_admin_eth0').option.ismulti() assert api.option('masterslaves.netmask_admin_eth0').option.ismulti()
assert not api.option('ip_admin_eth0.ip_admin_eth0').option.issubmulti() assert not api.option('masterslaves.ip_admin_eth0').option.issubmulti()
assert not api.option('ip_admin_eth0.netmask_admin_eth0').option.issubmulti() assert not api.option('masterslaves.netmask_admin_eth0').option.issubmulti()
assert api.option('ip_admin_eth0.ip_admin_eth0').option.ismaster() assert api.option('masterslaves.ip_admin_eth0').option.ismaster()
assert not api.option('ip_admin_eth0.ip_admin_eth0').option.isslave() assert not api.option('masterslaves.ip_admin_eth0').option.isslave()
assert not api.option('ip_admin_eth0.netmask_admin_eth0').option.ismaster() assert not api.option('masterslaves.netmask_admin_eth0').option.ismaster()
assert api.option('ip_admin_eth0.netmask_admin_eth0').option.isslave() assert api.option('masterslaves.netmask_admin_eth0').option.isslave()
assert api.option('ip_admin_eth0.netmask_admin_eth0').option.path() == 'ip_admin_eth0.netmask_admin_eth0' assert api.option('masterslaves.netmask_admin_eth0').option.path() == 'masterslaves.netmask_admin_eth0'
assert api.option('ip_admin_eth0.netmask_admin_eth0').option.defaultmulti() == 'value' assert api.option('masterslaves.netmask_admin_eth0').option.defaultmulti() == 'value'
if TIRAMISU_VERSION != 2: if TIRAMISU_VERSION != 2:

View file

@ -239,10 +239,9 @@ class SubConfig(object):
raise ConfigError(_("can't assign to a SymLinkOption")) raise ConfigError(_("can't assign to a SymLinkOption"))
context = option_bag.config_bag.context context = option_bag.config_bag.context
context.cfgimpl_get_settings().validate_properties(option_bag) context.cfgimpl_get_settings().validate_properties(option_bag)
if option_bag.option.impl_is_master_slaves('master'): if option_bag.option.impl_is_master_slaves('master') and len(value) < self._impl_length:
self.cfgimpl_get_description().impl_validate_value(option_bag.option, raise SlaveError(_('cannot reduce length of the master "{}"'
value, '').format(option_bag.option.impl_get_display_name()))
self)
return context.cfgimpl_get_values().setvalue(value, return context.cfgimpl_get_values().setvalue(value,
option_bag, option_bag,
_commit) _commit)

View file

@ -21,26 +21,30 @@
# ____________________________________________________________ # ____________________________________________________________
import weakref import weakref
from itertools import chain from itertools import chain
from typing import List, Iterator, Optional, Any
from ..i18n import _ from ..i18n import _
from ..setting import groups, undefined, OptionBag from ..setting import groups, undefined, OptionBag, Settings
from ..value import Values
from .optiondescription import OptionDescription from .optiondescription import OptionDescription
from .syndynoptiondescription import SynDynMasterSlaves from .syndynoptiondescription import SynDynMasterSlaves
from .baseoption import BaseOption
from .option import Option from .option import Option
from ..error import SlaveError, PropertiesOptionError, RequirementError from ..error import SlaveError, PropertiesOptionError, RequirementError
from ..function import ParamOption from ..function import ParamOption
class MasterSlaves(OptionDescription): class MasterSlaves(OptionDescription):
__slots__ = ('master', 'slaves') __slots__ = ('master',
'slaves')
def __init__(self, def __init__(self,
name, name: str,
doc, doc: str,
children, children: List[BaseOption],
requires=None, requires=None,
properties=None): properties=None) -> None:
super(MasterSlaves, self).__init__(name, super(MasterSlaves, self).__init__(name,
doc, doc,
@ -50,9 +54,11 @@ class MasterSlaves(OptionDescription):
self._group_type = groups.master self._group_type = groups.master
slaves = [] slaves = []
if len(children) < 2: if len(children) < 2:
raise ValueError(_('a master and a slave are mandatories in masterslaves "{}"').format(name)) raise ValueError(_('a master and a slave are mandatories in masterslaves "{}"'
'').format(name))
master = children[0] master = children[0]
for idx, child in enumerate(children): for idx, child in enumerate(children):
if __debug__:
if child.impl_is_symlinkoption(): if child.impl_is_symlinkoption():
raise ValueError(_('masterslaves "{0}" shall not have ' raise ValueError(_('masterslaves "{0}" shall not have '
"a symlinkoption").format(self.impl_get_display_name())) "a symlinkoption").format(self.impl_get_display_name()))
@ -61,15 +67,16 @@ class MasterSlaves(OptionDescription):
'a subgroup').format(self.impl_get_display_name())) 'a subgroup').format(self.impl_get_display_name()))
if not child.impl_is_multi(): if not child.impl_is_multi():
raise ValueError(_('only multi option allowed in masterslaves "{0}" but option ' raise ValueError(_('only multi option allowed in masterslaves "{0}" but option '
'"{1}" is not a multi').format(self.impl_get_display_name(), '"{1}" is not a multi'
'').format(self.impl_get_display_name(),
child.impl_get_display_name())) child.impl_get_display_name()))
if idx != 0 and child.impl_getdefault() != []: if idx != 0 and child.impl_getdefault() != []:
raise ValueError(_('not allowed default value for option "{0}" ' raise ValueError(_('not allowed default value for option "{0}" '
'in masterslaves "{1}"' 'in masterslaves "{1}"'
'').format(child.impl_get_display_name(), '').format(child.impl_get_display_name(),
self.impl_get_display_name())) self.impl_get_display_name()))
# no empty property for save
if idx != 0: if idx != 0:
# remove empty property for slave
child_properties = list(child._properties) child_properties = list(child._properties)
child_properties.remove('empty') child_properties.remove('empty')
child._properties = frozenset(child_properties) child._properties = frozenset(child_properties)
@ -77,63 +84,59 @@ class MasterSlaves(OptionDescription):
child._add_dependency(self) child._add_dependency(self)
child._master_slaves = weakref.ref(self) child._master_slaves = weakref.ref(self)
callback, callback_params = master.impl_get_callback() callback, callback_params = master.impl_get_callback()
if callback is not None and callback_params != None: if callback is not None and callback_params is not None:
for callbk in chain(callback_params.args, callback_params.kwargs.values()): for callbk in chain(callback_params.args, callback_params.kwargs.values()):
if isinstance(callbk, ParamOption): if isinstance(callbk, ParamOption) and callbk.option in slaves:
if callbk.option in slaves:
raise ValueError(_("callback of master's option shall " raise ValueError(_("callback of master's option shall "
"not refered a slave's ones")) "not refered to a slave's ones"))
# master should not have requires, only MasterSlaves should have # master should not have requires, only MasterSlaves should have
# so move requires to MasterSlaves # so move requires to MasterSlaves
# if MasterSlaves has requires to, cannot manage the move so raises # if MasterSlaves has requires too, cannot manage this move so raises
master_requires = getattr(master, '_requires', None) master_requires = getattr(master, '_requires', None)
if master_requires: if master_requires:
if self.impl_getrequires(): if __debug__ and self.impl_getrequires():
raise RequirementError(_('master {} have requirement, but MasterSlaves {} too' raise RequirementError(_('master {} have requirement, but MasterSlaves {} too'
'').format(master.impl_getname(), '').format(master.impl_getname(),
self.impl_getname())) self.impl_getname()))
master_calproperties = getattr(master, '_calc_properties', None) master_calproperties = getattr(master, '_calc_properties', None)
if master_calproperties: if master_calproperties:
if properties is not None: if __debug__ and properties is not None:
self.validate_properties(name, master_calproperties, frozenset(properties)) self.validate_properties(name, master_calproperties, frozenset(properties))
setattr(self, '_calc_properties', master_calproperties) setattr(self, '_calc_properties', master_calproperties)
setattr(self, '_requires', master_requires) setattr(self, '_requires', master_requires)
delattr(master, '_requires') delattr(master, '_requires')
all_requires = getattr(self, '_requires', None) if __debug__:
if all_requires: for requires_ in getattr(self, '_requires', ()):
for requires_ in all_requires:
for require in requires_: for require in requires_:
for require_opt, values in require[0]: for require_opt, values in require[0]:
if require_opt.impl_is_multi(): if require_opt.impl_is_multi() and require_opt.impl_is_master_slaves():
if require_opt.impl_is_master_slaves():
raise ValueError(_('malformed requirements option "{0}" ' raise ValueError(_('malformed requirements option "{0}" '
'must not be in slave for "{1}"').format( 'must not be in slave for "{1}"').format(
require_opt.impl_getname(), self.impl_getname())) require_opt.impl_getname(),
self.impl_getname()))
def is_master(self, opt): def is_master(self,
master = self._children[0][0] opt: Option) -> bool:
return opt.impl_getname() == master or (opt.impl_is_dynsymlinkoption() and master = self.getmaster()
opt.opt.impl_getname() == master) return opt == master or (opt.impl_is_dynsymlinkoption() and opt.opt == master)
def getmaster(self): def getmaster(self) -> Option:
return self._children[1][0] return self._children[1][0]
def getslaves(self): def getslaves(self) -> Iterator[Option]:
for slave in self._children[1][1:]: for slave in self._children[1][1:]:
yield slave yield slave
def in_same_group(self, opt): def in_same_group(self,
opt: Option) -> bool:
if opt.impl_is_dynsymlinkoption(): if opt.impl_is_dynsymlinkoption():
c_opt = opt.opt opt = opt.opt
else: return opt in self._children[1]
c_opt = opt
return c_opt in self._children[1]
def reset(self, def reset(self,
values, values: Values,
option_bag, option_bag: OptionBag,
_commit=True): _commit: bool=True) -> None:
config_bag = option_bag.config_bag.copy() config_bag = option_bag.config_bag.copy()
config_bag.remove_validation() config_bag.remove_validation()
for slave in self.getslaves(): for slave in self.getslaves():
@ -147,12 +150,12 @@ class MasterSlaves(OptionDescription):
_commit=_commit) _commit=_commit)
def pop(self, def pop(self,
values, values: Values,
index, index: int,
option_bag, option_bag: OptionBag,
slaves=undefined): slaves: Optional[List[Option]]=undefined) -> None:
if slaves is undefined: if slaves is undefined:
# slaves is not undefined only in SynDynMasterSlaves
slaves = self.getslaves() slaves = self.getslaves()
config_bag = option_bag.config_bag.copy() config_bag = option_bag.config_bag.copy()
config_bag.remove_validation() config_bag.remove_validation()
@ -167,8 +170,7 @@ class MasterSlaves(OptionDescription):
# do not check force_default_on_freeze # do not check force_default_on_freeze
soption_bag.properties = set() soption_bag.properties = set()
if not values.is_default_owner(soption_bag, if not values.is_default_owner(soption_bag,
validate_meta=False): validate_meta=False) and slavelen > index:
if slavelen > index:
values._p_.resetvalue_index(slave_path, values._p_.resetvalue_index(slave_path,
index, index,
True) True)
@ -179,32 +181,29 @@ class MasterSlaves(OptionDescription):
idx) idx)
def reset_cache(self, def reset_cache(self,
path, path: str,
values, values: Values,
settings, settings: Settings,
resetted_opts): resetted_opts: List[Option]) -> None:
master = self.getmaster()
slaves = self.getslaves()
self._reset_cache(path, self._reset_cache(path,
master, self.getmaster(),
slaves, self.getslaves(),
values, values,
settings, settings,
resetted_opts) resetted_opts)
def _reset_cache(self, def _reset_cache(self,
path, path: str,
master, master: Option,
slaves, slaves: List[Option],
values, values: Values,
settings, settings: Settings,
resetted_opts): resetted_opts: List[Option]) -> None:
super().reset_cache(path, super().reset_cache(path,
values, values,
settings, settings,
resetted_opts) resetted_opts)
mpath = master.impl_getpath() master.reset_cache(master.impl_getpath(),
master.reset_cache(mpath,
values, values,
settings, settings,
None) None)
@ -216,15 +215,7 @@ class MasterSlaves(OptionDescription):
None) None)
resetted_opts.append(spath) resetted_opts.append(spath)
def impl_validate_value(self, def impl_is_master_slaves(self) -> None:
option,
value,
context):
if isinstance(value, list) and len(value) < context._impl_length:
raise SlaveError(_('cannot reduce length of the master "{}"'
'').format(option.impl_get_display_name()))
def impl_is_master_slaves(self, *args, **kwargs):
return True return True
def to_dynoption(self, def to_dynoption(self,

View file

@ -380,11 +380,10 @@ class Option(BaseOption):
def impl_is_master_slaves(self, type_='both'): def impl_is_master_slaves(self, type_='both'):
master_slaves = self.impl_get_master_slaves() master_slaves = self.impl_get_master_slaves()
if master_slaves is not None: if master_slaves is not None:
if type_ in ('both', 'master') and \ if type_ == 'both':
master_slaves.is_master(self):
return True return True
if type_ in ('both', 'slave') and \ is_master = master_slaves.is_master(self)
not master_slaves.is_master(self): if (type_ == 'master' and is_master) or (type_ == 'slave' and not is_master):
return True return True
return False return False

View file

@ -312,9 +312,7 @@ class OptionDescription(OptionDescriptionWalk):
def impl_is_dynoptiondescription(self) -> bool: def impl_is_dynoptiondescription(self) -> bool:
return False return False
def impl_is_master_slaves(self, def impl_is_master_slaves(self) -> bool:
*args,
**kwargs) -> bool:
return False return False
# ____________________________________________________________ # ____________________________________________________________

View file

@ -28,7 +28,7 @@ from .baseoption import BaseOption
from .syndynoption import SynDynOption from .syndynoption import SynDynOption
class SynDynOptionDescription(object): class SynDynOptionDescription:
__slots__ = ('_opt', __slots__ = ('_opt',
'_subpath', '_subpath',
'_suffix') '_suffix')