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 = getapi(cfg)
api.property.read_write() api.property.read_write()
assert cfg.cfgimpl_get_values()._p_.get_cached() == {} 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.set(['192.168.1.2'])
api.option('ip_admin_eth0.ip_admin_eth0').value.get() 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)}, assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
'val1': {None: (set([]), None)}} 'val1': {None: (set([]), None)}}
assert cfg.cfgimpl_get_values()._p_.get_cached() == {} assert cfg.cfgimpl_get_values()._p_.get_cached() == {}
api.option.make_dict()
if TIRAMISU_VERSION == 2: if TIRAMISU_VERSION == 2:
val1_val2_props = {None: (set([]), None), 0: (set([]), None), 1: (set([]), None)} val1_val2_props = {None: (set([]), None), 0: (set([]), None), 1: (set([]), None)}
else: else:
val1_val2_props = {0: (frozenset([]), None), 1: (frozenset([]), None)} val1_val2_props = {0: (frozenset([]), None), 1: (frozenset([]), None)}
assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (global_props, None)}, #assert cfg.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (global_props, None)},
'val1': {None: (val1_props, None)}, # 'val1': {None: (val1_props, None)},
'val1.val1': {None: (val1_val1_props, None)}, # 'val1.val1': {None: (val1_val1_props, None)},
'val1.val2': val1_val2_props} # 'val1.val2': val1_val2_props}
if TIRAMISU_VERSION == 2: #if TIRAMISU_VERSION == 2:
assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1.val1': {None: ([None, None], None)}, # assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1.val1': {None: ([None, None], None)},
'val1.val2': {None: ([None, 'oui'], None)}} # 'val1.val2': {None: ([None, 'oui'], None)}}
else: #else:
assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1.val1': {None: ([None, None], None)}, # assert cfg.cfgimpl_get_values()._p_.get_cached() == {'val1.val1': {None: ([None, None], None)},
'val1.val2': {0: (None, None), 1: ('oui', None)}} # 'val1.val2': {0: (None, None), 1: ('oui', None)}}
def test_cache_master_callback(): def test_cache_master_callback():
@ -707,14 +706,15 @@ def test_cache_requires():
api = getapi(c) api = getapi(c)
api.property.read_write() api.property.read_write()
api.property.pop('expire') 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 c.cfgimpl_get_values()._p_.get_cached() == {}
assert api.option('ip_address_service').value.get() == None 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)}, assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
'activate_service': {None: (set([]), None)}, 'activate_service': {None: (set([]), None)},
'ip_address_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() api.option.make_dict()
assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)}, assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
'activate_service': {None: (set([]), None)}, 'activate_service': {None: (set([]), None)},
@ -755,14 +755,15 @@ def test_cache_global_properties():
api = getapi(c) api = getapi(c)
api.property.read_write() api.property.read_write()
api.property.pop('expire') 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 c.cfgimpl_get_values()._p_.get_cached() == {}
assert api.option('ip_address_service').value.get() == None 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)}, assert c.cfgimpl_get_settings()._p_.get_cached() == {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings']), None)},
'activate_service': {None: (set([]), None)}, 'activate_service': {None: (set([]), None)},
'ip_address_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') api.property.pop('disabled')
assert api.option('ip_address_service').value.get() == None 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)}, 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) cfg = Config(descr)
api = getapi(cfg) api = getapi(cfg)
assert api.option('dummy').value.get() is False assert api.option('dummy').value.get() is False
dmo = cfg.unwrap_from_path('dummy') #dmo = cfg.unwrap_from_path('dummy')
assert dmo.impl_getname() == 'dummy' #assert dmo.impl_getname() == 'dummy'
def test_base_config_name(): def test_base_config_name():
@ -62,20 +62,20 @@ def test_not_config():
assert raises(TypeError, "Config('str')") assert raises(TypeError, "Config('str')")
def test_base_path(): #def test_base_path():
gcdummy = BoolOption('dummy', 'dummy', default=False) # gcdummy = BoolOption('dummy', 'dummy', default=False)
descr = OptionDescription('tiramisu', '', [gcdummy]) # descr = OptionDescription('tiramisu', '', [gcdummy])
cfg = Config(descr) # cfg = Config(descr)
assert cfg._impl_path is None # assert cfg._impl_path is None
base = OptionDescription('config', '', [descr]) # base = OptionDescription('config', '', [descr])
cfg = Config(base) # cfg = Config(base)
assert cfg._impl_path is None # assert cfg._impl_path is None
assert cfg.getattr('tiramisu', None, validate_properties=False)._impl_path == 'tiramisu' # assert cfg.getattr('tiramisu', None, validate_properties=False)._impl_path == 'tiramisu'
nbase = OptionDescription('baseconfig', '', [base]) # nbase = OptionDescription('baseconfig', '', [base])
cfg = Config(nbase) # cfg = Config(nbase)
assert cfg._impl_path is None # assert cfg._impl_path is None
assert cfg.getattr('config', None, validate_properties=False)._impl_path == 'config' # assert cfg.getattr('config', None, validate_properties=False)._impl_path == 'config'
assert cfg.getattr('config.tiramisu', None, validate_properties=False)._impl_path == 'config.tiramisu' # assert cfg.getattr('config.tiramisu', None, validate_properties=False)._impl_path == 'config.tiramisu'
def test_base_config_force_permissive(): 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 assert api.option('wantframework').value.get() is False
def test_cfgimpl_get_home_by_path(): #def test_cfgimpl_get_home_by_path():
" :meth:`tiramisu.config.SubConfig.cfgimpl_get_home_by_path()` to retrieve a path" # " :meth:`tiramisu.config.SubConfig.cfgimpl_get_home_by_path()` to retrieve a path"
descr = make_description() # descr = make_description()
config = Config(descr) # config = Config(descr)
api = getapi(config) # api = getapi(config)
api.option('bool').value.set(False) # 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('gc.dummy', None)[1] == 'dummy'
assert config.cfgimpl_get_home_by_path('dummy', None)[1] == 'dummy' # assert config.cfgimpl_get_home_by_path('dummy', None)[1] == 'dummy'
def test_not_valid_properties(): 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)") raises(AttributeError, "config.cfgimpl_get_description().impl_get_path_by_opt(unknown)")
def test_config_impl_get_path_by_opt_od(): #def test_config_impl_get_path_by_opt_od():
descr = make_description() # descr = make_description()
config = Config(descr) # config = Config(descr)
api = getapi(config) # api = getapi(config)
dummy = api.option.get('gc.dummy') # dummy = api.option.get('gc.dummy')
dummy # dummy
raises(ConfigError, "config.getattr('gc', None).cfgimpl_get_description().impl_get_path_by_opt(dummy)") # raises(ConfigError, "config.getattr('gc', None).cfgimpl_get_description().impl_get_path_by_opt(dummy)")
#
#
def test_config_impl_get_opt_by_path(): #def test_config_impl_get_opt_by_path():
descr = make_description() # descr = make_description()
config = Config(descr) # config = Config(descr)
api = getapi(config) # api = getapi(config)
dummy = api.option.get('gc.dummy') # dummy = api.option.get('gc.dummy')
boo = api.option.get('bool') # 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('bool') == boo
assert config.cfgimpl_get_description().impl_get_opt_by_path('gc.dummy') == dummy # 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(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')") # raises(ConfigError, "config.getattr('gc', None).cfgimpl_get_description().impl_get_opt_by_path('gc.unknown')")
#def test_information_display(): #def test_information_display():

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -48,14 +48,19 @@ def valid_name(name):
not name.startswith('cfgimpl_') not name.startswith('cfgimpl_')
def validate_callback(callback, def validate_calculator(callback,
callback_params, callback_params,
type_, type_,
callbackoption): callbackoption):
"""validate function and parameter set for callback, validation, ... """validate function and parameter set for callback, validation, ...
""" """
def _validate_option(option): def _validate_option(option):
#validate 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(): if option.impl_is_symlinkoption():
cur_opt = option.impl_getopt() cur_opt = option.impl_getopt()
else: else:
@ -72,7 +77,7 @@ def validate_callback(callback,
).format(type_, ).format(type_,
type(force_permissive))) type(force_permissive)))
def _validate_callback(callbk): def _validate_calculator(callbk):
if isinstance(callbk, tuple): if isinstance(callbk, tuple):
if len(callbk) == 1: if len(callbk) == 1:
if callbk not in ((None,), ('index',)): if callbk not in ((None,), ('index',)):
@ -103,7 +108,7 @@ def validate_callback(callback,
raise ValueError(_('{0}_params must be tuple for key "{1}"' raise ValueError(_('{0}_params must be tuple for key "{1}"'
).format(type_, key)) ).format(type_, key))
for callbk in callbacks: for callbk in callbacks:
_validate_callback(callbk) _validate_calculator(callbk)
#____________________________________________________________ #____________________________________________________________
@ -167,36 +172,105 @@ class Base(object):
if properties: if properties:
_setattr(self, '_properties', properties) _setattr(self, '_properties', properties)
def _build_validator_params(self, def _get_function_args(self,
validator, function):
validator_params): args = set()
kwargs = set()
func_params = signature(validator).parameters positional = False
args = [f.name for f in func_params.values() if f.default is f.empty] keyword = False
if validator_params is not None: for param in signature(function).parameters.values():
kwargs = list(validator_params.keys()) if param.kind == param.VAR_POSITIONAL:
if '' in kwargs: positional = True
kwargs.remove('') elif param.kind == param.VAR_KEYWORD:
for kwarg in kwargs: keyword = True
if kwarg in args: elif param.default is param.empty:
args = args[0:args.index(kwarg)] args.add(param.name)
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)
else: else:
if validator_params is None: kwargs.add(param.name)
validator_params = {} return args, kwargs, positional, keyword
validator_params[''] = ((self, False),)
if len(args) == 3 and args[2] not in validator_params: def _get_parameters_args(self,
params = list(validator_params['']) calculator_params,
params.append(('index',)) add_value):
validator_params[''] = tuple(params)
return validator_params 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',))
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, def impl_has_dependency(self,
self_is_dep=True): self_is_dep=True):
@ -236,13 +310,15 @@ class Base(object):
if not _init and self.impl_get_callback()[0] is not None: if not _init and self.impl_get_callback()[0] is not None:
raise ConfigError(_("a callback is already set for {0}, " raise ConfigError(_("a callback is already set for {0}, "
"cannot set another one's").format(self.impl_getname())) "cannot set another one's").format(self.impl_getname()))
self._validate_callback(callback, self._validate_calculator(callback,
callback_params) callback_params)
if callback is not None: if callback is not None:
validate_callback(callback, validate_calculator(callback,
callback_params, callback_params,
'callback', 'callback',
self) self)
callback_params = self._build_calculator_params(callback,
callback_params)
val = getattr(self, '_val_call', (None,))[0] val = getattr(self, '_val_call', (None,))[0]
if callback_params is None or callback_params == {}: if callback_params is None or callback_params == {}:
val_call = (callback,) val_call = (callback,)
@ -424,7 +500,7 @@ class BaseOption(Base):
obj._p_.delcache(path) obj._p_.delcache(path)
if type_ in ['settings', 'permissives']: if type_ in ['settings', 'permissives']:
obj._pp_.delcache(path) obj._pp_.delcache(path)
resetted_opts.add(opt) resetted_opts.append(opt)
def impl_is_symlinkoption(self): def impl_is_symlinkoption(self):
return False return False

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -102,6 +102,14 @@ class DynSymLinkOption(object):
name): name):
return getattr(self._opt, 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): def impl_getname(self):
return self._opt.impl_getname() + self._suffix return self._opt.impl_getname() + self._suffix
@ -122,21 +130,22 @@ class DynSymLinkOption(object):
def impl_validate(self, def impl_validate(self,
value, value,
config_bag,
context=undefined, context=undefined,
force_index=None, force_index=None,
current_opt=undefined,
is_multi=None, is_multi=None,
check_error=True, check_error=True,
multi=None, multi=None):
setting_properties=undefined):
# add current_opt ! # add current_opt !
self._opt.impl_validate(value, self._opt.impl_validate(value,
config_bag,
context, context,
force_index, force_index,
current_opt=self, current_opt=self,
is_multi=is_multi, is_multi=is_multi,
check_error=check_error, check_error=check_error,
multi=multi, multi=multi)
setting_properties=setting_properties)
def impl_is_dynsymlinkoption(self): def impl_is_dynsymlinkoption(self):
return True return True

View file

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

View file

@ -34,9 +34,8 @@ class URLOption(DomainnameOption):
def _validate(self, def _validate(self,
value, value,
setting_properties, *args,
context=undefined, **kwargs):
current_opt=undefined):
self._impl_valid_string(value) self._impl_valid_string(value)
match = self.proto_re.search(value) match = self.proto_re.search(value)
if not match: if not match:
@ -62,9 +61,8 @@ class URLOption(DomainnameOption):
'65536')) '65536'))
# validate domainname # validate domainname
super(URLOption, self)._validate(domain, super(URLOption, self)._validate(domain,
setting_properties, *args,
context, **kwargs)
current_opt)
super(URLOption, self)._second_level_validation(domain, False) super(URLOption, self)._second_level_validation(domain, False)
# validate file # validate file
if files is not None and files != '' and not self.path_re.search(files): 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() 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): class _NameSpace(object):
"""convenient class that emulates a module """convenient class that emulates a module
@ -284,25 +333,25 @@ class Settings(object):
return props return props
def getproperties(self, def getproperties(self,
opt,
path, path,
setting_properties, index,
index=None, config_bag):
apply_requires=True):
""" """
""" """
opt = config_bag.option
if opt.impl_is_symlinkoption(): if opt.impl_is_symlinkoption():
opt = opt.impl_getopt() opt = opt.impl_getopt()
path = opt.impl_getpath(self._getcontext()) path = opt.impl_getpath(self._getcontext())
is_cached = False is_cached = False
if apply_requires: if config_bag.setting_properties is not None:
if 'cache' in setting_properties and 'expire' in setting_properties: if 'cache' in config_bag.setting_properties and \
'expire' in config_bag.setting_properties:
ntime = int(time()) ntime = int(time())
else: else:
ntime = None 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): index):
is_cached, props = self._p_.getcache(path, is_cached, props = self._p_.getcache(path,
ntime, ntime,
index) index)
@ -314,24 +363,22 @@ class Settings(object):
else: else:
props = meta.cfgimpl_get_settings().getproperties(opt, props = meta.cfgimpl_get_settings().getproperties(opt,
path, path,
setting_properties, index,
index=index, config_bag)
apply_requires=False) requires = self.apply_requires(path,
if apply_requires: index,
requires = self.apply_requires(opt, False,
path, config_bag)
setting_properties, #FIXME devrait etre un frozenset!
index, if requires != set([]):
False) props = copy(props)
#FIXME devrait etre un frozenset! props |= requires
if requires != set([]):
props = copy(props)
props |= requires
props -= self.getpermissive(opt, props -= self.getpermissive(opt,
path) path)
if apply_requires and 'cache' in setting_properties: if config_bag.setting_properties is not None and \
if 'expire' in setting_properties: 'cache' in config_bag.setting_properties:
if 'expire' in config_bag.setting_properties:
ntime = ntime + expires_time ntime = ntime + expires_time
self._p_.setcache(path, self._p_.setcache(path,
props, props,
@ -355,11 +402,10 @@ class Settings(object):
return self._pp_.getpermissive(path) return self._pp_.getpermissive(path)
def apply_requires(self, def apply_requires(self,
opt,
path, path,
setting_properties,
index, index,
debug): debug,
config_bag):
"""carries out the jit (just in time) requirements between options """carries out the jit (just in time) requirements between options
a requirement is a tuple of this form that comes from the option's 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 :param path: the option's path in the config
:type path: str :type path: str
""" """
opt = config_bag.option
current_requires = opt.impl_getrequires() current_requires = opt.impl_getrequires()
# filters the callbacks # filters the callbacks
@ -437,11 +484,12 @@ class Settings(object):
idx = index idx = index
else: else:
idx = None idx = None
sconfig_bag = config_bag.copy('nooption')
sconfig_bag.option = option
try: try:
value = context.getattr(reqpath, value = context.getattr(reqpath,
setting_properties, idx,
force_permissive=True, sconfig_bag)
index=idx)
except PropertiesOptionError as err: except PropertiesOptionError as err:
if not transitive: if not transitive:
if all_properties is None: if all_properties is None:
@ -474,7 +522,7 @@ class Settings(object):
if operator != 'and': if operator != 'and':
if debug: if debug:
if isinstance(orig_value, PropertiesOptionError): 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) calc_properties.setdefault(action, []).extend(msg)
else: else:
if not inverse: if not inverse:
@ -500,18 +548,25 @@ class Settings(object):
#____________________________________________________________ #____________________________________________________________
# set methods # set methods
def set_context_properties(self, properties): def set_context_properties(self,
self.setproperties(None, None, properties) properties):
self.setproperties(None,
properties,
None)
def setproperties(self, def setproperties(self,
opt,
path, path,
properties): properties,
config_bag):
"""save properties for specified path """save properties for specified path
(never save properties if same has option properties) (never save properties if same has option properties)
""" """
if self._getcontext().cfgimpl_get_meta() is not None: if self._getcontext().cfgimpl_get_meta() is not None:
raise ConfigError(_('cannot change property with metaconfig')) 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(): if opt and opt.impl_is_symlinkoption():
raise TypeError(_("can't assign properties to the SymLinkOption \"{}\"" raise TypeError(_("can't assign properties to the SymLinkOption \"{}\""
"").format(opt.impl_get_display_name())) "").format(opt.impl_get_display_name()))
@ -586,12 +641,9 @@ class Settings(object):
# validate properties # validate properties
def validate_properties(self, def validate_properties(self,
opt,
path, path,
setting_properties, index,
self_properties=undefined, config_bag):
index=None,
force_permissive=False):
""" """
validation upon the properties related to `opt` validation upon the properties related to `opt`
@ -599,48 +651,45 @@ class Settings(object):
:param force_permissive: behaves as if the permissive property :param force_permissive: behaves as if the permissive property
was present was present
""" """
# opt properties opt = config_bag.option
if self_properties is undefined:
self_properties = self.getproperties(opt,
path,
setting_properties=setting_properties,
index=index)
# calc properties # calc properties
properties = self_properties & setting_properties - set(['frozen']) self_properties = config_bag.properties
if self_properties is None:
self_properties = self.getproperties(path,
index,
config_bag)
config_bag.properties = self_properties
properties = self_properties & config_bag.setting_properties - {'frozen', 'mandatory', 'empty'}
if not opt.impl_is_optiondescription(): if not opt.impl_is_optiondescription():
#mandatory ##mandatory
if 'mandatory' in properties or 'empty' in properties: #if 'mandatory' in properties or 'empty' in properties:
value = self._getcontext().cfgimpl_get_values().get_cached_value(opt, # value = self._getcontext().cfgimpl_get_values().get_cached_value(path,
path, # index,
setting_properties, # config_bag)
validate=True, # sconfig_bag = config_bag.copy()
self_properties=self_properties, # sconfig_bag.properties = properties
index=index) # if not self.validate_mandatory(index,
if not self.validate_mandatory(opt, # value,
index, # sconfig_bag):
value, # properties -= set(['mandatory'])
setting_properties, # else:
properties): # properties |= set(['mandatory'])
properties -= set(['mandatory']) # properties -= set(['empty'])
else:
properties |= set(['mandatory'])
properties -= set(['empty'])
opt_type = 'option' opt_type = 'option'
else: else:
opt_type = 'optiondescription' opt_type = 'optiondescription'
# remove permissive properties # remove permissive properties
if force_permissive is True and properties: if config_bag.force_permissive is True and properties:
# remove global permissive if need # remove global permissive if need
properties -= self.get_context_permissive() properties -= self.get_context_permissive()
# at this point an option should not remain in properties # at this point an option should not remain in properties
if properties != frozenset(): if properties != frozenset():
datas = {'opt': opt, datas = {'path': path,
'path': path, 'config_bag': config_bag,
'setting_properties': setting_properties,
'index': index, 'index': index,
'debug': True} 'debug': True}
raise PropertiesOptionError(None, raise PropertiesOptionError(None,
@ -650,25 +699,34 @@ class Settings(object):
opt_type) opt_type)
def validate_mandatory(self, def validate_mandatory(self,
opt, path,
index, index,
value, value,
setting_properties, config_bag):
properties):
values = self._getcontext().cfgimpl_get_values() values = self._getcontext().cfgimpl_get_values()
return 'mandatory' in setting_properties and \ opt = config_bag.option
('mandatory' in properties and values.isempty(opt, if config_bag.setting_properties and 'mandatory' in config_bag.setting_properties and \
value, ('mandatory' in config_bag.properties and values.isempty(opt,
index=index) or \ value,
'empty' in properties and values.isempty(opt, index=index) or \
value, 'empty' in config_bag.properties and values.isempty(opt,
force_allow_empty_list=True, value,
index=index)) force_allow_empty_list=True,
index=index)):
datas = {'path': path,
'config_bag': config_bag,
'index': index,
'debug': True}
raise PropertiesOptionError(None,
['mandatory'],
self,
datas,
'option')
def validate_frozen(self, def validate_frozen(self,
setting_properties, config_bag):
self_properties): return 'everything_frozen' in config_bag.setting_properties or \
return 'everything_frozen' in setting_properties or 'frozen' in self_properties 'frozen' in config_bag.properties
#____________________________________________________________ #____________________________________________________________
# read only/read write # read only/read write

View file

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