add config_bag and convert some tests

This commit is contained in:
Emmanuel Garette 2017-12-19 23:11:45 +01:00
parent b5f785d62c
commit 538e6a792a
33 changed files with 2432 additions and 1319 deletions

View file

@ -374,7 +374,7 @@ def test_cache_master_slave():
api = getapi(cfg)
api.property.read_write()
assert cfg.cfgimpl_get_values()._p_.get_cached() == {}
assert cfg.cfgimpl_get_settings()._p_.get_cached() == {}
#assert cfg.cfgimpl_get_settings()._p_.get_cached() == {}
#
api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.2'])
api.option('ip_admin_eth0.ip_admin_eth0').value.get()
@ -581,21 +581,20 @@ def test_cache_master_and_slaves_master():
assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
'val1': {None: (set([]), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached() == {}
api.option.make_dict()
if TIRAMISU_VERSION == 2:
val1_val2_props = {None: (set([]), None), 0: (set([]), None), 1: (set([]), None)}
else:
val1_val2_props = {0: (frozenset([]), None), 1: (frozenset([]), None)}
assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (global_props, None)},
'val1': {None: (val1_props, None)},
'val1.val1': {None: (val1_val1_props, None)},
'val1.val2': val1_val2_props}
if TIRAMISU_VERSION == 2:
assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1.val1': {None: ([None, None], None)},
'val1.val2': {None: ([None, 'oui'], None)}}
else:
assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1.val1': {None: ([None, None], None)},
'val1.val2': {0: (None, None), 1: ('oui', None)}}
#assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (global_props, None)},
# 'val1': {None: (val1_props, None)},
# 'val1.val1': {None: (val1_val1_props, None)},
# 'val1.val2': val1_val2_props}
#if TIRAMISU_VERSION == 2:
# assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1.val1': {None: ([None, None], None)},
# 'val1.val2': {None: ([None, 'oui'], None)}}
#else:
# assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1.val1': {None: ([None, None], None)},
# 'val1.val2': {0: (None, None), 1: ('oui', None)}}
def test_cache_master_callback():
@ -707,14 +706,15 @@ def test_cache_requires():
api = getapi(c)
api.property.read_write()
api.property.pop('expire')
assert c.cfgimpl_get_settings()._p_.get_cached() == {}
#assert c.cfgimpl_get_settings()._p_.get_cached() == {}
assert c.cfgimpl_get_values()._p_.get_cached() == {}
assert api.option('ip_address_service').value.get() == None
assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
'activate_service': {None: (set([]), None)},
'ip_address_service': {None: (set([]), None)}}
assert c.cfgimpl_get_values()._p_.get_cached() == {'ip_address_service': {None: (None, None)}}
assert c.cfgimpl_get_values()._p_.get_cached() == {'ip_address_service': {None: (None, None)},
'activate_service': {None: (True, None)}}
api.option.make_dict()
assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
'activate_service': {None: (set([]), None)},
@ -755,14 +755,15 @@ def test_cache_global_properties():
api = getapi(c)
api.property.read_write()
api.property.pop('expire')
assert c.cfgimpl_get_settings()._p_.get_cached() == {}
#assert c.cfgimpl_get_settings()._p_.get_cached() == {}
assert c.cfgimpl_get_values()._p_.get_cached() == {}
assert api.option('ip_address_service').value.get() == None
assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
'activate_service': {None: (set([]), None)},
'ip_address_service': {None: (set([]), None)}}
assert c.cfgimpl_get_values()._p_.get_cached() == {'ip_address_service': {None: (None, None)}}
assert c.cfgimpl_get_values()._p_.get_cached() == {'ip_address_service': {None: (None, None)},
'activate_service': {None: (True, None)}}
api.property.pop('disabled')
assert api.option('ip_address_service').value.get() == None
assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'frozen', 'hidden', 'validator', 'warnings']), None)},

View file

@ -46,8 +46,8 @@ def test_base_config():
cfg = Config(descr)
api = getapi(cfg)
assert api.option('dummy').value.get() is False
dmo = cfg.unwrap_from_path('dummy')
assert dmo.impl_getname() == 'dummy'
#dmo = cfg.unwrap_from_path('dummy')
#assert dmo.impl_getname() == 'dummy'
def test_base_config_name():
@ -62,20 +62,20 @@ def test_not_config():
assert raises(TypeError, "Config('str')")
def test_base_path():
gcdummy = BoolOption('dummy', 'dummy', default=False)
descr = OptionDescription('tiramisu', '', [gcdummy])
cfg = Config(descr)
assert cfg._impl_path is None
base = OptionDescription('config', '', [descr])
cfg = Config(base)
assert cfg._impl_path is None
assert cfg.getattr('tiramisu', None, validate_properties=False)._impl_path == 'tiramisu'
nbase = OptionDescription('baseconfig', '', [base])
cfg = Config(nbase)
assert cfg._impl_path is None
assert cfg.getattr('config', None, validate_properties=False)._impl_path == 'config'
assert cfg.getattr('config.tiramisu', None, validate_properties=False)._impl_path == 'config.tiramisu'
#def test_base_path():
# gcdummy = BoolOption('dummy', 'dummy', default=False)
# descr = OptionDescription('tiramisu', '', [gcdummy])
# cfg = Config(descr)
# assert cfg._impl_path is None
# base = OptionDescription('config', '', [descr])
# cfg = Config(base)
# assert cfg._impl_path is None
# assert cfg.getattr('tiramisu', None, validate_properties=False)._impl_path == 'tiramisu'
# nbase = OptionDescription('baseconfig', '', [base])
# cfg = Config(nbase)
# assert cfg._impl_path is None
# assert cfg.getattr('config', None, validate_properties=False)._impl_path == 'config'
# assert cfg.getattr('config.tiramisu', None, validate_properties=False)._impl_path == 'config.tiramisu'
def test_base_config_force_permissive():
@ -129,14 +129,14 @@ def test_base_config_in_a_tree():
assert api.option('wantframework').value.get() is False
def test_cfgimpl_get_home_by_path():
" :meth:`tiramisu.config.SubConfig.cfgimpl_get_home_by_path()` to retrieve a path"
descr = make_description()
config = Config(descr)
api = getapi(config)
api.option('bool').value.set(False)
assert config.cfgimpl_get_home_by_path('gc.dummy', None)[1] == 'dummy'
assert config.cfgimpl_get_home_by_path('dummy', None)[1] == 'dummy'
#def test_cfgimpl_get_home_by_path():
# " :meth:`tiramisu.config.SubConfig.cfgimpl_get_home_by_path()` to retrieve a path"
# descr = make_description()
# config = Config(descr)
# api = getapi(config)
# api.option('bool').value.set(False)
# assert config.cfgimpl_get_home_by_path('gc.dummy', None)[1] == 'dummy'
# assert config.cfgimpl_get_home_by_path('dummy', None)[1] == 'dummy'
def test_not_valid_properties():
@ -172,25 +172,25 @@ def test_config_impl_get_path_by_opt():
raises(AttributeError, "config.cfgimpl_get_description().impl_get_path_by_opt(unknown)")
def test_config_impl_get_path_by_opt_od():
descr = make_description()
config = Config(descr)
api = getapi(config)
dummy = api.option.get('gc.dummy')
dummy
raises(ConfigError, "config.getattr('gc', None).cfgimpl_get_description().impl_get_path_by_opt(dummy)")
def test_config_impl_get_opt_by_path():
descr = make_description()
config = Config(descr)
api = getapi(config)
dummy = api.option.get('gc.dummy')
boo = api.option.get('bool')
assert config.cfgimpl_get_description().impl_get_opt_by_path('bool') == boo
assert config.cfgimpl_get_description().impl_get_opt_by_path('gc.dummy') == dummy
raises(AttributeError, "config.cfgimpl_get_description().impl_get_opt_by_path('gc.unknown')")
raises(ConfigError, "config.getattr('gc', None).cfgimpl_get_description().impl_get_opt_by_path('gc.unknown')")
#def test_config_impl_get_path_by_opt_od():
# descr = make_description()
# config = Config(descr)
# api = getapi(config)
# dummy = api.option.get('gc.dummy')
# dummy
# raises(ConfigError, "config.getattr('gc', None).cfgimpl_get_description().impl_get_path_by_opt(dummy)")
#
#
#def test_config_impl_get_opt_by_path():
# descr = make_description()
# config = Config(descr)
# api = getapi(config)
# dummy = api.option.get('gc.dummy')
# boo = api.option.get('bool')
# assert config.cfgimpl_get_description().impl_get_opt_by_path('bool') == boo
# assert config.cfgimpl_get_description().impl_get_opt_by_path('gc.dummy') == dummy
# raises(AttributeError, "config.cfgimpl_get_description().impl_get_opt_by_path('gc.unknown')")
# raises(ConfigError, "config.getattr('gc', None).cfgimpl_get_description().impl_get_opt_by_path('gc.unknown')")
#def test_information_display():

View file

@ -715,9 +715,8 @@ def test_consistency_dyndescription_default():
st.impl_add_consistency('not_equal', st2)
od2 = OptionDescription('od', '', [od])
api = getapi(Config(od2))
print('===>', api.option('od.dodval1.st2val1').value.get())
raises(ValueError, "api.option('od.dodval1.st2val1').value.get()")
raises(ValueError, "api.option('od.dodval2.st2val2').value.get()")
raises(ValueError, "api.option('od.dodval1.st2val1').value.set('yes')")
raises(ValueError, "api.option('od.dodval2.st2val2').value.set('yes')")
def test_consistency_dyndescription_default_multi2():
@ -732,7 +731,7 @@ def test_consistency_only_one_dyndescription():
st = StrOption('st', '')
st
st2 = StrOption('st2', '')
DynOptionDescription('dod', '', [st2], callback=return_list)
dod = DynOptionDescription('dod', '', [st2], callback=return_list)
raises(ConfigError, "st.impl_add_consistency('not_equal', st2)")
raises(ConfigError, "st2.impl_add_consistency('not_equal', st)")

View file

@ -293,7 +293,7 @@ def test_mandatory_disabled():
api.option('str1').value.get()
except PropertiesOptionError as err:
prop = err.proptype
assert set(prop) == set(['disabled', 'mandatory'])
assert set(prop) == {'disabled'}
def test_mandatory_unicode():

View file

@ -0,0 +1,99 @@
"""these tests are here to create some :class:`tiramisu.option.Option`'s
and to compare them
"""
from .autopath import do_autopath
do_autopath()
from py.test import raises
from tiramisu.option import IntOption, OptionDescription
from tiramisu.config import Config
def a_func():
return None
def test_option_valid_name():
IntOption('test', '')
raises(ValueError, 'IntOption(1, "")')
raises(ValueError, 'IntOption("1test", "")')
IntOption("test1", "")
raises(ValueError, 'IntOption("impl_test", "")')
raises(ValueError, 'IntOption("_test", "")')
raises(ValueError, 'IntOption("unwrap_from_path", "")')
raises(ValueError, 'IntOption(" ", "")')
def test_option_with_callback():
#no default value with callback
raises(ValueError, "IntOption('test', '', default=1, callback=a_func)")
def test_option_get_information():
description = "it's ok"
string = 'some informations'
i = IntOption('test', description)
raises(ValueError, "i.impl_get_information('noinfo')")
i.impl_set_information('info', string)
assert i.impl_get_information('info') == string
raises(ValueError, "i.impl_get_information('noinfo')")
assert i.impl_get_information('noinfo', 'default') == 'default'
assert i.impl_get_information('doc') == description
assert i.impl_getdoc() == description
def test_option_get_information_config():
description = "it's ok"
string = 'some informations'
string
i = IntOption('test', description)
od = OptionDescription('od', '', [i])
Config(od)
raises(ValueError, "i.impl_get_information('noinfo')")
raises(AttributeError, "i.impl_set_information('info', string)")
# assert i.impl_get_information('info') == string
raises(ValueError, "i.impl_get_information('noinfo')")
assert i.impl_get_information('noinfo', 'default') == 'default'
assert i.impl_get_information('doc') == description
assert i.impl_getdoc() == description
def test_option_get_information_config2():
description = "it's ok"
string = 'some informations'
i = IntOption('test', description)
i.impl_set_information('info', string)
od = OptionDescription('od', '', [i])
Config(od)
raises(ValueError, "i.impl_get_information('noinfo')")
raises(AttributeError, "i.impl_set_information('info', 'hello')")
assert i.impl_get_information('info') == string
raises(ValueError, "i.impl_get_information('noinfo')")
assert i.impl_get_information('noinfo', 'default') == 'default'
assert i.impl_get_information('doc') == description
assert i.impl_getdoc() == description
def test_optiondescription_get_information():
description = "it's ok"
string = 'some informations'
o = OptionDescription('test', description, [])
o.impl_set_information('info', string)
assert o.impl_get_information('info') == string
raises(ValueError, "o.impl_get_information('noinfo')")
assert o.impl_get_information('noinfo', 'default') == 'default'
assert o.impl_get_information('doc') == description
assert o.impl_getdoc() == description
def test_option_multi():
IntOption('test', '', multi=True)
IntOption('test', '', multi=True, default_multi=1)
IntOption('test', '', default=[1], multi=True, default_multi=1)
#add default_multi to not multi's option
raises(ValueError, "IntOption('test', '', default_multi=1)")
#unvalid default_multi
raises(ValueError, "IntOption('test', '', multi=True, default_multi='yes')")
#not default_multi with callback
raises(ValueError, "IntOption('test', '', multi=True, default_multi=1, callback=a_func)")

File diff suppressed because it is too large Load diff

View file

@ -17,7 +17,7 @@
from inspect import ismethod, getdoc
from .error import APIError, PropertiesOptionError, ConfigError
from .i18n import _
from .setting import owners, undefined
from .setting import ConfigBag, owners, undefined
from .option import ChoiceOption
from time import time
from copy import deepcopy
@ -79,6 +79,7 @@ def display_count():
print('==> moy:', MOD_COUNT_TIME[class_name][func]['total'] / MOD_COUNT_TIME[class_name][func]['nb'])
MOD_COUNT_TIME = deepcopy(COUNT_TIME)
class CommonTiramisuOption(object):
icon = '\u2937'
tmpl_help = u' {} {}: {}'
@ -87,30 +88,23 @@ class CommonTiramisuOption(object):
slave_need_index = True
def __init__(self,
opt,
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint):
config_bag):
opt = config_bag.option
if not self.allow_optiondescription and opt.impl_is_optiondescription():
raise APIError(_('option must not be an optiondescription'))
self._opt = opt
self._path = path
self.path = path
self.index = index
self.config_bag = config_bag
if self.slave_need_index:
self._test_slave_index()
self.config = config
self.setting_properties = setting_properties
self.force_permissive = force_permissive
self.force_unrestraint = force_unrestraint
if not self.allow_unrestraint:
self._unrestraint_not_allowed(force_unrestraint)
self._unrestraint_not_allowed(self.config_bag.force_unrestraint)
def _test_slave_index(self):
if not self._opt.impl_is_optiondescription() and self.index is None and \
self._opt.impl_is_master_slaves('slave'):
if not self.config_bag.option.impl_is_optiondescription() and self.index is None and \
self.config_bag.option.impl_is_master_slaves('slave'):
raise APIError('index must be set with a slave option')
def _unrestraint_not_allowed(self, force_unrestraint):
@ -143,24 +137,6 @@ class TiramisuOptionOption(CommonTiramisuOption):
allow_optiondescription = True
slave_need_index = False
def __init__(self,
opt,
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint):
super(TiramisuOptionOption, self).__init__(opt,
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint)
if config:
self.values = self.config.cfgimpl_get_values()
@count
def ismulti(self):
"""test if option could have multi value"""
@ -202,46 +178,37 @@ class TiramisuOptionOption(CommonTiramisuOption):
def getdefaultmulti(self):
return self._opt.impl_getdefault_multi()
@count
def has_dependency(self, self_is_dep=True):
return self.config_bag.option.impl_has_dependency(self_is_dep)
class TiramisuOptionOwner(CommonTiramisuOption):
"""manager option's owner"""
def __init__(self,
opt,
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint):
config_bag):
super(TiramisuOptionOwner, self).__init__(opt,
path,
super(TiramisuOptionOwner, self).__init__(path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint)
if config:
self.values = self.config.cfgimpl_get_values()
config_bag)
self.values = self.config_bag.config.cfgimpl_get_values()
@count
def get(self):
"""get owner for a specified option"""
return self.values.getowner(self._opt,
path=self._path,
setting_properties=self.setting_properties,
index=self.index,
force_permissive=self.force_permissive)
return self.values.getowner(self.path,
self.index,
self.config_bag)
@count
def isdefault(self):
"""is option has defaut value"""
return self.values.is_default_owner(self._opt,
self._path,
self.setting_properties,
index=self.index,
force_permissive=self.force_permissive)
return self.values.is_default_owner(self.path,
self.index,
self.config_bag)
@count
def set(self, owner):
@ -254,44 +221,34 @@ class TiramisuOptionOwner(CommonTiramisuOption):
except AttributeError:
owners.addowner(owner)
obj_owner = getattr(owners, owner)
self.values.setowner(self._opt,
path=self._path,
owner=obj_owner,
setting_properties=self.setting_properties,
index=self.index)
self.values.setowner(self.path,
self.index,
obj_owner,
self.config_bag)
class TiramisuOptionProperty(CommonTiramisuOption):
"""manager option's property"""
#allow_unrestraint = True
allow_optiondescription = True
allow_unrestraint = True
slave_need_index = False
def __init__(self,
opt,
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint):
super(TiramisuOptionProperty, self).__init__(opt,
path,
config_bag):
super(TiramisuOptionProperty, self).__init__(path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint)
if config:
self.settings = config.cfgimpl_get_settings()
config_bag)
self.settings = config_bag.config.cfgimpl_get_settings()
@count
def get(self):
self._test_slave_index()
properties = self.settings.getproperties(self._opt,
self._path,
self.setting_properties,
index=self.index)
properties = self.settings.getproperties(self.path,
self.index,
self.config_bag)
if TIRAMISU_VERSION == 2:
properties = properties.get()
return set(properties)
@ -300,9 +257,9 @@ class TiramisuOptionProperty(CommonTiramisuOption):
def set(self, properties):
"""set properties for a specified option"""
properties = frozenset(properties)
self.settings.setproperties(opt=self._opt,
path=self._path,
properties=properties)
self.settings.setproperties(path=self.path,
properties=properties,
config_bag=self.config_bag)
@count
def add(self, prop):
@ -331,22 +288,13 @@ class TiramisuOptionPermissive(CommonTiramisuOption):
slave_need_index = False
def __init__(self,
opt,
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint):
super(TiramisuOptionPermissive, self).__init__(opt,
path,
config_bag):
super(TiramisuOptionPermissive, self).__init__(path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint)
if config:
self.settings = config.cfgimpl_get_settings()
config_bag)
self.settings = config_bag.config.cfgimpl_get_settings()
@count
def get(self):
@ -377,7 +325,7 @@ class TiramisuOptionInformation(CommonTiramisuOption):
@count
def get(self, name, default=undefined):
return self._opt.impl_get_information(name, default)
return self.config_bag.option.impl_get_information(name, default)
class TiramisuOptionValue(CommonTiramisuOption):
@ -387,11 +335,10 @@ class TiramisuOptionValue(CommonTiramisuOption):
@count
def get(self):
self._test_slave_index()
settings = self.config.cfgimpl_get_settings()
value = self.config.getattr(self._path,
index=self.index,
setting_properties=self.setting_properties,
force_permissive=self.force_permissive)
settings = self.config_bag.config.cfgimpl_get_settings()
value = self.config_bag.config.getattr(self.path,
self.index,
self.config_bag)
if isinstance(value, Multi):
value = list(value)
return value
@ -400,25 +347,22 @@ class TiramisuOptionValue(CommonTiramisuOption):
def set(self, value):
"""set a value for a specified option"""
self._test_slave_index()
values = self.config.cfgimpl_get_values()
values = self.config_bag.config.cfgimpl_get_values()
if isinstance(value, list):
while undefined in value:
idx = value.index(undefined)
value[idx] = values.getdefaultvalue(self._opt,
self._path,
self.setting_properties,
idx)
value[idx] = values.getdefaultvalue(self.path,
idx,
self.config_bag)
else:
if value == undefined:
value = values.getdefaultvalue(self._opt,
self._path,
self.setting_properties,
self.index)
self.config.setattr(self._path,
value = values.getdefaultvalue(self.path,
self.index,
self.config_bag)
self.config_bag.config.setattr(self.path,
self.index,
value,
index=self.index,
setting_properties=self.setting_properties,
force_permissive=self.force_permissive)
self.config_bag)
@count
def pop(self, index):
@ -426,39 +370,37 @@ class TiramisuOptionValue(CommonTiramisuOption):
"""
self._test_slave_index()
#FIXME only for master
self.config.delattr(self._path,
index=index,
setting_properties=self.setting_properties,
force_permissive=self.force_permissive)
self.config_bag.config.delattr(self.path,
index,
self.config_bag)
@count
def reset(self):
"""reset value for a value"""
self._test_slave_index()
self.config.delattr(self._path,
index=self.index,
setting_properties=self.setting_properties,
force_permissive=self.force_permissive)
self.config_bag.config.delattr(self.path,
self.index,
self.config_bag)
@count
def len(self):
#FIXME only for slave
subconfig_path = self._path.rsplit('.', 1)[0]
subconfig = self.config.getattr(subconfig_path,
setting_properties=self.setting_properties,
force_permissive=self.force_permissive)
None,
self.config_bag)
return subconfig.cfgimpl_get_length()
def __getattr__(self, name):
if name == 'list':
if isinstance(self._opt, ChoiceOption):
if isinstance(self.config_bag.option, ChoiceOption):
return self._list
raise APIError(_('{} allowed only for choiceoption').format(name))
raise APIError(_('{} is unknown').format(name))
@count
def _list(self):
return self._opt.impl_get_values(context=self.config,
setting_properties=self.setting_properties)
return self.config_bag.option.impl_get_values(self.config_bag)
def registers(registers, prefix):
@ -474,21 +416,13 @@ class TiramisuOption(object):
tmpl_help = ' {} {}: {}'
def __init__(self,
opt,
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint):
config_bag):
self._opt = opt
self._path = path
self.index = index
self.config = config
self.setting_properties = setting_properties
self.force_permissive = force_permissive
self.force_unrestraint = force_unrestraint
self.config_bag = config_bag
self.registers = {}
registers(self.registers, self.__class__.__name__)
@ -502,13 +436,9 @@ class TiramisuOption(object):
def __getattr__(self, subfunc):
if subfunc in self.registers:
return self.registers[subfunc](self._opt,
self._path,
return self.registers[subfunc](self._path,
self.index,
self.config,
self.setting_properties,
self.force_permissive,
self.force_unrestraint)
self.config_bag)
elif subfunc == 'help':
return self._help()
else:
@ -520,70 +450,65 @@ class TiramisuOption(object):
withvalue=undefined,
withoption=None,
fullpath=False):
return self.config.getattr(setting_properties=self.setting_properties,
name=self._path).make_dict(setting_properties=self.setting_properties,
return self.config_bag.config.getattr(self._path,
None,
self.config_bag).make_dict(config_bag=self.config_bag,
flatten=flatten,
fullpath=fullpath,
withoption=withoption,
force_permissive=self.force_permissive,
withvalue=withvalue)
class TiramisuContext(object):
def __init__(self,
config,
force_permissive,
force_unrestraint,
setting_properties=None):
if setting_properties is None:
setting_properties = config.cfgimpl_get_settings().get_context_properties()
self.config = config
self.force_permissive = force_permissive
self.force_unrestraint = force_unrestraint
self.setting_properties = setting_properties
config_bag):
self.config_bag = config_bag
class TiramisuContextInformation(TiramisuContext):
@count
def get(self, name, default=undefined):
return self.config.impl_get_information(name, default)
return self.config_bag.config.impl_get_information(name, default)
@count
def set(self, name, value):
self.config.impl_set_information(name, value)
self.config_bag.config.impl_set_information(name, value)
@count
def reset(self, name):
self.config.impl_del_information(name)
self.config_bag.config.impl_del_information(name)
class TiramisuContextValue(TiramisuContext):
@count
def mandatory_warnings(self):
return self.config.cfgimpl_get_values().mandatory_warnings(self.setting_properties)
return self.config_bag.config.cfgimpl_get_values().mandatory_warnings(self.config_bag)
@count
def get(self):
return self.config.cfgimpl_get_values().get_modified_values()
return self.config_bag.config.cfgimpl_get_values().get_modified_values()
class TiramisuContextOwner(TiramisuContext):
@count
def get(self):
return self.config.cfgimpl_get_settings().getowner()
return self.config_bag.config.cfgimpl_get_settings().getowner()
class TiramisuContextProperty(TiramisuContext):
@count
def read_only(self):
self.config.cfgimpl_get_settings().read_only()
settings = self.config_bag.config.cfgimpl_get_settings()
settings.read_only()
self.config_bag.setting_properties = settings.get_context_properties()
@count
def read_write(self):
self.config.cfgimpl_get_settings().read_write()
settings = self.config_bag.config.cfgimpl_get_settings()
settings.read_write()
# #FIXME ?
settings = self.config.cfgimpl_get_settings()
settings.set_context_permissive(frozenset(['hidden']))
self.config_bag.setting_properties = settings.get_context_properties()
#/FIXME ?
@count
@ -591,20 +516,23 @@ class TiramisuContextProperty(TiramisuContext):
props = self.get()
props.add(prop)
self.set(props)
self.config_bag.setting_properties = self.config_bag.config.cfgimpl_get_settings().get_context_properties()
@count
def pop(self, prop):
props = self.get()
props.remove(prop)
self.set(props)
self.config_bag.setting_properties = self.config_bag.config.cfgimpl_get_settings().get_context_properties()
@count
def get(self):
return set(self.config.cfgimpl_get_settings().get_context_properties())
return set(self.config_bag.setting_properties)
@count
def set(self, props):
self.config.cfgimpl_get_settings().set_context_properties(frozenset(props))
self.config_bag.config.cfgimpl_get_settings().set_context_properties(frozenset(props))
self.config_bag.setting_properties = self.config_bag.config.cfgimpl_get_settings().get_context_properties()
class TiramisuContextPermissive(TiramisuContext):
@ -613,7 +541,7 @@ class TiramisuContextPermissive(TiramisuContext):
def set(self, permissives):
if TIRAMISU_VERSION != 2:
permissives = frozenset(permissives)
self.config.cfgimpl_get_settings().set_context_permissive(permissives)
self.config_bag.config.cfgimpl_get_settings().set_context_permissive(permissives)
class TiramisuContextOption(TiramisuContext):
@ -621,28 +549,24 @@ class TiramisuContextOption(TiramisuContext):
def find_first(self,
name,
type='option'):
check_properties = self.force_unrestraint or self.force_unrestraint
return self.config.find_first(byname=name,
check_properties = self.config_bag.force_unrestraint or self.config_bag.force_unrestraint
return self.config_bag.config.find_first(byname=name,
type_=type,
setting_properties=self.setting_properties,
force_permissive=self.force_permissive,
check_properties=not self.force_unrestraint)
config_bag=self.config_bag)
@count
def find(self,
name,
type='option'):
return self.config.find(byname=name,
return self.config_bag.config.find(byname=name,
type_=type,
setting_properties=self.setting_properties,
force_permissive=self.force_permissive,
check_properties=not self.force_unrestraint)
config_bag=self.config_bag)
@count
def get(self, path):
return self.config.unwrap_from_path(path,
validate=False,
validate_properties=False)
return self.config_bag.config.unwrap_from_path(path,
None,
self.config_bag)
@count
def make_dict(self,
@ -650,58 +574,39 @@ class TiramisuContextOption(TiramisuContext):
withvalue=undefined,
withoption=None,
fullpath=False):
return self.config.make_dict(setting_properties=self.setting_properties,
return self.config_bag.config.make_dict(self.config_bag,
flatten=flatten,
fullpath=fullpath,
force_permissive=self.force_permissive,
withoption=withoption,
withvalue=withvalue)
class TiramisuDispatcherOption(TiramisuContextOption):
def __init__(self,
config,
force_permissive,
force_unrestraint):
self.setting_properties = config.cfgimpl_get_settings().get_context_properties()
super(TiramisuDispatcherOption, self).__init__(config,
force_permissive,
force_unrestraint,
self.setting_properties)
def __call__(self, path, index=None):
validate = not self.force_unrestraint
if validate:
s_properties = self.setting_properties
else:
s_properties = None
opt = self.config.unwrap_from_path(path,
setting_properties=s_properties,
validate=validate,
validate_properties=validate,
force_permissive=self.force_permissive,
index=index)
config_bag = self.config_bag.copy()
validate = not config_bag.force_unrestraint
config_bag.validate = validate
config_bag.validate_properties = validate
if not validate:
config_bag.setting_properties = None
opt = config_bag.config.unwrap_from_path(path,
index,
config_bag)
config_bag.option = opt
if index is not None and not opt.impl_is_master_slaves('slave'):
raise APIError('index must be set only with a slave option')
if opt.impl_is_symlinkoption():
true_opt = opt.impl_getopt()
true_path = true_opt.impl_getpath(self.config)
self.config.unwrap_from_path(true_path,
setting_properties=s_properties,
validate=validate,
validate_properties=validate,
force_permissive=self.force_permissive,
index=index)
else:
true_opt = None
true_path = None
return TiramisuOption(opt,
path,
config_bag.ori_option = config_bag.option
config_bag.option = opt.impl_getopt()
true_path = config_bag.option.impl_getpath(self.config_bag.config)
config_bag.config.unwrap_from_path(true_path,
index,
self.config,
self.setting_properties,
self.force_permissive,
self.force_unrestraint)
config_bag)
else:
true_path = None
return TiramisuOption(path,
index,
config_bag)
class TiramisuAPI(object):
@ -721,23 +626,20 @@ class TiramisuAPI(object):
def __getattr__(self, subfunc):
if subfunc == 'forcepermissive':
return TiramisuAPI(self._config,
return TiramisuAPI(config=self._config,
force_permissive=True,
force_unrestraint=self.force_unrestraint)
elif subfunc == 'unrestraint':
return TiramisuAPI(self._config,
force_permissive=self.force_permissive,
force_unrestraint=True)
elif subfunc == 'config':
return TiramisuAPI(self._config,
elif subfunc in ['unrestraint', 'config']:
return TiramisuAPI(config=self._config,
force_permissive=self.force_permissive,
force_unrestraint=True)
elif subfunc == 'help':
return self._help()
elif subfunc in self.registers:
return self.registers[subfunc](self._config,
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))

View file

@ -30,9 +30,8 @@ def carry_out_calculation(option,
context,
callback,
callback_params,
setting_properties,
index=undefined,
validate=True,
index,
config_bag,
is_validator=False):
"""a function that carries out a calculation for an option's value
@ -144,25 +143,26 @@ def carry_out_calculation(option,
If calculate return list, this list is extend to return value.
"""
tcparams = {}
args = []
kwargs = {}
# if callback_params has a callback, launch several time calculate()
master_slave = False
has_option = False
# multi's option should have same value for all option
if option._is_subdyn():
tcparams['suffix'] = [(option.impl_getsuffix(), False)]
kwargs['suffix'] = option.impl_getsuffix()
for key, callbacks in callback_params.items():
for callbk in callbacks:
if isinstance(callbk, tuple):
if context is undefined:
if not isinstance(callbk, tuple):
# callbk is a value and not a multi
value = callbk
elif context is undefined:
return undefined
if callbk[0] is None: # pragma: optional cover
elif callbk[0] is None: # pragma: optional cover
#Not an option, set full context
tcparams.setdefault(key, []).append((context.duplicate(
force_values=get_default_values_storages(),
force_settings=get_default_settings_storages()), False))
value = context.duplicate(force_values=get_default_values_storages(),
force_settings=get_default_settings_storages())
elif callbk[0] == 'index':
tcparams.setdefault(key, []).append((index, False))
value = index
else:
# callbk is something link (opt, True|False)
opt, force_permissive = callbk
@ -172,82 +172,62 @@ def carry_out_calculation(option,
option.impl_getsuffix())
path = opt.impl_getpath(context)
else:
path = context.cfgimpl_get_description(
).impl_get_path_by_opt(opt)
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 opt == option:
valid = False
sconfig_bag.validate = False
if index is not None and opt.impl_is_master_slaves() and \
opt.impl_get_master_slaves().in_same_group(option):
if opt.impl_is_master_slaves('slave'):
index_ = index
with_index = False
else:
valid = validate
# get value
index_ = None
with_index = True
else:
index_ = None
with_index = False
try:
# get value
value = context.getattr(path,
force_permissive=True,
validate=valid,
setting_properties=setting_properties)
index_,
sconfig_bag)
if with_index:
value = value[index]
except PropertiesOptionError as err:
if force_permissive:
continue
raise ConfigError(_('unable to carry out a calculation for "{}"'
', {}').format(option.impl_get_display_name(), err))
# convert to list, not modifie this multi
if value.__class__.__name__ == 'Multi':
has_option = True
value = list(value)
if opt != option and opt.impl_is_master_slaves() and \
opt.impl_get_master_slaves().in_same_group(option):
master_slave = True
is_multi = True
if key == '':
args.append(value)
else:
is_multi = False
tcparams.setdefault(key, []).append((value, is_multi))
else:
# callbk is a value and not a multi
tcparams.setdefault(key, []).append((callbk, False))
kwargs[key] = value
# if one value is a multi, launch several time calculate
# if index is set, return a value
# if no index, return a list
if master_slave:
ret = []
args = []
kwargs = {}
for key, couples in tcparams.items():
for couple in couples:
value, ismulti = couple
if ismulti:
val = value[index]
else:
val = value
if key == '':
args.append(val)
else:
kwargs[key] = val
return calculate(option, callback, is_validator, args, kwargs)
else:
# no value is multi
# return a single value
args = []
kwargs = {}
for key, couples in tcparams.items():
for couple in couples:
# couple[1] (ismulti) is always False
if key == '':
args.append(couple[0])
else:
kwargs[key] = couple[0]
ret = calculate(option, callback, is_validator, args, kwargs)
if not option.impl_is_optiondescription() and callback_params != {} and isinstance(ret, list) and \
ret = calculate(option,
callback,
is_validator,
args,
kwargs)
if isinstance(ret, list) and not option.impl_is_dynoptiondescription() and \
option.impl_is_master_slaves('slave'):
if not has_option and index not in [None, undefined]:
if index < len(ret):
ret = ret[index]
if args or kwargs:
raise SlaveError(_('function "{}" return the list "{}" for the slave option "{}"'
'').format(callback.__name__,
ret,
option.impl_getname()))
else:
ret = None
else:
raise SlaveError(_("callback cannot return a list for a "
"slave option ({0})").format(option.impl_getname()))
raise SlaveError(_('function "{}" with arguments "{}" and "{}" '
'return the list "{}" for the slave option "{}"'
'').format(callback.__name__,
args,
kwargs,
value,
option.impl_get_display_name()))
return ret
@ -267,7 +247,7 @@ def calculate(option, callback, is_validator, args, kwargs):
error = err
except Exception as err:
error = err
if len(args) != 0 or len(kwargs) != 0:
if args or kwargs:
msg = _('unexpected error "{0}" in function "{1}" with arguments "{3}" and "{4}" '
'for option "{2}"').format(str(error),
callback.__name__,

View file

@ -20,25 +20,19 @@
# ____________________________________________________________
"options handler global entry point"
import weakref
import sys
from time import time
from copy import copy
from .error import PropertiesOptionError, ConfigError, ConflictError
from .option import OptionDescription, Option, SymLinkOption, \
DynSymLinkOption, SynDynOptionDescription
from .option.baseoption import valid_name
from .setting import groups, Settings, default_encoding, undefined
from .storage import get_storages, set_storage, get_default_values_storages
from .error import PropertiesOptionError, ConfigError, ConflictError, SlaveError
from .option.syndynoptiondescription import SynDynOptionDescription
from .option.baseoption import BaseOption, valid_name
from .setting import ConfigBag, groups, Settings, undefined
from .storage import get_storages, get_default_values_storages
from .value import Values # , Multi
from .i18n import _
if sys.version_info[0] >= 3: # pragma: no cover
xrange = range
class SubConfig(object):
"""Sub configuration management entry.
Tree if OptionDescription's responsability. SubConfig are generated
@ -48,15 +42,12 @@ class SubConfig(object):
__slots__ = ('_impl_context',
'_impl_descr',
'_impl_path',
'_impl_setting_properties',
'_impl_length')
def __init__(self,
descr,
context,
setting_properties,
validate,
force_permissive,
config_bag,
subpath=None):
""" Configuration option management master class
@ -68,8 +59,7 @@ class SubConfig(object):
"""
# main option description
error = False
if descr is not None and not isinstance(descr, OptionDescription) and \
not isinstance(descr, SynDynOptionDescription): # pragma: optional cover
if descr is not None and (not isinstance(descr, (BaseOption, SynDynOptionDescription)) or not descr.impl_is_optiondescription()):
error = True
if error:
raise TypeError(_('descr must be an optiondescription, not {0}'
@ -80,23 +70,15 @@ class SubConfig(object):
raise ValueError('context must be a Weakref')
self._impl_context = context
self._impl_path = subpath
if setting_properties is not undefined:
self._impl_setting_properties = setting_properties
if setting_properties is not None and descr.impl_get_group_type() == groups.master:
if config_bag.setting_properties is not None and \
descr.impl_get_group_type() == groups.master:
master = descr.getmaster()
context_ = context()
masterp = master.impl_getpath(context_)
context_.cfgimpl_get_settings().validate_properties(master,
masterp,
setting_properties,
force_permissive=force_permissive)
value = context_.cfgimpl_get_values().get_cached_value(master,
masterp,
setting_properties,
validate=validate,
force_permissive=force_permissive,
self_properties=undefined,
index=None)
masterpath = master.impl_getname()
mconfig_bag = config_bag.copy('nooption')
mconfig_bag.option = master
value = self.getattr(masterpath,
None,
mconfig_bag)
self._impl_length = len(value)
def cfgimpl_get_length(self):
@ -121,7 +103,7 @@ class SubConfig(object):
settings,
'settings',
tresetted_opts)
resetted_opts |= tresetted_opts
resetted_opts.extend(tresetted_opts)
for woption in opt._get_dependencies(self):
option = woption()
if option in resetted_opts:
@ -145,7 +127,7 @@ class SubConfig(object):
:type only_expired: boolean
"""
if resetted_opts is None:
resetted_opts = set()
resetted_opts = []
context = self._cfgimpl_get_context()
values = context.cfgimpl_get_values()
@ -170,16 +152,14 @@ class SubConfig(object):
def cfgimpl_get_home_by_path(self,
path,
setting_properties,
validate_properties=True,
force_permissive=False):
config_bag):
""":returns: tuple (config, name)"""
path = path.split('.')
for step in path[:-1]:
sconfig_bag = config_bag.copy('nooption')
self = self.getattr(step,
force_permissive=force_permissive,
validate_properties=validate_properties,
setting_properties=setting_properties)
None,
sconfig_bag)
return self, path[-1]
# ______________________________________________________________________
@ -233,9 +213,7 @@ class SubConfig(object):
groups.GroupType): # pragma: optional cover
raise TypeError(_("unknown group_type: {0}").format(group_type))
context = self._cfgimpl_get_context()
setting_properties = context.cfgimpl_get_settings().get_context_properties()
for child in self.cfgimpl_get_description().impl_getchildren(context=context,
setting_properties=setting_properties):
for child in self.cfgimpl_get_description().impl_getchildren(config_bag):
if child.impl_is_optiondescription():
try:
if group_type is None or (group_type is not None and
@ -245,11 +223,6 @@ class SubConfig(object):
yield name, self.getattr(name,
force_permissive=force_permissive,
setting_properties=setting_properties)
except GeneratorExit: # pragma: optional cover
if sys.version_info[0] < 3:
raise StopIteration
else:
raise GeneratorExit()
except PropertiesOptionError: # pragma: optional cover
pass
# ______________________________________________________________________
@ -296,19 +269,11 @@ class SubConfig(object):
def cfgimpl_get_values(self):
return self._cfgimpl_get_context()._impl_values
# ____________________________________________________________
# attribute methods
def __setattr__(self, name, value):
"attribute notation mechanism for the setting of the value of an option"
self.setattr(name,
value)
def setattr(self,
name,
index,
value,
force_permissive=False,
index=None,
setting_properties=None,
config_bag,
_commit=True):
if name.startswith('_impl_'):
@ -318,72 +283,65 @@ class SubConfig(object):
context = self._cfgimpl_get_context()
if '.' in name: # pragma: optional cover
self, name = self.cfgimpl_get_home_by_path(name,
force_permissive=force_permissive,
setting_properties=setting_properties)
config_bag)
child = self.cfgimpl_get_description().impl_getchild(name,
setting_properties,
config_bag,
self)
if isinstance(child, (OptionDescription, SynDynOptionDescription)):
if child.impl_is_optiondescription() or isinstance(child, SynDynOptionDescription):
raise TypeError(_("can't assign to an OptionDescription")) # pragma: optional cover
elif child.impl_is_symlinkoption():
raise TypeError(_("can't assign to a SymLinkOption"))
else:
subpath = self._get_subpath(name)
if config_bag.setting_properties:
self.cfgimpl_get_settings().validate_properties(subpath,
index,
config_bag)
self.cfgimpl_get_description().impl_validate_value(child,
value,
self)
subpath = self._get_subpath(name)
return self.cfgimpl_get_values().setvalue(child,
value,
subpath,
force_permissive,
return self.cfgimpl_get_values().setvalue(subpath,
index,
setting_properties,
value,
config_bag,
_commit)
def delattr(self,
name,
index=None,
force_permissive=False,
setting_properties=None,
validate=True):
index,
config_bag):
context = self._cfgimpl_get_context()
if '.' in name: # pragma: optional cover
self, name = self.cfgimpl_get_home_by_path(name,
force_permissive=force_permissive,
setting_properties=setting_properties)
child = self.cfgimpl_get_description().impl_getchild(name,
setting_properties,
config_bag)
if config_bag.option is None:
config_bag.option = self.cfgimpl_get_description().impl_getchild(name,
config_bag,
self)
if isinstance(child, (OptionDescription, SynDynOptionDescription)):
option = config_bag.option
if option.impl_is_optiondescription() or isinstance(option, SynDynOptionDescription):
raise TypeError(_("can't delete an OptionDescription")) # pragma: optional cover
elif child.impl_is_symlinkoption():
elif 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 child.impl_is_master_slaves('master'):
if option.impl_is_master_slaves('master'):
values.reset_master(self,
child,
subpath,
index,
force_permissive,
setting_properties)
elif child.impl_is_master_slaves('slave'):
values.reset_slave(child,
subpath,
config_bag)
elif option.impl_is_master_slaves('slave'):
values.reset_slave(subpath,
index,
setting_properties,
force_permissive=force_permissive,
validate=validate)
config_bag)
else:
raise ValueError(_("can delete value with index only with a master or a slave"))
else:
values.reset(child,
subpath,
setting_properties,
force_permissive=force_permissive,
validate=validate)
values.reset(subpath,
config_bag)
def _get_subpath(self, name):
if self._impl_path is None:
@ -394,11 +352,8 @@ class SubConfig(object):
def getattr(self,
name,
setting_properties,
force_permissive=False,
validate=True,
validate_properties=True,
index=None,
index,
config_bag,
returns_option=False):
"""
attribute notation mechanism for accessing the value of an option
@ -408,40 +363,38 @@ class SubConfig(object):
"""
if '.' in name:
self, name = self.cfgimpl_get_home_by_path(name,
force_permissive=force_permissive,
validate_properties=validate_properties,
setting_properties=setting_properties)
config_bag)
context = self._cfgimpl_get_context()
option = config_bag.option
if option is None:
option = self.cfgimpl_get_description().impl_getchild(name,
setting_properties,
config_bag,
self)
config_bag.option = option
if option.impl_is_symlinkoption():
if returns_option is True:
return option
path = context.cfgimpl_get_description().impl_get_path_by_opt(option.impl_getopt())
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,
validate=validate,
validate_properties=validate_properties,
force_permissive=force_permissive,
setting_properties=setting_properties,
index=index)
index,
sconfig_bag)
subpath = self._get_subpath(name)
if setting_properties:
self.cfgimpl_get_settings().validate_properties(option,
subpath,
setting_properties,
index=index,
force_permissive=force_permissive)
if config_bag.setting_properties:
self.cfgimpl_get_settings().validate_properties(subpath,
index,
config_bag)
if option.impl_is_optiondescription():
if returns_option is True:
return option
return SubConfig(option,
self._impl_context,
setting_properties,
validate,
force_permissive,
config_bag,
subpath)
if option.impl_is_master_slaves('slave'):
@ -452,33 +405,41 @@ class SubConfig(object):
if index >= length:
raise IndexError(_('index ({}) is higher than the master length ({}) '
'for "{}"').format(index,
length,
option.impl_get_display_name()))
slave_len = self.cfgimpl_get_values()._p_.get_max_length(subpath)
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))
elif index:
raise IndexError(_('index is forbidden for the not slave "{}"'
'').format(subpath))
if validate:
self.cfgimpl_get_description().impl_validate(context,
force_permissive,
setting_properties)
#FIXME deja fiat dans get_cached_value
#if config_bag.validate:
# option.impl_validate(context,
# config_bag)
value = self.cfgimpl_get_values().get_cached_value(subpath,
index,
config_bag)
if config_bag.validate_properties:
self.cfgimpl_get_settings().validate_mandatory(subpath,
index,
value,
config_bag)
#FIXME utiliser le config_bag !
if returns_option is True:
return option
return self.cfgimpl_get_values().get_cached_value(option,
subpath,
setting_properties,
validate=validate,
force_permissive=force_permissive,
index=index)
return value
def find(self,
setting_properties,
config_bag,
bytype=None,
byname=None,
byvalue=undefined,
type_='option',
check_properties=True,
force_permissive=False):
type_='option'):
"""
finds a list of options recursively in the config
@ -490,22 +451,18 @@ class SubConfig(object):
return self._cfgimpl_get_context()._find(bytype,
byname,
byvalue,
setting_properties=setting_properties,
config_bag,
first=False,
type_=type_,
_subpath=self.cfgimpl_get_path(False),
check_properties=check_properties,
force_permissive=force_permissive)
_subpath=self.cfgimpl_get_path(False))
def find_first(self,
setting_properties,
config_bag,
bytype=None,
byname=None,
byvalue=undefined,
type_='option',
raise_if_not_found=True,
check_properties=True,
force_permissive=False):
raise_if_not_found=True):
"""
finds an option recursively in the config
@ -517,40 +474,36 @@ class SubConfig(object):
return self._cfgimpl_get_context()._find(bytype,
byname,
byvalue,
setting_properties=setting_properties,
config_bag,
first=True,
type_=type_,
_subpath=self.cfgimpl_get_path(False),
raise_if_not_found=raise_if_not_found,
check_properties=check_properties,
force_permissive=force_permissive)
raise_if_not_found=raise_if_not_found)
def _find(self,
bytype,
byname,
byvalue,
config_bag,
first,
type_='option',
_subpath=None,
check_properties=True,
raise_if_not_found=True,
force_permissive=False,
only_path=undefined,
only_option=undefined,
setting_properties=None):
only_option=undefined):
"""
convenience method for finding an option that lives only in the subtree
: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():
def _filter_by_value(sconfig_bag):
if byvalue is undefined:
return True
try:
value = self.getattr(path,
force_permissive=force_permissive,
setting_properties=setting_properties)
None,
sconfig_bag)
except PropertiesOptionError:
return False
if isinstance(value, list):
@ -562,11 +515,11 @@ class SubConfig(object):
raise ValueError(_('unknown type_ type {0}'
'for _find').format(type_))
find_results = []
# if value and/or check_properties are set, need all avalaible option
# if value and/or validate_properties are set, need all avalaible option
# If first one has no good value or not good property check second one
# and so on
only_first = first is True and byvalue is undefined and \
check_properties is None
config_bag.validate_properties is False
if only_path is not undefined:
options = [(only_path, only_option)]
else:
@ -574,23 +527,24 @@ class SubConfig(object):
byname,
_subpath,
only_first,
self._cfgimpl_get_context(),
setting_properties)
config_bag)
for path, option in options:
if not _filter_by_value():
sconfig_bag = config_bag.copy('nooption')
sconfig_bag.option = option
if not _filter_by_value(sconfig_bag):
continue
#remove option with propertyerror, ...
if check_properties:
if config_bag.validate_properties:
try:
self.unwrap_from_path(path,
setting_properties=setting_properties,
force_permissive=force_permissive)
None,
config_bag)
except PropertiesOptionError:
continue
if type_ == 'value':
retval = self.getattr(path,
force_permissive=force_permissive,
setting_properties=setting_properties)
None,
config_bag)
elif type_ == 'path':
retval = path
elif type_ == 'option':
@ -613,12 +567,11 @@ class SubConfig(object):
return find_results
def make_dict(self,
setting_properties,
config_bag,
flatten=False,
_currpath=None,
withoption=None,
withvalue=undefined,
force_permissive=False,
fullpath=False):
"""exports the whole config into a `dict`, for example:
@ -670,11 +623,13 @@ class SubConfig(object):
first=False,
type_='path',
_subpath=self.cfgimpl_get_path(False),
force_permissive=force_permissive,
setting_properties=setting_properties):
config_bag=config_bag):
path = '.'.join(path.split('.')[:-1])
opt = context.unwrap_from_path(path,
force_permissive=True)
None,
config_bag)
sconfig_bag = config_bag.copy('nooption')
sconfig_bag.option = opt
mypath = self.cfgimpl_get_path()
if mypath is not None:
if mypath == path:
@ -688,25 +643,23 @@ class SubConfig(object):
'should start with {1}'
'').format(path, mypath))
path = path[len(tmypath):]
self._make_sub_dict(opt,
path,
self._make_sub_dict(path,
pathsvalues,
_currpath,
flatten,
force_permissive=force_permissive,
setting_properties=setting_properties,
sconfig_bag,
fullpath=fullpath)
#withoption can be set to None below !
if withoption is None:
for opt in self.cfgimpl_get_description().impl_getchildren(setting_properties):
for opt in self.cfgimpl_get_description().impl_getchildren(config_bag):
sconfig_bag = config_bag.copy('nooption')
sconfig_bag.option = opt
path = opt.impl_getname()
self._make_sub_dict(opt,
path,
self._make_sub_dict(path,
pathsvalues,
_currpath,
flatten,
force_permissive=force_permissive,
setting_properties=setting_properties,
sconfig_bag,
fullpath=fullpath)
if _currpath == []:
options = dict(pathsvalues)
@ -714,42 +667,39 @@ class SubConfig(object):
return pathsvalues
def _make_sub_dict(self,
option,
name,
pathsvalues,
_currpath,
flatten,
setting_properties,
force_permissive=False,
config_bag,
fullpath=False):
try:
option = config_bag.option
if not option.impl_is_optiondescription() and option.impl_is_master_slaves('slave'):
ret = []
length = self.cfgimpl_get_length()
if length:
for idx in range(length):
config_bag.properties = None
ret.append(self.getattr(name,
index=idx,
force_permissive=force_permissive,
setting_properties=setting_properties))
elif setting_properties:
idx,
config_bag))
elif config_bag.setting_properties:
path = self._get_subpath(name)
self.cfgimpl_get_settings().validate_properties(option,
path,
setting_properties,
force_permissive=force_permissive)
self.cfgimpl_get_settings().validate_properties(path,
None,
config_bag)
else:
ret = self.getattr(name,
force_permissive=force_permissive,
setting_properties=setting_properties)
None,
config_bag)
except PropertiesOptionError:
pass
else:
if option.impl_is_optiondescription():
pathsvalues += ret.make_dict(setting_properties,
pathsvalues += ret.make_dict(config_bag,
flatten=flatten,
_currpath=_currpath + [name],
force_permissive=force_permissive,
fullpath=fullpath)
else:
if flatten:
@ -777,7 +727,10 @@ class SubConfig(object):
class _CommonConfig(SubConfig):
"abstract base class for the Config, GroupConfig and the MetaConfig"
__slots__ = ('_impl_values', '_impl_settings', '_impl_meta', '_impl_test')
__slots__ = ('_impl_values',
'_impl_settings',
'_impl_meta',
'_impl_test')
def _impl_build_all_caches(self,
force_store_values):
@ -790,11 +743,8 @@ class _CommonConfig(SubConfig):
def unwrap_from_path(self,
path,
setting_properties=None,
force_permissive=False,
index=None,
validate=True,
validate_properties=True):
index,
config_bag):
"""convenience method to extract and Option() object from the Config()
and it is **fast**: finds the option directly in the appropriate
namespace
@ -803,40 +753,33 @@ class _CommonConfig(SubConfig):
"""
if '.' in path:
self, path = self.cfgimpl_get_home_by_path(path,
force_permissive=force_permissive,
validate_properties=validate_properties,
setting_properties=setting_properties)
config_bag)
option = self.cfgimpl_get_description().impl_getchild(path,
setting_properties,
config_bag,
self)
if not validate_properties:
if not config_bag.validate_properties:
return option
else:
if option.impl_is_symlinkoption():
true_option = option.impl_getopt()
true_path = true_option.impl_getpath(self._cfgimpl_get_context())
self, path = self.cfgimpl_get_context().cfgimpl_get_home_by_path(true_path,
force_permissive=force_permissive,
validate_properties=validate_properties,
setting_properties=setting_properties)
config_bag)
config_bag.option = true_option
else:
true_option = option
true_path = path
if not true_option.impl_is_optiondescription() and index is None and \
true_option.impl_is_master_slaves('slave'):
subpath = self._get_subpath(true_path)
self.cfgimpl_get_settings().validate_properties(true_option,
subpath,
setting_properties,
force_permissive=force_permissive)
return option
self.getattr(path,
validate=validate,
force_permissive=force_permissive,
index=index,
setting_properties=setting_properties,
validate_properties=validate_properties,
returns_option=True)
config_bag.option = option
#if not option.impl_is_optiondescription() and index is None and \
# config_bag.option.impl_is_master_slaves('slave'):
# subpath = self._get_subpath(true_path)
# self.cfgimpl_get_settings().validate_properties(subpath,
# index,
# config_bag)
# return option
#self.getattr(path,
# index,
# config_bag,
# returns_option=True)
return option
def cfgimpl_get_path(self, dyn=True):
@ -918,6 +861,7 @@ class Config(_CommonConfig):
:param persistent: if persistent, don't delete storage when leaving
:type persistent: `boolean`
"""
self._impl_meta = None
if force_settings is not None and force_values is not None:
if isinstance(force_settings, tuple):
self._impl_settings = Settings(self,
@ -940,10 +884,8 @@ class Config(_CommonConfig):
values)
super(Config, self).__init__(descr,
weakref.ref(self),
undefined,
True,
False)
self._impl_meta = None
ConfigBag(self),
None)
#undocumented option used only in test script
self._impl_test = False
if _duplicate is False and (force_settings is None or force_values is None):
@ -1007,7 +949,9 @@ class GroupConfig(_CommonConfig):
only_expired=False,
opt=None,
path=None,
resetted_opts=set()):
resetted_opts=None):
if resetted_opts is None:
resetted_opts = []
if isinstance(self, MetaConfig):
super(GroupConfig, self).cfgimpl_reset_cache(only_expired=only_expired,
opt=opt,

View file

@ -38,11 +38,11 @@ def display_list(lst, separator='and'):
for l in lst[:-1]:
if not isinstance(l, str):
l = str(l)
lst_.append(l)
lst_.append('"{}"'.join(_(l)))
last = lst[-1]
if not isinstance(last, str):
last = str(last)
return ', '.join(lst_) + _(' "{}" ').format(separator) + last
last = str(_(last))
return ', '.join(lst_) + _(' {} ').format(separator) + '"{}"'.format(last)
# Exceptions for an Option
@ -88,12 +88,12 @@ class PropertiesOptionError(AttributeError):
return str(_('cannot access to {0} "{1}" because "{2}" has {3} {4}'
'').format(self._type,
self._orig_opt.impl_get_display_name(),
self._datas['opt'].impl_get_display_name(),
self._datas['config_bag'].option.impl_get_display_name(),
prop_msg,
msg))
return str(_('cannot access to {0} "{1}" because has {2} {3}'
'').format(self._type,
self._datas['opt'].impl_get_display_name(),
self._datas['config_bag'].option.impl_get_display_name(),
prop_msg,
msg))

View file

@ -48,14 +48,19 @@ def valid_name(name):
not name.startswith('cfgimpl_')
def validate_callback(callback,
def validate_calculator(callback,
callback_params,
type_,
callbackoption):
"""validate function and parameter set for callback, validation, ...
"""
def _validate_option(option):
#validate option
if not isinstance(option, OnlyOption):
raise ValueError(_('{}_params must have an option'
' not a {} for first argument'
).format(type_, type(option)))
if option.impl_is_symlinkoption():
cur_opt = option.impl_getopt()
else:
@ -72,7 +77,7 @@ def validate_callback(callback,
).format(type_,
type(force_permissive)))
def _validate_callback(callbk):
def _validate_calculator(callbk):
if isinstance(callbk, tuple):
if len(callbk) == 1:
if callbk not in ((None,), ('index',)):
@ -103,7 +108,7 @@ def validate_callback(callback,
raise ValueError(_('{0}_params must be tuple for key "{1}"'
).format(type_, key))
for callbk in callbacks:
_validate_callback(callbk)
_validate_calculator(callbk)
#____________________________________________________________
@ -167,36 +172,105 @@ class Base(object):
if properties:
_setattr(self, '_properties', properties)
def _build_validator_params(self,
validator,
validator_params):
func_params = signature(validator).parameters
args = [f.name for f in func_params.values() if f.default is f.empty]
if validator_params is not None:
kwargs = list(validator_params.keys())
if '' in kwargs:
kwargs.remove('')
for kwarg in kwargs:
if kwarg in args:
args = args[0:args.index(kwarg)]
len_args = len(validator_params.get('', []))
if len_args != 0 and len(args) >= len_args:
args = args[0:len(args)-len_args]
if len(args) >= 2:
if validator_params is not None and '' in validator_params:
params = list(validator_params[''])
params.append((self, False))
validator_params[''] = tuple(params)
def _get_function_args(self,
function):
args = set()
kwargs = set()
positional = False
keyword = False
for param in signature(function).parameters.values():
if param.kind == param.VAR_POSITIONAL:
positional = True
elif param.kind == param.VAR_KEYWORD:
keyword = True
elif param.default is param.empty:
args.add(param.name)
else:
if validator_params is None:
validator_params = {}
validator_params[''] = ((self, False),)
if len(args) == 3 and args[2] not in validator_params:
params = list(validator_params[''])
kwargs.add(param.name)
return args, kwargs, positional, keyword
def _get_parameters_args(self,
calculator_params,
add_value):
args = set()
kwargs = set()
if add_value:
args.add('value')
for param in calculator_params.keys():
if param == '':
for idx, _ in enumerate(calculator_params['']):
# construct an appropriate name
args.add('param{}'.format(idx))
else:
kwargs.add(param)
return args, kwargs
def _build_calculator_params(self,
calculator,
calculator_params,
add_value=False):
if calculator_params is not None:
func_args, func_kwargs, func_positional, func_keyword = self._get_function_args(calculator)
calculator_args, calculator_kwargs = self._get_parameters_args(calculator_params, add_value)
# remove knowned kwargs
common_kwargs = func_kwargs & calculator_kwargs
func_kwargs -= common_kwargs
calculator_kwargs -= common_kwargs
# remove knowned calculator's kwargs in func's args
common = func_args & calculator_kwargs
func_args -= common
calculator_kwargs -= common
# remove unknown calculator's args in func's args
for idx in range(min(len(calculator_args), len(func_args))):
func_args.pop()
calculator_args.pop()
# remove unknown calculator's args in func's kwargs
func_kwargs_left = func_kwargs - {'index', 'self'}
func_kwargs_pop = set()
for idx in range(min(len(calculator_args), len(func_kwargs_left))):
func_kwargs_pop.add(func_kwargs_left.pop())
calculator_args.pop()
func_kwargs -= func_kwargs_pop
if func_positional:
calculator_args = set()
if func_keyword:
calculator_kwargs = set()
if calculator_args or calculator_kwargs:
# there is more args/kwargs than expected!
raise ConfigError(_('cannot find those arguments "{}" in function "{}" for "{}"'
'').format(list(calculator_args | calculator_kwargs),
calculator.__name__,
self.impl_get_display_name()))
has_self = False
has_index = False
if func_args:
# there is extra args/kwargs
if not self.impl_is_optiondescription() and self.impl_is_multi():
params = list(calculator_params[''])
if add_value:
# only for validator
has_self = True
params.append((self, False))
func_args.pop()
if func_args:
has_index = True
params.append(('index',))
validator_params[''] = tuple(params)
return validator_params
func_args.pop()
if func_args:
raise ConfigError(_('missing those arguements "{}" in function "{}" for "{}"'
'').format(list(func_args),
calculator.__name__,
self.impl_get_display_name()))
calculator_params[''] = tuple(params)
if not self.impl_is_optiondescription() and self.impl_is_multi():
if add_value and not has_self and 'self' in func_kwargs:
# only for validator
calculator_params['self'] = (self, False)
if not has_index and 'index' in func_kwargs:
calculator_params['index'] = (('index',),)
return calculator_params
def impl_has_dependency(self,
self_is_dep=True):
@ -236,13 +310,15 @@ class Base(object):
if not _init and self.impl_get_callback()[0] is not None:
raise ConfigError(_("a callback is already set for {0}, "
"cannot set another one's").format(self.impl_getname()))
self._validate_callback(callback,
self._validate_calculator(callback,
callback_params)
if callback is not None:
validate_callback(callback,
validate_calculator(callback,
callback_params,
'callback',
self)
callback_params = self._build_calculator_params(callback,
callback_params)
val = getattr(self, '_val_call', (None,))[0]
if callback_params is None or callback_params == {}:
val_call = (callback,)
@ -424,7 +500,7 @@ class BaseOption(Base):
obj._p_.delcache(path)
if type_ in ['settings', 'permissives']:
obj._pp_.delcache(path)
resetted_opts.add(opt)
resetted_opts.append(opt)
def impl_is_symlinkoption(self):
return False

View file

@ -31,8 +31,7 @@ class BoolOption(Option):
def _validate(self,
value,
setting_properties,
context=undefined,
current_opt=undefined):
*args,
**kwargs):
if not isinstance(value, bool):
raise ValueError()

View file

@ -32,9 +32,8 @@ class BroadcastOption(Option):
def _validate(self,
value,
setting_properties,
context=undefined,
current_opt=undefined):
*args,
**kwargs):
self._impl_valid_string(value)
if value.count('.') != 3:
raise ValueError()

View file

@ -22,7 +22,7 @@ from types import FunctionType
from ..setting import undefined
from ..i18n import _
from .baseoption import validate_callback
from .baseoption import validate_calculator
from .option import Option
from ..autolib import carry_out_calculation
from ..error import ConfigError, display_list
@ -56,7 +56,7 @@ class ChoiceOption(Option):
:param values: is a list of values the option can possibly take
"""
if isinstance(values, FunctionType):
validate_callback(values,
validate_calculator(values,
values_params,
'values',
self)
@ -83,22 +83,22 @@ class ChoiceOption(Option):
warnings_only=warnings_only)
def impl_get_values(self,
setting_properties,
context,
config_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 context is None:
values = []
if config_bag is undefined:
values = undefined
else:
values = carry_out_calculation(current_opt,
setting_properties=setting_properties,
context=context,
callback=values,
callback_params=getattr(self, '_choice_values_params', {}))
config_bag.config,
values,
getattr(self, '_choice_values_params', {}),
None,
config_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()))
@ -107,16 +107,14 @@ class ChoiceOption(Option):
def _validate(self,
value,
setting_properties,
context=undefined,
config_bag,
current_opt=undefined):
values = self.impl_get_values(setting_properties,
context,
values = self.impl_get_values(config_bag,
current_opt=current_opt)
if values is not undefined and not value in values:
if len(values) == 1:
raise ValueError(_('only {0} is allowed'
raise ValueError(_('only "{0}" is allowed'
'').format(values[0]))
else:
raise ValueError(_('only {0} are allowed'
raise ValueError(_('only "{0}" are allowed'
'').format(display_list(values)))

View file

@ -31,9 +31,8 @@ class DateOption(Option):
def _validate(self,
value,
setting_properties,
context=undefined,
current_opt=undefined):
*args,
**kwargs):
self._impl_valid_string(value)
try:
datetime.strptime(value, "%Y-%m-%d")

View file

@ -99,9 +99,8 @@ class DomainnameOption(Option):
def _validate(self,
value,
setting_properties,
context=undefined,
current_opt=undefined):
*args,
**kwargs):
self._impl_valid_string(value)
def _valid_length(val):

View file

@ -53,7 +53,7 @@ class DynOptionDescription(OptionDescription):
if child.impl_get_group_type() != groups.master:
raise ConfigError(_('cannot set optiondescription in a '
'dynoptiondescription'))
for chld in child.impl_getchildren(setting_properties=undefined):
for chld in child.impl_getchildren(config_bag=undefined):
chld._impl_setsubdyn(self)
if child.impl_is_symlinkoption():
raise ConfigError(_('cannot set symlinkoption in a '
@ -63,7 +63,7 @@ class DynOptionDescription(OptionDescription):
self.impl_set_callback(callback,
callback_params)
def _validate_callback(self,
def _validate_calculator(self,
callback,
callback_params):
if callback is None:
@ -71,14 +71,14 @@ class DynOptionDescription(OptionDescription):
'').format(self.impl_get_display_name()))
def _impl_get_suffixes(self,
context,
setting_properties):
config_bag):
callback, callback_params = self.impl_get_callback()
values = carry_out_calculation(self,
context=context,
callback=callback,
callback_params=callback_params,
setting_properties=setting_properties)
config_bag.config,
callback,
callback_params,
None,
config_bag)
if not isinstance(values, list):
raise ValueError(_('invalid suffix "{}" for option "{}", must be a list'
'').format(values,

View file

@ -31,8 +31,7 @@ class FloatOption(Option):
def _validate(self,
value,
setting_properties,
context=undefined,
current_opt=undefined):
*args,
**kwargs):
if not isinstance(value, float):
raise ValueError()

View file

@ -31,8 +31,7 @@ class IntOption(Option):
def _validate(self,
value,
setting_properties,
context=undefined,
current_opt=undefined):
*args,
**kwargs):
if not isinstance(value, int):
raise ValueError()

View file

@ -64,9 +64,8 @@ class IPOption(Option):
def _validate(self,
value,
setting_properties,
context=undefined,
current_opt=undefined):
*args,
**kwargs):
# sometimes an ip term starts with a zero
# but this does not fit in some case, for example bind does not like it
self._impl_valid_string(value)

View file

@ -104,26 +104,23 @@ class MasterSlaves(OptionDescription):
return c_opt in self._children[1]
def reset(self,
opt,
values,
setting_properties,
_commit=True,
force_permissive=False):
config_bag,
_commit=True):
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,
slave_path,
setting_properties,
validate=False,
_commit=_commit,
force_permissive=force_permissive)
values.reset(slave_path,
sconfig_bag,
_commit=_commit)
def pop(self,
values,
index,
setting_properties,
force_permissive,
config_bag,
slaves=undefined):
context = values._getcontext()
@ -132,12 +129,12 @@ class MasterSlaves(OptionDescription):
for slave in slaves:
slave_path = slave.impl_getpath(context)
slavelen = values._p_.get_max_length(slave_path)
if not values.is_default_owner(slave,
slave_path,
setting_properties,
validate_meta=False,
index=index,
force_permissive=force_permissive):
sconfig_bag = config_bag.copy('nooption')
sconfig_bag.option = slave
if not values.is_default_owner(slave_path,
index,
config_bag,
validate_meta=False):
if slavelen > index:
values._p_.resetvalue_index(slave_path,
index)

View file

@ -33,9 +33,8 @@ class NetmaskOption(Option):
def _validate(self,
value,
setting_properties,
context=undefined,
current_opt=undefined):
*args,
**kwargs):
self._impl_valid_string(value)
if value.count('.') != 3:
raise ValueError()

View file

@ -32,9 +32,8 @@ class NetworkOption(Option):
def _validate(self,
value,
setting_properties,
context=undefined,
current_opt=undefined):
*args,
**kwargs):
self._impl_valid_string(value)
if value.count('.') != 3:
raise ValueError()

View file

@ -23,7 +23,7 @@ import warnings
import sys
import weakref
from .baseoption import OnlyOption, submulti, validate_callback, STATIC_TUPLE
from .baseoption import OnlyOption, submulti, validate_calculator, STATIC_TUPLE
from .symlinkoption import DynSymLinkOption
from ..i18n import _
from ..setting import log, undefined, debug
@ -102,14 +102,13 @@ class Option(OnlyOption):
if multi is not False and default is None:
default = []
if validator is not None:
if multi: # and validator_params is None:
validator_params = self._build_validator_params(validator,
validator_params)
validate_callback(validator,
validate_calculator(validator,
validator_params,
'validator',
self)
validator_params = self._build_calculator_params(validator,
validator_params,
add_value=True)
if validator_params is None:
val_call = (validator,)
else:
@ -133,9 +132,10 @@ class Option(OnlyOption):
is_multi=is_multi)
if is_multi and default_multi is not None:
def test_multi_value(value):
err = self._validate(value,
try:
self._validate(value,
undefined)
if err:
except ValueError as err:
raise ValueError(_("invalid default_multi value {0} "
"for option {1}: {2}").format(str(value),
self.impl_getname(),
@ -154,7 +154,8 @@ class Option(OnlyOption):
if unique is not undefined:
_setattr(self, '_unique', unique)
self.impl_validate(default,
is_multi=is_multi)
is_multi=is_multi,
config_bag=undefined)
if (is_multi and default != []) or \
(not is_multi and default is not None):
if is_multi:
@ -183,7 +184,7 @@ class Option(OnlyOption):
opts,
warnings_only,
transitive,
setting_properties):
config_bag):
"""Launch consistency now
:param func: function name, this name should start with _cons_
@ -205,37 +206,39 @@ class Option(OnlyOption):
"""
if context is not undefined:
descr = context.cfgimpl_get_description()
if config_bag is not undefined and config_bag.fromconsistency == option:
return
all_cons_vals = []
all_cons_opts = []
val_consistencies = True
for wopt in opts:
opt = wopt()
if (isinstance(opt, DynSymLinkOption) and option._dyn == opt._dyn) or \
option == opt:
for opt in opts:
if isinstance(opt, weakref.ReferenceType):
opt = opt()
if config_bag is not undefined:
if config_bag.fromconsistency == opt:
break
sconfig_bag = config_bag.copy('nooption')
sconfig_bag.option = opt
sconfig_bag.fromconsistency = option
else:
sconfig_bag = undefined
if option == opt:
# option is current option
# we have already value, so use it
all_cons_vals.append(value)
all_cons_opts.append(opt)
else:
path = None
is_multi = opt.impl_is_multi() and not opt.impl_is_master_slaves()
#if context, calculate value, otherwise get default value
if context is not undefined:
if isinstance(opt, DynSymLinkOption):
path = opt.impl_getpath(context)
else:
#FIXME ca devrait etre impl_getpath ??)
path = descr.impl_get_path_by_opt(opt)
if is_multi:
_index = None
else:
_index = index
try:
opt_value = context.getattr(path,
setting_properties,
validate=False,
index=_index,
force_permissive=True)
index,
sconfig_bag)
except PropertiesOptionError as err:
if debug: # pragma: no cover
log.debug('propertyerror in _launch_consistency: {0}'.format(err))
@ -248,14 +251,15 @@ class Option(OnlyOption):
else:
opt_value = opt.impl_getdefault()
if index is not None:
if len(opt_value) >= index:
if len(opt_value) <= index:
opt_value = opt.impl_getdefault_multi()
else:
opt_value = opt_value[index]
if self.impl_is_multi() and index is None:
is_multi = self.impl_is_multi()
if is_multi and index is None:
# only check propertyerror for master/slaves is transitive
val_consistencies = False
break
if is_multi and isinstance(opt_value, list):
all_cons_vals.extend(opt_value)
for len_ in xrange(len(opt_value)):
@ -263,10 +267,12 @@ class Option(OnlyOption):
else:
all_cons_vals.append(opt_value)
all_cons_opts.append(opt)
if val_consistencies:
else:
try:
getattr(self, func)(current_opt, all_cons_opts, all_cons_vals, warnings_only)
getattr(self, func)(current_opt,
all_cons_opts,
all_cons_vals,
warnings_only)
except ValueError as err:
if warnings_only:
msg = _('attention, "{0}" could be an invalid {1} for "{2}", {3}'
@ -295,13 +301,13 @@ class Option(OnlyOption):
def impl_validate(self,
value,
config_bag,
context=undefined,
force_index=None,
current_opt=undefined,
is_multi=None,
check_error=True,
multi=None,
setting_properties=undefined):
multi=None):
"""
:param value: the option's value
:param context: Config's context
@ -314,7 +320,9 @@ class Option(OnlyOption):
if current_opt is undefined:
current_opt = self
if check_error is False and not 'warnings' in setting_properties:
if config_bag is not undefined and \
((check_error is True and not 'validator' in config_bag.setting_properties) or \
(check_error is False and not 'warnings' in config_bag.setting_properties)):
return
def _is_not_unique(value):
@ -348,8 +356,8 @@ class Option(OnlyOption):
context=context,
callback=validator,
callback_params=validator_params_,
setting_properties=setting_properties,
index=_index,
config_bag=config_bag,
is_validator=True)
def do_validation(_value,
@ -364,9 +372,12 @@ 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,
setting_properties,
context,
config_bag,
current_opt)
if ((check_error and not is_warnings_only) or
(not check_error and is_warnings_only)):
@ -379,7 +390,7 @@ class Option(OnlyOption):
context,
_index,
check_error,
setting_properties)
config_bag)
except ValueError as err:
if debug: # pragma: no cover
log.debug('do_validation: value: {0}, index: {1}:'
@ -436,6 +447,7 @@ class Option(OnlyOption):
'must be a list').format(value,
self.impl_getname()))
elif self.impl_is_submulti():
if value:
for idx, val in enumerate(value):
_is_not_unique(val)
if not isinstance(val, list):
@ -446,18 +458,26 @@ class Option(OnlyOption):
for slave_val in val:
do_validation(slave_val,
idx)
else:
self._valid_consistency(current_opt,
None,
context,
None,
check_error,
config_bag)
else:
_is_not_unique(value)
if value:
for idx, val in enumerate(value):
do_validation(val,
idx)
#self._valid_consistency(current_opt,
# None,
# context,
# None,
# display_warnings,
# display_error,
# setting_properties)
else:
self._valid_consistency(current_opt,
None,
context,
None,
check_error,
config_bag)
def impl_is_dynsymlinkoption(self):
return False
@ -496,11 +516,9 @@ class Option(OnlyOption):
if self.impl_is_submulti():
raise ConfigError(_('cannot add consistency with submulti option'))
is_multi = self.impl_is_multi()
for wopt in other_opts:
if isinstance(wopt, weakref.ReferenceType):
opt = wopt()
else:
opt = wopt
for opt in other_opts:
if isinstance(opt, weakref.ReferenceType):
opt = opt()
if opt.impl_is_submulti():
raise ConfigError(_('cannot add consistency with submulti option'))
if not isinstance(opt, Option):
@ -561,7 +579,12 @@ class Option(OnlyOption):
all_cons_opts,
params)
#validate default value when add consistency
self.impl_validate(self.impl_getdefault())
#FIXME validation!
self.impl_validate(self.impl_getdefault(),
undefined)
self.impl_validate(self.impl_getdefault(),
undefined,
check_error=False)
#FIXME
#if err:
# self._del_consistency()
@ -583,7 +606,7 @@ class Option(OnlyOption):
context,
index,
check_error,
setting_properties):
config_bag):
if context is not undefined:
descr = context.cfgimpl_get_description()
if descr._cache_consistencies is None:
@ -602,17 +625,16 @@ class Option(OnlyOption):
transitive = params.get('transitive', True)
#all_cons_opts[0] is the option where func is set
if isinstance(option, DynSymLinkOption):
subpath = '.'.join(option._dyn.split('.')[:-1])
namelen = len(option.impl_getopt().impl_getname())
suffix = option.impl_getname()[namelen:]
opts = []
for opt in all_cons_opts:
opts.append(DynSymLinkOption(opt,
subpath,
suffix))
opts.append(DynSymLinkOption(opt(),
option._rootpath,
option._suffix))
wopt = opts[0]
else:
opts = all_cons_opts
opts[0]()._launch_consistency(self,
wopt = opts[0]()
wopt._launch_consistency(self,
func,
option,
value,
@ -621,14 +643,14 @@ class Option(OnlyOption):
opts,
warnings_only,
transitive,
setting_properties)
config_bag)
def _cons_not_equal(self,
current_opt,
opts,
vals,
warnings_only):
equal = set()
equal = list()
is_current = False
for idx_inf, val_inf in enumerate(vals):
for idx_sup, val_sup in enumerate(vals[idx_inf + 1:]):
@ -637,10 +659,10 @@ class Option(OnlyOption):
if opt_ == current_opt:
is_current = True
else:
equal.add(opt_)
equal.append(opt_)
if equal:
if debug: # pragma: no cover
log.debug(_('_cons_not_equal: {} are not different').format(display_list(list(equal))))
log.debug(_('_cons_not_equal: {} are not different').format(display_list(equal)))
if is_current:
if warnings_only:
msg = _('should be different from the value of {}')
@ -669,7 +691,7 @@ class Option(OnlyOption):
default_value = None
return getattr(self, '_default_multi', default_value)
def _validate_callback(self,
def _validate_calculator(self,
callback,
callback_params):
"""callback_params:
@ -742,9 +764,8 @@ class RegexpOption(Option):
def _validate(self,
value,
setting_properties,
context=undefined,
current_opt=undefined):
*args,
**kwargs):
err = self._impl_valid_string(value)
if err:
return err

View file

@ -22,7 +22,7 @@ from copy import copy
from ..i18n import _
from ..setting import groups, undefined, owners
from ..setting import ConfigBag, groups, undefined, owners
from .baseoption import BaseOption
from .option import ALLOWED_CONST_LIST, DynSymLinkOption
from .syndynoptiondescription import SynDynOptionDescription
@ -54,7 +54,7 @@ class CacheOptionDescription(BaseOption):
else:
init = False
for option in self.impl_getchildren(setting_properties=undefined,
for option in self.impl_getchildren(config_bag=undefined,
dyn=False):
cache_option.append(option)
if path == '':
@ -83,7 +83,8 @@ class CacheOptionDescription(BaseOption):
'must be a master/slaves').format(
option.impl_getname()))
masterslaves = option.impl_get_master_slaves()
for opt in all_cons_opts:
for weak_opt in all_cons_opts:
opt = weak_opt()
if func not in ALLOWED_CONST_LIST and is_multi:
if not opt.impl_is_master_slaves():
raise ConfigError(_('malformed consistency option "{0}" '
@ -93,7 +94,7 @@ class CacheOptionDescription(BaseOption):
raise ConfigError(_('malformed consistency option "{0}" '
'must be in same master/slaves for "{1}"').format(
option.impl_getname(), opt.impl_getname()))
_consistencies.setdefault(opt,
_consistencies.setdefault(weak_opt,
[]).append((func,
all_cons_opts,
params))
@ -133,8 +134,9 @@ class CacheOptionDescription(BaseOption):
raise ConflictError(_('duplicate option: {0}').format(opt))
if _consistencies != {}:
self._cache_consistencies = {}
for opt, cons in _consistencies.items():
if opt() not in cache_option: # pragma: optional cover
for weak_opt, cons in _consistencies.items():
opt = weak_opt()
if opt not in cache_option: # pragma: optional cover
raise ConfigError(_('consistency with option {0} '
'which is not in Config').format(
opt.impl_getname()))
@ -165,12 +167,10 @@ class CacheOptionDescription(BaseOption):
if force_store_values is False:
raise Exception('ok ca existe ...')
if force_store_values and not values._p_.hasvalue(subpath):
value = values.getvalue(option,
subpath,
index=None,
setting_properties=None,
self_properties=None,
validate=False)
config_bag = ConfigBag(config=context, option=option)
value = values.getvalue(subpath,
None,
config_bag)
value_setted = True
values._p_.setvalue(subpath,
value,
@ -197,7 +197,7 @@ class CacheOptionDescription(BaseOption):
if cache_path is None:
cache_path = []
cache_option = []
for option in self.impl_getchildren(setting_properties=undefined,
for option in self.impl_getchildren(config_bag=undefined,
dyn=False):
attr = option.impl_getname()
path = str('.'.join(_currpath + [attr]))
@ -221,8 +221,7 @@ class OptionDescriptionWalk(CacheOptionDescription):
byname,
_subpath,
only_first,
context,
setting_properties):
config_bag):
find_results = []
def _rebuild_dynpath(path,
@ -250,8 +249,7 @@ class OptionDescriptionWalk(CacheOptionDescription):
found = False
if byname.startswith(name):
subdyn = option._subdyn()
for suffix in subdyn._impl_get_suffixes(context,
setting_properties):
for suffix in subdyn._impl_get_suffixes(config_bag):
if byname == name + suffix:
found = True
path = _rebuild_dynpath(path,
@ -282,8 +280,7 @@ class OptionDescriptionWalk(CacheOptionDescription):
if byname is None:
if option._is_subdyn():
name = option.impl_getname()
for suffix in option._subdyn._impl_get_suffixes(context,
setting_properties):
for suffix in option._subdyn._impl_get_suffixes(config_bag):
path = _rebuild_dynpath(path,
suffix,
option._subdyn)
@ -318,8 +315,7 @@ class OptionDescriptionWalk(CacheOptionDescription):
if bytype == byname is None:
if option._is_subdyn():
name = option.impl_getname()
for suffix in option._subdyn._impl_get_suffixes(context,
setting_properties):
for suffix in option._subdyn._impl_get_suffixes(config_bag):
path = _rebuild_dynpath(path,
suffix,
option._subdyn)
@ -342,7 +338,7 @@ class OptionDescriptionWalk(CacheOptionDescription):
def impl_getchild(self,
name,
setting_properties,
config_bag,
subconfig):
if name in self._children[0]:
child = self._children[1][self._children[0].index(name)]
@ -350,8 +346,8 @@ class OptionDescriptionWalk(CacheOptionDescription):
return child
else:
child = self._impl_search_dynchild(name,
subconfig=subconfig,
setting_properties=setting_properties)
subconfig,
config_bag)
if child:
return child
raise AttributeError(_('unknown Option {0} '
@ -375,14 +371,14 @@ class OptionDescriptionWalk(CacheOptionDescription):
return self._cache_paths[1][self._cache_paths[0].index(opt)]
def impl_getchildren(self,
setting_properties,
dyn=True,
context=undefined):
config_bag,
dyn=True):
for child in self._impl_st_getchildren():
cname = child.impl_getname()
if dyn and child.impl_is_dynoptiondescription():
for value in child._impl_get_suffixes(context,
setting_properties):
sconfig_bag = config_bag.copy('nooption')
sconfig_bag.option = child
for value in child._impl_get_suffixes(sconfig_bag):
yield SynDynOptionDescription(child,
cname + value,
value)
@ -398,12 +394,13 @@ class OptionDescriptionWalk(CacheOptionDescription):
def _impl_search_dynchild(self,
name,
subconfig,
setting_properties):
config_bag):
for child in self._impl_st_getchildren(only_dyn=True):
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(subconfig._cfgimpl_get_context(),
setting_properties):
for value in child._impl_get_suffixes(sconfig_bag):
if name == cname + value:
return SynDynOptionDescription(child,
subconfig.cfgimpl_get_path(),
@ -507,7 +504,6 @@ class OptionDescription(OptionDescriptionWalk):
return self._group_type
def impl_validate_value(self,
option,
value,
context):
*args,
**kwargs):
pass

View file

@ -31,7 +31,6 @@ class PasswordOption(Option):
def _validate(self,
value,
setting_properties,
context=undefined,
current_opt=undefined):
*args,
**kwargs):
self._impl_valid_string(value)

View file

@ -98,9 +98,8 @@ class PortOption(Option):
def _validate(self,
value,
setting_properties,
context=undefined,
current_opt=undefined):
*args,
**kwargs):
if isinstance(value, int):
value = str(value)
self._impl_valid_string(value)

View file

@ -32,9 +32,8 @@ class StrOption(Option):
def _validate(self,
value,
setting_properties,
context=undefined,
current_opt=undefined):
*args,
**kwargs):
if not isinstance(value, str):
raise ValueError()

View file

@ -102,6 +102,14 @@ class DynSymLinkOption(object):
name):
return getattr(self._opt, name)
def __eq__(self, left):
if not isinstance(left, DynSymLinkOption):
return False
return self._opt == left._opt and \
self._rootpath == left._rootpath and \
self._suffix == left._suffix
return True
def impl_getname(self):
return self._opt.impl_getname() + self._suffix
@ -122,21 +130,22 @@ class DynSymLinkOption(object):
def impl_validate(self,
value,
config_bag,
context=undefined,
force_index=None,
current_opt=undefined,
is_multi=None,
check_error=True,
multi=None,
setting_properties=undefined):
multi=None):
# add current_opt !
self._opt.impl_validate(value,
config_bag,
context,
force_index,
current_opt=self,
is_multi=is_multi,
check_error=check_error,
multi=multi,
setting_properties=setting_properties)
multi=multi)
def impl_is_dynsymlinkoption(self):
return True

View file

@ -45,7 +45,7 @@ class SynDynOptionDescription(object):
def impl_getchild(self,
name,
setting_properties,
config_bag,
subconfig):
try:
if name.endswith(self._suffix):
@ -65,11 +65,10 @@ class SynDynOptionDescription(object):
return self._opt.impl_getname() + self._suffix
def impl_getchildren(self,
setting_properties,
dyn=True,
context=undefined):
config_bag,
dyn=True):
children = []
for child in self._opt.impl_getchildren(setting_properties):
for child in self._opt.impl_getchildren(config_bag):
yield(self._opt._impl_get_dynchild(child,
self._suffix,
self._subpath))

View file

@ -34,9 +34,8 @@ class URLOption(DomainnameOption):
def _validate(self,
value,
setting_properties,
context=undefined,
current_opt=undefined):
*args,
**kwargs):
self._impl_valid_string(value)
match = self.proto_re.search(value)
if not match:
@ -62,9 +61,8 @@ class URLOption(DomainnameOption):
'65536'))
# validate domainname
super(URLOption, self)._validate(domain,
setting_properties,
context,
current_opt)
*args,
**kwargs)
super(URLOption, self)._second_level_validation(domain, False)
# validate file
if files is not None and files != '' and not self.path_re.search(files):

View file

@ -118,6 +118,55 @@ debug = False
static_set = frozenset()
class ConfigBag(object):
__slots__ = ('default',
'config',
'option',
'ori_option',
'properties',
'validate',
'validate_properties',
'setting_properties',
'force_permissive',
'force_unrestraint',
'display_warnings',
'trusted_cached_properties',
'fromconsistency',
)
def __init__(self, config, **kwargs):
self.default = {'force_permissive': False,
'force_unrestraint': False,
'validate': True,
'validate_properties': True,
'display_warnings': True,
'trusted_cached_properties': True,
}
self.config = config
for key, value in kwargs.items():
if value != self.default.get(key):
setattr(self, key, value)
def __getattr__(self, key):
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.default.get(key)
def copy(self, filters='all'):
kwargs = {}
for key in self.__slots__:
if filters == 'nooption' and (key.startswith('option') or \
key == 'properties'):
continue
if key != 'default':
value = getattr(self, key)
if value != self.default.get(key):
kwargs[key] = value
return ConfigBag(**kwargs)
# ____________________________________________________________
class _NameSpace(object):
"""convenient class that emulates a module
@ -284,24 +333,24 @@ class Settings(object):
return props
def getproperties(self,
opt,
path,
setting_properties,
index=None,
apply_requires=True):
index,
config_bag):
"""
"""
opt = config_bag.option
if opt.impl_is_symlinkoption():
opt = opt.impl_getopt()
path = opt.impl_getpath(self._getcontext())
is_cached = False
if apply_requires:
if 'cache' in setting_properties and 'expire' in setting_properties:
if config_bag.setting_properties is not None:
if 'cache' in config_bag.setting_properties and \
'expire' in config_bag.setting_properties:
ntime = int(time())
else:
ntime = None
if 'cache' in setting_properties and self._p_.hascache(path,
if 'cache' in config_bag.setting_properties and self._p_.hascache(path,
index):
is_cached, props = self._p_.getcache(path,
ntime,
@ -314,15 +363,12 @@ class Settings(object):
else:
props = meta.cfgimpl_get_settings().getproperties(opt,
path,
setting_properties,
index=index,
apply_requires=False)
if apply_requires:
requires = self.apply_requires(opt,
path,
setting_properties,
index,
False)
config_bag)
requires = self.apply_requires(path,
index,
False,
config_bag)
#FIXME devrait etre un frozenset!
if requires != set([]):
props = copy(props)
@ -330,8 +376,9 @@ class Settings(object):
props -= self.getpermissive(opt,
path)
if apply_requires and 'cache' in setting_properties:
if 'expire' in setting_properties:
if config_bag.setting_properties is not None and \
'cache' in config_bag.setting_properties:
if 'expire' in config_bag.setting_properties:
ntime = ntime + expires_time
self._p_.setcache(path,
props,
@ -355,11 +402,10 @@ class Settings(object):
return self._pp_.getpermissive(path)
def apply_requires(self,
opt,
path,
setting_properties,
index,
debug):
debug,
config_bag):
"""carries out the jit (just in time) requirements between options
a requirement is a tuple of this form that comes from the option's
@ -403,6 +449,7 @@ class Settings(object):
:param path: the option's path in the config
:type path: str
"""
opt = config_bag.option
current_requires = opt.impl_getrequires()
# filters the callbacks
@ -437,11 +484,12 @@ class Settings(object):
idx = index
else:
idx = None
sconfig_bag = config_bag.copy('nooption')
sconfig_bag.option = option
try:
value = context.getattr(reqpath,
setting_properties,
force_permissive=True,
index=idx)
idx,
sconfig_bag)
except PropertiesOptionError as err:
if not transitive:
if all_properties is None:
@ -474,7 +522,7 @@ class Settings(object):
if operator != 'and':
if debug:
if isinstance(orig_value, PropertiesOptionError):
for msg in orig_value._settings.apply_requires(**orig_value._datas).values():
for msg in orig_value.cfgimpl_get_settings().apply_requires(**orig_value._datas).values():
calc_properties.setdefault(action, []).extend(msg)
else:
if not inverse:
@ -500,18 +548,25 @@ class Settings(object):
#____________________________________________________________
# set methods
def set_context_properties(self, properties):
self.setproperties(None, None, properties)
def set_context_properties(self,
properties):
self.setproperties(None,
properties,
None)
def setproperties(self,
opt,
path,
properties):
properties,
config_bag):
"""save properties for specified path
(never save properties if same has option properties)
"""
if self._getcontext().cfgimpl_get_meta() is not None:
raise ConfigError(_('cannot change property with metaconfig'))
if config_bag is None:
opt = None
else:
opt = config_bag.option
if opt and opt.impl_is_symlinkoption():
raise TypeError(_("can't assign properties to the SymLinkOption \"{}\""
"").format(opt.impl_get_display_name()))
@ -586,12 +641,9 @@ class Settings(object):
# validate properties
def validate_properties(self,
opt,
path,
setting_properties,
self_properties=undefined,
index=None,
force_permissive=False):
index,
config_bag):
"""
validation upon the properties related to `opt`
@ -599,48 +651,45 @@ class Settings(object):
:param force_permissive: behaves as if the permissive property
was present
"""
# opt properties
if self_properties is undefined:
self_properties = self.getproperties(opt,
path,
setting_properties=setting_properties,
index=index)
opt = config_bag.option
# calc properties
properties = self_properties & setting_properties - set(['frozen'])
if not opt.impl_is_optiondescription():
#mandatory
if 'mandatory' in properties or 'empty' in properties:
value = self._getcontext().cfgimpl_get_values().get_cached_value(opt,
path,
setting_properties,
validate=True,
self_properties=self_properties,
index=index)
if not self.validate_mandatory(opt,
self_properties = config_bag.properties
if self_properties is None:
self_properties = self.getproperties(path,
index,
value,
setting_properties,
properties):
properties -= set(['mandatory'])
else:
properties |= set(['mandatory'])
properties -= set(['empty'])
config_bag)
config_bag.properties = self_properties
properties = self_properties & config_bag.setting_properties - {'frozen', 'mandatory', 'empty'}
if not opt.impl_is_optiondescription():
##mandatory
#if 'mandatory' in properties or 'empty' in properties:
# value = self._getcontext().cfgimpl_get_values().get_cached_value(path,
# index,
# config_bag)
# sconfig_bag = config_bag.copy()
# sconfig_bag.properties = properties
# if not self.validate_mandatory(index,
# value,
# sconfig_bag):
# properties -= set(['mandatory'])
# else:
# properties |= set(['mandatory'])
# properties -= set(['empty'])
opt_type = 'option'
else:
opt_type = 'optiondescription'
# remove permissive properties
if force_permissive is True and properties:
if config_bag.force_permissive is True 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():
datas = {'opt': opt,
'path': path,
'setting_properties': setting_properties,
datas = {'path': path,
'config_bag': config_bag,
'index': index,
'debug': True}
raise PropertiesOptionError(None,
@ -650,25 +699,34 @@ class Settings(object):
opt_type)
def validate_mandatory(self,
opt,
path,
index,
value,
setting_properties,
properties):
config_bag):
values = self._getcontext().cfgimpl_get_values()
return 'mandatory' in setting_properties and \
('mandatory' in properties and values.isempty(opt,
opt = config_bag.option
if config_bag.setting_properties and 'mandatory' in config_bag.setting_properties and \
('mandatory' in config_bag.properties and values.isempty(opt,
value,
index=index) or \
'empty' in properties and values.isempty(opt,
'empty' in config_bag.properties and values.isempty(opt,
value,
force_allow_empty_list=True,
index=index))
index=index)):
datas = {'path': path,
'config_bag': config_bag,
'index': index,
'debug': True}
raise PropertiesOptionError(None,
['mandatory'],
self,
datas,
'option')
def validate_frozen(self,
setting_properties,
self_properties):
return 'everything_frozen' in setting_properties or 'frozen' in self_properties
config_bag):
return 'everything_frozen' in config_bag.setting_properties or \
'frozen' in config_bag.properties
#____________________________________________________________
# read only/read write

View file

@ -64,15 +64,9 @@ class Values(object):
# get value
def get_cached_value(self,
opt,
path,
setting_properties,
validate=True,
force_permissive=False,
self_properties=undefined,
index=None,
display_warnings=True,
trusted_cached_properties=True):
index,
config_bag):
"""get value directly in cache if set
otherwise calculated value and set it in cache
@ -90,6 +84,8 @@ class Values(object):
"""
ntime = None
# try to retrive value in cache
setting_properties = config_bag.setting_properties
is_cached = False
if setting_properties and 'cache' in setting_properties and \
self._p_.hascache(path,
index):
@ -98,30 +94,33 @@ class Values(object):
is_cached, value = self._p_.getcache(path,
ntime,
index)
if is_cached:
return value
if not is_cached:
# no cached value so get value
if validate and 'validator' in setting_properties:
value = self.get_validated_value(opt,
path,
setting_properties,
self_properties,
index=index,
display_warnings=display_warnings,
force_permissive=force_permissive)
else:
value = self.getvalue(opt,
path,
value = self.getvalue(path,
index,
setting_properties,
self_properties,
validate,
force_permissive=force_permissive)
config_bag)
#FIXME suboptimal ...
# validate value
if config_bag.validate:
context = self._getcontext()
opt = config_bag.option
opt.impl_validate(value,
context=context,
force_index=index,
check_error=True,
config_bag=config_bag)
if config_bag.display_warnings:
opt.impl_validate(value,
context=context,
force_index=index,
check_error=False,
config_bag=config_bag)
# store value in cache
if setting_properties and 'cache' in setting_properties and \
validate and force_permissive is False \
and trusted_cached_properties is True:
if not is_cached and \
setting_properties and 'cache' in setting_properties and \
config_bag.validate and config_bag.force_permissive is False and \
config_bag.trusted_cached_properties is True:
if 'expire' in setting_properties:
if ntime is None:
ntime = int(time())
@ -131,69 +130,49 @@ class Values(object):
return value
def get_validated_value(self,
opt,
path,
setting_properties,
self_properties=undefined,
index=None,
display_warnings=True,
force_permissive=False):
index,
config_bag):
"""get value and validate it
index is None for slave value, if value returned is not a list, just return []
:param opt: the `Option` that we want to get value
:param path: the path of the `Option`
:param setting_properties: global properties
:param self_properties: properties for this `Option`
:param index: index for a slave `Option`
:param display_warnings: display warnings or not
:param force_permissive: force permissive when check properties
:returns: value
"""
value = self.getvalue(opt,
path,
value = self.getvalue(path,
index,
setting_properties,
self_properties,
validate=True,
force_permissive=force_permissive)
config_bag)
context = self._getcontext()
opt = config_bag.option
opt.impl_validate(value,
context,
context=context,
force_index=index,
check_error=True,
setting_properties=setting_properties)
if display_warnings:
config_bag=config_bag)
if config_bag.display_warnings:
opt.impl_validate(value,
context,
context=context,
force_index=index,
check_error=False,
setting_properties=setting_properties)
config_bag=config_bag)
return value
def getvalue(self,
opt,
path,
index,
setting_properties,
self_properties,
validate,
force_permissive=False):
config_bag):
"""actually retrieves the value
:param opt: the `Option` that we want to get value
:param path: the path of the `Option`
:param index: index for a slave `Option`
:param setting_properties: global properties
:param self_properties: properties for this `Option`
:param validate: validate value
:param force_permissive: force permissive when check properties
:returns: value
"""
# get owner and value from store
# index allowed only for slave
opt = config_bag.option
is_slave = opt.impl_is_master_slaves('slave')
if index is None or not is_slave:
_index = None
@ -207,12 +186,13 @@ class Values(object):
if owner != owners.default:
# 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 self_properties is undefined:
self_properties = config_bag.properties
if self_properties is None:
settings = self._getcontext().cfgimpl_get_settings()
self_properties = settings.getproperties(opt,
path,
setting_properties=setting_properties,
index=index)
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 index is not None and not is_slave:
@ -222,18 +202,14 @@ class Values(object):
#so return default value
else:
return value
return self._getdefaultvalue(opt,
path,
return self._getdefaultvalue(path,
index,
validate,
setting_properties,
force_permissive=force_permissive)
config_bag)
def getdefaultvalue(self,
opt,
path,
setting_properties=undefined,
index=None):
index,
config_bag):
"""get default value:
- get meta config value or
- get calculated value or
@ -245,20 +221,16 @@ class Values(object):
:type index: int
:returns: default value
"""
return self._getdefaultvalue(opt,
path,
return self._getdefaultvalue(path,
index,
True,
setting_properties)
config_bag)
def _getdefaultvalue(self,
opt,
path,
index,
validate,
setting_properties,
force_permissive=False):
config_bag):
context = self._getcontext()
opt = config_bag.option
def _reset_cache():
# calculated value could be a new value, so reset cache
context.cfgimpl_reset_cache(opt=opt,
@ -268,18 +240,15 @@ class Values(object):
index_ = index
else:
index_ = None
if self._is_meta(opt,
path,
if self._is_meta(path,
index_,
setting_properties,
force_permissive=force_permissive):
config_bag):
meta = context.cfgimpl_get_meta()
# retrieved value from meta config
try:
value = meta.getattr(path,
index=index,
setting_properties=setting_properties,
force_permissive=force_permissive)
index,
config_bag)
except PropertiesOptionError:
# if properties error, return an other default value
# unexpected error, should not happened
@ -294,9 +263,8 @@ class Values(object):
context=context,
callback=callback,
callback_params=callback_params,
setting_properties=setting_properties,
index=index,
validate=validate)
config_bag=config_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)):
@ -383,62 +351,61 @@ class Values(object):
# set value
def setvalue(self,
opt,
value,
path,
force_permissive,
index,
setting_properties,
value,
config_bag,
_commit):
context = self._getcontext()
owner = context.cfgimpl_get_settings().getowner()
if 'validator' in setting_properties:
if opt._has_consistencies():
if 'validator' in config_bag.setting_properties and config_bag.validate:
if config_bag.option._has_consistencies():
# set value to a fake config when option has dependency
# validation will be complet in this case (consistency, ...)
tested_context = context._gen_fake_values()
tested_values = tested_context.cfgimpl_get_values()
tested_values._setvalue(opt,
path,
sconfig_bag = config_bag.copy()
sconfig_bag.validate = False
tested_context.cfgimpl_get_values().setvalue(path,
index,
value,
index=index,
owner=owner)
sconfig_bag,
True)
tested_context.getattr(path,
index,
config_bag)
else:
tested_context = context
tested_values = self
tested_values.setvalue_validation(opt,
self.setvalue_validation(path,
index,
value,
path,
setting_properties,
index)
config_bag)
self._setvalue(opt,
path,
self._setvalue(path,
index,
value,
owner,
index=index,
config_bag,
commit=_commit)
def setvalue_validation(self,
opt,
value,
path,
setting_properties,
index):
index,
value,
config_bag):
context = self._getcontext()
settings = context.cfgimpl_get_settings()
# First validate properties with this value
self_properties = settings.getproperties(opt,
path,
setting_properties=setting_properties,
index=index)
if settings.validate_frozen(setting_properties,
self_properties):
datas = {'opt': opt,
'path': path,
'setting_properties': setting_properties,
self_properties = config_bag.self_properties
if self_properties is None:
self_properties = settings.getproperties(path,
index,
config_bag)
config_bag.properties = self_properties
opt = config_bag.option
if settings.validate_frozen(config_bag):
datas = {'path': path,
'config_bag': config_bag,
'index': index,
'debug': True}
raise PropertiesOptionError(None,
@ -446,43 +413,32 @@ class Values(object):
settings,
datas,
'option')
if settings.validate_mandatory(opt,
settings.validate_mandatory(path,
index,
value,
setting_properties,
self_properties):
datas = {'opt': opt,
'path': path,
'setting_properties': setting_properties,
'index': index,
'debug': True}
raise PropertiesOptionError(None,
['mandatory'],
settings,
datas,
'option')
config_bag)
# Value must be valid for option
opt.impl_validate(value,
config_bag,
context,
check_error=True,
force_index=index,
setting_properties=setting_properties)
force_index=index)
# No error found so emit warnings
opt.impl_validate(value,
config_bag,
context,
check_error=False,
force_index=index,
setting_properties=setting_properties)
force_index=index)
def _setvalue(self,
opt,
path,
index,
value,
owner,
index=None,
config_bag,
commit=True):
self._getcontext().cfgimpl_reset_cache(opt=opt,
self._getcontext().cfgimpl_reset_cache(opt=config_bag.option,
path=path)
if isinstance(value, list):
# copy
@ -494,11 +450,9 @@ class Values(object):
commit)
def _is_meta(self,
opt,
path,
index,
setting_properties,
force_permissive=False,
config_bag,
force_owner_is_default=False):
if not force_owner_is_default and self._p_.hasvalue(path,
@ -509,6 +463,7 @@ class Values(object):
meta = context.cfgimpl_get_meta()
if meta is None:
return False
opt = config_bag.option
if opt.impl_is_master_slaves('slave'):
master = opt.impl_get_master_slaves().getmaster()
masterp = master.impl_getpath(context)
@ -516,22 +471,18 @@ class Values(object):
if self._p_.hasvalue(masterp,
index=index):
return False
return not meta.cfgimpl_get_values().is_default_owner(opt,
path,
setting_properties,
index=index,
force_permissive=force_permissive)
return not meta.cfgimpl_get_values().is_default_owner(path,
index,
config_bag)
#______________________________________________________________________
# owner
def getowner(self,
opt,
path,
setting_properties,
index=None,
force_permissive=False):
index,
config_bag):
"""
retrieves the option's owner
@ -540,35 +491,37 @@ class Values(object):
was present
:returns: a `setting.owners.Owner` object
"""
opt = config_bag.option
if opt.impl_is_symlinkoption():
config_bag.ori_option = opt
opt = opt.impl_getopt()
config_bag.option = opt
path = opt.impl_getpath(self._getcontext())
return self._getowner(opt,
path,
setting_properties,
index=index,
force_permissive=force_permissive)
return self._getowner(path,
index,
config_bag)
def _getowner(self,
opt,
path,
setting_properties,
force_permissive=False,
index,
config_bag,
validate_meta=undefined,
self_properties=undefined,
only_default=False,
index=None):
only_default=False):
"""get owner of an option
"""
context = self._getcontext()
opt = config_bag.option
if opt.impl_is_symlinkoption():
config_bag.ori_option = opt
opt = opt.impl_getopt()
config_bag.option = opt
path = opt.impl_getpath(context)
#FIXME pas deja fait ??
if self_properties is undefined:
self_properties = context.cfgimpl_get_settings().getproperties(opt,
path,
setting_properties)
self_properties = config_bag.properties
if self_properties is None:
self_properties = context.cfgimpl_get_settings().getproperties(path,
index,
config_bag)
config_bag.properties = self_properties
if 'frozen' in self_properties and 'force_default_on_freeze' in self_properties:
return owners.default
if only_default:
@ -583,28 +536,26 @@ class Values(object):
index=index)
if owner is owners.default and validate_meta is not False:
if validate_meta is undefined:
validate_meta = self._is_meta(opt,
path,
validate_meta = self._is_meta(path,
index,
setting_properties,
force_permissive=force_permissive,
config_bag=config_bag,
force_owner_is_default=True)
if validate_meta:
owner = owners.meta
return owner
def setowner(self,
opt,
path,
index,
owner,
setting_properties,
index=None):
config_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
if opt.impl_is_symlinkoption():
raise TypeError(_("can't set owner for the SymLinkOption \"{}\""
"").format(opt.impl_get_display_name()))
@ -617,83 +568,66 @@ class Values(object):
if not self._p_.hasvalue(path):
raise ConfigError(_('no value for {0} cannot change owner to {1}'
'').format(path, owner))
self.setowner_validation(opt,
path,
setting_properties,
index)
self.setowner_validation(path,
index,
config_bag)
self._p_.setowner(path, owner, index=index)
def is_default_owner(self,
opt,
path,
setting_properties,
validate_meta=undefined,
self_properties=undefined,
index=None,
force_permissive=False):
owner = self._getowner(opt,
path,
setting_properties,
index,
config_bag,
validate_meta=undefined):
owner = self._getowner(path,
index,
config_bag,
validate_meta=validate_meta,
self_properties=self_properties,
only_default=True,
index=index,
force_permissive=force_permissive)
only_default=True)
return owner == owners.default
#______________________________________________________________________
# reset
def reset(self,
opt,
path,
setting_properties,
validate=True,
_commit=True,
force_permissive=False):
config_bag,
_commit=True):
context = self._getcontext()
setting = context.cfgimpl_get_settings()
hasvalue = self._p_.hasvalue(path)
if validate and hasvalue and 'validator' in setting_properties:
if config_bag.validate and hasvalue and 'validator' in config_bag.setting_properties:
fake_context = context._gen_fake_values()
fake_value = fake_context.cfgimpl_get_values()
fake_value.reset(opt,
path,
setting_properties,
validate=False)
value = fake_value._getdefaultvalue(opt,
path,
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,
validate,
setting_properties)
fake_value.setvalue_validation(opt,
value,
path,
setting_properties,
None)
config_bag)
opt = config_bag.option
if opt.impl_is_master_slaves('master'):
opt.impl_get_master_slaves().reset(opt,
self,
setting_properties,
_commit=_commit,
force_permissive=force_permissive)
opt.impl_get_master_slaves().reset(self,
config_bag,
_commit=_commit)
if hasvalue:
if 'force_store_value' in setting.getproperties(opt,
path,
setting_properties,
apply_requires=False):
value = self._getdefaultvalue(opt,
path,
if 'force_store_value' in setting.getproperties(path,
None,
config_bag):
value = self._getdefaultvalue(path,
None,
config_bag)
self._setvalue(path,
None,
validate,
setting_properties)
self._setvalue(opt,
path,
value,
owners.forced,
None,
config_bag,
commit=_commit)
else:
self._p_.resetvalue(path,
@ -702,78 +636,65 @@ class Values(object):
path=path)
def reset_slave(self,
opt,
path,
index,
setting_properties,
validate=True,
force_permissive=False):
config_bag):
context = self._getcontext()
if validate and 'validator' in setting_properties:
if config_bag.validate and 'validator' in config_bag.setting_properties:
fake_context = context._gen_fake_values()
fake_value = fake_context.cfgimpl_get_values()
fake_value.reset_slave(opt,
path,
sconfig_bag = config_bag.copy()
sconfig_bag.validate = False
fake_value.reset_slave(path,
index,
setting_properties,
validate=False)
value = fake_value._getdefaultvalue(opt,
path,
sconfig_bag)
value = fake_value._getdefaultvalue(path,
index,
config_bag)
fake_value.setvalue_validation(path,
index,
validate,
setting_properties)
fake_value.setvalue_validation(opt,
value,
path,
setting_properties,
index)
config_bag)
self._p_.resetvalue_index(path, index)
def reset_master(self,
subconfig,
opt,
path,
index,
force_permissive,
setting_properties):
config_bag):
current_value = self.get_cached_value(opt,
path,
setting_properties,
force_permissive=force_permissive)
current_value = self.get_cached_value(path,
None,
config_bag)
current_value.pop(index)
self.setvalue(opt,
self.setvalue(path,
None,
current_value,
path,
force_permissive=force_permissive,
index=None,
setting_properties=setting_properties,
config_bag,
_commit=True)
subconfig.cfgimpl_get_description().pop(self,
index,
setting_properties,
force_permissive)
config_bag)
def setowner_validation(self,
opt,
path,
setting_properties,
index):
index,
config_bag):
context = self._getcontext()
settings = context.cfgimpl_get_settings()
# First validate properties with this value
self_properties = settings.getproperties(opt,
path,
setting_properties=setting_properties,
index=index)
if settings.validate_frozen(setting_properties,
self_properties):
datas = {'opt': opt,
'path': path,
'setting_properties': setting_properties,
self_properties = config_bag.properties
if self_properties is None:
self_properties = settings.getproperties(path,
None,
config_bag)
config_bag.properties = self_properties
if settings.validate_frozen(config_bag):
datas = {'path': path,
'config_bag': config_bag,
'index': index,
'debug': True}
raise PropertiesOptionError(None,
@ -807,7 +728,7 @@ class Values(object):
# mandatory warnings
def mandatory_warnings(self,
setting_properties):
config_bag):
"""convenience function to trace Options that are mandatory and
where no value has been set
@ -816,69 +737,75 @@ class Values(object):
context = self._getcontext()
settings = context.cfgimpl_get_settings()
# copy
setting_properties = set(setting_properties)
od_setting_properties = config_bag.setting_properties - {'mandatory', 'empty'}
setting_properties = set(config_bag.setting_properties)
setting_properties.update(['mandatory', 'empty'])
def _mandatory_warnings(description, currpath):
config_bag.setting_properties = frozenset(setting_properties)
config_bag.force_permissive = True
config_bag.trusted_cached_properties = False
config_bag.display_warnings = False
def _mandatory_warnings(description, currpath, config):
is_masterslaves = description.is_masterslaves()
lenmaster = None
for opt in description.impl_getchildren(context=context,
setting_properties=setting_properties):
name = opt.impl_getname()
optmaster = None
pathmaster = None
for option in description.impl_getchildren(config_bag):
sconfig_bag = config_bag.copy('nooption')
sconfig_bag.option = option
name = option.impl_getname()
path = '.'.join(currpath + [name])
if opt.impl_is_optiondescription():
if option.impl_is_optiondescription():
sconfig_bag.setting_properties = od_setting_properties
try:
settings.validate_properties(opt,
path,
setting_properties,
force_permissive=True)
for path in _mandatory_warnings(opt,
currpath + [name]):
yield path
except PropertiesOptionError:
subconfig = config.getattr(name,
None,
sconfig_bag)
except PropertiesOptionError as err:
pass
elif not opt.impl_is_symlinkoption():
self_properties = settings.getproperties(opt,
path,
setting_properties=setting_properties)
else:
for path in _mandatory_warnings(option,
currpath + [name],
subconfig):
yield path
elif not option.impl_is_symlinkoption():
# don't check symlink
self_properties = settings.getproperties(path,
None,
sconfig_bag)
sconfig_bag.properties = self_properties
if 'mandatory' in self_properties or 'empty' in self_properties:
try:
if opt.impl_is_master_slaves('slave'):
if option.impl_is_master_slaves('slave'):
if lenmaster is None:
# master is a length (so int) if value is already calculated
# otherwise get value and calculate length
values = self.get_cached_value(optmaster,
pathmaster,
setting_properties,
self_properties=self_properties,
trusted_cached_properties=False,
force_permissive=True,
validate=True,
display_warnings=False)
nconfig_bag = config_bag.copy('nooption')
nconfig_bag.option = optmaster
values = config.getattr(pathmaster,
None,
nconfig_bag)
lenmaster = len(values)
if not lenmaster:
settings.validate_properties(opt,
path,
setting_properties,
self_properties=self_properties,
force_permissive=True)
else:
#if not lenmaster:
# settings.validate_properties(path,
# None,
# sconfig_bag)
#else:
for index in range(lenmaster):
settings.validate_properties(opt,
path,
setting_properties,
self_properties=self_properties,
index=index,
force_permissive=True)
values = config.getattr(name,
index,
sconfig_bag)
else:
settings.validate_properties(opt,
path,
setting_properties,
self_properties=self_properties,
force_permissive=True)
value = config.getattr(name,
None,
sconfig_bag)
if is_masterslaves:
lenmaster = len(value)
pathmaster = name
optmaster = option
except PropertiesOptionError as err:
if err.proptype == frozenset(['mandatory']):
if err.proptype == ['mandatory']:
yield path
if is_masterslaves and lenmaster is None:
break
@ -887,10 +814,7 @@ class Values(object):
yield path
if is_masterslaves and lenmaster is None:
break
if is_masterslaves and lenmaster is None:
pathmaster = path
optmaster = opt
descr = context.cfgimpl_get_description()
for path in _mandatory_warnings(descr, []):
for path in _mandatory_warnings(descr, [], context):
yield path