ConfigBag optimisation

This commit is contained in:
Emmanuel Garette 2018-08-01 08:37:58 +02:00
parent acdddcfe9c
commit 41c17004d2
19 changed files with 1163 additions and 1160 deletions

View File

@ -246,7 +246,7 @@ def test_reset_cache():
api.option('u1').value.get()
assert 'u1' in values._p_.get_cached()
assert 'u1' in settings._p_.get_cached()
c.cfgimpl_reset_cache(None, None, None)
c.cfgimpl_reset_cache(None, None)
assert 'u1' not in values._p_.get_cached()
assert 'u1' not in settings._p_.get_cached()
api.option('u1').value.get()
@ -258,7 +258,7 @@ def test_reset_cache():
assert 'u1' in settings._p_.get_cached()
assert 'u2' in values._p_.get_cached()
assert 'u2' in settings._p_.get_cached()
c.cfgimpl_reset_cache(None, None, None)
c.cfgimpl_reset_cache(None, None)
assert 'u1' not in values._p_.get_cached()
assert 'u1' not in settings._p_.get_cached()
assert 'u2' not in values._p_.get_cached()
@ -273,7 +273,7 @@ def test_reset_cache():
# values = c.cfgimpl_get_values()
# api.option('od1.u1').value.get()
# assert 'od1.u1' in values._p_.get_cached()
# c.od1.cfgimpl_reset_cache(None, None, None)
# c.od1.cfgimpl_reset_cache(None, None)
# assert 'od1.u1' not in values._p_.get_cached()

View File

@ -429,10 +429,10 @@ def test_invalid_option():
raises(ValueError, "DomainnameOption('a', '', multi=True, default_multi=1)")
def test_help():
stro = StrOption('s', '', multi=True)
od1 = OptionDescription('o', '', [stro])
od2 = OptionDescription('o', '', [od1])
cfg = Config(od2)
api = getapi(cfg)
api.help(_display=False, _valid=True)
#def test_help():
# stro = StrOption('s', '', multi=True)
# od1 = OptionDescription('o', '', [stro])
# od2 = OptionDescription('o', '', [od1])
# cfg = Config(od2)
# api = getapi(cfg)
# api.help(_display=False, _valid=True)

View File

@ -110,8 +110,8 @@ def test_iter_on_groups():
descr = make_description()
api = getapi(Config(descr))
api.property.read_write()
result = list(api.option('creole').list('optiondescription', group_type=groups.family))
group_names = [res[0] for res in result]
result = api.option('creole').list('optiondescription', group_type=groups.family)
group_names = [res.option.name() for res in result]
assert group_names == ['general', 'interface1']
for i in api.option('creole').list('optiondescription', group_type=groups.family):
#test StopIteration
@ -123,13 +123,15 @@ def test_iter_on_groups_force_permissive():
api = getapi(Config(descr))
api.property.read_write()
api.permissive.set(frozenset(['hidden']))
#result = list(config.creole.general.__iter__(force_permissive=True))
group_names = list(api.forcepermissive.option('creole.general').list())
result = api.forcepermissive.option('creole.general').list()
group_names = [res.option.name() for res in result]
ass = ['numero_etab', 'nom_machine', 'nombre_interfaces',
'activer_proxy_client', 'mode_conteneur_actif',
'mode_conteneur_actif2', 'serveur_ntp', 'time_zone']
assert group_names == ass
group_names = list(api.option('creole.general').list())
# mode_conteneur_actif2 is not visible is not forcepermissive
result = api.option('creole.general').list()
group_names = [res.option.name() for res in result]
ass.remove('mode_conteneur_actif2')
assert group_names == ass
@ -139,8 +141,8 @@ def test_iter_group_on_groups_force_permissive():
api = getapi(Config(descr))
api.property.read_write()
api.permissive.set(frozenset(['hidden']))
result = list(api.forcepermissive.option('creole').list(type='optiondescription', group_type=groups.family))
group_names = [res[0] for res in result]
result = api.forcepermissive.option('creole').list(type='optiondescription', group_type=groups.family)
group_names = [res.option.name() for res in result]
assert group_names == ['general', 'interface1', 'new']
@ -149,8 +151,8 @@ def test_iter_on_groups_props():
api = getapi(Config(descr))
api.property.read_write()
api.option('creole.interface1').property.add('disabled')
result = list(api.option('creole').list(type='optiondescription', group_type=groups.family))
group_names = [res[0] for res in result]
result = api.option('creole').list(type='optiondescription', group_type=groups.family)
group_names = [res.option.name() for res in result]
assert group_names == ['general']

View File

@ -796,33 +796,32 @@ def test_callback_master_and_slaves_slave_cal():
val1 = StrOption('val1', "", multi=True, callback=return_value, callback_params=Params(ParamOption(val3)))
val2 = StrOption('val2', "", multi=True, callback=return_val)
interface1 = MasterSlaves('val1', '', [val1, val2])
#interface1.impl_set_group_type(groups.master)
maconfig = OptionDescription('rootconfig', '', [interface1, val3])
api = getapi(Config(maconfig))
api.property.read_write()
#
assert api.option('val3').value.get() == []
assert api.option('val1.val1').value.get() == []
#
api.option('val1.val1').value.set(['val1'])
api.option('val3').value.set(['val1'])
assert api.option('val1.val1').value.get() == ['val1']
assert api.option('val1.val2', 0).value.get() == 'val'
#
api.option('val1.val1').value.reset()
api.option('val1.val2', 0).value.set('val')
#
api.option('val3').value.set(['val1', 'val2'])
assert api.option('val1.val2', 0).value.get() == 'val'
assert api.option('val1.val2', 1).value.get() == 'val'
assert api.option('val1.val1').value.get() == ['val1', 'val2']
# len of slave is higher than master's one
api.option('val1.val2', 0).value.set('val1')
api.option('val1.val2', 1).value.set('val2')
api.option('val3').value.set(['val1'])
# cannot remove slave's value because master is calculated
# so raise
if TIRAMISU_VERSION == 2:
raises(SlaveError, "api.option('val1.val1').value.get()")
raises(SlaveError, "api.option('val1.val2', 0).value.get()")
else:
assert api.option('val1.val1').value.get() == ['val1']
raises(SlaveError, "api.option('val1.val2', 0).value.get()")
assert api.option('val1.val1').value.get() == ['val1']
raises(SlaveError, "api.option('val1.val2', 0).value.get()")
#
api.option('val3').value.set(['val1', 'val2', 'val3'])
assert api.option('val1.val2', 0).value.get() == 'val1'
assert api.option('val1.val2', 1).value.get() == 'val2'
@ -1020,6 +1019,7 @@ def test_callback_hidden():
api = getapi(Config(maconfig))
api.property.read_write()
raises(PropertiesOptionError, "api.option('od1.opt1').value.get()")
# do not raise, forcepermissive
api.option('od2.opt2').value.get()

View File

@ -5,7 +5,7 @@ do_autopath()
from py.test import raises
try:
from tiramisu.setting import ConfigBag
from tiramisu.setting import OptionBag, ConfigBag
tiramisu_version = 3
except:
tiramisu_version = 2
@ -151,10 +151,12 @@ def test_slots_config():
c = Config(od2)
raises(AttributeError, "c.x = 1")
raises(AttributeError, "c.cfgimpl_x = 1")
if tiramisu_version == 2:
sc = c.getattr('a')
else:
sc = c.getattr('a', None, ConfigBag(c))
option_bag = OptionBag()
option_bag.set_option(od2,
'a',
None,
ConfigBag(c))
sc = c.getattr('a', option_bag)
assert isinstance(sc, SubConfig)
raises(AttributeError, "sc.x = 1")
raises(AttributeError, "sc.cfgimpl_x = 1")

View File

@ -22,7 +22,7 @@ from typing import List, Any, Optional, Callable, Union, Dict
from .error import APIError, ConfigError, SlaveError, PropertiesOptionError
from .i18n import _
from .setting import ConfigBag, owners, Undefined, undefined, FORBIDDEN_SET_PROPERTIES
from .setting import ConfigBag, OptionBag, owners, groups, Undefined, undefined, FORBIDDEN_SET_PROPERTIES
from .config import Config, SubConfig, GroupConfig, MetaConfig
from .option import ChoiceOption
@ -102,35 +102,36 @@ class TiramisuHelp:
options.append(self.tmpl_help.format(space, self.icon, root + 'unrestraint', _('access to option without property restriction')))
options.append(self.tmpl_help.format(space, self.icon, root + 'forcepermissive', _('access to option without verifying permissive property')))
root = '[unrestraint.|forcepermissive.]'
modules = list(self.registers.keys())
modules.sort()
for module_name in modules:
module = self.registers[module_name]
instance_module = module(None)
if isinstance(instance_module, TiramisuDispatcher):
if _valid and not getdoc(module.__call__): # pragma: no cover
raise Exception('unknown doc for {}'.format('__call__'))
module_doc = _(getdoc(module.__call__))
module_signature = signature(module.__call__)
module_args = [str(module_signature.parameters[key]) for key in list(module_signature.parameters.keys())[1:]]
module_args = '(' + ', '.join(module_args) + ')'
options.append(self.tmpl_help.format(space, self.icon, root + module_name + module_args, module_doc))
if hasattr(module, 'subhelp'):
instance_submodule = module.subhelp(None, None, None, None, None)
options.extend(instance_submodule.help(init=False, space=space + ' ', root=root + module_name + module_args + '.'))
else:
root = root + '[config(path).]'
if isinstance(instance_module, CommonTiramisuOption):
if _valid and not getdoc(module): # pragma: no cover
raise Exception('unknown doc for {}'.format(module.__class__.__name__))
module_doc = _(getdoc(module))
options.append(self.tmpl_help.format(space, self.icon, root + module_name, module_doc))
if isinstance(instance_module, TiramisuContext):
if _valid and not getdoc(module): # pragma: no cover
raise Exception('unknown doc for {}'.format(module.__class__.__name__))
module_doc = _(getdoc(module))
options.append(self.tmpl_help.format(space, self.icon, root + module_name, module_doc))
options.extend(instance_module.help(init=False, space=space + ' ', root=root + '{}.'.format(module_name)))
if 'registers' in dir(self):
modules = list(self.registers.keys())
modules.sort()
for module_name in modules:
module = self.registers[module_name]
instance_module = module(None)
if isinstance(instance_module, TiramisuDispatcher):
if _valid and not getdoc(module.__call__): # pragma: no cover
raise Exception('unknown doc for {}'.format('__call__'))
module_doc = _(getdoc(module.__call__))
module_signature = signature(module.__call__)
module_args = [str(module_signature.parameters[key]) for key in list(module_signature.parameters.keys())[1:]]
module_args = '(' + ', '.join(module_args) + ')'
options.append(self.tmpl_help.format(space, self.icon, root + module_name + module_args, module_doc))
if hasattr(module, 'subhelp'):
instance_submodule = module.subhelp(None, None, None, None, None)
options.extend(instance_submodule.help(init=False, space=space + ' ', root=root + module_name + module_args + '.'))
else:
root = root + '[config(path).]'
if isinstance(instance_module, CommonTiramisuOption):
if _valid and not getdoc(module): # pragma: no cover
raise Exception('unknown doc for {}'.format(module.__class__.__name__))
module_doc = _(getdoc(module))
options.append(self.tmpl_help.format(space, self.icon, root + module_name, module_doc))
if isinstance(instance_module, TiramisuContext):
if _valid and not getdoc(module): # pragma: no cover
raise Exception('unknown doc for {}'.format(module.__class__.__name__))
module_doc = _(getdoc(module))
options.append(self.tmpl_help.format(space, self.icon, root + module_name, module_doc))
options.extend(instance_module.help(init=False, space=space + ' ', root=root + '{}.'.format(module_name)))
funcs = dir(self)
funcs.sort()
@ -159,20 +160,21 @@ class CommonTiramisu(TiramisuHelp):
registers = {}
def _get_option(self) -> Any:
option = self.config_bag.option
option = self.option_bag.option
if option is None:
option = self.subconfig.cfgimpl_get_description().impl_getchild(self._name,
self.config_bag,
self.subconfig)
self.config_bag.option = option
self.option_bag.set_option(option,
self._path,
self.index,
self.config_bag)
if self.config_bag.setting_properties:
self.config_bag.config.cfgimpl_get_settings().validate_properties(self._path,
self.index,
self.config_bag)
self.config_bag.config.cfgimpl_get_settings().validate_properties(self.option_bag)
if self.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(option, self.config_bag)
self._length = self.subconfig.cfgimpl_get_length_slave(self.option_bag)
if self.index >= self._length:
raise SlaveError(_('index "{}" is higher than the master length "{}" '
'for option "{}"').format(self.index,
@ -188,14 +190,16 @@ class CommonTiramisuOption(CommonTiramisu):
slave_need_index = True
def __init__(self,
name: Optional[str],
path: Optional[str]=None,
index: Optional[int]=None,
subconfig: Any=None,
config_bag: Optional[ConfigBag]=None) -> None:
name: str,
path: str,
index: int,
subconfig: Union[Config, SubConfig],
config_bag: ConfigBag,
option_bag: OptionBag) -> None:
self._path = path
self.index = index
self.config_bag = config_bag
self.option_bag = option_bag
self._name = name
self.subconfig = subconfig
if config_bag is not None and self.slave_need_index:
@ -310,7 +314,8 @@ class TiramisuOptionOption(CommonTiramisuOption):
return option.impl_getrequires()
def __getattr__(self, name: str) -> Callable:
if not self._get_option().impl_is_optiondescription() and name != 'get_option':
#if not self._get_option().impl_is_optiondescription() and name != 'get_option':
if not self._get_option().impl_is_optiondescription():
subkey = '_' + name
if subkey in dir(self):
func = getattr(self, subkey)
@ -327,17 +332,19 @@ class TiramisuOptionOwner(CommonTiramisuOption):
"""manager option's owner"""
def __init__(self,
name: Optional[str],
path: Optional[str]=None,
index: Optional[int]=None,
subconfig: Union[None, Config, SubConfig]=None,
config_bag: Optional[ConfigBag]=None) -> None:
name: str,
path: str,
index: int,
subconfig: Union[Config, SubConfig],
config_bag: ConfigBag,
option_bag: OptionBag) -> None:
super().__init__(name,
path,
index,
subconfig,
config_bag)
config_bag,
option_bag)
if config_bag:
self.values = self.config_bag.config.cfgimpl_get_values()
@ -345,17 +352,13 @@ class TiramisuOptionOwner(CommonTiramisuOption):
def get(self):
"""get owner for a specified option"""
option = self._get_option()
return self.values.getowner(self._path,
self.index,
self.config_bag)
return self.values.getowner(self.option_bag)
@count
def isdefault(self):
"""is option has defaut value"""
self._get_option()
return self.values.is_default_owner(self._path,
self.index,
self.config_bag)
return self.values.is_default_owner(self.option_bag)
@count
def set(self, owner):
@ -369,10 +372,8 @@ class TiramisuOptionOwner(CommonTiramisuOption):
except AttributeError:
owners.addowner(owner)
obj_owner = getattr(owners, owner)
self.values.setowner(self._path,
self.index,
obj_owner,
self.config_bag)
self.values.setowner(obj_owner,
self.option_bag)
class TiramisuOptionProperty(CommonTiramisuOption):
@ -381,16 +382,18 @@ class TiramisuOptionProperty(CommonTiramisuOption):
slave_need_index = False
def __init__(self,
name: Optional[str],
path: Optional[str]=None,
index: Optional[int]=None,
subconfig: Union[None, Config, SubConfig]=None,
config_bag: Optional[ConfigBag]=None) -> None:
name: str,
path: str,
index: int,
subconfig: Union[Config, SubConfig],
config_bag: ConfigBag,
option_bag: OptionBag) -> None:
super().__init__(name,
path,
index,
subconfig,
config_bag)
config_bag,
option_bag)
if config_bag:
self.settings = config_bag.config.cfgimpl_get_settings()
@ -400,12 +403,9 @@ class TiramisuOptionProperty(CommonTiramisuOption):
self._get_option()
if apply_requires:
self._test_slave_index()
properties = self.settings.getproperties(self._path,
self.index,
self.config_bag,
apply_requires)
if TIRAMISU_VERSION == 2:
properties = properties.get()
else:
self.option_bag.apply_requires = False
properties = self.option_bag.properties
return set(properties)
@count
@ -415,33 +415,27 @@ class TiramisuOptionProperty(CommonTiramisuOption):
if prop in FORBIDDEN_SET_PROPERTIES:
raise ConfigError(_('cannot add this property: "{0}"').format(
' '.join(prop)))
props = self.settings.getproperties(self._path,
None,
self.config_bag,
props = self.settings.getproperties(self.option_bag,
apply_requires=False)
self.settings.setproperties(self._path,
props | {prop},
self.config_bag)
self.option_bag)
@count
def pop(self, prop):
"""remove new property for an option"""
self._get_option()
props = self.settings.getproperties(self._path,
self.index,
self.config_bag,
props = self.settings.getproperties(self.option_bag,
apply_requires=False)
self.settings.setproperties(self._path,
props - {prop},
self.config_bag)
self.option_bag)
@count
def reset(self):
"""reset all personalised properties"""
self._get_option()
self.settings.reset(self.config_bag.option,
self._path,
self.config_bag)
self.settings.reset(self.option_bag)
class TiramisuOptionPermissive(CommonTiramisuOption):
@ -450,16 +444,18 @@ class TiramisuOptionPermissive(CommonTiramisuOption):
slave_need_index = False
def __init__(self,
name: Optional[str],
path: Optional[str]=None,
index: Optional[int]=None,
subconfig: Union[None, Config, SubConfig]=None,
config_bag: Optional[ConfigBag]=None) -> None:
name: str,
path: str,
index: int,
subconfig: Union[Config, SubConfig],
config_bag: ConfigBag,
option_bag: OptionBag) -> None:
super().__init__(name,
path,
index,
subconfig,
config_bag)
config_bag,
option_bag)
if config_bag:
self.settings = config_bag.config.cfgimpl_get_settings()
@ -475,21 +471,9 @@ class TiramisuOptionPermissive(CommonTiramisuOption):
@count
def set(self, permissives):
"""set permissives value"""
if TIRAMISU_VERSION == 2:
permissives = tuple(permissives)
path = self._path
opt = self._opt
self.settings.setpermissive(opt=opt,
path=path,
config_bag=self.config_bag,
permissive=permissives)
else:
path = self._path
opt = self._get_option()
self.settings.setpermissive(opt=opt,
path=path,
config_bag=self.config_bag,
permissives=permissives)
self._get_option()
self.settings.setpermissive(self.option_bag,
permissives=permissives)
@count
def reset(self):
@ -526,12 +510,10 @@ class TiramisuOptionValue(CommonTiramisuOption):
@count
def get(self):
"""get option's value"""
self._get_option()
self._test_slave_index()
settings = self.config_bag.config.cfgimpl_get_settings()
value = self.subconfig.getattr(self._name,
self.index,
self.config_bag)
self.option_bag)
#if isinstance(value, Multi):
# value = list(value)
return value
@ -545,35 +527,35 @@ class TiramisuOptionValue(CommonTiramisuOption):
if isinstance(value, list):
while undefined in value:
idx = value.index(undefined)
value[idx] = values.getdefaultvalue(self._path,
idx,
self.config_bag)
option_bag = OptionBag()
option_bag.set_option(self.option_bag.option,
self.option_bag.path,
idx,
self.config_bag)
value[idx] = values.getdefaultvalue(option_bag)
else:
if value == undefined:
value = values.getdefaultvalue(self._path,
self.index,
self.config_bag)
self.subconfig.setattr(self._name,
self.index,
value,
self.config_bag)
value = values.getdefaultvalue(self.option_bag)
self.subconfig.setattr(value,
self.option_bag)
@count
def _pop(self, index):
"""pop value for a master option (only for master option)"""
self._get_option()
self.config_bag.config.delattr(self._path,
index,
self.config_bag)
if self.option_bag.option.impl_is_symlinkoption():
raise TypeError(_("can't delete a SymLinkOption"))
self.config_bag.config.cfgimpl_get_values().reset_master(index,
self.option_bag,
self.subconfig)
@count
def reset(self):
"""reset value for a value"""
self._get_option()
self._test_slave_index()
self.config_bag.config.delattr(self._path,
self.index,
self.config_bag)
#self.config_bag.config.delattr(self.option_bag)
self.subconfig.delattr(self.option_bag)
@count
def _len_master(self):
@ -590,7 +572,7 @@ class TiramisuOptionValue(CommonTiramisuOption):
option = self._get_option()
# for example if index is None
if '_length' not in vars(self):
self._length = self.subconfig.cfgimpl_get_length_slave(option, self.config_bag)
self._length = self.subconfig.cfgimpl_get_length_slave(self.option_bag)
return self._length
def __getattr__(self, name: str) -> Callable:
@ -608,7 +590,8 @@ class TiramisuOptionValue(CommonTiramisuOption):
@count
def _list(self):
"""all values available for an option (only for choiceoption)"""
return self.config_bag.option.impl_get_values(self.config_bag)
self._get_option()
return self._get_option().impl_get_values(self.option_bag)
def registers(registers: Dict[str, type], prefix: str) -> None:
@ -620,19 +603,27 @@ def registers(registers: Dict[str, type], prefix: str) -> None:
class TiramisuOption(CommonTiramisu):
registers = {}
def __init__(self,
name: Optional[str],
path: Optional[str]=None,
index: Optional[int]=None,
subconfig: Union[None, Config, SubConfig]=None,
config_bag: Optional[ConfigBag]=None) -> None:
config_bag: Optional[ConfigBag]=None,
option_bag: Optional[OptionBag]=None) -> None:
self._name = name
self.subconfig = subconfig
if subconfig == None:
raise Exception()
self._path = path
self.index = index
self.config_bag = config_bag
self.registers = {}
registers(self.registers, self.__class__.__name__)
if option_bag:
self.option_bag = option_bag
else:
self.option_bag = OptionBag()
if not self.registers:
registers(self.registers, self.__class__.__name__)
def __getattr__(self, subfunc: str) -> Any:
if subfunc in self.registers:
@ -640,11 +631,14 @@ class TiramisuOption(CommonTiramisu):
self._path,
self.index,
self.subconfig,
self.config_bag)
self.config_bag,
self.option_bag)
elif subfunc == 'make_dict' and self._get_option().impl_is_optiondescription():
return self._make_dict
elif subfunc == 'find' and self._get_option().impl_is_optiondescription():
return self._find
elif subfunc == 'get' and self._get_option().impl_is_optiondescription():
return self._get
elif subfunc == 'list' and self._get_option().impl_is_optiondescription():
return self._list
elif subfunc == 'group_type' and self._get_option().impl_is_optiondescription():
@ -659,9 +653,9 @@ class TiramisuOption(CommonTiramisu):
withoption=None,
fullpath=False):
"""return dict with path as key and value for an optiondescription (only for optiondescription)"""
self._get_option()
return self.config_bag.config.getattr(self._path,
None,
self.config_bag).make_dict(config_bag=self.config_bag,
self.option_bag).make_dict(config_bag=self.config_bag,
flatten=flatten,
fullpath=fullpath,
withoption=withoption,
@ -680,19 +674,42 @@ class TiramisuOption(CommonTiramisu):
bytype=type,
_subpath=self._path,
config_bag=self.config_bag):
config_bag = self.config_bag.copy('nooption')
subconfig, name = config_bag.config.cfgimpl_get_home_by_path(path,
config_bag)
subconfig, name = self.config_bag.config.cfgimpl_get_home_by_path(path,
self.config_bag)
t_option = TiramisuOption(name,
path,
None, # index for a slave ?
subconfig,
config_bag)
self.config_bag)
if first:
return t_option
ret.append(t_option)
return ret
@count
def _get(self, name):
self._get_option()
current_option = self.option_bag.option.impl_getchild(name,
self.config_bag,
self.subconfig)
path = self.option_bag.path + '.' + name
option_bag= OptionBag()
option_bag.set_option(current_option,
path,
None,
self.config_bag)
if current_option.impl_is_optiondescription():
subconfig = self.subconfig.getattr(name,
option_bag)
else:
subconfig = self.subconfig
return TiramisuOption(name,
path,
None,
subconfig,
self.config_bag,
option_bag)
@count
def _group_type(self):
"""get type for an optiondescription (only for optiondescription)"""
@ -703,26 +720,57 @@ class TiramisuOption(CommonTiramisu):
type='all',
group_type=None):
"""list options in an optiondescription (only for optiondescription)"""
if type == 'optiondescription':
return self.config_bag.config.getattr(self._path,
None,
self.config_bag
).iter_groups(self.config_bag, group_type)
elif type == 'all':
return self.config_bag.config.getattr(self._path,
None,
self.config_bag
).cfgimpl_get_children(self.config_bag)
else:
if type not in ('all', 'optiondescription'):
raise APIError(_('unknown list type {}').format(type))
if group_type is not None and not isinstance(group_type,
groups.GroupType):
raise TypeError(_("unknown group_type: {0}").format(group_type))
def _filter(opt):
if not self.config_bag.force_unrestraint:
name = opt.impl_getname()
path = subconfig._get_subpath(name)
option_bag = OptionBag()
option_bag.set_option(opt,
path,
None,
self.config_bag)
self.subconfig.getattr(name,
option_bag)
option = self._get_option()
name = option.impl_getname()
path = self.subconfig._get_subpath(name)
option_bag = OptionBag()
option_bag.set_option(option,
path,
None,
self.config_bag)
subconfig = self.subconfig.getattr(name,
option_bag)
for opt in option.impl_getchildren(self.config_bag):
try:
subsubconfig = _filter(opt)
except PropertiesOptionError:
continue
if opt.impl_is_optiondescription():
if type == 'optiondescription' and \
(group_type and opt.impl_get_group_type() != group_type):
continue
else:
if type == 'optiondescription':
continue
name = opt.impl_getname()
yield TiramisuOption(name,
subconfig._get_subpath(name),
None,
subconfig,
self.config_bag)
class TiramisuContext(TiramisuHelp):
def __init__(self,
config_bag: Optional[ConfigBag]) -> None:
self.config_bag = config_bag
self.registers = {}
registers(self.registers, self.__class__.__name__)
class TiramisuContextInformation(TiramisuContext):
@ -778,7 +826,8 @@ class TiramisuContextValue(TiramisuContext):
def reset(self,
path):
"""reset value for a GroupConfig or a MetaConfig"""
self.config_bag.config.reset(path, self.config_bag)
self.config_bag.config.reset(path,
self.config_bag)
@count
def exportation(self):
@ -789,7 +838,7 @@ class TiramisuContextValue(TiramisuContext):
def importation(self, values):
"""import values"""
self.config_bag.config.cfgimpl_get_values()._p_.importation(values)
self.config_bag.config.cfgimpl_reset_cache(None, None, None)
self.config_bag.config.cfgimpl_reset_cache(None, None)
class TiramisuContextOwner(TiramisuContext):
@ -819,7 +868,10 @@ class TiramisuContextProperty(TiramisuContext):
"""set configuration to read only mode"""
settings = self.config_bag.config.cfgimpl_get_settings()
settings.read_only()
self.config_bag.delete('setting_properties')
try:
del self.config_bag.setting_properties
except AttributeError:
pass
@count
def read_write(self):
@ -828,7 +880,10 @@ class TiramisuContextProperty(TiramisuContext):
settings.read_write()
# #FIXME ?
settings.set_context_permissive(frozenset(['hidden']))
self.config_bag.delete('setting_properties')
try:
del self.config_bag.setting_properties
except AttributeError:
pass
#/FIXME ?
@count
@ -859,9 +914,7 @@ class TiramisuContextProperty(TiramisuContext):
@count
def reset(self):
"""remove configuration properties"""
self.config_bag.config.cfgimpl_get_settings().reset(None,
None,
None)
self.config_bag.config.cfgimpl_get_settings().reset(None)
@count
def exportation(self):
@ -872,7 +925,8 @@ class TiramisuContextProperty(TiramisuContext):
def importation(self, properties):
"""import configuration properties"""
self.config_bag.config.cfgimpl_get_settings()._p_.importation(properties)
self.config_bag.config.cfgimpl_reset_cache(None, None, None)
self.config_bag.config.cfgimpl_reset_cache(None,
None)
class TiramisuContextPermissive(TiramisuContext):
@ -897,7 +951,8 @@ class TiramisuContextPermissive(TiramisuContext):
def importation(self, permissives):
"""import configuration permissives"""
self.config_bag.config.cfgimpl_get_settings()._pp_.importation(permissives)
self.config_bag.config.cfgimpl_reset_cache(None, None, None)
self.config_bag.config.cfgimpl_reset_cache(None,
None)
@ -918,28 +973,28 @@ class TiramisuContextOption(TiramisuContext):
bytype=type,
#_subpath=self._path,
config_bag=self.config_bag):
config_bag = self.config_bag.copy('nooption')
subconfig, name = config_bag.config.cfgimpl_get_home_by_path(path,
config_bag)
subconfig, name = self.config_bag.config.cfgimpl_get_home_by_path(path,
self.config_bag)
t_option = TiramisuOption(name,
path,
None, # index for a slave ?
subconfig,
config_bag)
self.config_bag)
if first:
return t_option
ret.append(t_option)
return ret
#@count
#def get(self, path):
# """"""
# config_bag = self.config_bag.copy()
# config_bag.validate = False
# config_bag.force_unrestraint = True
# config_bag.setting_properties = None
# return self.config_bag.config.unwrap_from_path(path,
# config_bag)
@count
def get(self, name):
option = self.config_bag.config.cfgimpl_get_description().impl_getchild(name,
self.config_bag,
self.config_bag.config)
return TiramisuOption(name,
name,
None,
self.config_bag.config,
self.config_bag)
@count
def make_dict(self,
@ -960,11 +1015,24 @@ class TiramisuContextOption(TiramisuContext):
group_type=None,
recursive=False):
"""list content of an optiondescription"""
# FIXME should return TiramisuOption !!!
if group_type is not None and not isinstance(group_type,
groups.GroupType):
raise TypeError(_("unknown group_type: {0}").format(group_type))
if type == 'optiondescription':
if recursive:
raise APIError(_('not implemented yet'))
else:
return self.config_bag.config.iter_groups(self.config_bag, group_type)
if not self.config_bag.force_unrestraint:
option = self.config_bag.config.cfgimpl_get_description()
for opt in option.impl_getchildren(self.config_bag):
if type == 'optiondescription' and not opt.impl_is_optiondescription():
continue
yield opt.impl_getname()
else:
# FIXME itergroups !!!
return self.config_bag.config.iter_groups(self.config_bag, group_type)
elif type == 'all':
if group_type:
raise APIError(_('not implemented yet'))
@ -998,68 +1066,80 @@ class TiramisuDispatcher:
pass
class TiramisuAPI(TiramisuHelp):
registers = {}
def __init__(self,
config: Union[Config, GroupConfig, MetaConfig, ConfigBag]) -> None:
self._config = config
if not self.registers:
registers(self.registers, 'TiramisuContext')
registers(self.registers, 'TiramisuDispatcher')
def __getattr__(self, subfunc: str) -> Any:
if subfunc == 'forcepermissive':
if isinstance(self._config, ConfigBag):
config = self._config.config
force = self._config.force_unrestraint
else:
config = self._config
force = None
config_bag = ConfigBag(config=config,
force_permissive=True)
if force is not None:
config_bag.force_unrestraint = force
return TiramisuAPI(config_bag)
elif subfunc == 'unrestraint':
if isinstance(self._config, ConfigBag):
config = self._config.config
force = self._config.force_permissive
else:
config = self._config
force = None
config_bag = ConfigBag(config=config,
force_unrestraint=True)
if force is not None:
config_bag.force_permissive = force
return TiramisuAPI(config_bag)
elif subfunc in self.registers:
if not isinstance(self._config, ConfigBag):
config_bag = ConfigBag(config=self._config)
else:
config_bag = self._config
return self.registers[subfunc](config_bag)
else:
raise APIError(_('please specify a valid sub function ({})').format(subfunc))
class TiramisuDispatcherConfig(TiramisuDispatcher, TiramisuContextConfig):
def __call__(self, path: Optional[str]):
def __call__(self,
path: Optional[str]) -> TiramisuAPI:
"""select a child Tiramisu configuration (only with MetaConfig or GroupConfig)"""
config = self.config_bag.config
if path is None:
return TiramisuAPI(config,
force_permissive=self.config_bag.force_permissive,
force_unrestraint=self.config_bag.force_unrestraint)
return TiramisuAPI(self.config_bag)
spaths = path.split('.')
config = self.config_bag.config
for spath in spaths:
config = config.getconfig(spath)
return TiramisuAPI(config,
force_permissive=self.config_bag.force_permissive,
force_unrestraint=self.config_bag.force_unrestraint)
config_bag = ConfigBag(config=config,
force_unrestraint=self.config_bag.force_unrestraint,
force_permissive=self.config_bag.force_permissive)
return TiramisuAPI(config_bag)
class TiramisuDispatcherOption(TiramisuDispatcher, TiramisuContextOption):
subhelp = TiramisuOption
def __call__(self, path: str, index: Optional[int]=None) -> TiramisuOption:
def __call__(self,
path: str,
index: Optional[int]=None) -> TiramisuOption:
"""select a option (index only for slave option)"""
config_bag = self.config_bag.copy()
validate = not config_bag.force_unrestraint
if not validate:
config_bag.setting_properties = None
subconfig, name = config_bag.config.cfgimpl_get_home_by_path(path,
config_bag)
subconfig, name = self.config_bag.config.cfgimpl_get_home_by_path(path,
self.config_bag)
return TiramisuOption(name,
path,
index,
subconfig,
config_bag)
class TiramisuAPI(TiramisuHelp):
def __init__(self,
config: Union[Config, GroupConfig, MetaConfig],
force_permissive: bool=False,
force_unrestraint: bool=False) -> None:
self._config = config
self.force_permissive = force_permissive
self.force_unrestraint = force_unrestraint
self.registers = {}
registers(self.registers, 'TiramisuContext')
registers(self.registers, 'TiramisuDispatcher')
def __getattr__(self, subfunc: str) -> Any:
if subfunc == 'forcepermissive':
return TiramisuAPI(config=self._config,
force_permissive=True,
force_unrestraint=self.force_unrestraint)
elif subfunc == 'unrestraint':
return TiramisuAPI(config=self._config,
force_permissive=self.force_permissive,
force_unrestraint=True)
elif subfunc in self.registers:
config_bag = ConfigBag(config=self._config,
force_permissive=self.force_permissive,
force_unrestraint=self.force_unrestraint)
return self.registers[subfunc](config_bag)
else:
raise APIError(_('please specify a valid sub function ({})').format(subfunc))
self.config_bag)
@count

View File

@ -23,7 +23,7 @@ from typing import Any, Optional, Union, Callable, Dict, List
from .error import PropertiesOptionError, ConfigError, SlaveError
from .i18n import _
from .setting import undefined, ConfigBag, Undefined
from .setting import undefined, ConfigBag, OptionBag, Undefined
from .option.symlinkoption import DynSymLinkOption
from .storage import get_default_values_storages, get_default_settings_storages
from .function import ParamValue, ParamContext, ParamIndex, ParamOption, Params
@ -34,7 +34,7 @@ def manager_callback(callbk: Union[ParamOption, ParamValue],
option,
index: Optional[int],
orig_value,
config_bag: ConfigBag,
option_bag: OptionBag,
context) -> Any:
"""replace Param by true value"""
if isinstance(callbk, ParamValue):
@ -55,10 +55,6 @@ def manager_callback(callbk: Union[ParamOption, ParamValue],
path = opt.impl_getpath(context)
else:
path = context.cfgimpl_get_description().impl_get_path_by_opt(opt)
# don't validate if option is option that we tried to validate
sconfig_bag = config_bag.copy('nooption')
sconfig_bag.option = opt
sconfig_bag.force_permissive = True
if index is not None and opt.impl_is_master_slaves() and \
opt.impl_get_master_slaves().in_same_group(option):
if opt == option:
@ -76,15 +72,25 @@ def manager_callback(callbk: Union[ParamOption, ParamValue],
if opt == option and orig_value is not undefined and \
(not opt.impl_is_master_slaves('slave') or index is None):
return orig_value
# don't validate if option is option that we tried to validate
config_bag = ConfigBag(config=option_bag.config_bag.config,
_setting_properties=option_bag.config_bag._setting_properties,
force_permissive=True,
force_unrestraint=option_bag.config_bag.force_unrestraint,
_validate=option_bag.config_bag._validate)
soption_bag = OptionBag()
soption_bag.set_option(opt,
path,
index_,
config_bag)
soption_bag.fromconsistency = option_bag.fromconsistency.copy()
if opt == option:
sconfig_bag.setting_properties = None
sconfig_bag.force_unrestraint= False
sconfig_bag.validate = False
soption_bag.config_bag.force_unrestraint = True
soption_bag.config_bag.validate = False
try:
# get value
value = context.getattr(path,
index_,
sconfig_bag)
soption_bag)
if with_index:
return value[index]
return value
@ -100,7 +106,7 @@ def carry_out_calculation(option,
callback: Callable,
callback_params: Optional[Params],
index: Optional[int],
config_bag: Optional[ConfigBag],
option_bag: Optional[OptionBag],
orig_value=undefined,
is_validator: int=False):
@ -217,7 +223,7 @@ def carry_out_calculation(option,
kwargs = {}
# if callback_params has a callback, launch several time calculate()
if option.issubdyn():
#FIXME why here? should be ParamSuffix !
#FIXME why here? should be a ParamSuffix !
kwargs['suffix'] = option.impl_getsuffix()
if callback_params:
for callbk in callback_params.args:
@ -226,7 +232,7 @@ def carry_out_calculation(option,
option,
index,
orig_value,
config_bag,
option_bag,
context)
if value is undefined:
return undefined
@ -239,7 +245,7 @@ def carry_out_calculation(option,
option,
index,
orig_value,
config_bag,
option_bag,
context)
if value is undefined:
return undefined

View File

@ -20,7 +20,6 @@
# ____________________________________________________________
"options handler global entry point"
import weakref
from time import time
from copy import copy
@ -29,7 +28,7 @@ from .option.syndynoptiondescription import SynDynOptionDescription
from .option.dynoptiondescription import DynOptionDescription
from .option.masterslave import MasterSlaves
from .option.baseoption import BaseOption, valid_name
from .setting import ConfigBag, groups, Settings, undefined
from .setting import OptionBag, ConfigBag, groups, Settings, undefined
from .storage import get_storages, get_default_values_storages
from .value import Values # , Multi
from .i18n import _
@ -50,7 +49,8 @@ class SubConfig(object):
descr,
context,
config_bag,
subpath=None):
subpath=None,
fromconsistency=None):
""" Configuration option management master class
:param descr: describes the configuration schema
@ -73,23 +73,38 @@ class SubConfig(object):
descr.impl_get_group_type() == groups.master:
master = descr.getmaster()
masterpath = master.impl_getname()
mconfig_bag = config_bag.copy('nooption')
mconfig_bag.option = master
mconfig_bag.validate = False
full_masterpath = self._get_subpath(masterpath)
cconfig_bag = ConfigBag(config=config_bag.config,
_setting_properties=config_bag._setting_properties,
force_permissive=config_bag.force_permissive,
force_unrestraint=config_bag.force_unrestraint,
_validate=False)
moption_bag = OptionBag()
moption_bag.set_option(master,
full_masterpath,
None,
cconfig_bag)
if fromconsistency:
moption_bag.fromconsistency = fromconsistency
value = self.getattr(masterpath,
None,
mconfig_bag)
moption_bag)
self._impl_length = len(value)
def cfgimpl_get_length(self):
return self._impl_length
def cfgimpl_get_length_slave(self, option, config_bag):
if option.impl_is_symlinkoption():
def cfgimpl_get_length_slave(self,
option_bag):
if option_bag.option.impl_is_symlinkoption():
context = self.cfgimpl_get_context()
sconfig_bag = config_bag.copy('nooption')
subconfig, _ = context.cfgimpl_get_home_by_path(option.impl_getopt().impl_getpath(context),
sconfig_bag)
#soption_bag = OptionBag()
#soption_bag.set_option(option_bag.option.impl_getopt(),
# option_bag.option.impl_getopt().impl_getpath(context),
# None,
# option_bag.config_bag)
path = option_bag.option.impl_getopt().impl_getpath(context)
subconfig, _ = context.cfgimpl_get_home_by_path(path,
option_bag.config_bag)
return subconfig.cfgimpl_get_length()
else:
return self.cfgimpl_get_length()
@ -99,54 +114,65 @@ class SubConfig(object):
values,
settings,
resetted_opts,
config_bag,
opt,
path):
option_bag):
if path in resetted_opts:
if option_bag.path in resetted_opts:
return
resetted_opts.append(path)
for woption in opt._get_dependencies(self):
resetted_opts.append(option_bag.path)
for woption in option_bag.option._get_dependencies(self):
option = woption()
if option.impl_is_dynoptiondescription():
for doption in option.get_syndynoptiondescriptions(config_bag):
for doption in option.get_syndynoptiondescriptions(option_bag):
doption_path = doption.impl_getpath(self)
doption_bag = OptionBag()
doption_bag.set_option(doption,
doption_path,
option_bag.index,
option_bag.config_bag)
self.reset_one_option_cache(desc,
values,
settings,
resetted_opts,
config_bag,
doption,
doption_path)
doption_bag)
elif option.issubdyn():
for doption in desc.build_dynoptions(option, config_bag):
doption_bag = OptionBag()
doption_path = option.impl_getpath(self)
doption_bag.set_option(option,
doption_path,
option_bag.index,
option_bag.config_bag)
for doption in desc.build_dynoptions(doption_bag):
doption_path = doption.impl_getpath(self)
doption_bag = OptionBag()
doption_bag.set_option(doption,
doption_path,
option_bag.index,
option_bag.config_bag)
self.reset_one_option_cache(desc,
values,
settings,
resetted_opts,
config_bag,
doption,
doption_path)
doption_bag)
else:
option_path = option.impl_getpath(self)
doption_bag = OptionBag()
doption_bag.set_option(option,
option_path,
option_bag.index,
option_bag.config_bag)
self.reset_one_option_cache(desc,
values,
settings,
resetted_opts,
config_bag,
option,
option_path)
doption_bag)
del option
opt.reset_cache(path,
values,
settings,
resetted_opts)
option_bag.option.reset_cache(option_bag.path,
values,
settings,
resetted_opts)
def cfgimpl_reset_cache(self,
opt,
path,
config_bag,
option_bag,
resetted_opts=None):
"""reset all settings in cache
"""
@ -158,79 +184,40 @@ class SubConfig(object):
values = context.cfgimpl_get_values()
settings = context.cfgimpl_get_settings()
if not None in (opt, path):
if option_bag is not None:
self.reset_one_option_cache(desc,
values,
settings,
resetted_opts,
config_bag,
opt,
path)
option_bag)
else:
values._p_.reset_all_cache()
settings._p_.reset_all_cache()
def cfgimpl_get_home_by_path(self,
path,
config_bag):
config_bag,
fromconsistency=None):
""":returns: tuple (config, name)"""
path = path.split('.')
for step in path[:-1]:
sconfig_bag = config_bag.copy('nooption')
option_bag = OptionBag()
option = self.cfgimpl_get_description().impl_getchild(step,
config_bag,
self)
subpath = self._get_subpath(step)
option_bag.set_option(option,
subpath,
None,
config_bag)
if fromconsistency is not None:
option_bag.fromconsistency = fromconsistency
self = self.getattr(step,
None,
sconfig_bag)
option_bag)
if not isinstance(self, SubConfig):
raise AttributeError(_('unknown option {}').format(path[-1]))
return self, path[-1]
# ______________________________________________________________________
def iter_groups(self,
config_bag,
group_type=None):
"""iteration on groups objects only.
All groups are returned if `group_type` is `None`, otherwise the groups
can be filtered by categories (families, or whatever).
:param group_type: if defined, is an instance of `groups.GroupType`
or `groups.MasterGroupType` that lives in
`setting.groups`
"""
if group_type is not None and not isinstance(group_type,
groups.GroupType):
raise TypeError(_("unknown group_type: {0}").format(group_type))
for child in self.cfgimpl_get_description().impl_getchildren(config_bag):
if child.impl_is_optiondescription():
nconfig_bag = config_bag.copy('nooption')
nconfig_bag.option = child
try:
if group_type is None or (group_type is not None and
child.impl_get_group_type()
== group_type):
name = child.impl_getname()
yield name, self.getattr(name,
None,
nconfig_bag)
except PropertiesOptionError:
pass
def cfgimpl_get_children(self,
config_bag):
context = self.cfgimpl_get_context()
for opt in self.cfgimpl_get_description().impl_getchildren(config_bag):
nconfig_bag = config_bag.copy('nooption')
nconfig_bag.option = opt
name = opt.impl_getname()
if nconfig_bag.setting_properties is not None:
subpath = self._get_subpath(name)
try:
context.cfgimpl_get_settings().validate_properties(subpath,
None,
nconfig_bag)
except PropertiesOptionError:
continue
yield name
# ______________________________________________________________________
def cfgimpl_get_context(self):
"""context could be None, we need to test it
@ -245,7 +232,7 @@ class SubConfig(object):
def cfgimpl_get_description(self):
if self._impl_descr is None:
raise ConfigError(_('no option description found for this config'
raise ConfigError(_('there is no option description for this config'
' (may be GroupConfig)'))
else:
return self._impl_descr
@ -257,63 +244,39 @@ class SubConfig(object):
return self.cfgimpl_get_context()._impl_values
def setattr(self,
name,
index,
value,
config_bag,
option_bag,
_commit=True):
context = self.cfgimpl_get_context()
if '.' in name:
# when set_value
self, name = self.cfgimpl_get_home_by_path(name,
config_bag)
if config_bag.option is None:
config_bag.option = self.cfgimpl_get_description().impl_getchild(name,
config_bag,
self)
if config_bag.option.impl_is_symlinkoption():
#self, name = self.cfgimpl_get_home_by_path(option_bag.path,
# option_bag.config_bag)
#if config_bag.option is None:
# config_bag.option = self.cfgimpl_get_description().impl_getchild(name,
# config_bag,
# self)
if option_bag.option.impl_is_symlinkoption():
raise ConfigError(_("can't assign to a SymLinkOption"))
else:
path = self._get_subpath(name)
if config_bag.setting_properties:
context.cfgimpl_get_settings().validate_properties(path,
index,
config_bag)
self.cfgimpl_get_description().impl_validate_value(config_bag.option,
context = self.cfgimpl_get_context()
if option_bag.config_bag.setting_properties:
context.cfgimpl_get_settings().validate_properties(option_bag)
self.cfgimpl_get_description().impl_validate_value(option_bag.option,
value,
self)
return context.cfgimpl_get_values().setvalue(path,
index,
value,
config_bag,
return context.cfgimpl_get_values().setvalue(value,
option_bag,
_commit)
def delattr(self,
name,
index,
config_bag):
if '.' in name:
self, name = self.cfgimpl_get_home_by_path(name,
config_bag)
option = config_bag.option
option_bag):
option = option_bag.option
if option.impl_is_symlinkoption():
raise TypeError(_("can't delete a SymLinkOption"))
subpath = self._get_subpath(name)
values = self.cfgimpl_get_values()
if index is not None:
if option.impl_is_master_slaves('master'):
values.reset_master(self,
subpath,
index,
config_bag)
elif option.impl_is_master_slaves('slave'):
values.reset_slave(subpath,
index,
config_bag)
if option_bag.index is not None:
values.reset_slave(option_bag)
else:
values.reset(subpath,
config_bag)
values.reset(option_bag)
def _get_subpath(self, name):
if self._impl_path is None:
@ -324,71 +287,73 @@ class SubConfig(object):
def getattr(self,
name,
index,
config_bag):
option_bag):
"""
attribute notation mechanism for accessing the value of an option
:param name: attribute name
:return: option's value if name is an option name, OptionDescription
otherwise
"""
config_bag = option_bag.config_bag
if '.' in name:
if option_bag.fromconsistency:
fromconsistency = option_bag.fromconsistency.copy()
else:
fromconsistency = None
self, name = self.cfgimpl_get_home_by_path(name,
config_bag)
config_bag,
fromconsistency)
context = self.cfgimpl_get_context()
option = config_bag.option
if option is None:
option = self.cfgimpl_get_description().impl_getchild(name,
config_bag,
self)
config_bag.option = option
option = option_bag.option
if option.impl_is_symlinkoption():
opt = option.impl_getopt()
path = context.cfgimpl_get_description().impl_get_path_by_opt(opt)
sconfig_bag = config_bag.copy('nooption')
sconfig_bag.ori_option = option
sconfig_bag.option = opt
return context.getattr(path,
index,
sconfig_bag)
soption_bag = OptionBag()
soption_bag.set_option(option.impl_getopt(),
None,
option_bag.index,
config_bag)
soption_bag.ori_option = option
context = self.cfgimpl_get_context()
return context.getattr(soption_bag.path,
soption_bag)
subpath = self._get_subpath(name)
if config_bag.setting_properties:
self.cfgimpl_get_settings().validate_properties(subpath,
index,
config_bag)
self.cfgimpl_get_settings().validate_properties(option_bag)
if option.impl_is_optiondescription():
if option_bag.fromconsistency:
fromconsistency = option_bag.fromconsistency.copy()
else:
fromconsistency = None
return SubConfig(option,
self._impl_context,
config_bag,
subpath)
option_bag.path,
fromconsistency)
if option.impl_is_master_slaves('slave'):
length = self.cfgimpl_get_length_slave(option, config_bag)
slave_len = self.cfgimpl_get_values()._p_.get_max_length(subpath)
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,
length,
subpath))
if option.impl_is_master_slaves('slave') and index is None:
option_bag.index))
if option.impl_is_master_slaves('slave') and option_bag.index is None:
value = []
for idx in range(length):
config_bag.properties = None
soption_bag = OptionBag()
soption_bag.set_option(option,
option_bag.path,
idx,
config_bag)
soption_bag.fromconsistency = option_bag.fromconsistency.copy()
value.append(self.getattr(name,
idx,
config_bag))
soption_bag))
else:
value = self.cfgimpl_get_values().get_cached_value(subpath,
index,
config_bag)
value = self.cfgimpl_get_values().get_cached_value(option_bag)
if config_bag.validate_properties:
self.cfgimpl_get_settings().validate_mandatory(subpath,
index,
value,
config_bag)
self.cfgimpl_get_settings().validate_mandatory(value,
option_bag)
return value
def find(self,
@ -406,11 +371,10 @@ class SubConfig(object):
:param first: return only one option if True, a list otherwise
:return: find list or an exception if nothing has been found
"""
def _filter_by_value(sconfig_bag):
def _filter_by_value(soption_bag):
try:
value = self.getattr(path,
None,
sconfig_bag)
soption_bag)
except PropertiesOptionError:
return False
if isinstance(value, list):
@ -427,18 +391,19 @@ class SubConfig(object):
_subpath,
config_bag)
for path, option in options:
sconfig_bag = config_bag.copy('nooption')
sconfig_bag.option = option
if byvalue is not undefined and not _filter_by_value(sconfig_bag):
option_bag = OptionBag()
option_bag.set_option(option,
path,
None,
config_bag)
if byvalue is not undefined and not _filter_by_value(option_bag):
continue
elif sconfig_bag.validate_properties:
elif config_bag.validate_properties:
#remove option with propertyerror, ...
try:
self.unwrap_from_path(path,
sconfig_bag)
self.cfgimpl_get_settings().validate_properties(path,
None,
sconfig_bag)
config_bag)
self.cfgimpl_get_settings().validate_properties(option_bag)
except PropertiesOptionError:
continue
found = True
@ -513,8 +478,11 @@ class SubConfig(object):
path = '.'.join(path.split('.')[:-1])
opt = context.unwrap_from_path(path,
config_bag)
sconfig_bag = config_bag.copy('nooption')
sconfig_bag.option = opt
soption_bag = OptionBag()
soption_bag.set_option(opt,
path,
None,
config_bag)
if mypath is not None:
if mypath == path:
withoption = None
@ -531,19 +499,24 @@ class SubConfig(object):
pathsvalues,
_currpath,
flatten,
sconfig_bag,
soption_bag,
fullpath=fullpath)
#withoption can be set to None below !
if withoption is None:
for opt in self.cfgimpl_get_description().impl_getchildren(config_bag, context):
sconfig_bag = config_bag.copy('nooption')
sconfig_bag.option = opt
path = opt.impl_getname()
self._make_sub_dict(path,
name = opt.impl_getname()
path = self._get_subpath(name)
soption_bag = OptionBag()
soption_bag.set_option(opt,
path,
None,
config_bag)
#path = self._get_subpath(name)
self._make_sub_dict(name,
pathsvalues,
_currpath,
flatten,
sconfig_bag,
soption_bag,
fullpath=fullpath)
if _currpath == []:
options = dict(pathsvalues)
@ -555,33 +528,32 @@ class SubConfig(object):
pathsvalues,
_currpath,
flatten,
config_bag,
option_bag,
fullpath=False):
try:
option = config_bag.option
option = option_bag.option
if not option.impl_is_optiondescription() and option.impl_is_master_slaves('slave'):
ret = []
length = self.cfgimpl_get_length_slave(option, config_bag)
length = self.cfgimpl_get_length_slave(option_bag)
if length:
for idx in range(length):
config_bag.properties = None
soption_bag = OptionBag()
soption_bag.set_option(option,
option_bag.path,
idx,
option_bag.config_bag)
ret.append(self.getattr(name,
idx,
config_bag))
elif config_bag.setting_properties:
path = self._get_subpath(name)
self.cfgimpl_get_settings().validate_properties(path,
None,
config_bag)
soption_bag))
elif option_bag.config_bag.setting_properties:
self.cfgimpl_get_settings().validate_properties(option_bag)
else:
ret = self.getattr(name,
None,
config_bag)
option_bag)
except PropertiesOptionError:
pass
else:
if option.impl_is_optiondescription():
pathsvalues += ret.make_dict(config_bag,
pathsvalues += ret.make_dict(option_bag.config_bag,
flatten=flatten,
_currpath=_currpath + [name],
fullpath=fullpath)
@ -638,12 +610,12 @@ class _CommonConfig(SubConfig):
true_option = option.impl_getopt()
context = self.cfgimpl_get_context()
true_path = true_option.impl_getpath(context)
self, path = context.cfgimpl_get_home_by_path(true_path,
self, path = context.cfgimpl_get_home_by_path(path,
config_bag)
config_bag.option = true_option
else:
true_path = path
config_bag.option = option
#config_bag.option = option
return option
def cfgimpl_get_path(self, dyn=True):
@ -816,25 +788,15 @@ class GroupConfig(_CommonConfig):
return self._impl_children
def cfgimpl_reset_cache(self,
opt,
path,
config_bag,
option_bag,
resetted_opts=None):
if resetted_opts is None:
resetted_opts = []
if isinstance(self, MetaConfig):
super(GroupConfig, self).cfgimpl_reset_cache(opt,
path,
config_bag=config_bag,
super(GroupConfig, self).cfgimpl_reset_cache(option_bag,
resetted_opts=copy(resetted_opts))
for child in self._impl_children:
if config_bag is None:
nconfig_bag = config_bag
else:
nconfig_bag = config_bag.copy('nooption')
child.cfgimpl_reset_cache(opt,
path,
config_bag=nconfig_bag,
child.cfgimpl_reset_cache(option_bag,
resetted_opts=copy(resetted_opts))
def set_value(self,
@ -857,16 +819,21 @@ class GroupConfig(_CommonConfig):
only_config=only_config,
_commit=False))
else:
nconfig_bag = config_bag.copy('nooption')
child.setattr(path,
index,
value,
nconfig_bag,
subconfig, name = child.cfgimpl_get_home_by_path(path,
config_bag)
option = subconfig.cfgimpl_get_description().impl_getchild(name,
config_bag,
child)
option_bag = OptionBag()
option_bag.set_option(option,
path,
index,
config_bag)
child.setattr(value,
option_bag,
_commit=False)
except PropertiesOptionError as err:
ret.append(PropertiesOptionError(err._path,
err._index,
err._config_bag,
ret.append(PropertiesOptionError(err._option_bag,
err.proptype,
err._settings,
err._opt_type,
@ -905,8 +872,6 @@ class GroupConfig(_CommonConfig):
ret = []
for child in self._impl_children:
nconfig_bag = config_bag.copy('nooption')
nconfig_bag.option = child
if isinstance(child, GroupConfig):
ret.extend(child.find_firsts(byname=byname,
bypath=bypath,
@ -1011,59 +976,77 @@ class MetaConfig(GroupConfig):
' cannot be set together'))
opt = self.cfgimpl_get_description().impl_get_opt_by_path(path)
for child in self._impl_children:
nconfig_bag = config_bag.copy('nooption')
nconfig_bag.option = opt
subconfig, name = child.cfgimpl_get_home_by_path(path,
config_bag)
option = subconfig.cfgimpl_get_description().impl_getchild(name,
config_bag,
child)
option_bag = OptionBag()
option_bag.set_option(option,
path,
index,
config_bag)
if force_default_if_same:
if not child.cfgimpl_get_values()._p_.hasvalue(path):
child_value = undefined
else:
child_value = child.getattr(path,
None,
nconfig_bag)
child_value = child.getattr(name,
option_bag)
if force_default or (force_default_if_same and value == child_value):
child.cfgimpl_get_values().reset(path,
nconfig_bag,
child.cfgimpl_get_values().reset(option_bag,
_commit=False)
continue
if force_dont_change_value:
try:
child_value = child.getattr(path,
None,
nconfig_bag)
child_value = child.getattr(name,
option_bag)
if value != child_value:
child.setattr(path,
None,
child_value,
nconfig_bag,
child.setattr(child_value,
option_bag,
_commit=False)
except (PropertiesOptionError, ValueError, SlaveError) as err:
ret.append(err)
nconfig_bag = config_bag.copy('nooption')
try:
self.setattr(path,
index,
value,
nconfig_bag,
_commit=_commit)
subconfig, name = self.cfgimpl_get_home_by_path(path,
config_bag)
option = subconfig.cfgimpl_get_description().impl_getchild(name,
config_bag,
self)
option_bag = OptionBag()
option_bag.set_option(option,
path,
index,
config_bag)
self.setattr(value,
option_bag,
_commit=False)
except (PropertiesOptionError, ValueError, SlaveError) as err:
ret.append(err)
return ret
def reset(self, path, config_bag):
#FIXME not working with DynSymLinkOption
#FIXME fonctionne avec sous metaconfig ??
opt = self.cfgimpl_get_description().impl_get_opt_by_path(path)
config_bag.option = opt
config_bag.validate = False
def reset(self,
path,
config_bag):
rconfig_bag = ConfigBag(config=config_bag.config,
_setting_properties=config_bag._setting_properties,
force_permissive=config_bag.force_permissive,
force_unrestraint=config_bag.force_unrestraint,
_validate=False)
subconfig, name = self.cfgimpl_get_home_by_path(path,
config_bag)
option = subconfig.cfgimpl_get_description().impl_getchild(name,
config_bag,
self)
option_bag = OptionBag()
option_bag.set_option(option,
path,
option,
rconfig_bag)
for child in self._impl_children:
sconfig_bag = config_bag.copy('nooption')
sconfig_bag.option = opt
child.cfgimpl_get_values().reset(path,
sconfig_bag,
child.cfgimpl_get_values().reset(option_bag,
_commit=False)
self.cfgimpl_get_values().reset(path,
config_bag)
self.cfgimpl_get_values().reset(option_bag)
def new_config(self,
session_id,

View File

@ -53,31 +53,27 @@ def display_list(lst, separator='and', add_quote=False):
class PropertiesOptionError(AttributeError):
"attempt to access to an option with a property that is not allowed"
def __init__(self,
path,
index,
config_bag,
option_bag,
proptype,
settings,
opt_type=None,
requires=None,
name=None,
orig_opt=None):
self._path = path
self._index = index
if opt_type:
self._opt_type = opt_type
self._requires = requires
self._name = name
self._orig_opt = orig_opt
else:
if config_bag.option.impl_is_optiondescription():
if option_bag.option.impl_is_optiondescription():
self._opt_type = 'optiondescription'
else:
self._opt_type = 'option'
self._requires = config_bag.option.impl_getrequires()
self._name = config_bag.option.impl_get_display_name()
self._requires = option_bag.option.impl_getrequires()
self._name = option_bag.option.impl_get_display_name()
self._orig_opt = None
self._config_bag = config_bag.copy()
self._option_bag = option_bag
self.proptype = proptype
self._settings = settings
self.msg = None
@ -90,12 +86,8 @@ class PropertiesOptionError(AttributeError):
#this part is a bit slow, so only execute when display
if self.msg:
return self.msg
req = self._settings.apply_requires(self._path,
self._requires,
self._index,
True,
self._config_bag,
self._name)
req = self._settings.apply_requires(self._option_bag,
True)
#if req != {} or self._orig_opt is not None:
if req != {}:
only_one = len(req) == 1
@ -123,7 +115,7 @@ class PropertiesOptionError(AttributeError):
self._name,
prop_msg,
msg))
del self._path, self._index, self._requires, self._opt_type, self._name, self._config_bag
del self._requires, self._opt_type, self._name, self._option_bag
del self._settings, self._orig_opt
return self.msg

View File

@ -81,22 +81,26 @@ class ChoiceOption(Option):
warnings_only=warnings_only)
def impl_get_values(self,
config_bag,
option_bag,
current_opt=undefined):
if current_opt is undefined:
current_opt = self
#FIXME cache? but in context...
values = self._choice_values
if isinstance(values, FunctionType):
if config_bag is undefined:
if option_bag is undefined:
values = undefined
else:
if option_bag.config_bag == undefined:
config = undefined
else:
config = option_bag.config_bag.config
values = carry_out_calculation(current_opt,
config_bag.config,
values,
getattr(self, '_choice_values_params', {}),
None,
config_bag)
context=config,
callback=values,
callback_params=getattr(self, '_choice_values_params', {}),
index=None,
option_bag=option_bag)
if values is not undefined and not isinstance(values, list):
raise ConfigError(_('calculated values for {0} is not a list'
'').format(self.impl_getname()))
@ -105,9 +109,9 @@ class ChoiceOption(Option):
def _validate(self,
value,
config_bag,
option_bag,
current_opt=undefined):
values = self.impl_get_values(config_bag,
values = self.impl_get_values(option_bag,
current_opt=current_opt)
if values is not undefined and not value in values:
if len(values) == 1:

View File

@ -72,14 +72,14 @@ class DynOptionDescription(OptionDescription):
'').format(self.impl_get_display_name()))
def _impl_get_suffixes(self,
config_bag):
option_bag):
callback, callback_params = self.impl_get_callback()
values = carry_out_calculation(self,
config_bag.config,
option_bag.config_bag.config,
callback,
callback_params,
None,
config_bag)
option_bag)
if not isinstance(values, list):
raise ValueError(_('DynOptionDescription callback for option "{}", is not a list ({})'
'').format(self.impl_get_display_name(), values))
@ -92,9 +92,9 @@ class DynOptionDescription(OptionDescription):
self.impl_get_display_name()))
return values
def get_syndynoptiondescriptions(self, config_bag):
subpath = self.impl_getpath(config_bag.config).rsplit('.', 1)[0]
for suffix in self._impl_get_suffixes(config_bag):
def get_syndynoptiondescriptions(self, option_bag):
subpath = self.impl_getpath(option_bag.config_bag.config).rsplit('.', 1)[0]
for suffix in self._impl_get_suffixes(option_bag):
yield SynDynOptionDescription(self,
subpath,
suffix)

View File

@ -24,7 +24,7 @@ from itertools import chain
from ..i18n import _
from ..setting import groups, undefined
from ..setting import groups, undefined, OptionBag, ConfigBag
from .optiondescription import OptionDescription
from .option import Option
from ..error import SlaveError, PropertiesOptionError
@ -104,35 +104,49 @@ class MasterSlaves(OptionDescription):
def reset(self,
values,
config_bag,
option_bag,
_commit=True):
config_bag = ConfigBag(config=option_bag.config_bag.config,
_setting_properties=option_bag.config_bag._setting_properties,
force_permissive=option_bag.config_bag.force_permissive,
force_unrestraint=option_bag.config_bag.force_unrestraint,
_validate=False)
for slave in self.getslaves():
sconfig_bag = config_bag.copy('nooption')
sconfig_bag.option = slave
sconfig_bag.validate = False
slave_path = slave.impl_getpath(values._getcontext())
values.reset(slave_path,
sconfig_bag,
soption_bag = OptionBag()
soption_bag.set_option(slave,
slave_path,
None,
config_bag)
values.reset(soption_bag,
_commit=_commit)
def pop(self,
values,
index,
config_bag,
option_bag,
slaves=undefined):
context = values._getcontext()
if slaves is undefined:
slaves = self.getslaves()
config_bag = ConfigBag(config=option_bag.config_bag.config,
_setting_properties=None,
force_permissive=option_bag.config_bag.force_permissive,
force_unrestraint=option_bag.config_bag.force_unrestraint,
_validate=False)
for slave in slaves:
slave_path = slave.impl_getpath(context)
slavelen = values._p_.get_max_length(slave_path)
sconfig_bag = config_bag.copy('nooption')
sconfig_bag.option = slave
if not values.is_default_owner(slave_path,
index,
config_bag,
soption_bag = OptionBag()
soption_bag.set_option(slave,
slave_path,
index,
config_bag)
# do not check force_default_on_freeze
soption_bag.properties = {}
if not values.is_default_owner(soption_bag,
validate_meta=False):
if slavelen > index:
values._p_.resetvalue_index(slave_path,

View File

@ -95,9 +95,15 @@ class NetmaskOption(Option):
if make_net and ip.prefixlen() != 32:
val_ip = IP(val_ipnetwork)
if ip.net() == val_ip:
msg = _('this is a network with netmask "{0}" ("{1}")')
if current_opt == opts[1]:
msg = _('this is a network with netmask "{0}" ("{1}")')
else:
msg = _('this is a network with {2} "{0}" ("{1}")')
if ip.broadcast() == val_ip:
msg = _('this is a broadcast with netmask "{0}" ("{1}")')
if current_opt == opts[1]:
msg = _('this is a broadcast with netmask "{0}" ("{1}")')
else:
msg = _('this is a broadcast with {2} "{0}" ("{1}")')
except ValueError:
if not make_net:
@ -106,5 +112,10 @@ class NetmaskOption(Option):
else:
raise ValueError(_('with {2} "{0}" ("{1}")').format(val_ipnetwork, opts[1].impl_get_display_name(), typ))
if msg is not None:
raise ValueError(msg.format(val_netmask,
opts[1].impl_get_display_name()))
if current_opt == opts[1]:
raise ValueError(msg.format(val_netmask,
opts[1].impl_get_display_name()))
else:
raise ValueError(msg.format(val_ipnetwork,
opts[0].impl_get_display_name(),
typ))

View File

@ -25,7 +25,7 @@ import weakref
from .baseoption import OnlyOption, submulti, STATIC_TUPLE
from .symlinkoption import DynSymLinkOption
from ..i18n import _
from ..setting import log, undefined, debug
from ..setting import log, undefined, debug, OptionBag, ConfigBag
from ..autolib import carry_out_calculation
from ..error import (ConfigError, ValueWarning, PropertiesOptionError,
display_list)
@ -145,9 +145,13 @@ class Option(OnlyOption):
_setattr(self, '_default_multi', default_multi)
if unique is not undefined:
_setattr(self, '_unique', unique)
option_bag = OptionBag()
option_bag.set_option(self,
undefined,
None,
undefined)
self.impl_validate(default,
is_multi=is_multi,
config_bag=undefined)
option_bag)
if (is_multi and default != []) or \
(not is_multi and default is not None):
if is_multi:
@ -180,34 +184,25 @@ class Option(OnlyOption):
def impl_validate(self,
value,
config_bag,
option_bag,
context=undefined,
force_index=None,
current_opt=undefined,
is_multi=None,
check_error=True,
multi=None):
check_error=True):
"""
:param value: the option's value
:param context: Config's context
:type context: :class:`tiramisu.config.Config`
:type validate: boolean
:param force_index: if multi, value has to be a list
not if force_index is not None
:type force_index: integer
"""
if current_opt is undefined:
current_opt = self
if option_bag:
config_bag = option_bag.config_bag
force_index = option_bag.index
else:
config_bag = undefined
force_index = None
if check_error and config_bag is not undefined and \
not config_bag.validate:
# just to check propertieserror
self.valid_consistency(current_opt,
self.valid_consistency(option_bag,
value,
context,
force_index,
check_error,
config_bag)
check_error)
return
def _is_not_unique(value):
@ -233,13 +228,13 @@ class Option(OnlyOption):
args.insert(0, ParamValue(val))
validator_params_ = Params(tuple(args), kwargs)
# Raise ValueError if not valid
carry_out_calculation(current_opt,
carry_out_calculation(option_bag.ori_option,
context=context,
callback=validator,
callback_params=validator_params_,
index=_index,
option_bag=option_bag,
orig_value=value,
config_bag=config_bag,
is_validator=True)
def do_validation(_value,
@ -251,13 +246,9 @@ class Option(OnlyOption):
if _value is not None:
if check_error:
# option validation
if config_bag is undefined:
setting_properties = None
else:
setting_properties = config_bag.setting_properties
self._validate(_value,
config_bag,
current_opt)
option_bag,
option_bag.ori_option)
if ((check_error and not is_warnings_only) or
(not check_error and is_warnings_only)):
calculation_validator(_value,
@ -265,13 +256,13 @@ class Option(OnlyOption):
self._second_level_validation(_value,
is_warnings_only)
if is_multi is None:
is_multi = self.impl_is_multi()
#if is_multi is None:
# is_multi = self.impl_is_multi()
is_warnings_only = getattr(self, '_warnings_only', False)
try:
val = value
if not is_multi:
if not self.impl_is_multi():
do_validation(val, None)
elif force_index is not None:
if self.impl_is_submulti():
@ -282,14 +273,6 @@ class Option(OnlyOption):
do_validation(val,
force_index)
else:
if multi is not None and self.impl_is_unique() and value in multi:
if not self.impl_is_submulti() and len(multi) - 1 >= force_index:
lst = list(multi)
lst.pop(force_index)
else:
lst = multi
if value in lst:
raise ValueError(_('this value is not uniq'))
do_validation(val,
force_index)
elif not isinstance(value, list):
@ -309,17 +292,15 @@ class Option(OnlyOption):
do_validation(val,
idx)
self.valid_consistency(current_opt,
self.valid_consistency(option_bag,
value,
context,
force_index,
check_error,
config_bag)
check_error)
except ValueError as err:
if debug: # pragma: no cover
log.debug('do_validation: value: {0}, index: {1}:'
' {2}'.format(val,
_index,
force_index,
err),
exc_info=True)
if is_warnings_only:
@ -443,15 +424,16 @@ class Option(OnlyOption):
all_cons_opts,
params)
#validate default value when add consistency
#FIXME validation!
option_bag = OptionBag()
option_bag.set_option(self,
undefined,
None,
undefined)
self.impl_validate(self.impl_getdefault(),
undefined)
option_bag)
self.impl_validate(self.impl_getdefault(),
undefined,
option_bag,
check_error=False)
#FIXME
#if err:
# self._del_consistency()
if func != '_cons_not_equal':
#consistency could generate warnings or errors
self._has_dependency = True
@ -465,37 +447,45 @@ class Option(OnlyOption):
opt._add_dependency(self)
def valid_consistency(self,
option,
option_bag,
value,
context,
index,
check_error,
config_bag):
check_error):
if context is not undefined:
descr = context.cfgimpl_get_description()
# no consistency found at all
if descr._cache_consistencies is None:
return
# get consistencies for this option
if isinstance(option, DynSymLinkOption):
consistencies = descr._cache_consistencies.get(option.impl_getopt())
if isinstance(option_bag.option, DynSymLinkOption):
consistencies = descr._cache_consistencies.get(option_bag.option.impl_getopt())
else:
consistencies = descr._cache_consistencies.get(option)
consistencies = descr._cache_consistencies.get(option_bag.option)
else:
# is no context, get consistencies in option
consistencies = option.get_consistencies()
if consistencies is not None:
consistencies = option_bag.option.get_consistencies()
if consistencies:
if option_bag.config_bag is undefined:
cconfig_bag = undefined
elif option_bag.config_bag.force_permissive != True:
cconfig_bag = ConfigBag(config=option_bag.config_bag.config,
_setting_properties=option_bag.config_bag._setting_properties,
force_permissive=True,
force_unrestraint=option_bag.config_bag.force_unrestraint,
_validate=option_bag.config_bag._validate)
else:
cconfig_bag = option_bag.config_bag
for cons_id, func, all_cons_opts, params in consistencies:
warnings_only = params.get('warnings_only', False)
if (warnings_only and not check_error) or (not warnings_only and check_error):
transitive = params.get('transitive', True)
#all_cons_opts[0] is the option where func is set
if isinstance(option, DynSymLinkOption):
if isinstance(option_bag.ori_option, DynSymLinkOption):
opts = []
for opt in all_cons_opts:
opts.append(DynSymLinkOption(opt(),
option._rootpath,
option._suffix))
option_bag.ori_option._rootpath,
option_bag.ori_option._suffix))
wopt = opts[0]
else:
opts = all_cons_opts
@ -503,25 +493,23 @@ class Option(OnlyOption):
wopt.launch_consistency(self,
func,
cons_id,
option,
option_bag,
value,
context,
index,
opts,
warnings_only,
transitive,
config_bag)
cconfig_bag)
def _get_consistency_value(self,
orig_option,
option_bag,
current_option,
index,
cons_id,
context,
config_bag,
value,
transitive,
func):
index = option_bag.index
if func in ALLOWED_CONST_LIST:
index = None
index_ = None
@ -529,7 +517,7 @@ class Option(OnlyOption):
index_ = None
else:
index_ = index
if orig_option == current_option:
if option_bag.ori_option == current_option:
# orig_option is current option
# we have already value, so use it
return value
@ -537,14 +525,18 @@ class Option(OnlyOption):
#if no context get default value
return current_option.impl_getdefault()
#otherwise calculate value
sconfig_bag = config_bag.copy('nooption')
sconfig_bag.option = current_option
sconfig_bag.fromconsistency.append(cons_id)
sconfig_bag.force_permissive = True
path = current_option.impl_getpath(context)
coption_bag = OptionBag()
coption_bag.set_option(current_option,
path,
index_,
config_bag)
cons_ids = option_bag.fromconsistency.copy()
cons_ids.append(cons_id)
coption_bag.fromconsistency = cons_ids
opt_value = context.getattr(path,
index_,
sconfig_bag)
coption_bag)
if index_ is None and index is not None:
if len(opt_value) <= index:
opt_value = current_option.impl_getdefault_multi()
@ -556,10 +548,9 @@ class Option(OnlyOption):
current_opt,
func,
cons_id,
option,
option_bag,
value,
context,
index,
opts,
warnings_only,
transitive,
@ -583,9 +574,7 @@ class Option(OnlyOption):
:param transitive: propertyerror is transitive
:type transitive: `boolean`
"""
#if context is not undefined:
# descr = context.cfgimpl_get_description()
if config_bag is not undefined and cons_id in config_bag.fromconsistency:
if cons_id in option_bag.fromconsistency:
return
all_cons_vals = []
all_cons_opts = []
@ -595,31 +584,30 @@ class Option(OnlyOption):
opt = opt()
is_multi = False
try:
opt_value = self._get_consistency_value(option,
opt_value = self._get_consistency_value(option_bag,
opt,
index,
cons_id,
context,
config_bag,
value,
transitive,
func)
except PropertiesOptionError as err:
if debug: # pragma: no cover
log.debug('propertyerror in launch_consistency: {0}'.format(err))
if transitive:
err.set_orig_opt(option)
err.set_orig_opt(option_bag.option)
raise err
else:
if opt.impl_is_multi() and index is None and func not in ALLOWED_CONST_LIST:
if opt.impl_is_multi() and option_bag.index is None and \
func not in ALLOWED_CONST_LIST:
len_value = len(opt_value)
if length is not None and length != len_value:
if context is undefined:
return
raise ValueError(_('unexpected length of "{}" in constency "{}", should be "{}"'
'').format(len(opt_value),
opt.impl_get_display_name(),
length))
raise ValueError(_('unexpected length of "{}" in constency "{}", '
'should be "{}"').format(len(opt_value),
opt.impl_get_display_name(),
length))
else:
length = len_value
is_multi = True

View File

@ -22,7 +22,7 @@ from copy import copy
from ..i18n import _
from ..setting import ConfigBag, groups, undefined, owners
from ..setting import ConfigBag, OptionBag, groups, undefined, owners
from .baseoption import BaseOption, OnlyOption
from .option import ALLOWED_CONST_LIST, DynSymLinkOption
from .syndynoptiondescription import SynDynOptionDescription
@ -173,11 +173,14 @@ class CacheOptionDescription(BaseOption):
'"force_store_value" property').format(
option.impl_get_display_name()))
if not values._p_.hasvalue(subpath):
config_bag = ConfigBag(config=context, option=option)
config_bag.properties = frozenset()
value = values.getvalue(subpath,
None,
config_bag)
config_bag = ConfigBag(config=context)
option_bag = OptionBag()
option_bag.set_option(option,
subpath,
None,
config_bag)
option_bag.properties = frozenset()
value = values.getvalue(option_bag)
value_setted = True
values._p_.setvalue(subpath,
value,
@ -224,13 +227,14 @@ class OptionDescriptionWalk(CacheOptionDescription):
__slots__ = ('_children',)
def build_dynoptions(self,
option,
config_bag):
option_bag):
option = option_bag.option
dynopt = option.getsubdyn()
rootpath = self.impl_get_path_by_opt(dynopt)
ori_index = len(rootpath) + 1
subpaths = [rootpath] + option.impl_getpath(config_bag.config)[ori_index:].split('.')[:-1]
for suffix in dynopt._impl_get_suffixes(config_bag):
subpaths = [rootpath] + option.impl_getpath(
option_bag.config_bag.config)[ori_index:].split('.')[:-1]
for suffix in dynopt._impl_get_suffixes(option_bag):
subpath = '.'.join([subp + suffix for subp in subpaths])
if isinstance(option, OnlyOption):
yield DynSymLinkOption(option,
@ -257,7 +261,12 @@ class OptionDescriptionWalk(CacheOptionDescription):
name = option.impl_getname()
if option.issubdyn():
if byname.startswith(name):
for doption in self.build_dynoptions(option, config_bag):
option_bag = OptionBag()
option_bag.set_option(option,
path,
None,
config_bag)
for doption in self.build_dynoptions(option_bag):
if byname == doption.impl_getname():
dpath = doption.impl_getpath(config_bag.config)
return (dpath, doption)
@ -319,9 +328,12 @@ class OptionDescriptionWalk(CacheOptionDescription):
subpath = ''
else:
subpath = self.impl_getpath(config_bag.config)
sconfig_bag = config_bag.copy('nooption')
sconfig_bag.option = child
for suffix in child._impl_get_suffixes(sconfig_bag):
option_bag = OptionBag()
option_bag.set_option(child,
subpath,
None,
config_bag)
for suffix in child._impl_get_suffixes(option_bag):
yield SynDynOptionDescription(child,
subpath,
suffix)
@ -339,11 +351,16 @@ class OptionDescriptionWalk(CacheOptionDescription):
subconfig,
config_bag):
for child in self._impl_st_getchildren(only_dyn=True):
sconfig_bag = config_bag.copy('nooption')
sconfig_bag.option = child
#sconfig_bag = config_bag.copy('nooption')
#sconfig_bag.option = child
cname = child.impl_getname()
if name.startswith(cname):
for value in child._impl_get_suffixes(sconfig_bag):
option_bag = OptionBag()
option_bag.set_option(child,
subconfig.cfgimpl_get_path(),
None,
config_bag)
for value in child._impl_get_suffixes(option_bag):
if name == cname + value:
return SynDynOptionDescription(child,
subconfig.cfgimpl_get_path(),

View File

@ -20,7 +20,7 @@
# ____________________________________________________________
from .baseoption import OnlyOption
from ..i18n import _
from ..setting import undefined
from ..setting import undefined, OptionBag
class SymLinkOption(OnlyOption):
@ -104,22 +104,21 @@ class DynSymLinkOption(object):
def impl_validate(self,
value,
config_bag,
option_bag,
context=undefined,
force_index=None,
current_opt=undefined,
is_multi=None,
check_error=True,
multi=None):
# add current_opt !
check_error=True):
context = option_bag.config_bag.config
soption_bag = OptionBag()
soption_bag.set_option(self._opt,
self.impl_getpath(context),
option_bag.index,
option_bag.config_bag)
soption_bag.ori_option = option_bag.option
soption_bag.fromconsistency = option_bag.fromconsistency.copy()
self._opt.impl_validate(value,
config_bag,
context,
force_index,
current_opt=self,
is_multi=is_multi,
check_error=check_error,
multi=multi)
soption_bag,
context=context,
check_error=check_error)
def impl_is_dynsymlinkoption(self):
return True

View File

@ -117,77 +117,99 @@ debug = False
static_set = frozenset()
class ConfigBag(object):
__slots__ = ('default',
'config',
'option',
'ori_option',
'properties',
'setting_properties',
'force_permissive',
'force_unrestraint',
'trusted_cached_properties',
'fromconsistency',
'_validator'
class OptionBag:
__slots__ = ('option', # current option
'path',
'index',
'config_bag',
'ori_option', # original option (for example useful for symlinkoption)
'properties', # properties of current option
'apply_requires',
'fromconsistency' # history for consistency
)
def __init__(self):
self.option = None
self.fromconsistency = []
def set_option(self,
option,
path,
index,
config_bag):
if self.option != None:
raise Exception('hu?')
if path is None:
path = config_bag.config.cfgimpl_get_description().impl_get_path_by_opt(option)
self.path = path
self.index = index
self.option = option
self.config_bag = config_bag
def __getattr__(self, key):
if key == 'properties':
settings = self.config_bag.config.cfgimpl_get_settings()
self.properties = settings.getproperties(self, apply_requires=self.apply_requires)
return self.properties
elif key == 'ori_option':
return self.option
elif key == 'apply_requires':
return True
raise KeyError('unknown key {} for OptionBag'.format(key))
class ConfigBag:
__slots__ = ('config', # link to the current config (context)
'_setting_properties', # properties for current config
'force_permissive', # force permissive
'force_unrestraint', # do not validate properties
'_validate', # validate
)
def __init__(self, config, **kwargs):
self.default = {'force_permissive': False,
'force_unrestraint': False,
'trusted_cached_properties': True,
}
self.force_permissive = False
self.force_unrestraint = False
self.config = config
self._validator = True
self.fromconsistency = []
self._validate = True
for key, value in kwargs.items():
if value != self.default.get(key):
setattr(self, key, value)
setattr(self, key, value)
def __getattr__(self, key):
if key == 'validate_properties':
return not self.force_unrestraint
if key == 'validate':
if self.setting_properties is not None:
return 'validator' in self.setting_properties
return self._validator
if self._validate and self._setting_properties is not None:
return 'validator' in self._setting_properties
return self._validate
if key == 'setting_properties':
if self.force_unrestraint:
return None
self.setting_properties = self.config.cfgimpl_get_settings().get_context_properties()
return self.setting_properties
return self._setting_properties
if key == '_setting_properties':
self._setting_properties = self.config.cfgimpl_get_settings().get_context_properties()
if self._validate is False:
self._setting_properties = self._setting_properties - {'validator'}
return self._setting_properties
if key not in self.__slots__:
raise KeyError('unknown key {}'.format(key))
return self.default.get(key)
raise KeyError('unknown key {} for ConfigBag'.format(key))
return None
def __setattr__(self, key, value):
if key == 'validate':
if self.setting_properties is not None:
if value is False:
self.setting_properties = frozenset(set(self.setting_properties) - {'validator'})
else:
self.setting_properties = frozenset(set(self.setting_properties) | {'validator'})
else:
self._validator = value
try:
del self._setting_properties
except AttributeError:
pass
self._validate = value
else:
super().__setattr__(key, value)
def delete(self, key):
try:
return self.__delattr__(key)
except AttributeError:
pass
def copy(self, filters='all'):
def copy(self):
kwargs = {}
for key in self.__slots__:
if filters == 'nooption' and (key.startswith('option') or \
key == 'properties'):
continue
if key == 'fromconsistency':
if key == 'fromconsistency' and self.fromconsistency != []:
kwargs['fromconsistency'] = copy(self.fromconsistency)
elif key != 'default':
value = getattr(self, key)
if value != self.default.get(key):
kwargs[key] = value
else:
kwargs[key] = getattr(self, key)
return ConfigBag(**kwargs)
@ -357,13 +379,14 @@ class Settings(object):
return props
def getproperties(self,
path,
index,
config_bag,
option_bag,
apply_requires=True):
"""
"""
opt = config_bag.option
opt = option_bag.option
config_bag = option_bag.config_bag
path = option_bag.path
index = option_bag.index
if opt.impl_is_symlinkoption():
opt = opt.impl_getopt()
path = opt.impl_getpath(self._getcontext())
@ -384,17 +407,11 @@ class Settings(object):
props = self._p_.getproperties(path,
opt.impl_getproperties())
else:
props = meta.cfgimpl_get_settings().getproperties(path,
index,
config_bag,
props = meta.cfgimpl_get_settings().getproperties(option_bag,
apply_requires)
if apply_requires:
props |= self.apply_requires(path,
opt.impl_getrequires(),
index,
False,
config_bag,
opt.impl_get_display_name())
props |= self.apply_requires(option_bag,
False)
props -= self.getpermissive(opt,
path)
if apply_requires:
@ -421,12 +438,8 @@ class Settings(object):
return self._pp_.getpermissive(path)
def apply_requires(self,
path,
current_requires,
index,
readable,
config_bag,
name):
option_bag,
readable):
"""carries out the jit (just in time) requirements between options
a requirement is a tuple of this form that comes from the option's
@ -470,7 +483,7 @@ class Settings(object):
:param path: the option's path in the config
:type path: str
"""
#current_requires = opt.impl_getrequires()
current_requires = option_bag.option.impl_getrequires()
# filters the callbacks
if readable:
@ -489,32 +502,38 @@ class Settings(object):
breaked = False
for option, expected in exps:
reqpath = option.impl_getpath(context)
#FIXME c'est un peut tard !
if reqpath.startswith(path + '.'):
#FIXME c'est un peu tard !
if reqpath.startswith(option_bag.path + '.'):
raise RequirementError(_("malformed requirements "
"imbrication detected for option:"
" '{0}' with requirement on: "
"'{1}'").format(path, reqpath))
"'{1}'").format(option_bag.path, reqpath))
idx = None
is_indexed = False
if option.impl_is_master_slaves('slave'):
idx = index
idx = option_bag.index
elif option.impl_is_multi():
is_indexed = True
sconfig_bag = config_bag.copy('nooption')
if config_bag.option == option:
sconfig_bag.setting_properties = None
sconfig_bag.force_unrestraint= False
sconfig_bag.validate = False
else:
sconfig_bag.force_permissive = True
sconfig_bag.option = option
config_bag = ConfigBag(config=option_bag.config_bag.config,
_setting_properties=option_bag.config_bag._setting_properties,
force_permissive=True,
force_unrestraint=option_bag.config_bag.force_unrestraint,
_validate=option_bag.config_bag._validate)
soption_bag = OptionBag()
soption_bag.set_option(option,
reqpath,
idx,
config_bag)
soption_bag.config_bag.force_permissive = True
if option_bag.option == option:
soption_bag.config_bag.force_unrestraint = True
soption_bag.config_bag.validate = False
soption_bag.apply_requires = False
try:
value = context.getattr(reqpath,
idx,
sconfig_bag)
soption_bag)
if is_indexed:
value = value[index]
value = value[option_bag.index]
except PropertiesOptionError as err:
properties = err.proptype
if not transitive:
@ -532,19 +551,15 @@ class Settings(object):
prop_msg = _('properties')
raise RequirementError(_('cannot access to option "{0}" because '
'required option "{1}" has {2} {3}'
'').format(name,
'').format(option_bag.option.impl_get_display_name(),
option.impl_get_display_name(),
prop_msg,
display_list(list(properties), add_quote=True)))
# transitive action, add action
if operator != 'and':
if readable:
for msg in self.apply_requires(err._path,
err._requires,
err._index,
True,
err._config_bag,
err._name).values():
for msg in self.apply_requires(err._option_bag,
True).values():
calc_properties.setdefault(action, []).extend(msg)
else:
calc_properties.add(action)
@ -587,23 +602,25 @@ class Settings(object):
def setproperties(self,
path,
properties,
config_bag):
option_bag):
"""save properties for specified path
(never save properties if same has option properties)
"""
# should have index !!!
if self._getcontext().cfgimpl_get_meta() is not None:
raise ConfigError(_('cannot change property with metaconfig'))
if path is not None and config_bag.option.impl_getrequires() is not None:
not_allowed_props = properties & getattr(config_bag.option, '_calc_properties', static_set)
if path is not None and option_bag.option.impl_getrequires() is not None:
not_allowed_props = properties & \
getattr(option_bag.option, '_calc_properties', static_set)
if not_allowed_props:
raise ValueError(_('cannot set property {} for option "{}" this property is calculated'
'').format(display_list(list(not_allowed_props), add_quote=True),
config_bag.option.impl_get_display_name()))
if config_bag is None:
raise ValueError(_('cannot set property {} for option "{}" this property is '
'calculated').format(display_list(list(not_allowed_props),
add_quote=True),
option_bag.option.impl_get_display_name()))
if option_bag is None:
opt = None
else:
opt = config_bag.option
opt = option_bag.option
if opt and opt.impl_is_symlinkoption():
raise TypeError(_("can't assign property to the symlinkoption \"{}\""
"").format(opt.impl_get_display_name()))
@ -616,21 +633,20 @@ class Settings(object):
self._p_.setproperties(path,
properties)
#values too because of slave values could have a PropertiesOptionError has value
self._getcontext().cfgimpl_reset_cache(opt,
path,
config_bag)
self._getcontext().cfgimpl_reset_cache(option_bag)
if option_bag is not None:
try:
del option_bag.properties
except AttributeError:
pass
def set_context_permissive(self,
permissive):
self.setpermissive(None,
None,
None,
permissive)
def setpermissive(self,
opt,
path,
config_bag,
option_bag,
permissives):
"""
enables us to put the permissives in the storage
@ -645,51 +661,55 @@ class Settings(object):
raise ConfigError(_('cannot change permissive with metaconfig'))
if not isinstance(permissives, frozenset):
raise TypeError(_('permissive must be a frozenset'))
if opt and opt.impl_is_symlinkoption():
raise TypeError(_("can't assign permissive to the symlinkoption \"{}\""
"").format(opt.impl_get_display_name()))
if option_bag is not None:
opt = option_bag.option
if opt and opt.impl_is_symlinkoption():
raise TypeError(_("can't assign permissive to the symlinkoption \"{}\""
"").format(opt.impl_get_display_name()))
path = option_bag.path
else:
path = None
forbidden_permissives = FORBIDDEN_SET_PERMISSIVES & permissives
if forbidden_permissives:
raise ConfigError(_('cannot add those permissives: {0}').format(
' '.join(forbidden_permissives)))
self._pp_.setpermissive(path, permissives)
self._getcontext().cfgimpl_reset_cache(opt,
path,
config_bag)
if option_bag is not None:
self._getcontext().cfgimpl_reset_cache(option_bag)
#____________________________________________________________
# reset methods
def reset(self,
opt,
path,
config_bag,
all_properties=False):
option_bag):
# all_properties=False):
if self._getcontext().cfgimpl_get_meta() is not None:
raise ConfigError(_('cannot change property with metaconfig'))
if option_bag is None:
opt = None
else:
opt = option_bag.option
if opt and opt.impl_is_symlinkoption():
raise TypeError(_("can't reset properties to the symlinkoption \"{}\""
"").format(opt.impl_get_display_name()))
if all_properties and (path or opt):
raise ValueError(_('opt and all_properties must not be set '
'together in reset'))
if all_properties:
self._p_.reset_all_properties()
#if all_properties and (path or opt):
# raise ValueError(_('opt and all_properties must not be set '
# 'together in reset'))
#if all_properties:
# self._p_.reset_all_properties()
else:
if opt is not None and path is None:
path = opt.impl_getpath(self._getcontext())
if opt is not None:
path = option_bag.path
else:
path = None
self._p_.delproperties(path)
self._getcontext().cfgimpl_reset_cache(opt,
path,
config_bag)
self._getcontext().cfgimpl_reset_cache(option_bag)
#____________________________________________________________
# validate properties
def validate_properties(self,
path,
index,
config_bag):
option_bag):
"""
validation upon the properties related to `opt`
@ -697,70 +717,56 @@ class Settings(object):
:param force_permissive: behaves as if the permissive property
was present
"""
opt = config_bag.option
# calc properties
self_properties = config_bag.properties
if self_properties is None:
self_properties = self.getproperties(path,
index,
config_bag)
config_bag.properties = self_properties
self_properties = option_bag.properties
config_bag = option_bag.config_bag
properties = self_properties & config_bag.setting_properties - {'frozen', 'mandatory', 'empty'}
# remove permissive properties
if (config_bag.force_permissive is True or 'permissive' in config_bag.setting_properties) and properties:
if (config_bag.force_permissive is True or \
'permissive' in config_bag.setting_properties) and properties:
# remove global permissive if need
properties -= self.get_context_permissive()
# at this point an option should not remain in properties
if properties != frozenset():
raise PropertiesOptionError(path,
index,
config_bag,
raise PropertiesOptionError(option_bag,
properties,
self)
def validate_mandatory(self,
path,
index,
value,
config_bag):
option_bag):
values = self._getcontext().cfgimpl_get_values()
opt = config_bag.option
opt = option_bag.option
config_bag = option_bag.config_bag
is_mandatory = False
if config_bag.setting_properties and 'mandatory' in config_bag.setting_properties:
if (config_bag.force_permissive is True or 'permissive' in config_bag.setting_properties) and \
'mandatory' in self.get_context_permissive():
pass
elif 'mandatory' in config_bag.properties and values.isempty(opt,
elif 'mandatory' in option_bag.properties and values.isempty(opt,
value,
index=index):
index=option_bag.index):
is_mandatory = True
if 'empty' in config_bag.properties and values.isempty(opt,
if 'empty' in option_bag.properties and values.isempty(opt,
value,
force_allow_empty_list=True,
index=index):
index=option_bag.index):
is_mandatory = True
if is_mandatory:
raise PropertiesOptionError(path,
index,
config_bag,
raise PropertiesOptionError(option_bag,
['mandatory'],
self)
def validate_frozen(self,
path,
index,
config_bag):
if config_bag.setting_properties and \
('everything_frozen' in config_bag.setting_properties or
'frozen' in config_bag.properties) and \
not ((config_bag.force_permissive is True or
'permissive' in config_bag.setting_properties) and
option_bag):
if option_bag.config_bag.setting_properties and \
('everything_frozen' in option_bag.config_bag.setting_properties or
'frozen' in option_bag.properties) and \
not ((option_bag.config_bag.force_permissive is True or
'permissive' in option_bag.config_bag.setting_properties) and
'frozen' in self.get_context_permissive()):
raise PropertiesOptionError(path,
index,
config_bag,
raise PropertiesOptionError(option_bag,
['frozen'],
self)
return False

View File

@ -44,13 +44,14 @@ class Cache(DictCache):
_display_classname(self),
id(self)))
self._setcache(path, index, val, time())
if DEBUG:
print('not setcache {} with index {} and value {} in {} ({})'.format(path,
index,
val,
_display_classname(self),
id(self)))
return
elif DEBUG:
print('not setcache {} with index {} and value {} and props {} and {} in {} ({})'.format(path,
index,
val,
props,
self_props,
_display_classname(self),
id(self)))
def getcache(self,
path,
@ -119,5 +120,5 @@ class Cache(DictCache):
example: {'path1': {'index1': ('value1', 'time1')}, 'path2': {'index2': ('value2', 'time2', )}}
"""
if DEBUG:
print('get_chached', self._cache)
print('get_chached {} for {} ({})'.format(self._cache, _display_classname(self), id(self)))
return self._get_cached()

View File

@ -17,7 +17,7 @@
# ____________________________________________________________
import weakref
from .error import ConfigError, PropertiesOptionError
from .setting import owners, expires_time, undefined, forbidden_owners
from .setting import owners, expires_time, undefined, forbidden_owners, OptionBag, ConfigBag
from .autolib import carry_out_calculation
from .i18n import _
@ -63,9 +63,7 @@ class Values(object):
# get value
def get_cached_value(self,
path,
index,
config_bag):
option_bag):
"""get value directly in cache if set
otherwise calculated value and set it in cache
@ -81,40 +79,36 @@ class Values(object):
:returns: value
"""
# try to retrive value in cache
setting_properties = config_bag.setting_properties
is_cached, value = self._p_.getcache(path,
setting_properties = option_bag.config_bag.setting_properties
is_cached, value = self._p_.getcache(option_bag.path,
expires_time,
index,
option_bag.index,
setting_properties,
config_bag.properties,
option_bag.properties,
'value')
if not is_cached:
# no cached value so get value
value = self.getvalue(path,
index,
config_bag)
value = self.getvalue(option_bag)
# validate value
context = self._getcontext()
opt = config_bag.option
opt = option_bag.option
opt.impl_validate(value,
option_bag,
context=context,
force_index=index,
check_error=True,
config_bag=config_bag)
check_error=True)
if setting_properties and 'warnings' in setting_properties:
opt.impl_validate(value,
option_bag,
context=context,
force_index=index,
check_error=False,
config_bag=config_bag)
check_error=False)
# store value in cache
if not is_cached:
self._p_.setcache(path,
index,
self._p_.setcache(option_bag.path,
option_bag.index,
value,
setting_properties,
config_bag.properties)
option_bag.properties)
if isinstance(value, list):
# return a copy, so value cannot be modified
return value.copy()
@ -122,9 +116,7 @@ class Values(object):
return value
def getvalue(self,
path,
index,
config_bag):
option_bag):
"""actually retrieves the value
:param path: the path of the `Option`
@ -134,37 +126,22 @@ class Values(object):
"""
# get owner and value from store
# index allowed only for slave
opt = config_bag.option
is_slave = opt.impl_is_master_slaves('slave')
index = option_bag.index
is_slave = option_bag.option.impl_is_master_slaves('slave')
if index is None or not is_slave:
_index = None
else:
_index = index
owner, value = self._p_.getowner(path,
owner, value = self._p_.getowner(option_bag.path,
owners.default,
index=_index,
with_value=True)
if owner != owners.default:
if config_bag.setting_properties is None:
# get property without apply requires
settings = self._getcontext().cfgimpl_get_settings()
self_properties = settings.getproperties(path,
index,
config_bag,
apply_requires=False)
else:
# if a value is store in storage, check if not frozen + force_default_on_freeze
# if frozen + force_default_on_freeze => force default value
self_properties = config_bag.properties
if self_properties is None:
settings = self._getcontext().cfgimpl_get_settings()
self_properties = settings.getproperties(path,
index,
config_bag)
config_bag.properties = self_properties
if not ('frozen' in self_properties and \
'force_default_on_freeze' in self_properties):
# if a value is store in storage, check if not frozen + force_default_on_freeze
# if frozen + force_default_on_freeze => force default value
if not ('frozen' in option_bag.properties and \
'force_default_on_freeze' in option_bag.properties):
if index is not None and not is_slave:
if len(value) > index:
return value[index]
@ -172,14 +149,10 @@ class Values(object):
#so return default value
else:
return value
return self.getdefaultvalue(path,
index,
config_bag)
return self.getdefaultvalue(option_bag)
def getdefaultvalue(self,
path,
index,
config_bag):
option_bag):
"""get default value:
- get meta config value or
- get calculated value or
@ -192,36 +165,43 @@ class Values(object):
:returns: default value
"""
context = self._getcontext()
opt = config_bag.option
config_bag = option_bag.config_bag
opt = option_bag.option
index = option_bag.index
def _reset_cache(_value):
is_cache, cache_value = self._p_.getcache(path,
is_cache, cache_value = self._p_.getcache(option_bag.path,
expires_time,
index,
config_bag.setting_properties,
config_bag.properties,
option_bag.properties,
'value')
if is_cache and cache_value == _value:
# calculation return same value as previous value,
# so do not invalidate cache
return
# calculated value is a new value, so reset cache
context.cfgimpl_reset_cache(opt,
path,
config_bag)
context.cfgimpl_reset_cache(option_bag)
if opt.impl_is_master_slaves('slave'):
index_ = index
else:
index_ = None
if self._is_meta(path,
index_,
config_bag):
if option_bag.index != index_:
moption_bag = OptionBag()
moption_bag.set_option(opt,
option_bag.path,
index_,
config_bag)
moption_bag.fromconsistency = option_bag.fromconsistency.copy()
else:
moption_bag = option_bag
if self._is_meta(moption_bag):
meta = context.cfgimpl_get_meta()
# retrieved value from meta config
try:
value = meta.getattr(path,
index,
config_bag)
# FIXME could have different property!
value = meta.getattr(moption_bag.path,
moption_bag)
except PropertiesOptionError:
# if properties error, return an other default value
# unexpected error, should not happened
@ -237,7 +217,7 @@ class Values(object):
callback=callback,
callback_params=callback_params,
index=index,
config_bag=config_bag)
option_bag=option_bag)
if isinstance(value, list) and index is not None:
# if value is a list and index is set
if opt.impl_is_submulti() and (value == [] or not isinstance(value[0], list)):
@ -309,116 +289,94 @@ class Values(object):
# set value
def setvalue(self,
path,
index,
value,
config_bag,
option_bag,
_commit):
context = self._getcontext()
owner = context.cfgimpl_get_settings().getowner()
if config_bag.validate:
if index is not None or config_bag.option._has_consistencies(context):
if option_bag.config_bag.validate:
if option_bag.index is not None or option_bag.option._has_consistencies(context):
# set value to a fake config when option has dependency
# validation will be complet in this case (consistency, ...)
tested_context = context._gen_fake_values()
sconfig_bag = config_bag.copy()
sconfig_bag.validate = False
tested_context.cfgimpl_get_values().setvalue(path,
index,
value,
sconfig_bag,
True)
sconfig_bag.validate = True
tested_context.getattr(path,
index,
sconfig_bag)
#sconfig_bag = config_bag.copy()
ori_validate = option_bag.config_bag.validate
if ori_validate is True:
option_bag.config_bag.validate = False
try:
tested_context.cfgimpl_get_values().setvalue(value,
option_bag,
True)
option_bag.config_bag.validate = True
tested_context.getattr(option_bag.path,
option_bag)
except Exception as exc:
if ori_validate is True:
option_bag.config_bag.validate = True
raise exc
else:
self.setvalue_validation(path,
index,
value,
config_bag)
self.setvalue_validation(value,
option_bag)
self._setvalue(path,
index,
self._setvalue(option_bag,
value,
owner,
config_bag,
commit=_commit)
def setvalue_validation(self,
path,
index,
value,
config_bag):
option_bag):
context = self._getcontext()
settings = context.cfgimpl_get_settings()
# First validate properties with this value
self_properties = config_bag.properties
if self_properties is None:
self_properties = settings.getproperties(path,
index,
config_bag)
config_bag.properties = self_properties
opt = config_bag.option
settings.validate_frozen(path,
index,
config_bag)
settings.validate_mandatory(path,
index,
value,
config_bag)
opt = option_bag.option
settings.validate_frozen(option_bag)
settings.validate_mandatory(value,
option_bag)
# Value must be valid for option
opt.impl_validate(value,
config_bag,
option_bag,
context,
check_error=True,
force_index=index)
if config_bag.setting_properties and 'warnings' in config_bag.setting_properties:
check_error=True)
if option_bag.config_bag.setting_properties and \
'warnings' in option_bag.config_bag.setting_properties:
# No error found so emit warnings
opt.impl_validate(value,
config_bag,
option_bag,
context,
check_error=False,
force_index=index)
check_error=False)
def _setvalue(self,
path,
index,
option_bag,
value,
owner,
config_bag,
commit=True):
self._getcontext().cfgimpl_reset_cache(config_bag.option,
path,
config_bag)
self._getcontext().cfgimpl_reset_cache(option_bag)
if isinstance(value, list):
# copy
value = list(value)
self._p_.setvalue(path,
value = value.copy()
self._p_.setvalue(option_bag.path,
value,
owner,
index,
option_bag.index,
commit)
def _is_meta(self,
path,
index,
config_bag,
option_bag,
force_owner_is_default=False):
if not force_owner_is_default and self._p_.hasvalue(path,
index=index):
if not force_owner_is_default and self._p_.hasvalue(option_bag.path,
index=option_bag.index):
# has already a value, so not meta
return False
context = self._getcontext()
meta = context.cfgimpl_get_meta()
if meta is None:
return False
opt = config_bag.option
opt = option_bag.option
if opt.impl_is_master_slaves('slave'):
master = opt.impl_get_master_slaves().getmaster()
masterp = master.impl_getpath(context)
@ -426,29 +384,23 @@ class Values(object):
if self._p_.hasvalue(masterp,
index=None):
return False
return not meta.cfgimpl_get_values().is_default_owner(path,
index,
config_bag)
return not meta.cfgimpl_get_values().is_default_owner(option_bag)
#______________________________________________________________________
# owner
def is_default_owner(self,
path,
index,
config_bag,
option_bag,
validate_meta=undefined):
return self._getowner(path,
index,
config_bag,
validate_meta=validate_meta,
only_default=True) == owners.default
return self.getowner(option_bag,
validate_meta=validate_meta,
only_default=True) == owners.default
def getowner(self,
path,
index,
config_bag):
option_bag,
validate_meta=True,
only_default=False):
"""
retrieves the option's owner
@ -457,199 +409,144 @@ class Values(object):
was present
:returns: a `setting.owners.Owner` object
"""
return self._getowner(path,
index,
config_bag)
def _getowner(self,
path,
index,
config_bag,
validate_meta=True,
only_default=False):
"""get owner of an option
"""
context = self._getcontext()
opt = config_bag.option
opt = option_bag.option
if opt.impl_is_symlinkoption():
config_bag.ori_option = opt
option_bag.ori_option = opt
opt = opt.impl_getopt()
config_bag.option = opt
path = opt.impl_getpath(context)
self_properties = config_bag.properties
option_bag.option = opt
option_bag.path = opt.impl_getpath(context)
self_properties = option_bag.properties
settings = context.cfgimpl_get_settings()
if self_properties is None:
self_properties = settings.getproperties(path,
index,
config_bag)
config_bag.properties = self_properties
if config_bag.setting_properties is not None:
settings.validate_properties(path,
index,
config_bag)
if option_bag.config_bag.setting_properties is not None:
settings.validate_properties(option_bag)
if 'frozen' in self_properties and 'force_default_on_freeze' in self_properties:
return owners.default
if only_default:
if self._p_.hasvalue(path,
index):
if self._p_.hasvalue(option_bag.path,
option_bag.index):
owner = undefined
else:
owner = owners.default
else:
owner = self._p_.getowner(path,
owner = self._p_.getowner(option_bag.path,
owners.default,
index=index)
index=option_bag.index)
if owner is owners.default and validate_meta is not False:
meta = context.cfgimpl_get_meta()
if meta is not None and self._is_meta(path,
index,
config_bag):
owner = meta.cfgimpl_get_values()._getowner(path,
index,
config_bag,
only_default=only_default)
if meta is not None and self._is_meta(option_bag):
owner = meta.cfgimpl_get_values().getowner(option_bag,
only_default=only_default)
return owner
def setowner(self,
path,
index,
owner,
config_bag):
option_bag):
"""
sets a owner to an option
:param opt: the `option.Option` object
:param owner: a valid owner, that is a `setting.owners.Owner` object
"""
opt = config_bag.option
opt = option_bag.option
if opt.impl_is_symlinkoption():
raise ConfigError(_("can't set owner for the symlinkoption \"{}\""
"").format(opt.impl_get_display_name()))
if owner in forbidden_owners:
raise ConfigError(_('set owner "{0}" is forbidden').format(str(owner)))
if not self._p_.hasvalue(path):
if not self._p_.hasvalue(option_bag.path):
raise ConfigError(_('no value for {0} cannot change owner to {1}'
'').format(path, owner))
self.setowner_validation(path,
index,
config_bag)
self._p_.setowner(path, owner, index=index)
'').format(option_bag.path, owner))
self._getcontext().cfgimpl_get_settings().validate_frozen(option_bag)
self._p_.setowner(option_bag.path,
owner,
index=option_bag.index)
#______________________________________________________________________
# reset
def reset(self,
path,
config_bag,
option_bag,
_commit=True):
context = self._getcontext()
setting = context.cfgimpl_get_settings()
hasvalue = self._p_.hasvalue(path)
hasvalue = self._p_.hasvalue(option_bag.path)
if hasvalue and config_bag.validate:
if hasvalue and option_bag.config_bag.validate:
ori_validate = option_bag.config_bag.validate
if ori_validate is True:
option_bag.config_bag.validate = False
fake_context = context._gen_fake_values()
fake_value = fake_context.cfgimpl_get_values()
sconfig_bag = config_bag.copy()
sconfig_bag.validate = False
fake_value.reset(path,
sconfig_bag)
value = fake_value.getdefaultvalue(path,
None,
config_bag)
fake_value.setvalue_validation(path,
None,
value,
config_bag)
opt = config_bag.option
fake_value.reset(option_bag)
if ori_validate is True:
option_bag.config_bag.validate = True
value = fake_value.getdefaultvalue(option_bag)
fake_value.setvalue_validation(value,
option_bag)
opt = option_bag.option
if opt.impl_is_master_slaves('master'):
opt.impl_get_master_slaves().reset(self,
config_bag,
option_bag,
_commit=_commit)
if hasvalue:
if 'force_store_value' in setting.getproperties(path,
None,
config_bag):
value = self.getdefaultvalue(path,
None,
config_bag)
self._setvalue(path,
None,
if 'force_store_value' in option_bag.properties:
value = self.getdefaultvalue(option_bag)
self._setvalue(option_bag,
value,
owners.forced,
config_bag,
commit=_commit)
else:
self._p_.resetvalue(path,
self._p_.resetvalue(option_bag.path,
_commit)
context.cfgimpl_reset_cache(config_bag.option,
path,
config_bag)
if not opt.impl_is_master_slaves('master'):
# if master, already reset behind
pass
context.cfgimpl_reset_cache(option_bag)
def reset_slave(self,
path,
index,
config_bag):
option_bag):
if self._p_.hasvalue(path, index=index):
if self._p_.hasvalue(option_bag.path, index=option_bag.index):
context = self._getcontext()
if config_bag.validate:
if option_bag.config_bag.validate:
fake_context = context._gen_fake_values()
fake_value = fake_context.cfgimpl_get_values()
sconfig_bag = config_bag.copy()
sconfig_bag.validate = False
fake_value.reset_slave(path,
index,
sconfig_bag)
value = fake_value.getdefaultvalue(path,
index,
config_bag)
fake_value.setvalue_validation(path,
index,
value,
config_bag)
self._p_.resetvalue_index(path, index)
context.cfgimpl_reset_cache(config_bag.option,
path,
config_bag)
ori_validate = option_bag.config_bag.validate
option_bag.config_bag.validate = False
try:
fake_value.reset_slave(option_bag)
value = fake_value.getdefaultvalue(option_bag)
fake_value.setvalue_validation(value,
option_bag)
option_bag.config_bag.validate = ori_validate
except Exception as err:
option_bag.config_bag.validate = ori_validate
raise err
self._p_.resetvalue_index(option_bag.path, option_bag.index)
context.cfgimpl_reset_cache(option_bag)
def reset_master(self,
subconfig,
path,
index,
config_bag):
option_bag,
subconfig):
current_value = self.get_cached_value(path,
None,
config_bag)
current_value = self.get_cached_value(option_bag)
length = len(current_value)
if index >= length:
raise IndexError(_('index "{}" is higher than the length "{}" '
'for option "{}"').format(index,
length,
config_bag.option.impl_get_display_name()))
option_bag.option.impl_get_display_name()))
current_value.pop(index)
self.setvalue(path,
None,
current_value,
config_bag,
self.setvalue(current_value,
option_bag,
_commit=True)
subconfig.cfgimpl_get_description().pop(self,
index,
config_bag)
def setowner_validation(self,
path,
index,
config_bag):
context = self._getcontext()
settings = context.cfgimpl_get_settings()
# First validate properties with this value
self_properties = config_bag.properties
settings.validate_frozen(path,
index,
config_bag)
option_bag)
#______________________________________________________________________
# information
@ -684,24 +581,26 @@ class Values(object):
settings = context.cfgimpl_get_settings()
# for option in config.cfgimpl_get_children(self.config_bag):
for option in description.impl_getchildren(config_bag, context):
sconfig_bag = config_bag.copy('nooption')
sconfig_bag.option = option
name = option.impl_getname()
path = '.'.join(currpath + [name])
if option.impl_is_optiondescription():
ori_setting_properties = sconfig_bag.setting_properties
sconfig_bag.setting_properties = od_setting_properties
ori_setting_properties = config_bag._setting_properties
config_bag._setting_properties = od_setting_properties
try:
option_bag = OptionBag()
option_bag.set_option(option,
path,
None,
config_bag)
subconfig = config.getattr(name,
None,
sconfig_bag)
option_bag)
except PropertiesOptionError as err:
pass
else:
sconfig_bag.setting_properties = ori_setting_properties
config_bag._setting_properties = ori_setting_properties
for path in self._mandatory_warnings(context,
sconfig_bag,
config_bag,
option,
currpath + [name],
subconfig,
@ -711,26 +610,24 @@ class Values(object):
# don't verifying symlink
try:
if not option.impl_is_master_slaves('slave'):
self_properties = settings.getproperties(path,
None,
sconfig_bag)
sconfig_bag.properties = self_properties
if 'mandatory' in self_properties or 'empty' in self_properties:
option_bag = OptionBag()
option_bag.set_option(option,
path,
None,
config_bag)
if 'mandatory' in option_bag.properties or 'empty' in option_bag.properties:
config.getattr(name,
None,
sconfig_bag)
option_bag)
else:
for index in range(config.cfgimpl_get_length()):
self_properties = settings.getproperties(path,
index,
sconfig_bag)
sconfig_bag.properties = self_properties
if 'mandatory' in self_properties:
option_bag = OptionBag()
option_bag.set_option(option,
path,
index,
config_bag)
if 'mandatory' in option_bag.properties:
config.getattr(name,
index,
sconfig_bag)
option_bag)
except PropertiesOptionError as err:
if err.proptype == ['mandatory']:
yield path
@ -750,7 +647,8 @@ class Values(object):
od_setting_properties = config_bag.setting_properties - {'mandatory', 'empty'}
setting_properties = set(config_bag.setting_properties) - {'warnings'}
setting_properties.update(['mandatory', 'empty'])
config_bag.setting_properties = frozenset(setting_properties)
config_bag = ConfigBag(config=config_bag.config)
config_bag._setting_properties = frozenset(setting_properties)
config_bag.force_permissive = True
descr = context.cfgimpl_get_description()