master/slaves => leader/followers

This commit is contained in:
2019-02-23 19:06:23 +01:00
parent b9ae1ec656
commit c3f968dbde
35 changed files with 923 additions and 1031 deletions

View File

@ -19,7 +19,7 @@ from time import time
from typing import List, Set, Any, Optional, Callable, Union, Dict
from .error import APIError, ConfigError, SlaveError, PropertiesOptionError
from .error import APIError, ConfigError, LeadershipError, PropertiesOptionError
from .i18n import _
from .setting import ConfigBag, OptionBag, owners, groups, Undefined, undefined, \
FORBIDDEN_SET_PROPERTIES, SPECIAL_PROPERTIES
@ -96,14 +96,14 @@ class CommonTiramisu(TiramisuHelp):
self._option_bag = option_bag
index = self._option_bag.index
if index is not None:
if option.impl_is_optiondescription() or not option.impl_is_master_slaves('slave'):
raise APIError('index must be set only with a slave option')
self._length = self._subconfig.cfgimpl_get_length_slave(self._option_bag)
if option.impl_is_optiondescription() or not option.impl_is_follower():
raise APIError('index must be set only with a follower option')
self._length = self._subconfig.cfgimpl_get_length_leadership(self._option_bag)
if index >= self._length:
raise SlaveError(_('index "{}" is higher than the master length "{}" '
'for option "{}"').format(index,
self._length,
option.impl_get_display_name()))
raise LeadershipError(_('index "{}" is higher than the leadership length "{}" '
'for option "{}"').format(index,
self._length,
option.impl_get_display_name()))
if not self._allow_optiondescription and option.impl_is_optiondescription():
raise APIError(_('option must not be an optiondescription'))
return option
@ -111,7 +111,7 @@ class CommonTiramisu(TiramisuHelp):
class CommonTiramisuOption(CommonTiramisu):
_allow_optiondescription = False
_slave_need_index = True
_follower_need_index = True
_validate_properties = False
def __init__(self,
@ -124,15 +124,15 @@ class CommonTiramisuOption(CommonTiramisu):
# for help()
if option_bag is not None and self._option_bag.config_bag.context.impl_type != 'group':
self._get_option()
if option_bag.config_bag is not None and self._slave_need_index:
self._test_slave_index()
if option_bag.config_bag is not None and self._follower_need_index:
self._test_follower_index()
def _test_slave_index(self) -> None:
def _test_follower_index(self) -> None:
option = self._option_bag.option
if not option.impl_is_optiondescription() and \
self._option_bag.index is None and \
option.impl_is_master_slaves('slave'):
raise APIError(_('index must be set with the slave option "{}"').format(self._option_bag.path))
option.impl_is_follower():
raise APIError(_('index must be set with the follower option "{}"').format(self._option_bag.path))
def __getattr__(self, name):
raise APIError(_('unknown method {}').format(name))
@ -141,7 +141,7 @@ class CommonTiramisuOption(CommonTiramisu):
class _TiramisuOptionOptionDescription(CommonTiramisuOption):
"""Manage option"""
_allow_optiondescription = True
_slave_need_index = False
_follower_need_index = False
def get(self):
"""Get Tiramisu option"""
@ -154,10 +154,10 @@ class _TiramisuOptionOptionDescription(CommonTiramisuOption):
type_ = type_.lower()
return type_
def ismasterslaves(self):
"""Test if option is a master or a slave"""
def isleadership(self):
"""Test if option is a leader or a follower"""
option = self._option_bag.option
return option.impl_is_master_slaves()
return option.impl_is_leadership()
def doc(self):
"""Get option document"""
@ -220,15 +220,15 @@ class _TiramisuOptionOption(_TiramisuOptionOptionDescription):
option = self._option_bag.option
return option.impl_is_submulti()
def ismaster(self):
"""Test if option is a master"""
def isleader(self):
"""Test if option is a leader"""
option = self._option_bag.option
return option.impl_is_master_slaves('master')
return option.impl_is_leader()
def isslave(self):
"""Test if option is a slave"""
def isfollower(self):
"""Test if option is a follower"""
option = self._option_bag.option
return option.impl_is_master_slaves('slave')
return option.impl_is_follower()
def issymlinkoption(self) -> bool:
option = self._option_bag.option
@ -258,7 +258,7 @@ class _TiramisuOptionOption(_TiramisuOptionOptionDescription):
class TiramisuOptionOption(CommonTiramisuOption):
"""Manage option"""
_allow_optiondescription = True
_slave_need_index = False
_follower_need_index = False
def __new__(cls,
name,
@ -318,7 +318,7 @@ class TiramisuOptionOwner(CommonTiramisuOption):
class TiramisuOptionProperty(CommonTiramisuOption):
"""Manage option's property"""
_allow_optiondescription = True
_slave_need_index = False
_follower_need_index = False
def __init__(self,
name: str,
@ -334,7 +334,7 @@ class TiramisuOptionProperty(CommonTiramisuOption):
only_raises=False):
"""Get properties for an option"""
option = self._option_bag.option
self._test_slave_index()
self._test_follower_index()
properties = self._option_bag.properties
if not only_raises:
return properties
@ -376,7 +376,7 @@ class TiramisuOptionProperty(CommonTiramisuOption):
class TiramisuOptionPermissive(CommonTiramisuOption):
"""Manage option's permissive"""
_allow_optiondescription = True
_slave_need_index = False
_follower_need_index = False
def __init__(self,
name: str,
@ -407,7 +407,7 @@ class TiramisuOptionPermissive(CommonTiramisuOption):
class TiramisuOptionInformation(CommonTiramisuOption):
"""Manage option's informations"""
_allow_optiondescription = True
_slave_need_index = False
_follower_need_index = False
def get(self, key, default=undefined):
"""Get information"""
@ -443,14 +443,14 @@ class _TiramisuOptionValueOption:
def get(self):
"""Get option's value"""
option = self._option_bag.option
self._test_slave_index()
self._test_follower_index()
return self._subconfig.getattr(self._name,
self._option_bag)
def set(self, value):
"""Change option's value"""
option = self._option_bag.option
self._test_slave_index()
self._test_follower_index()
values = self._option_bag.config_bag.context.cfgimpl_get_values()
if isinstance(value, list):
while undefined in value:
@ -464,16 +464,16 @@ class _TiramisuOptionValueOption:
def reset(self):
"""Reset value for an option"""
self._test_slave_index()
self._test_follower_index()
self._subconfig.delattr(self._option_bag)
def default(self):
"""Get default value (default of option or calculated value)"""
option = self._option_bag.option
values = self._option_bag.config_bag.context.cfgimpl_get_values()
if option.impl_is_master_slaves('slave') and self._option_bag.index is None:
if option.impl_is_follower() and self._option_bag.index is None:
value = []
length = self._subconfig.cfgimpl_get_length_slave(self._option_bag)
length = self._subconfig.cfgimpl_get_length_leadership(self._option_bag)
for idx in range(length):
soption_bag = OptionBag()
soption_bag.set_option(option,
@ -485,16 +485,17 @@ class _TiramisuOptionValueOption:
return values.getdefaultvalue(self._option_bag)
class _TiramisuOptionValueMaster:
class _TiramisuOptionValueLeader:
def pop(self, index):
"""Pop a value"""
assert not self._option_bag.option.impl_is_symlinkoption(), _("can't delete a SymLinkOption")
self._option_bag.config_bag.context.cfgimpl_get_values().reset_master(index,
self._option_bag,
self._subconfig)
option_bag = self._option_bag
assert not option_bag.option.impl_is_symlinkoption(), _("can't delete a SymLinkOption")
option_bag.config_bag.context.cfgimpl_get_values().reset_leadership(index,
option_bag,
self._subconfig)
def len(self):
"""Length of master option"""
"""Length of leadership"""
option = self._option_bag.option
# for example if index is None
if '_length' not in vars(self):
@ -508,13 +509,13 @@ class _TiramisuOptionValueGroup:
self._option_bag.config_bag.context.reset(self._option_bag.path)
class _TiramisuOptionValueSlave:
class _TiramisuOptionValueFollower:
def len(self):
"""Length of slave option"""
"""Length of follower option"""
option = self._option_bag.option
# for example if index is None
if '_length' not in vars(self):
self._length = self._subconfig.cfgimpl_get_length_slave(self._option_bag)
self._length = self._subconfig.cfgimpl_get_length_leadership(self._option_bag)
return self._length
@ -550,7 +551,7 @@ class _TiramisuOptionValueOptionDescription:
class TiramisuOptionValue(CommonTiramisuOption):
"""Manage option's value"""
_allow_optiondescription = True
_slave_need_index = False
_follower_need_index = False
def __new__(cls,
name,
@ -570,14 +571,14 @@ class TiramisuOptionValue(CommonTiramisuOption):
types.append(_TiramisuOptionValueOption)
if isinstance(option, ChoiceOption):
types.append(_TiramisuOptionValueChoiceOption)
if option.impl_is_master_slaves('master'):
types.append(_TiramisuOptionValueMaster)
elif option.impl_is_master_slaves('slave'):
types.append(_TiramisuOptionValueSlave)
if option.impl_is_leader():
types.append(_TiramisuOptionValueLeader)
elif option.impl_is_follower():
types.append(_TiramisuOptionValueFollower)
if option_bag.config_bag.context.impl_type == 'group':
types.append(_TiramisuOptionValueGroup)
new_type_dict = {'_allow_optiondescription': cls._allow_optiondescription,
'_slave_need_index': cls._slave_need_index}
'_follower_need_index': cls._follower_need_index}
new_type = type('TiramisuOptionValue', tuple(types), new_type_dict)(name=name,
subconfig=subconfig,
option_bag=option_bag)
@ -651,7 +652,7 @@ class _TiramisuOptionDescription(_TiramisuOption):
self._config_bag)
t_option = TiramisuOption(name,
path,
None, # index for a slave ?
None, # index for a follower ?
subconfig,
self._config_bag)
if first:

View File

@ -21,7 +21,7 @@
from typing import Any, Optional, Union, Callable, Dict, List
from .error import PropertiesOptionError, ConfigError, SlaveError
from .error import PropertiesOptionError, ConfigError, LeadershipError
from .i18n import _
from .setting import undefined, ConfigBag, OptionBag, Undefined
from .storage import get_default_values_storages, get_default_settings_storages
@ -51,12 +51,12 @@ def manager_callback(callbk: Union[ParamOption, ParamValue],
opt = opt.to_dynoption(option.rootpath,
option.impl_getsuffix())
path = opt.impl_getpath()
if index is not None and opt.impl_is_master_slaves() and \
opt.impl_get_master_slaves().in_same_group(option):
if index is not None and opt.impl_get_leadership() and \
opt.impl_get_leadership().in_same_group(option):
if opt == option:
index_ = None
with_index = False
elif opt.impl_is_master_slaves('slave'):
elif opt.impl_is_follower():
index_ = index
with_index = False
else:
@ -66,7 +66,7 @@ def manager_callback(callbk: Union[ParamOption, ParamValue],
index_ = None
with_index = False
if opt == option and orig_value is not undefined and \
(not opt.impl_is_master_slaves('slave') or index is None):
(not opt.impl_is_follower() or index is None):
return orig_value
# don't validate if option is option that we tried to validate
config_bag = config_bag.copy()
@ -152,17 +152,17 @@ def carry_out_calculation(option,
opt1 == 11
=> calculate(<function func at 0x1cea320>, [11], {})
- a multi option and not master/slave:
- a multi option and not leadership
opt1 == [1, 2, 3]
=> calculate(<function func at 0x223c320>, [[1, 2, 3]], {})
- option is master or slave of opt1:
- option is leader or follower of opt1:
opt1 == [1, 2, 3]
=> calculate(<function func at 0x223c320>, [1], {})
=> calculate(<function func at 0x223c320>, [2], {})
=> calculate(<function func at 0x223c320>, [3], {})
- opt is a master or slave but not related to option:
- opt is a leader or follower but not related to option:
opt1 == [1, 2, 3]
=> calculate(<function func at 0x11b0320>, [[1, 2, 3]], {})
@ -252,20 +252,20 @@ def carry_out_calculation(option,
args,
kwargs)
if isinstance(ret, list) and not option.impl_is_dynoptiondescription() and \
option.impl_is_master_slaves('slave'):
option.impl_is_follower():
if args or kwargs:
raise SlaveError(_('function "{}" with arguments "{}" and "{}" '
'return the list "{}" for the slave option "{}"'
'').format(callback.__name__,
args,
kwargs,
ret,
option.impl_get_display_name()))
raise LeadershipError(_('function "{}" with arguments "{}" and "{}" '
'return the list "{}" for the follower option "{}"'
'').format(callback.__name__,
args,
kwargs,
ret,
option.impl_get_display_name()))
else:
raise SlaveError(_('function "{}" return the list "{}" for the slave option "{}"'
'').format(callback.__name__,
ret,
option.impl_getname()))
raise LeadershipError(_('function "{}" return the list "{}" for the follower option "{}"'
'').format(callback.__name__,
ret,
option.impl_getname()))
return ret

View File

@ -23,10 +23,11 @@ import weakref
from copy import copy
from .error import PropertiesOptionError, ConfigError, ConflictError, SlaveError
from .option import SynDynOptionDescription, DynOptionDescription, MasterSlaves
from .error import PropertiesOptionError, ConfigError, ConflictError, \
LeadershipError
from .option import SynDynOptionDescription, DynOptionDescription, Leadership
from .option.baseoption import BaseOption, valid_name
from .setting import OptionBag, ConfigBag, groups, Settings, undefined
from .setting import OptionBag, ConfigBag, Settings, undefined
from .storage import get_storages, gen_storage_id, get_default_values_storages
from .value import Values
from .i18n import _
@ -49,7 +50,7 @@ class SubConfig(object):
config_bag,
subpath=None,
fromconsistency=None):
""" Configuration option management master class
""" Configuration option management class
:param descr: describes the configuration schema
:type descr: an instance of ``option.OptionDescription``
@ -58,10 +59,9 @@ class SubConfig(object):
:type subpath: `str` with the path name
"""
# main option description
error = False
if descr is not None and (not isinstance(descr, (BaseOption, SynDynOptionDescription)) or not descr.impl_is_optiondescription()):
error = True
if error:
if __debug__ and descr is not None and \
(not isinstance(descr, (BaseOption, SynDynOptionDescription)) or
not descr.impl_is_optiondescription()):
try:
msg = descr.impl_get_displayname()
except AttributeError:
@ -71,29 +71,28 @@ class SubConfig(object):
self._impl_descr = descr
self._impl_context = context
self._impl_path = subpath
if descr is not None and \
descr.impl_get_group_type() == groups.master:
master = descr.getmaster()
masterpath = master.impl_getname()
full_masterpath = self._get_subpath(masterpath)
if descr is not None and descr.impl_is_leadership():
leader = descr.get_leader()
leaderpath = leader.impl_getname()
full_leaderpath = self._get_subpath(leaderpath)
cconfig_bag = config_bag.copy()
cconfig_bag.remove_validation()
moption_bag = OptionBag()
moption_bag.set_option(master,
full_masterpath,
moption_bag.set_option(leader,
full_leaderpath,
None,
cconfig_bag)
if fromconsistency:
moption_bag.fromconsistency = fromconsistency
value = self.getattr(masterpath,
value = self.getattr(leaderpath,
moption_bag)
self._impl_length = len(value)
def cfgimpl_get_length(self):
return self._impl_length
def cfgimpl_get_length_slave(self,
option_bag):
def cfgimpl_get_length_leadership(self,
option_bag):
if option_bag.option.impl_is_symlinkoption():
context = self.cfgimpl_get_context()
path = option_bag.option.impl_getopt().impl_getpath()
@ -238,9 +237,9 @@ class SubConfig(object):
raise ConfigError(_("can't assign to a SymLinkOption"))
context = option_bag.config_bag.context
context.cfgimpl_get_settings().validate_properties(option_bag)
if option_bag.option.impl_is_master_slaves('master') and len(value) < self._impl_length:
raise SlaveError(_('cannot reduce length of the master "{}"'
'').format(option_bag.option.impl_get_display_name()))
if option_bag.option.impl_is_leader() and len(value) < self._impl_length:
raise LeadershipError(_('cannot reduce length of a leader "{}"'
'').format(option_bag.option.impl_get_display_name()))
return context.cfgimpl_get_values().setvalue(value,
option_bag,
_commit)
@ -253,8 +252,8 @@ class SubConfig(object):
raise TypeError(_("can't delete a SymLinkOption"))
values = self.cfgimpl_get_values()
if option_bag.index is not None:
values.reset_slave(option_bag,
_commit)
values.reset_follower(option_bag,
_commit)
else:
values.reset(option_bag,
_commit)
@ -313,16 +312,16 @@ class SubConfig(object):
self.cfgimpl_get_settings().validate_properties(option_bag)
if option.impl_is_master_slaves('slave'):
length = self.cfgimpl_get_length_slave(option_bag)
slave_len = self.cfgimpl_get_values()._p_.get_max_length(option_bag.path)
if slave_len > length:
raise SlaveError(_('slave option "{}" has higher length "{}" than the master '
'length "{}"').format(option.impl_get_display_name(),
slave_len,
if option.impl_is_follower():
length = self.cfgimpl_get_length_leadership(option_bag)
follower_len = self.cfgimpl_get_values()._p_.get_max_length(option_bag.path)
if follower_len > length:
raise LeadershipError(_('follower option "{}" has higher length "{}" than the leader '
'length "{}"').format(option.impl_get_display_name(),
follower_len,
length,
option_bag.index))
if option.impl_is_master_slaves('slave') and option_bag.index is None:
if option.impl_is_follower() and option_bag.index is None:
value = []
for idx in range(length):
soption_bag = OptionBag()
@ -717,7 +716,7 @@ class KernelConfig(_CommonConfig):
force_settings=None,
_duplicate=False,
storage=None):
""" Configuration option management master class
""" Configuration option management class
:param descr: describes the configuration schema
:type descr: an instance of ``option.OptionDescription``
@ -730,8 +729,8 @@ class KernelConfig(_CommonConfig):
:type persistent: `boolean`
"""
self._impl_meta = None
if isinstance(descr, MasterSlaves):
raise ConfigError(_('cannot set masterslaves object has root optiondescription'))
if isinstance(descr, Leadership):
raise ConfigError(_('cannot set leadership object has root optiondescription'))
if isinstance(descr, DynOptionDescription):
raise ConfigError(_('cannot set dynoptiondescription object has root optiondescription'))
if force_settings is not None and force_values is not None:
@ -872,7 +871,7 @@ class KernelGroupConfig(_CommonConfig):
err._requires,
err._name,
err._orig_opt))
except (ValueError, SlaveError, AttributeError) as err:
except (ValueError, LeadershipError, AttributeError) as err:
ret.append(err)
if _commit and self.impl_type != 'group':
self.cfgimpl_get_values()._p_.commit()
@ -1089,7 +1088,7 @@ class KernelMixConfig(KernelGroupConfig):
err._requires,
err._name,
err._orig_opt))
except (ValueError, SlaveError, AttributeError) as err:
except (ValueError, LeadershipError, AttributeError) as err:
ret.append(err)
try:
@ -1100,7 +1099,7 @@ class KernelMixConfig(KernelGroupConfig):
subconfig.setattr(value,
option_bag,
_commit=False)
except (PropertiesOptionError, ValueError, SlaveError) as err:
except (PropertiesOptionError, ValueError, LeadershipError) as err:
ret.append(err)
return ret

View File

@ -144,8 +144,8 @@ class RequirementError(Exception):
pass
class SlaveError(Exception):
"problem with a slave's value length"
class LeadershipError(Exception):
"problem with a leadership's value length"
pass

View File

@ -1,7 +1,7 @@
from .optiondescription import OptionDescription
from .dynoptiondescription import DynOptionDescription
from .syndynoptiondescription import SynDynOptionDescription, SynDynMasterSlaves
from .masterslaves import MasterSlaves
from .syndynoptiondescription import SynDynOptionDescription, SynDynLeadership
from .leadership import Leadership
from .baseoption import submulti
from .symlinkoption import SymLinkOption
from .syndynoption import SynDynOption
@ -25,8 +25,8 @@ from .filenameoption import FilenameOption
from .passwordoption import PasswordOption
__all__ = ('MasterSlaves', 'OptionDescription', 'DynOptionDescription',
'SynDynOptionDescription', 'SynDynMasterSlaves', 'Option', 'SymLinkOption',
__all__ = ('Leadership', 'OptionDescription', 'DynOptionDescription',
'SynDynOptionDescription', 'SynDynLeadership', 'Option', 'SymLinkOption',
'SynDynOption', 'ChoiceOption', 'BoolOption', 'DateOption',
'IntOption', 'FloatOption', 'StrOption', 'UnicodeOption',
'IPOption', 'PortOption', 'NetworkOption', 'NetmaskOption',

View File

@ -90,7 +90,7 @@ class Base:
properties = frozenset(properties)
if is_multi and 'empty' not in properties:
# if option is a multi, it cannot be "empty" (None not allowed in the list)
# "empty" is removed for slave's option
# "empty" is removed for follower's option
properties = properties | {'empty'}
if not isinstance(properties, frozenset):
raise TypeError(_('invalid properties type {0} for {1},'

View File

@ -52,7 +52,7 @@ class DynOptionDescription(OptionDescription):
# check children + set relation to this dynoptiondescription
for child in children:
if isinstance(child, OptionDescription):
if __debug__ and child.impl_get_group_type() != groups.master:
if __debug__ and child.impl_get_group_type() != groups.leadership:
raise ConfigError(_('cannot set optiondescription in a '
'dynoptiondescription'))
for chld in child.get_children(config_bag=undefined):

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
"master slaves support"
"Leadership support"
# Copyright (C) 2014-2019 Team tiramisu (see AUTHORS for all contributors)
#
# This program is free software: you can redistribute it and/or modify it
@ -28,16 +28,16 @@ from ..i18n import _
from ..setting import groups, undefined, OptionBag, Settings
from ..value import Values
from .optiondescription import OptionDescription
from .syndynoptiondescription import SynDynMasterSlaves
from .syndynoptiondescription import SynDynLeadership
from .baseoption import BaseOption
from .option import Option
from ..error import SlaveError, PropertiesOptionError, RequirementError
from ..error import RequirementError
from ..function import ParamOption
class MasterSlaves(OptionDescription):
__slots__ = ('master',
'slaves')
class Leadership(OptionDescription):
__slots__ = ('leader',
'followers')
def __init__(self,
name: str,
@ -46,86 +46,86 @@ class MasterSlaves(OptionDescription):
requires=None,
properties=None) -> None:
super(MasterSlaves, self).__init__(name,
doc,
children,
requires=requires,
properties=properties)
self._group_type = groups.master
slaves = []
super().__init__(name,
doc,
children,
requires=requires,
properties=properties)
self._group_type = groups.leadership
followers = []
if len(children) < 2:
raise ValueError(_('a master and a slave are mandatories in masterslaves "{}"'
raise ValueError(_('a leader and a follower are mandatories in leadership "{}"'
'').format(name))
master = children[0]
leader = children[0]
for idx, child in enumerate(children):
if __debug__:
if child.impl_is_symlinkoption():
raise ValueError(_('masterslaves "{0}" shall not have '
raise ValueError(_('leadership "{0}" shall not have '
"a symlinkoption").format(self.impl_get_display_name()))
if not isinstance(child, Option):
raise ValueError(_('masterslaves "{0}" shall not have '
raise ValueError(_('leadership "{0}" shall not have '
'a subgroup').format(self.impl_get_display_name()))
if not child.impl_is_multi():
raise ValueError(_('only multi option allowed in masterslaves "{0}" but option '
raise ValueError(_('only multi option allowed in leadership "{0}" but option '
'"{1}" is not a multi'
'').format(self.impl_get_display_name(),
child.impl_get_display_name()))
if idx != 0 and child.impl_getdefault() != []:
raise ValueError(_('not allowed default value for slave option "{0}" '
'in masterslaves "{1}"'
raise ValueError(_('not allowed default value for follower option "{0}" '
'in leadership "{1}"'
'').format(child.impl_get_display_name(),
self.impl_get_display_name()))
if idx != 0:
# remove empty property for slave
# remove empty property for follower
child_properties = list(child._properties)
child_properties.remove('empty')
child._properties = frozenset(child_properties)
slaves.append(child)
followers.append(child)
child._add_dependency(self)
child._master_slaves = weakref.ref(self)
callback, callback_params = master.impl_get_callback()
child._leadership = weakref.ref(self)
callback, callback_params = leader.impl_get_callback()
if callback is not None and callback_params is not None:
for callbk in chain(callback_params.args, callback_params.kwargs.values()):
if isinstance(callbk, ParamOption) and callbk.option in slaves:
raise ValueError(_("callback of master's option shall "
"not refered to a slave's ones"))
# master should not have requires, only MasterSlaves should have
# so move requires to MasterSlaves
# if MasterSlaves has requires too, cannot manage this move so raises
master_requires = getattr(master, '_requires', None)
if master_requires:
if isinstance(callbk, ParamOption) and callbk.option in followers:
raise ValueError(_("callback of leader's option shall "
"not refered to a follower's ones"))
# leader should not have requires, only Leadership should have
# so move requires to Leadership
# if Leadership has requires too, cannot manage this move so raises
leader_requires = getattr(leader, '_requires', None)
if leader_requires:
if __debug__ and self.impl_getrequires():
raise RequirementError(_('master {} have requirement, but MasterSlaves {} too'
'').format(master.impl_getname(),
raise RequirementError(_('leader {} have requirement, but Leadership {} too'
'').format(leader.impl_getname(),
self.impl_getname()))
master_calproperties = getattr(master, '_calc_properties', None)
if master_calproperties:
leader_calproperties = getattr(leader, '_calc_properties', None)
if leader_calproperties:
if __debug__ and properties is not None:
self.validate_properties(name, master_calproperties, frozenset(properties))
setattr(self, '_calc_properties', master_calproperties)
setattr(self, '_requires', master_requires)
delattr(master, '_requires')
self.validate_properties(name, leader_calproperties, frozenset(properties))
setattr(self, '_calc_properties', leader_calproperties)
setattr(self, '_requires', leader_requires)
delattr(leader, '_requires')
if __debug__:
for requires_ in getattr(self, '_requires', ()):
for require in requires_:
for require_opt, values in require[0]:
if require_opt.impl_is_multi() and require_opt.impl_is_master_slaves():
if require_opt.impl_is_multi() and require_opt.impl_get_leadership():
raise ValueError(_('malformed requirements option "{0}" '
'must not be in slave for "{1}"').format(
'must not be in follower for "{1}"').format(
require_opt.impl_getname(),
self.impl_getname()))
def is_master(self,
def is_leader(self,
opt: Option) -> bool:
master = self.getmaster()
return opt == master or (opt.impl_is_dynsymlinkoption() and opt.opt == master)
leader = self.get_leader()
return opt == leader or (opt.impl_is_dynsymlinkoption() and opt.opt == leader)
def getmaster(self) -> Option:
def get_leader(self) -> Option:
return self._children[1][0]
def getslaves(self) -> Iterator[Option]:
for slave in self._children[1][1:]:
yield slave
def get_followers(self) -> Iterator[Option]:
for follower in self._children[1][1:]:
yield follower
def in_same_group(self,
opt: Option) -> bool:
@ -139,11 +139,11 @@ class MasterSlaves(OptionDescription):
_commit: bool=True) -> None:
config_bag = option_bag.config_bag.copy()
config_bag.remove_validation()
for slave in self.getslaves():
slave_path = slave.impl_getpath()
for follower in self.get_followers():
follower_path = follower.impl_getpath()
soption_bag = OptionBag()
soption_bag.set_option(slave,
slave_path,
soption_bag.set_option(follower,
follower_path,
None,
config_bag)
values.reset(soption_bag,
@ -153,31 +153,31 @@ class MasterSlaves(OptionDescription):
values: Values,
index: int,
option_bag: OptionBag,
slaves: Optional[List[Option]]=undefined) -> None:
if slaves is undefined:
# slaves is not undefined only in SynDynMasterSlaves
slaves = self.getslaves()
followers: Optional[List[Option]]=undefined) -> None:
if followers is undefined:
# followers are not undefined only in SynDynLeadership
followers = self.get_followers()
config_bag = option_bag.config_bag.copy()
config_bag.remove_validation()
for slave in slaves:
slave_path = slave.impl_getpath()
slavelen = values._p_.get_max_length(slave_path)
for follower in followers:
follower_path = follower.impl_getpath()
followerlen = values._p_.get_max_length(follower_path)
soption_bag = OptionBag()
soption_bag.set_option(slave,
slave_path,
soption_bag.set_option(follower,
follower_path,
index,
config_bag)
# do not check force_default_on_freeze
soption_bag.properties = set()
if not values.is_default_owner(soption_bag,
validate_meta=False) and slavelen > index:
values._p_.resetvalue_index(slave_path,
validate_meta=False) and followerlen > index:
values._p_.resetvalue_index(follower_path,
index,
True)
if slavelen > index + 1:
for idx in range(index + 1, slavelen):
if values._p_.hasvalue(slave_path, idx):
values._p_.reduce_index(slave_path,
if followerlen > index + 1:
for idx in range(index + 1, followerlen):
if values._p_.hasvalue(follower_path, idx):
values._p_.reduce_index(follower_path,
idx)
def reset_cache(self,
@ -186,16 +186,16 @@ class MasterSlaves(OptionDescription):
settings: Settings,
resetted_opts: List[Option]) -> None:
self._reset_cache(path,
self.getmaster(),
self.getslaves(),
self.get_leader(),
self.get_followers(),
values,
settings,
resetted_opts)
def _reset_cache(self,
path: str,
master: Option,
slaves: List[Option],
leader: Option,
followers: List[Option],
values: Values,
settings: Settings,
resetted_opts: List[Option]) -> None:
@ -203,24 +203,24 @@ class MasterSlaves(OptionDescription):
values,
settings,
resetted_opts)
master.reset_cache(master.impl_getpath(),
leader.reset_cache(leader.impl_getpath(),
values,
settings,
None)
for slave in slaves:
spath = slave.impl_getpath()
slave.reset_cache(spath,
values,
settings,
None)
for follower in followers:
spath = follower.impl_getpath()
follower.reset_cache(spath,
values,
settings,
None)
resetted_opts.append(spath)
def impl_is_master_slaves(self) -> None:
def impl_is_leadership(self) -> None:
return True
def to_dynoption(self,
rootpath: str,
suffix: str) -> SynDynMasterSlaves:
return SynDynMasterSlaves(self,
rootpath,
suffix)
suffix: str) -> SynDynLeadership:
return SynDynLeadership(self,
rootpath,
suffix)

View File

@ -52,7 +52,7 @@ class Option(BaseOption):
#calcul
'_val_call',
#
'_master_slaves',
'_leadership',
'_choice_values',
'_choice_values_params',
)
@ -381,24 +381,27 @@ class Option(BaseOption):
pass
#__________________________________________________________________________
# master/slaves
# leadership
# def impl_is_leadership(self):
# return self.impl_get_leadership() is not None
def impl_is_master_slaves(self,
type_: str='both') -> bool:
master_slaves = self.impl_get_master_slaves()
if master_slaves is not None:
if type_ == 'both':
return True
is_master = master_slaves.is_master(self)
if (type_ == 'master' and is_master) or (type_ == 'slave' and not is_master):
return True
return False
def impl_is_leader(self):
leadership = self.impl_get_leadership()
if leadership is None:
return leadership
return self.impl_get_leadership().is_leader(self)
def impl_get_master_slaves(self):
masterslave = getattr(self, '_master_slaves', None)
if masterslave is None:
return masterslave
return masterslave()
def impl_is_follower(self):
leadership = self.impl_get_leadership()
if leadership is None:
return leadership
return not leadership.is_leader(self)
def impl_get_leadership(self):
leadership = getattr(self, '_leadership', None)
if leadership is None:
return leadership
return leadership()
#____________________________________________________________
# consistencies
@ -662,7 +665,7 @@ class Option(BaseOption):
if func in ALLOWED_CONST_LIST:
index = None
index_ = None
elif current_option.impl_is_master_slaves('master'):
elif current_option.impl_is_leader():
index = option_bag.index
index_ = None
else:
@ -681,8 +684,8 @@ class Option(BaseOption):
current_value = option_bag.config_bag.context.getattr(path,
coption_bag)
if index_ is None and index is not None:
#if self is a slave and current_option is a master and func not in ALLOWED_CONST_LIST
#return only the value of the master for isolate slave
#if self is a follower and current_option is a leader and func not in ALLOWED_CONST_LIST
#return only the value of the leader for isolate follower
current_value = current_value[index]
return current_value

View File

@ -26,7 +26,7 @@ from ..i18n import _
from ..setting import ConfigBag, OptionBag, groups, undefined, owners, Undefined
from .baseoption import BaseOption
from .option import ALLOWED_CONST_LIST
from .syndynoptiondescription import SynDynOptionDescription, SynDynMasterSlaves
from .syndynoptiondescription import SynDynOptionDescription, SynDynLeadership
from ..error import ConfigError, ConflictError
@ -80,9 +80,9 @@ class CacheOptionDescription(BaseOption):
properties = option.impl_getproperties()
if 'force_store_value' in properties:
if __debug__:
if option.impl_is_master_slaves('slave'):
if option.impl_is_follower():
# problem with index
raise ConfigError(_('the slave "{0}" cannot have '
raise ConfigError(_('the follower "{0}" cannot have '
'"force_store_value" property').format(
option.impl_get_display_name()))
if option.issubdyn():
@ -92,28 +92,28 @@ class CacheOptionDescription(BaseOption):
force_store_values.append((subpath, option))
if __debug__ and 'force_default_on_freeze' in properties and \
'frozen' not in properties and \
option.impl_is_master_slaves('master'):
raise ConfigError(_('a master ({0}) cannot have '
option.impl_is_leader():
raise ConfigError(_('a leader ({0}) cannot have '
'"force_default_on_freeze" property without "frozen"'
'').format(subpath))
for cons_id, func, all_cons_opts, params in option.get_consistencies():
option._valid_consistencies(all_cons_opts[1:], init=False)
if func not in ALLOWED_CONST_LIST and is_multi:
if __debug__ and not option.impl_is_master_slaves():
if __debug__ and not option.impl_get_leadership():
raise ConfigError(_('malformed consistency option "{0}" '
'must be a masterslaves').format(
'must be a leadership').format(
option.impl_getname()))
masterslaves = option.impl_get_master_slaves()
leadership = option.impl_get_leadership()
for weak_opt in all_cons_opts:
opt = weak_opt()
if __debug__ and func not in ALLOWED_CONST_LIST and is_multi:
if not opt.impl_is_master_slaves():
if not opt.impl_get_leadership():
raise ConfigError(_('malformed consistency option "{0}" '
'must not be a multi for "{1}"').format(
option.impl_getname(), opt.impl_getname()))
elif masterslaves != opt.impl_get_master_slaves():
elif leadership != opt.impl_get_leadership():
raise ConfigError(_('malformed consistency option "{0}" '
'must be in same masterslaves as "{1}"').format(
'must be in same leadership as "{1}"').format(
option.impl_getname(), opt.impl_getname()))
_consistencies.setdefault(weak_opt,
[]).append((_consistencies_id,
@ -126,25 +126,25 @@ class CacheOptionDescription(BaseOption):
self._add_dependency(option)
if __debug__:
is_slave = None
is_follower = None
if is_multi:
all_requires = option.impl_getrequires()
for requires in all_requires:
for require in requires:
#if option in require is a multi:
# * option in require must be a master or a slave
# * current option must be a slave (and only a slave)
# * option in require and current option must be in same masterslaves
# * option in require must be a leader or a follower
# * current option must be a follower (and only a follower)
# * option in require and current option must be in same leadership
for require_opt, values in require[0]:
if require_opt.impl_is_multi():
if is_slave is None:
is_slave = option.impl_is_master_slaves('slave')
if is_slave:
masterslaves = option.impl_get_master_slaves()
if is_slave and require_opt.impl_is_master_slaves():
if masterslaves != require_opt.impl_get_master_slaves():
if is_follower is None:
is_follower = option.impl_is_follower()
if is_follower:
leadership = option.impl_get_leadership()
if is_follower and require_opt.impl_get_leadership():
if leadership != require_opt.impl_get_leadership():
raise ValueError(_('malformed requirements option "{0}" '
'must be in same masterslaves for "{1}"').format(
'must be in same leadership for "{1}"').format(
require_opt.impl_getname(), option.impl_getname()))
else:
raise ValueError(_('malformed requirements option "{0}" '
@ -311,7 +311,7 @@ class OptionDescription(OptionDescriptionWalk):
def impl_is_dynoptiondescription(self) -> bool:
return False
def impl_is_master_slaves(self) -> bool:
def impl_is_leadership(self) -> bool:
return False
# ____________________________________________________________
@ -319,7 +319,7 @@ class OptionDescription(OptionDescriptionWalk):
group_type: groups.GroupType) -> None:
"""sets a given group object to an OptionDescription
:param group_type: an instance of `GroupType` or `MasterGroupType`
:param group_type: an instance of `GroupType` or `LeadershipGroupType`
that lives in `setting.groups`
"""
if self._group_type != groups.default:
@ -329,8 +329,8 @@ class OptionDescription(OptionDescriptionWalk):
if not isinstance(group_type, groups.GroupType):
raise ValueError(_('group_type: {0}'
' not allowed').format(group_type))
if isinstance(group_type, groups.MasterGroupType):
raise ConfigError('please use MasterSlaves object instead of OptionDescription')
if isinstance(group_type, groups.LeadershipGroupType):
raise ConfigError('please use Leadership object instead of OptionDescription')
self._group_type = group_type
def impl_get_group_type(self) -> groups.GroupType:

View File

@ -104,28 +104,27 @@ class SynDynOptionDescription:
return self._opt.impl_get_display_name() + self._suffix
class SynDynMasterSlaves(SynDynOptionDescription):
class SynDynLeadership(SynDynOptionDescription):
def get_leader(self) -> SynDynOption:
return self._opt.get_leader().to_dynoption(self.impl_getpath(),
self._suffix)
def getmaster(self) -> SynDynOption:
return self._opt.getmaster().to_dynoption(self.impl_getpath(),
self._suffix)
def getslaves(self) -> Iterator[SynDynOption]:
def get_followers(self) -> Iterator[SynDynOption]:
subpath = self.impl_getpath()
for slave in self._opt.getslaves():
yield slave.to_dynoption(subpath,
self._suffix)
for follower in self._opt.get_followers():
yield follower.to_dynoption(subpath,
self._suffix)
def reset_cache(self,
path: str,
values: Values,
settings: Settings,
resetted_opts: List[str]) -> None:
master = self.getmaster()
slaves = self.getslaves()
leader = self.get_leader()
followers = self.get_followers()
self._reset_cache(path,
master,
slaves,
leader,
followers,
values,
settings,
resetted_opts)
@ -134,5 +133,5 @@ class SynDynMasterSlaves(SynDynOptionDescription):
*args,
**kwargs) -> None:
self._opt.pop(*args,
slaves=self.getslaves(),
followers=self.get_followers(),
**kwargs)

View File

@ -75,7 +75,7 @@ everything_frozen
property)
empty
raise mandatory PropertiesOptionError if multi or master have empty value
raise mandatory PropertiesOptionError if multi or leader have empty value
validator
launch validator set by user in option (this property has no effect
@ -258,7 +258,7 @@ class GroupModule(_NameSpace):
"emulates a module to manage unique group (OptionDescription) names"
class GroupType(str):
"""allowed normal group (OptionDescription) names
*normal* means : groups that are not master
*normal* means : groups that are not leader
"""
pass
@ -266,9 +266,9 @@ class GroupModule(_NameSpace):
"""groups that are default (typically 'default')"""
pass
class MasterGroupType(GroupType):
class LeadershipGroupType(GroupType):
"""allowed normal group (OptionDescription) names
*master* means : groups that have the 'master' attribute set
*leadership* means : groups that have the 'leadership' attribute set
"""
pass
@ -301,12 +301,12 @@ groups = GroupModule()
default group set when creating a new optiondescription"""
groups.default = groups.DefaultGroupType('default')
"""groups.master
master group is a special optiondescription, all suboptions should be
multi option and all values should have same length, to find master's
option, the optiondescription's name should be same than de master's
"""groups.leadership
leadership group is a special optiondescription, all suboptions should be
multi option and all values should have same length, to find leader's
option, the optiondescription's name should be same than de leader's
option"""
groups.master = groups.MasterGroupType('master')
groups.leadership = groups.LeadershipGroupType('leadership')
""" groups.family
example of group, no special behavior with this group's type"""
@ -520,7 +520,7 @@ class Settings(object):
"'{1}'").format(option_bag.path, reqpath))
idx = None
is_indexed = False
if option.impl_is_master_slaves('slave'):
if option.impl_is_follower():
idx = option_bag.index
elif option.impl_is_multi() and option_bag.index is not None:
is_indexed = True
@ -638,13 +638,13 @@ class Settings(object):
"").format(opt.impl_get_display_name()))
if 'force_default_on_freeze' in properties and \
'frozen' not in properties and \
opt.impl_is_master_slaves('master'):
raise ConfigError(_('a master ({0}) cannot have '
opt.impl_is_leader():
raise ConfigError(_('a leader ({0}) cannot have '
'"force_default_on_freeze" property without "frozen"'
'').format(opt.impl_get_display_name()))
self._p_.setproperties(path,
properties)
#values too because of slave values could have a PropertiesOptionError has value
# values too because of follower values could have a PropertiesOptionError has value
context.cfgimpl_reset_cache(option_bag)
if option_bag is not None:
del option_bag.properties

View File

@ -36,7 +36,7 @@ class Cache(DictCache):
def setcache(self, path, index, val, self_props, props):
"""add val in cache for a specified path
if slave, add index
if follower, add index
"""
if 'cache' in props or 'cache' in self_props:
if DEBUG:

View File

@ -98,15 +98,15 @@ class Values(object):
"""actually retrieves the value
:param path: the path of the `Option`
:param index: index for a slave `Option`
:param index: index for a follower `Option`
:returns: value
"""
# get owner and value from store
# index allowed only for slave
# index allowed only for follower
index = option_bag.index
is_slave = option_bag.option.impl_is_master_slaves('slave')
if index is None or not is_slave:
is_follower = option_bag.option.impl_is_follower()
if index is None or not is_follower:
_index = None
else:
_index = index
@ -231,7 +231,7 @@ class Values(object):
else:
allow_empty_list = opt.impl_allow_empty_list()
if allow_empty_list is undefined:
allow_empty_list = opt.impl_is_master_slaves('slave')
allow_empty_list = opt.impl_is_follower()
isempty = value is None or (not allow_empty_list and value == []) or \
None in value or empty in value
else:
@ -315,11 +315,11 @@ class Values(object):
meta = context.cfgimpl_get_meta()
if meta is None:
return None
if option_bag.option.impl_is_master_slaves('slave'):
master = option_bag.option.impl_get_master_slaves().getmaster()
masterp = master.impl_getpath()
# slave could be a "meta" only if master hasn't value
if self._p_.hasvalue(masterp,
if option_bag.option.impl_is_follower():
leader = option_bag.option.impl_get_leadership().get_leader()
leaderpath = leader.impl_getpath()
# follower could be a "meta" only if leader hasn't value
if self._p_.hasvalue(leaderpath,
index=None):
return None
doption_bag = option_bag.copy()
@ -432,10 +432,10 @@ class Values(object):
fake_value.setvalue_validation(value,
soption_bag)
opt = option_bag.option
if opt.impl_is_master_slaves('master'):
opt.impl_get_master_slaves().reset(self,
option_bag,
_commit=_commit)
if opt.impl_is_leader():
opt.impl_get_leadership().reset(self,
option_bag,
_commit=_commit)
if hasvalue:
if 'force_store_value' in option_bag.properties:
value = self.getdefaultvalue(option_bag)
@ -449,9 +449,9 @@ class Values(object):
_commit)
context.cfgimpl_reset_cache(option_bag)
def reset_slave(self,
option_bag,
_commit=True):
def reset_follower(self,
option_bag,
_commit=True):
if self._p_.hasvalue(option_bag.path, index=option_bag.index):
context = option_bag.config_bag.context
@ -463,7 +463,7 @@ class Values(object):
config_bag.context = fake_context
soption_bag = option_bag.copy()
soption_bag.config_bag = config_bag
fake_value.reset_slave(soption_bag)
fake_value.reset_follower(soption_bag)
value = fake_value.getdefaultvalue(soption_bag)
fake_value.setvalue_validation(value,
soption_bag)
@ -472,10 +472,10 @@ class Values(object):
_commit)
context.cfgimpl_reset_cache(option_bag)
def reset_master(self,
index,
option_bag,
subconfig):
def reset_leadership(self,
index,
option_bag,
subconfig):
current_value = self.get_cached_value(option_bag)
length = len(current_value)
@ -552,7 +552,7 @@ class Values(object):
elif not option.impl_is_symlinkoption():
# don't verifying symlink
try:
if not option.impl_is_master_slaves('slave'):
if not option.impl_is_follower():
option_bag = OptionBag()
option_bag.set_option(option,
path,