This commit is contained in:
Emmanuel Garette 2017-11-12 14:33:05 +01:00
parent ee445aee85
commit 7ab7b810dc
13 changed files with 1439 additions and 1420 deletions

248
test/api/test_multi.py Normal file
View File

@ -0,0 +1,248 @@
"""test consistencies about multi and submulti"""
from py.test import raises
from .autopath import do_autopath
do_autopath()
from tiramisu.setting import groups
from tiramisu import Config, StrOption, IntOption, OptionDescription, MasterSlaves, getapi, \
submulti, undefined
from tiramisu.error import PropertiesOptionError
def return_val(val=None):
if val is None:
return 'val'
else:
return val
def return_list(value=None):
return ['val', 'val']
def return_list2(value=None):
return [['val', 'val']]
def test_multi_unique():
int_ = IntOption('int', '', multi=True, unique=True)
od_ = OptionDescription('od', '', [int_])
cfg = Config(od_)
api = getapi(cfg)
assert api.option('int').value.get() == []
value = [0]
api.option('int').value.set(value)
assert api.option('int').value.get() == value
value.append(1)
assert api.option('int').value.get() == [0]
raises(ValueError, "api.option('int').value.set([0, 0])")
raises(ValueError, "api.option('int').value.set([1, 0, 2, 3, 4, 5, 6, 0, 7])")
def test_multi_none():
str_ = StrOption('str', '', multi=True)
od_ = OptionDescription('od', '', [str_])
cfg = Config(od_)
cfg.read_only()
api = getapi(cfg)
assert api.option('str').value.get() == []
cfg.read_write()
api.option('str').value.set([None])
assert api.option('str').value.get() == [None]
cfg.read_only()
raises(PropertiesOptionError, "api.option('str').value.get()")
cfg.read_write()
api.option('str').value.set([''])
assert api.option('str').value.get() == ['']
cfg.read_only()
raises(PropertiesOptionError, "api.option('str').value.get()")
# ______________ submulti ______________
def test_append_submulti():
multi = StrOption('multi', '', multi=submulti)
multi2 = StrOption('multi2', '', default_multi=['yes'], multi=submulti)
multi3 = StrOption('multi3', '', default=[['yes']], multi=submulti)
od_ = OptionDescription('od', '', [multi, multi2, multi3])
cfg = Config(od_)
api = getapi(cfg)
#FIXME
owner = cfg.cfgimpl_get_settings().getowner()
assert api.option('multi').value.get() == []
assert api.option('multi').value.get() == []
assert api.option('multi').owner.isdefault()
api.option('multi').value.set([undefined])
assert api.option('multi').owner.get() == owner
value = api.option('multi').value.get()
assert value == [[]]
value.append(['no'])
assert api.option('multi').value.get() == [[]]
api.option('multi').value.set(value)
assert api.option('multi').value.get() == [[], ['no']]
#
assert api.option('multi2').value.get() == []
assert api.option('multi2').owner.isdefault()
api.option('multi2').value.set([undefined])
assert api.option('multi2').owner.get() == owner
assert api.option('multi2').value.get() == [['yes']]
api.option('multi2').value.set([['yes'], ['no']])
assert api.option('multi2').value.get() == [['yes'], ['no']]
#
assert api.option('multi3').value.get() == [['yes']]
assert api.option('multi3').owner.isdefault()
api.option('multi3').value.set([['yes'], undefined])
assert api.option('multi3').owner.get() == owner
assert api.option('multi3').value.get() == [['yes'], []]
api.option('multi3').value.set([['yes'], [], ['no']])
assert api.option('multi3').value.get() == [['yes'], [], ['no']]
def test_append_unvalide_submulti():
multi = StrOption('multi', '', multi=submulti)
multi2 = StrOption('multi2', '', default_multi=['yes'], multi=submulti)
multi3 = StrOption('multi3', '', default=[['yes']], multi=submulti)
od_ = OptionDescription('od', '', [multi, multi2, multi3])
cfg = Config(od_)
api = getapi(cfg)
assert api.option('multi').value.get() == []
assert api.option('multi').owner.isdefault()
raises(ValueError, "api.option('multi').value.set([1])")
assert api.option('multi').value.get() == []
assert api.option('multi').owner.isdefault()
#
assert api.option('multi2').value.get() == []
raises(ValueError, "api.option('multi2').value.set('no')")
assert api.option('multi2').owner.isdefault()
assert api.option('multi2').value.get() == []
#
assert api.option('multi3').value.get() == [['yes']]
assert api.option('multi3').owner.isdefault()
def test_submulti_unique():
int_ = IntOption('int', '', multi=submulti, unique=True)
od_ = OptionDescription('od', '', [int_])
cfg = Config(od_)
api = getapi(cfg)
assert api.option('int').value.get() == []
api.option('int').value.set([[0]])
assert api.option('int').value.get() == [[0]]
raises(ValueError, "api.option('int').value.set([[0, 0]])")
api.option('int').value.set([[0], [0]])
raises(ValueError, "api.option('int').value.set([[0], [1, 0, 2, 3, 4, 5, 6, 0, 7]])")
def test_callback_reset():
multi = StrOption('multi', '', multi=submulti, callback=return_val)
od_ = OptionDescription('od', '', [multi])
cfg = Config(od_)
cfg.read_write()
api = getapi(cfg)
#FIXME
owner = cfg.cfgimpl_get_settings().getowner()
assert api.option('multi').value.get() == [['val']]
assert api.option('multi').owner.isdefault()
api.option('multi').value.set([['val'], undefined])
assert api.option('multi').owner.get() == owner
assert api.option('multi').value.get() == [['val'], ['val']]
api.option('multi').value.reset()
assert api.option('multi').owner.isdefault()
assert api.option('multi').value.get() == [['val']]
api.option('multi').value.set([['val1']])
assert api.option('multi').owner.get() == owner
assert api.option('multi').value.get() == [['val1']]
def test_callback_submulti_list():
multi = StrOption('multi', '', multi=submulti, callback=return_list)
od_ = OptionDescription('od', '', [multi])
cfg = Config(od_)
cfg.read_write()
api = getapi(cfg)
owner = cfg.cfgimpl_get_settings().getowner()
assert api.option('multi').value.get() == [['val', 'val']]
assert api.option('multi').owner.isdefault()
api.option('multi').value.set([['val', 'val'], undefined])
assert api.option('multi').owner.get() == owner
assert api.option('multi').value.get() == [['val', 'val'], ['val', 'val']]
api.option('multi').value.set([['val', 'val'], undefined, undefined])
assert api.option('multi').value.get() == [['val', 'val'], ['val', 'val'], ['val', 'val']]
api.option('multi').value.reset()
assert api.option('multi').owner.isdefault()
def test_callback_submulti_list_list():
multi = StrOption('multi', '', multi=submulti, callback=return_list2)
od = OptionDescription('od', '', [multi])
cfg = Config(od)
cfg.read_write()
api = getapi(cfg)
owner = cfg.cfgimpl_get_settings().getowner()
assert api.option('multi').value.get() == [['val', 'val']]
assert api.option('multi').owner.isdefault()
api.option('multi').value.set([['val', 'val'], undefined])
assert api.option('multi').owner.get() == owner
assert api.option('multi').value.get() == [['val', 'val'], []]
api.option('multi').value.reset()
assert api.option('multi').owner.isdefault()
#FIXME
#def test_multi_submulti_meta():
# multi = StrOption('multi', '', multi=submulti)
# od = OptionDescription('od', '', [multi])
# conf1 = Config(od, session_id='conf1')
# conf1.read_write()
# conf2 = Config(od, session_id='conf2')
# conf2.read_write()
# meta = MetaConfig([conf1, conf2])
# meta.read_write()
# meta.multi = [['val']]
# assert meta.multi == [['val']]
# multi = conf1.multi[0]
# multi.append()
# assert conf1.multi == [['val', None]]
# assert meta.multi == [['val']]
# ____________________________________________________________
# Master Slaves
def test_values_with_master_and_slaves_submulti():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=submulti)
interface1 = MasterSlaves('f_ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
conf = OptionDescription('conf', '', [interface1])
cfg = Config(conf)
api = getapi(cfg)
cfg.read_write()
owner = cfg.cfgimpl_get_settings().getowner()
#FIXME
assert interface1.impl_get_group_type() == groups.master
assert api.option('f_ip_admin_eth0.ip_admin_eth0').owner.isdefault()
#FIXME raises(IndexError, "api.option('f_ip_admin_eth0.netmask_admin_eth0', 0).value.get()")
api.option('f_ip_admin_eth0.ip_admin_eth0').value.set(['192.168.230.145'])
assert api.option('f_ip_admin_eth0.ip_admin_eth0').value.get() == ['192.168.230.145']
assert api.option('f_ip_admin_eth0.netmask_admin_eth0', 0).value.get() == []
#FIXME raises(IndexError, "api.option('f_ip_admin_eth0.netmask_admin_eth0', 1).value.get()")
assert api.option('f_ip_admin_eth0.ip_admin_eth0').owner.get() == owner
assert api.option('f_ip_admin_eth0.netmask_admin_eth0', 0).owner.isdefault()
api.option('f_ip_admin_eth0.ip_admin_eth0').value.set(['192.168.230.145', '192.168.230.147'])
assert api.option('f_ip_admin_eth0.netmask_admin_eth0', 0).value.get() == []
assert api.option('f_ip_admin_eth0.netmask_admin_eth0', 1).value.get() == []
#FIXME raises(IndexError, "api.option('f_ip_admin_eth0.netmask_admin_eth0', 2).value.get()")
#FIXME raises(IndexError, "api.option('f_ip_admin_eth0.netmask_admin_eth0', 2).value.set(['255.255.255.0'])")
api.option('f_ip_admin_eth0.netmask_admin_eth0', 0).value.set(['255.255.255.0'])
assert api.option('f_ip_admin_eth0.netmask_admin_eth0', 0).value.get() == ['255.255.255.0']
assert api.option('f_ip_admin_eth0.netmask_admin_eth0', 1).value.get() == []
api.option('f_ip_admin_eth0.netmask_admin_eth0', 1).value.set(['255.255.255.255'])
assert api.option('f_ip_admin_eth0.netmask_admin_eth0', 0).value.get() == ['255.255.255.0']
assert api.option('f_ip_admin_eth0.netmask_admin_eth0', 1).value.get() == ['255.255.255.255']
assert api.option('f_ip_admin_eth0.ip_admin_eth0').value.get() == ['192.168.230.145', '192.168.230.147']
raises(ValueError, "api.option('f_ip_admin_eth0.ip_admin_eth0').value.set(['192.168.230.145'])")
api.option('f_ip_admin_eth0.ip_admin_eth0').value.pop(1)
assert api.option('f_ip_admin_eth0.ip_admin_eth0').value.get() == ['192.168.230.145']
assert api.option('f_ip_admin_eth0.netmask_admin_eth0', 0).value.get() == ['255.255.255.0']
#FIXME raises(IndexError, "api.option('f_ip_admin_eth0.netmask_admin_eth0', 1).value.get()")

View File

@ -138,18 +138,15 @@ def autocheck_value(api, path, **kwargs):
if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False): if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False):
if ismaster: if ismaster:
raises(APIError, "api.option(path, 0).value.set(first_value[0])") raises(APIError, "api.option(path, 0).value.set(first_value[0])")
api.option(path).value.append(first_value[0]) api.option(path).value.set([first_value[0]])
elif isslave: elif isslave:
#FIXME
print(api.option(path).value.append(first_value[0]))
raises(PropertiesOptionError, "api.option(path).value.append(first_value[0])")
api.option(path, 0).value.set(first_value[0]) api.option(path, 0).value.set(first_value[0])
raise Exception('pouet') raise Exception('pouet')
else: else:
api.option(path).value.set(first_value) api.option(path).value.set(first_value)
else: else:
if ismaster: if ismaster:
raises(PropertiesOptionError, "api.option(path).value.append(first_value[0])") raises(PropertiesOptionError, "api.option(path).value.set([first_value[0]])")
elif isslave: elif isslave:
raises(PropertiesOptionError, "api.option(path, 0).value.set(first_value[0])") raises(PropertiesOptionError, "api.option(path, 0).value.set(first_value[0])")
else: else:
@ -180,31 +177,30 @@ def autocheck_value(api, path, **kwargs):
if ismaster: if ismaster:
raises(APIError, "api.unrestraint.option(path).value.set(second_value[1])") raises(APIError, "api.unrestraint.option(path).value.set(second_value[1])")
elif isslave: elif isslave:
raises(APIError, "api.unrestraint.option(path).value.append(second_value[1])") raises(APIError, "api.unrestraint.option(path).value.set([first_value[0], second_value[1]])")
else: else:
raises(APIError, "api.unrestraint.option(path).value.set(second_value)") raises(APIError, "api.unrestraint.option(path).value.set(second_value)")
if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False): if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False):
if ismaster: if ismaster:
raises(APIError, "api.forcepermissive.option(path, 1).value.set(second_value[1])") raises(APIError, "api.forcepermissive.option(path, 1).value.set(second_value[1])")
api.forcepermissive.option(path).value.append(second_value[1]) api.forcepermissive.option(path).value.set([first_value[0], second_value[1]])
elif isslave: elif isslave:
#FIXME #FIXME
raises(PropertiesOptionError, "api.forcepermissive.option(path).value.append(second_value[1])") raises(PropertiesOptionError, "api.forcepermissive.option(path).value.set([first_value[0], second_value[1]])")
api.option(path, 1).value.set(second_value[1]) api.option(path, 1).value.set(second_value[1])
raise Exception('ca entre ici') raise Exception('ca entre ici')
else: else:
api.option(path).value.set(second_value) api.option(path).value.set(second_value)
elif kwargs.get('permissive', False): elif kwargs.get('permissive', False):
if ismaster: if ismaster:
api.forcepermissive.option(path).value.append(second_value[0]) api.forcepermissive.option(path).value.set([first_value[0], second_value[1]])
api.forcepermissive.option(path).value.append(second_value[1])
elif isslave: elif isslave:
api.forcepermissive.option(path, 1).value.set(second_value[1]) api.forcepermissive.option(path, 1).value.set(second_value[1])
else: else:
api.forcepermissive.option(path).value.set(first_value) api.forcepermissive.option(path).value.set(first_value)
else: else:
if ismaster: if ismaster:
raises(PropertiesOptionError, "api.forcepermissive.option(path).value.append(first_value[0])") raises(PropertiesOptionError, "api.forcepermissive.option(path).value.set([first_value[0]])")
elif isslave: elif isslave:
raises(PropertiesOptionError, "api.forcepermissive.option(path, 0).value.set(first_value[0])") raises(PropertiesOptionError, "api.forcepermissive.option(path, 0).value.set(first_value[0])")
else: else:
@ -240,15 +236,8 @@ def autocheck_value(api, path, **kwargs):
@autocheck @autocheck
def autocheck_reset_value(api, path, **kwargs): def autocheck_reset_value(api, path, **kwargs):
# check if is a multi, a master or a slave # check if is a multi, a master or a slave
if not kwargs.get('propertyerror', False): multi = api.unrestraint.option(path).option.ismulti()
multi = api.forcepermissive.option(path).option.ismulti() isslave = api.unrestraint.option(path).option.isslave()
ismaster = api.forcepermissive.option(path).option.ismaster()
isslave = api.forcepermissive.option(path).option.isslave()
else:
raises(PropertiesOptionError, "api.forcepermissive.option(path).option.ismulti()")
multi = api.unrestraint.option(path).option.ismulti()
ismaster = api.unrestraint.option(path).option.ismaster()
isslave = api.unrestraint.option(path).option.isslave()
# set default value (different if value is multi or not) # set default value (different if value is multi or not)
if not multi: if not multi:
@ -337,14 +326,8 @@ def autocheck_property(api, path, **kwargs):
"""get property from path """get property from path
""" """
# check if is a multi or a slave # check if is a multi or a slave
if not kwargs.get('propertyerror', False): multi = api.unrestraint.option(path).option.ismulti()
multi = api.forcepermissive.option(path).option.ismulti() isslave = api.unrestraint.option(path).option.isslave()
isslave = api.forcepermissive.option(path).option.isslave()
else:
raises(PropertiesOptionError, "api.forcepermissive.option(path).option.ismulti()")
raises(PropertiesOptionError, "api.forcepermissive.option(path).option.isslave()")
multi = api.unrestraint.option(path).option.ismulti()
isslave = api.unrestraint.option(path).option.isslave()
# define properties # define properties
properties = ['prop1', 'prop2'] properties = ['prop1', 'prop2']
@ -367,7 +350,10 @@ def autocheck_property(api, path, **kwargs):
assert set(api.option(path, 0).property.get()) == set(default_props) assert set(api.option(path, 0).property.get()) == set(default_props)
assert set(api.option(path, 1).property.get()) == set(default_props) assert set(api.option(path, 1).property.get()) == set(default_props)
else: else:
raises(PropertiesOptionError, "api.option(path).property.get()") if not isslave:
raises(PropertiesOptionError, "api.option(path).property.get()")
else:
raises(PropertiesOptionError, "api.option(path, 0).property.get()")
# get properties with permissive # get properties with permissive
if not isslave: if not isslave:
@ -390,17 +376,21 @@ def autocheck_property(api, path, **kwargs):
if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False): if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False):
api.option(path).property.set(properties) api.option(path).property.set(properties)
else: else:
raises(PropertiesOptionError, "api.option(path).property.set(properties)") if not isslave:
raises(PropertiesOptionError, "api.option(path).property.set(properties)")
else:
raises(PropertiesOptionError, "api.option(path, 0).property.set(properties)")
# check properties after set without permissive # check properties after set without permissive
if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False): if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False):
assert set(api.option(path).property.get()) == set(properties) assert set(api.option(path).property.get()) == set(properties)
assert set(api.forcepermissive.option(path).property.get()) == set(properties) assert set(api.forcepermissive.option(path).property.get()) == set(properties)
elif kwargs.get('permissive', False): elif kwargs.get('permissive', False):
raises(PropertiesOptionError, "api.option(path).property.get()")
if not isslave: if not isslave:
raises(PropertiesOptionError, "api.option(path).property.get()")
assert set(api.forcepermissive.option(path).property.get()) == set(default_props) assert set(api.forcepermissive.option(path).property.get()) == set(default_props)
else: else:
raises(PropertiesOptionError, "api.option(path, 0).property.get()")
assert set(api.forcepermissive.option(path, 0).property.get()) == set(default_props) assert set(api.forcepermissive.option(path, 0).property.get()) == set(default_props)
assert set(api.forcepermissive.option(path, 1).property.get()) == set(default_props) assert set(api.forcepermissive.option(path, 1).property.get()) == set(default_props)
else: else:
@ -588,7 +578,8 @@ def autocheck_owner_with_value(api, path, **kwargs):
if not isslave: if not isslave:
assert api.forcepermissive.option(path).owner.isdefault() is False assert api.forcepermissive.option(path).owner.isdefault() is False
else: else:
assert api.forcepermissive.option(path, 0).owner.isdefault() is False assert api.forcepermissive.option(path, 0).owner.isdefault() is True
assert api.forcepermissive.option(path, 1).owner.isdefault() is False
else: else:
raises(PropertiesOptionError, "api.forcepermissive.option(path).owner.isdefault()") raises(PropertiesOptionError, "api.forcepermissive.option(path).owner.isdefault()")
@ -773,18 +764,15 @@ def check_all(api, path, multi, **kwargs):
def make_api(options, multi): def make_api(options, multi):
def make_option(path): def make_option(path, option_infos):
option_infos = path.split('_') #FIXME
option_type = 'str' option_type = 'str'
option_properties = [] option_properties = []
for option_info in option_infos[1:]: if option_infos is not None:
if option_info in OPTIONS_TYPE: for prop in PROPERTIES:
option_type = option_info if option_infos.get(prop, False) is True:
elif option_info in PROPERTIES: option_properties.append(prop)
option_properties.append(option_info) args = [path, "{}'s option".format(path)]
else:
raise Exception('unknown {} in {}'.format(option_info, path))
args = [option_infos[0], "{}'s option".format(option_infos[0])]
kwargs = {} kwargs = {}
if option_properties != []: if option_properties != []:
kwargs['properties'] = tuple(option_properties) kwargs['properties'] = tuple(option_properties)
@ -794,23 +782,21 @@ def make_api(options, multi):
return tiramisu_option(*args, **kwargs) return tiramisu_option(*args, **kwargs)
def make_optiondescriptions(path, collected): def make_optiondescriptions(path, collected):
infos = path.split('_') infos = collected.get('properties', {})
name = infos[0]
properties = [] properties = []
kwargs = {} kwargs = {}
optiondescription = OptionDescription optiondescription = OptionDescription
for info in infos[1:]:
if info in PROPERTIES: for prop in PROPERTIES:
properties.append(info) if infos.get(prop, False) is True:
elif info == 'master': properties.append(prop)
if not multi: if infos.get('master', False) is True:
return if not multi:
optiondescription = MasterSlaves return
elif info == 'dyn': optiondescription = MasterSlaves
optiondescription = DynOptionDescription if infos.get('dyn', False) is True:
kwargs['callback'] = return_list optiondescription = DynOptionDescription
else: kwargs['callback'] = return_list
raise Exception('unknown {} in {}'.format(info, path))
options = [] options = []
if 'options' in collected: if 'options' in collected:
options.extend(collected['options']) options.extend(collected['options'])
@ -823,19 +809,20 @@ def make_api(options, multi):
options.append(option) options.append(option)
if properties != []: if properties != []:
kwargs['properties'] = tuple(properties) kwargs['properties'] = tuple(properties)
return optiondescription(name, "{}'s optiondescription".format(name), options, **kwargs) return optiondescription(path, "{}'s optiondescription".format(path), options, **kwargs)
collect_options = {} collect_options = {}
for option in options: for path, option in options.items():
if option is None: if option is None:
continue continue
local_collect_options = collect_options local_collect_options = collect_options
for optiondescription in option.split('.')[:-1]: for optiondescription in path.split('.')[:-1]:
local_collect_options.setdefault(optiondescription, {}) local_collect_options.setdefault(optiondescription, {})
local_collect_options = local_collect_options[optiondescription] local_collect_options = local_collect_options[optiondescription]
path = '.'.join(option.split('.')[:-1]) local_collect_options['properties'] = option.get(optiondescription, {})
option_name = option.split('.')[-1] option_name = path.split('.')[-1]
local_collect_options.setdefault("options", []).append(make_option(option_name)) path = '.'.join(path.split('.')[:-1])
local_collect_options.setdefault('options', []).append(make_option(option_name, option.get(option_name)))
rootod = make_optiondescriptions('root', collect_options) rootod = make_optiondescriptions('root', collect_options)
if rootod is None: if rootod is None:
@ -846,39 +833,45 @@ def make_api(options, multi):
DICT_PATHS = [ DICT_PATHS = [
#test a config without optiondescription #test a config without optiondescription
OrderedDict([('first', 'first'), OrderedDict([('first', {}),
('second', 'second_disabled'), ('second', {'second': {'disabled': True}}),
('third', 'third_hidden')]), ('third', {'third': {'hidden': True}})]),
#test a config with an optiondescription #test a config with an optiondescription
OrderedDict([('subod.first', 'subod.first'), OrderedDict([('subod.first', {}),
('subod.second', 'subod.second_disabled'), ('subod.second', {'second': {'disabled': True}}),
('subod.third', 'subod.third_hidden')]), ('subod.third', {'third': {'hidden': True}})]),
#test a config with two optiondescription #test a config with two optiondescription
OrderedDict([('subod.subsubod.first', 'subod.subsubod.first'), OrderedDict([('subod.subsubod.first', {}),
('subod.subsubod.second', 'subod.subsubod.second_disabled'), ('subod.subsubod.second', {'second': {'disabled': True}}),
('subod.subsubod.third', 'subod.subsubod.third_hidden')]), ('subod.subsubod.third', {'third': {'hidden': True}})]),
#test a config with mix of different optiondescription #test a config with mix of different optiondescription
OrderedDict([('first', 'first'), OrderedDict([('first', {}),
('subod.second', 'subod.second_disabled'), ('subod.second', {'second': {'disabled': True}}),
('subod.subsubod.third', 'subod.subsubod.third_hidden')]), ('subod.subsubod.third', {'third': {'hidden': True}})]),
#test a config with masterslaves #test a config with masterslaves
OrderedDict([('first.first', 'first_master.first'), OrderedDict([('odmaster.first', {'odmaster': {'master': True}}),
('first.second', 'first_master.second_disabled'), ('odmaster.second', {'second': {'disabled': True}}),
('first.third', 'first_master.third_hidden')]), ('odmaster.third', {'third': {'hidden': True}})]),
##test a config with dynoption ##test a config with dynoption
OrderedDict([('subodval1.firstval1', 'subod_dyn.first'), OrderedDict([('subod.firstv', {'subod': {'dyn': True}}),
('subodval1.secondval1', 'subod_dyn.second_disabled'), ('subod.second', {'second': {'disabled': True}}),
('subodval1.thirdval1', 'subod_dyn.third_hidden'), ('subod.third', {'third': {'hidden': True}}),
('subodval1.firstval1', None),
('subodval1.secondval1', None),
('subodval1.thirdval1', None),
('subodval2.firstval2', None), ('subodval2.firstval2', None),
('subodval2.secondval2', None), ('subodval2.secondval2', None),
('subodval2.thirdval2', None)]), ('subodval2.thirdval2', None)]),
#test a config with dynoption subdir #test a config with dynoption subdir
OrderedDict([('subod.subodval1.firstval1', 'subod.subod_dyn.first'), OrderedDict([('subod.subsubod.first', {'subod': {'dyn': True}}),
('subod.subodval1.secondval1', 'subod.subod_dyn.second_disabled'), ('subod.subsubod.second', {'second': {'disabled': True}}),
('subod.subodval1.thirdval1', 'subod.subod_dyn.third_hidden'), ('subod.subsubod.third', {'third': {'hidden': True}}),
('subod.subodval2.firstval2', None), ('subod.subsubodval1.firstval1', None),
('subod.subodval2.secondval2', None), ('subod.subsubodval1.secondval1', None),
('subod.subodval2.thirdval2', None)]) ('subod.subsubodval1.thirdval1', None),
('subod.subsubodval2.firstval2', None),
('subod.subsubodval2.secondval2', None),
('subod.subsubodval2.thirdval2', None)])
] ]
@ -892,7 +885,7 @@ def paths(request):
def test_options(paths): def test_options(paths):
lpaths = list(paths.keys()) lpaths = list(paths.keys())
for multi in (False, True): for multi in (False, True):
api = make_api(paths.values(), multi) api = make_api(paths, multi)
if api is None: if api is None:
continue continue
check_all(api, lpaths[0], multi) check_all(api, lpaths[0], multi)
@ -908,15 +901,18 @@ def test_options(paths):
DICT_PATHS2 = [ DICT_PATHS2 = [
OrderedDict([('subod.subsubod.first', 'subod.subsubod_hidden.first'), OrderedDict([('subod.subsubod.first', {'subsubod': {'hidden': True}}),
('subod.subsubod.second', 'subod.subsubod_hidden.second'), ('subod.subsubod.second', {}),
('subod.subsubod.third', 'subod.subsubod_hidden.third_hidden')]), ('subod.subsubod.third', {})]),
OrderedDict([('subod.subodval1.firstval1', 'subod.subod_dyn_hidden.first'), OrderedDict([('subod.subsubod.first', {'subsub': {'dyn': True, 'hidden': True}}),
('subod.subodval1.secondval1', 'subod.subod_dyn_hidden.second'), ('subod.subsubod.second', {}),
('subod.subodval1.thirdval1', 'subod.subod_dyn_hidden.third_hidden'), ('subod.subsubod.third', {}),
('subod.subodval2.firstval2', None), ('subod.subsubodval1.firstval1', None),
('subod.subodval2.secondval2', None), ('subod.subsubodval1.secondval1', None),
('subod.subodval2.thirdval2', None)]) ('subod.subsubodval1.thirdval1', None),
('subod.subsubodval2.firstval2', None),
('subod.subsubodval2.secondval2', None),
('subod.subsubodval2.thirdval2', None)])
] ]
@ -927,18 +923,19 @@ def paths2(request):
return request.param return request.param
def test_tree_od_permissive(paths2): #FIXME
"""permissive when optiondescription is hidden #def test_tree_od_permissive(paths2):
""" # """permissive when optiondescription is hidden
lpaths = list(paths2.keys()) # """
for multi in (False, True): # lpaths = list(paths2.keys())
api = make_api(paths2.values(), multi) # for multi in (False, True):
if api is None: # api = make_api(paths2, multi)
continue # if api is None:
check_all(api, lpaths[0], multi, permissive=True) # continue
check_all(api, lpaths[1], multi, permissive=True) # check_all(api, lpaths[0], multi, permissive=True)
check_all(api, lpaths[2], multi, permissive=True, extra_properties=['hidden']) # check_all(api, lpaths[1], multi, permissive=True)
if len(lpaths) == 6: # check_all(api, lpaths[2], multi, permissive=True, extra_properties=['hidden'])
check_all(api, lpaths[3], multi, permissive=True) # if len(lpaths) == 6:
check_all(api, lpaths[4], multi, permissive=True) # check_all(api, lpaths[3], multi, permissive=True)
check_all(api, lpaths[5], multi, permissive=True, extra_properties=['hidden']) # check_all(api, lpaths[4], multi, permissive=True)
# check_all(api, lpaths[5], multi, permissive=True, extra_properties=['hidden'])

View File

@ -2,7 +2,7 @@
from .autopath import do_autopath from .autopath import do_autopath
do_autopath() do_autopath()
from tiramisu.value import Multi #from tiramisu.value import Multi
from tiramisu.option import IntOption, StrOption, OptionDescription from tiramisu.option import IntOption, StrOption, OptionDescription
from tiramisu.config import Config from tiramisu.config import Config
from tiramisu.error import ConfigError, PropertiesOptionError from tiramisu.error import ConfigError, PropertiesOptionError
@ -12,33 +12,6 @@ import weakref
from py.test import raises from py.test import raises
def test_multi():
i = IntOption('int', '', multi=True)
o = OptionDescription('od', '', [i])
c = Config(o)
multi = Multi([1, 2, 3], weakref.ref(c), i, 'int')
raises(ValueError, "Multi([1,2,3], c, i, 'int')")
raises(ValueError, "Multi(multi, weakref.ref(c), i, 'int')")
assert c is multi._getcontext()
del(c)
raises(ConfigError, "multi._getcontext()")
def test_multi_unique():
i = IntOption('int', '', multi=True, unique=True)
o = OptionDescription('od', '', [i])
c = Config(o)
assert c.int == []
c.int = [0]
assert c.int == [0]
raises(ValueError, "c.int = [0, 0]")
raises(ValueError, "c.int = [1, 0, 2, 3, 4, 5, 6, 0, 7]")
raises(ValueError, "c.int.append(0)")
raises(ValueError, "c.int.extend([1, 2, 1, 3])")
raises(ValueError, "c.int.extend([1, 2, 0, 3])")
c.int.extend([4, 5, 6])
def test_non_valid_multi(): def test_non_valid_multi():
raises(ValueError, "IntOption('int', '', multi='string')") raises(ValueError, "IntOption('int', '', multi='string')")
raises(ValueError, "IntOption('int', '', multi=True, unique='string')") raises(ValueError, "IntOption('int', '', multi=True, unique='string')")
@ -46,21 +19,3 @@ def test_non_valid_multi():
def test_non_multi_unique(): def test_non_multi_unique():
raises(ValueError, "IntOption('int', '', unique=True)") raises(ValueError, "IntOption('int', '', unique=True)")
def test_multi_none():
s = StrOption('str', '', multi=True)
o = OptionDescription('od', '', [s])
c = Config(o)
c.read_only()
assert c.str == []
c.read_write()
c.str.append(None)
assert c.str == [None]
c.read_only()
raises(PropertiesOptionError, "c.str")
c.read_write()
c.str = ['']
assert c.str == ['']
c.read_only()
raises(PropertiesOptionError, "c.str")

View File

@ -5,7 +5,7 @@ do_autopath()
from tiramisu.setting import groups, owners from tiramisu.setting import groups, owners
from tiramisu.config import Config, MetaConfig from tiramisu.config import Config, MetaConfig
from tiramisu.option import StrOption, IntOption, OptionDescription, submulti, MasterSlaves from tiramisu.option import StrOption, IntOption, OptionDescription, submulti, MasterSlaves
from tiramisu.value import SubMulti, Multi #from tiramisu.value import SubMulti, Multi
from tiramisu.error import SlaveError from tiramisu.error import SlaveError
from py.test import raises from py.test import raises
@ -28,7 +28,7 @@ def return_list2(value=None):
def test_submulti(): def test_submulti():
multi = StrOption('multi', '', multi=submulti) multi = StrOption('multi', '', multi=submulti)
multi2 = StrOption('multi2', '', default_multi='yes', multi=submulti) multi2 = StrOption('multi2', '', default_multi=['yes'], multi=submulti)
multi3 = StrOption('multi3', '', default=[['yes']], multi=submulti) multi3 = StrOption('multi3', '', default=[['yes']], multi=submulti)
od = OptionDescription('od', '', [multi, multi2, multi3]) od = OptionDescription('od', '', [multi, multi2, multi3])
cfg = Config(od) cfg = Config(od)
@ -43,314 +43,6 @@ def test_submulti():
assert cfg.getowner(multi) == owners.default assert cfg.getowner(multi) == owners.default
def test_append_submulti():
multi = StrOption('multi', '', multi=submulti)
multi2 = StrOption('multi2', '', default_multi='yes', multi=submulti)
multi3 = StrOption('multi3', '', default=[['yes']], multi=submulti)
od = OptionDescription('od', '', [multi, multi2, multi3])
cfg = Config(od)
owner = cfg.cfgimpl_get_settings().getowner()
assert cfg.multi == []
assert cfg.getowner(multi) == owners.default
cfg.multi.append()
assert cfg.getowner(multi) == owner
assert cfg.multi == [[]]
cfg.multi.append(['no'])
assert cfg.multi == [[], ['no']]
#
assert cfg.multi2 == []
assert cfg.getowner(multi2) == owners.default
cfg.multi2.append()
assert cfg.getowner(multi2) == owner
assert cfg.multi2 == [['yes']]
cfg.multi2.append(['no'])
assert cfg.multi2 == [['yes'], ['no']]
#
assert cfg.multi3 == [['yes']]
assert cfg.getowner(multi3) == owners.default
cfg.multi3.append()
assert cfg.getowner(multi3) == owner
assert cfg.multi3 == [['yes'], []]
cfg.multi3.append(['no'])
assert cfg.multi3 == [['yes'], [], ['no']]
def test_append_unvalide_submulti():
multi = StrOption('multi', '', multi=submulti)
multi2 = StrOption('multi2', '', default_multi='yes', multi=submulti)
multi3 = StrOption('multi3', '', default=[['yes']], multi=submulti)
od = OptionDescription('od', '', [multi, multi2, multi3])
cfg = Config(od)
assert cfg.multi == []
assert cfg.getowner(multi) == owners.default
raises(ValueError, "cfg.multi.append(1)")
assert cfg.multi == []
assert cfg.getowner(multi) == owners.default
#
assert cfg.multi2 == []
raises(ValueError, "cfg.multi2.append('no')")
assert cfg.getowner(multi) == owners.default
assert cfg.multi2 == []
#
assert cfg.multi3 == [['yes']]
assert cfg.getowner(multi3) == owners.default
raises(ValueError, "cfg.multi3[0].append(1)")
assert cfg.multi3 == [['yes']]
assert cfg.getowner(multi3) == owners.default
raises(ValueError, "cfg.multi3[0].append([])")
assert cfg.multi3 == [['yes']]
assert cfg.getowner(multi3) == owners.default
def test_pop_submulti():
multi = StrOption('multi', '', multi=submulti)
multi2 = StrOption('multi2', '', default_multi='yes', multi=submulti)
multi3 = StrOption('multi3', '', default=[['yes']], multi=submulti)
od = OptionDescription('od', '', [multi, multi2, multi3])
cfg = Config(od)
owner = cfg.cfgimpl_get_settings().getowner()
assert cfg.multi == []
assert cfg.getowner(multi3) == owners.default
cfg.multi = [['no', 'yes'], ['peharps']]
assert cfg.getowner(multi) == owner
assert cfg.multi == [['no', 'yes'], ['peharps']]
cfg.multi[0].pop(1)
assert cfg.multi == [['no'], ['peharps']]
cfg.multi[0].pop(0)
assert cfg.multi == [[], ['peharps']]
cfg.multi.pop(1)
assert cfg.multi == [[]]
cfg.multi.pop(0)
assert cfg.multi == []
#
assert cfg.multi3 == [['yes']]
assert cfg.getowner(multi3) == owners.default
cfg.multi3.pop(0)
assert cfg.getowner(multi) == owner
assert cfg.multi3 == []
del(cfg.multi3)
assert cfg.getowner(multi3) == owners.default
cfg.multi3[0].pop(0)
assert cfg.getowner(multi3) == owner
assert cfg.multi3 == [[]]
def test_sort_submulti():
multi = StrOption('multi', '', multi=submulti)
multi2 = StrOption('multi2', '', default_multi='yes', multi=submulti)
multi3 = StrOption('multi3', '', default=[['yes']], multi=submulti)
od = OptionDescription('od', '', [multi, multi2, multi3])
cfg = Config(od)
owner = cfg.cfgimpl_get_settings().getowner()
assert cfg.multi == []
assert cfg.getowner(multi) == owners.default
cfg.multi.sort()
assert cfg.getowner(multi) == owner
cfg.multi = [['no', 'yes'], ['peharps']]
cfg.multi.sort()
assert cfg.multi == [['no', 'yes'], ['peharps']]
cfg.multi.sort(reverse=True)
assert cfg.multi == [['peharps'], ['no', 'yes']]
cfg.multi[1].sort(reverse=True)
assert cfg.multi == [['peharps'], ['yes', 'no']]
cfg.multi[1].sort()
assert cfg.multi == [['peharps'], ['no', 'yes']]
#
assert cfg.multi3 == [['yes']]
assert cfg.getowner(multi3) == owners.default
cfg.multi3.sort()
assert cfg.getowner(multi) == owner
assert cfg.multi3 == [['yes']]
del(cfg.multi3)
assert cfg.getowner(multi3) == owners.default
cfg.multi3[0].sort()
assert cfg.getowner(multi) == owner
assert cfg.multi3 == [['yes']]
def test_reverse_submulti():
multi = StrOption('multi', '', multi=submulti)
multi2 = StrOption('multi2', '', default_multi='yes', multi=submulti)
multi3 = StrOption('multi3', '', default=[['yes']], multi=submulti)
od = OptionDescription('od', '', [multi, multi2, multi3])
cfg = Config(od)
owner = cfg.cfgimpl_get_settings().getowner()
assert cfg.multi == []
assert cfg.getowner(multi) == owners.default
cfg.multi.reverse()
assert cfg.getowner(multi) == owner
cfg.multi = [['no', 'yes'], ['peharps']]
cfg.multi.reverse()
assert cfg.multi == [['peharps'], ['no', 'yes']]
cfg.multi[1].reverse()
assert cfg.multi == [['peharps'], ['yes', 'no']]
#
assert cfg.multi3 == [['yes']]
assert cfg.getowner(multi3) == owners.default
cfg.multi3.reverse()
assert cfg.getowner(multi) == owner
assert cfg.multi3 == [['yes']]
del(cfg.multi3)
assert cfg.getowner(multi3) == owners.default
cfg.multi3[0].reverse()
assert cfg.getowner(multi) == owner
assert cfg.multi3 == [['yes']]
def test_insert_submulti():
multi = StrOption('multi', '', multi=submulti)
multi2 = StrOption('multi2', '', default_multi='yes', multi=submulti)
multi3 = StrOption('multi3', '', default=[['yes']], multi=submulti)
od = OptionDescription('od', '', [multi, multi2, multi3])
cfg = Config(od)
owner = cfg.cfgimpl_get_settings().getowner()
assert cfg.multi == []
assert cfg.getowner(multi) == owners.default
cfg.multi.insert(0, ['no'])
assert cfg.getowner(multi) == owner
assert cfg.multi == [['no']]
assert isinstance(cfg.multi, Multi)
assert isinstance(cfg.multi[0], SubMulti)
#
assert cfg.multi3 == [['yes']]
assert cfg.getowner(multi3) == owners.default
cfg.multi3.insert(1, [])
assert cfg.getowner(multi3) == owner
assert cfg.multi3 == [['yes'], []]
cfg.multi3.insert(0, ['no'])
assert cfg.multi3 == [['no'], ['yes'], []]
del(cfg.multi3)
assert cfg.getowner(multi3) == owners.default
cfg.multi3[0].insert(0, 'no')
assert cfg.getowner(multi3) == owner
assert cfg.multi3 == [['no', 'yes']]
def test_insert_unvalide_submulti():
multi = StrOption('multi', '', multi=submulti)
multi2 = StrOption('multi2', '', default_multi='yes', multi=submulti)
multi3 = StrOption('multi3', '', default=[['yes']], multi=submulti)
od = OptionDescription('od', '', [multi, multi2, multi3])
cfg = Config(od)
assert cfg.multi == []
assert cfg.getowner(multi) == owners.default
raises(ValueError, "cfg.multi.insert(0, 1)")
assert cfg.multi == []
assert cfg.getowner(multi) == owners.default
#
assert cfg.multi3 == [['yes']]
assert cfg.getowner(multi3) == owners.default
raises(ValueError, "cfg.multi3[0].insert(0, 1)")
assert cfg.multi3 == [['yes']]
assert cfg.getowner(multi3) == owners.default
def test_extend_submulti():
multi = StrOption('multi', '', multi=submulti)
multi2 = StrOption('multi2', '', default_multi='yes', multi=submulti)
multi3 = StrOption('multi3', '', default=[['yes']], multi=submulti)
od = OptionDescription('od', '', [multi, multi2, multi3])
cfg = Config(od)
owner = cfg.cfgimpl_get_settings().getowner()
assert cfg.multi == []
assert cfg.getowner(multi) == owners.default
cfg.multi.extend([['no']])
assert cfg.getowner(multi) == owner
assert cfg.multi == [['no']]
assert isinstance(cfg.multi, Multi)
assert isinstance(cfg.multi[0], SubMulti)
#
assert cfg.multi3 == [['yes']]
assert cfg.getowner(multi3) == owners.default
cfg.multi3.extend([[]])
assert cfg.getowner(multi3) == owner
assert cfg.multi3 == [['yes'], []]
cfg.multi3.extend([['no']])
assert cfg.multi3 == [['yes'], [], ['no']]
del(cfg.multi3)
assert cfg.getowner(multi3) == owners.default
cfg.multi3[0].extend(['no'])
assert cfg.getowner(multi3) == owner
assert cfg.multi3 == [['yes', 'no']]
def test_extend_unvalide_submulti():
multi = StrOption('multi', '', multi=submulti)
multi2 = StrOption('multi2', '', default_multi='yes', multi=submulti)
multi3 = StrOption('multi3', '', default=[['yes']], multi=submulti)
od = OptionDescription('od', '', [multi, multi2, multi3])
cfg = Config(od)
assert cfg.multi == []
assert cfg.getowner(multi) == owners.default
raises(ValueError, "cfg.multi.extend([[1]])")
assert cfg.multi == []
assert cfg.getowner(multi) == owners.default
#
assert cfg.multi3 == [['yes']]
assert cfg.getowner(multi3) == owners.default
raises(ValueError, "cfg.multi3[0].extend([1])")
assert cfg.multi3 == [['yes']]
assert cfg.getowner(multi3) == owners.default
def test_callback_submulti_str():
multi = StrOption('multi', '', multi=submulti, callback=return_val)
od = OptionDescription('od', '', [multi])
cfg = Config(od)
cfg.read_write()
owner = cfg.cfgimpl_get_settings().getowner()
assert cfg.getowner(multi) == owners.default
assert cfg.multi == [['val']]
cfg.multi.append()
assert cfg.getowner(multi) == owner
assert cfg.multi == [['val'], ['val']]
del(cfg.multi)
assert cfg.getowner(multi) == owners.default
cfg.multi[0].append()
assert cfg.getowner(multi) == owner
assert cfg.multi == [['val', 'val']]
def test_callback_submulti_list():
multi = StrOption('multi', '', multi=submulti, callback=return_list)
od = OptionDescription('od', '', [multi])
cfg = Config(od)
cfg.read_write()
owner = cfg.cfgimpl_get_settings().getowner()
assert cfg.multi == [['val', 'val']]
assert cfg.getowner(multi) == owners.default
cfg.multi.append()
assert cfg.getowner(multi) == owner
assert cfg.multi == [['val', 'val'], ['val', 'val']]
cfg.multi.append()
assert cfg.multi == [['val', 'val'], ['val', 'val'], ['val', 'val']]
del(cfg.multi)
assert cfg.getowner(multi) == owners.default
cfg.multi[0].append()
assert cfg.getowner(multi) == owner
assert cfg.multi == [['val', 'val', None]]
def test_callback_submulti_list_list():
multi = StrOption('multi', '', multi=submulti, callback=return_list2)
od = OptionDescription('od', '', [multi])
cfg = Config(od)
cfg.read_write()
owner = cfg.cfgimpl_get_settings().getowner()
assert cfg.multi == [['val', 'val']]
assert cfg.getowner(multi) == owners.default
cfg.multi.append()
assert cfg.getowner(multi) == owner
assert cfg.multi == [['val', 'val'], []]
del(cfg.multi)
assert cfg.getowner(multi) == owners.default
cfg.multi[0].append()
assert cfg.getowner(multi) == owner
assert cfg.multi == [['val', 'val', None]]
del(cfg.multi)
cfg.multi.append()
#FIXME multi sur une master #FIXME multi sur une master
@ -371,35 +63,6 @@ def test_groups_with_master_in_config_submulti():
assert interface1.impl_get_group_type() == groups.master assert interface1.impl_get_group_type() == groups.master
def test_values_with_master_and_slaves_submulti():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=submulti)
interface1 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
#interface1.impl_set_group_type(groups.master)
maconfig = OptionDescription('toto', '', [interface1])
cfg = Config(maconfig)
cfg.read_write()
owner = cfg.cfgimpl_get_settings().getowner()
assert interface1.impl_get_group_type() == groups.master
assert cfg.getowner(ip_admin_eth0) == owners.default
assert cfg.getowner(netmask_admin_eth0) == owners.default
assert cfg.ip_admin_eth0.netmask_admin_eth0 == []
cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
assert cfg.ip_admin_eth0.ip_admin_eth0 == ["192.168.230.145"]
assert cfg.ip_admin_eth0.netmask_admin_eth0 == [[]]
assert cfg.getowner(ip_admin_eth0) == owner
assert cfg.getowner(netmask_admin_eth0) == owners.default
cfg.ip_admin_eth0.ip_admin_eth0 = ["192.168.230.145", "192.168.230.147"]
assert cfg.ip_admin_eth0.netmask_admin_eth0 == [[], []]
raises(SlaveError, 'cfg.ip_admin_eth0.netmask_admin_eth0.append(None)')
raises(SlaveError, 'cfg.ip_admin_eth0.netmask_admin_eth0.pop(0)')
cfg.ip_admin_eth0.netmask_admin_eth0[0].append('255.255.255.0')
assert cfg.ip_admin_eth0.netmask_admin_eth0 == [['255.255.255.0'], []]
cfg.ip_admin_eth0.netmask_admin_eth0[0].pop(0)
assert cfg.ip_admin_eth0.netmask_admin_eth0 == [[], []]
raises(ValueError, 'cfg.ip_admin_eth0.netmask_admin_eth0 = ["255.255.255.0", "255.255.255.0"]')
def test_reset_values_with_master_and_slaves_submulti(): def test_reset_values_with_master_and_slaves_submulti():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True) ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=submulti) netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=submulti)
@ -663,54 +326,3 @@ def test_callback_submulti():
assert cfg.getowner(multi2) == owners.default assert cfg.getowner(multi2) == owners.default
assert cfg.multi == [['val']] assert cfg.multi == [['val']]
assert cfg.multi2 == [['val']] assert cfg.multi2 == [['val']]
def test_submulti_unique():
i = IntOption('int', '', multi=submulti, unique=True)
o = OptionDescription('od', '', [i])
c = Config(o)
assert c.int == []
c.int = [[0]]
assert c.int == [[0]]
raises(ValueError, "c.int = [[0, 0]]")
c.int = [[0], [0]]
raises(ValueError, "c.int[0] = [1, 0, 2, 3, 4, 5, 6, 0, 7]")
raises(ValueError, "c.int[0].append(0)")
raises(ValueError, "c.int[0].extend([1, 2, 1, 3])")
raises(ValueError, "c.int[0].extend([1, 2, 0, 3])")
c.int[0].extend([4, 5, 6])
def test_multi_submulti_meta():
multi = StrOption('multi', '', multi=submulti)
od = OptionDescription('od', '', [multi])
conf1 = Config(od, session_id='conf1')
conf1.read_write()
conf2 = Config(od, session_id='conf2')
conf2.read_write()
meta = MetaConfig([conf1, conf2])
meta.read_write()
meta.multi = [['val']]
assert meta.multi == [['val']]
multi = conf1.multi[0]
multi.append()
assert conf1.multi == [['val', None]]
assert meta.multi == [['val']]
def test_multi_submulti_meta_no_cache():
multi = StrOption('multi', '', multi=submulti)
od = OptionDescription('od', '', [multi])
conf1 = Config(od, session_id='conf1_1')
conf1.read_write()
conf2 = Config(od, session_id='conf2_1')
conf2.read_write()
meta = MetaConfig([conf1, conf2])
meta.read_write()
meta.cfgimpl_get_settings().remove('cache')
meta.multi = [['val']]
assert meta.multi == [['val']]
multi = conf1.multi[0]
multi.append()
assert conf1.multi == [['val', None]]
assert meta.multi == [['val']]

View File

@ -35,6 +35,7 @@ class CommonTiramisu(object):
path, path,
index, index,
config, config,
setting_properties,
force_permissive, force_permissive,
force_unrestraint): force_unrestraint):
self.opt = opt self.opt = opt
@ -43,6 +44,7 @@ class CommonTiramisu(object):
if self.slave_need_index: if self.slave_need_index:
self._test_slave_index() self._test_slave_index()
self.config = config self.config = config
self.setting_properties = setting_properties
self.force_permissive = force_permissive self.force_permissive = force_permissive
self.force_unrestraint = force_unrestraint self.force_unrestraint = force_unrestraint
if not self.allow_unrestraint: if not self.allow_unrestraint:
@ -81,11 +83,19 @@ class TiramisuOptionOption(CommonTiramisu):
allow_unrestraint = True allow_unrestraint = True
slave_need_index = False slave_need_index = False
def __init__(self, opt, path, index, config, force_permissive, force_unrestraint): def __init__(self,
opt,
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint):
super(TiramisuOptionOption, self).__init__(opt, super(TiramisuOptionOption, self).__init__(opt,
path, path,
index, index,
config, config,
setting_properties,
force_permissive, force_permissive,
force_unrestraint) force_unrestraint)
if config: if config:
@ -117,11 +127,19 @@ class TiramisuOptionOption(CommonTiramisu):
class TiramisuOptionOwner(CommonTiramisu): class TiramisuOptionOwner(CommonTiramisu):
"""manager option's owner""" """manager option's owner"""
def __init__(self, opt, path, index, config, force_permissive, force_unrestraint): def __init__(self,
opt,
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint):
super(TiramisuOptionOwner, self).__init__(opt, super(TiramisuOptionOwner, self).__init__(opt,
path, path,
index, index,
config, config,
setting_properties,
force_permissive, force_permissive,
force_unrestraint) force_unrestraint)
if config: if config:
@ -135,9 +153,8 @@ class TiramisuOptionOwner(CommonTiramisu):
def isdefault(self): def isdefault(self):
"""is option has defaut value""" """is option has defaut value"""
#FIXME isdefault for slave should have index!
#FIXME should not be here, just for check property
return self.values.is_default_owner(self.opt, return self.values.is_default_owner(self.opt,
index=self.index,
force_permissive=self.force_permissive) force_permissive=self.force_permissive)
def set(self, owner): def set(self, owner):
@ -158,11 +175,19 @@ class TiramisuOptionProperty(CommonTiramisu):
#allow_unrestraint = True #allow_unrestraint = True
slave_need_index = False slave_need_index = False
def __init__(self, opt, path, index, config, force_permissive, force_unrestraint): def __init__(self,
opt,
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint):
super(TiramisuOptionProperty, self).__init__(opt, super(TiramisuOptionProperty, self).__init__(opt,
path, path,
index, index,
config, config,
setting_properties,
force_permissive, force_permissive,
force_unrestraint) force_unrestraint)
if config: if config:
@ -170,7 +195,10 @@ class TiramisuOptionProperty(CommonTiramisu):
def get(self): def get(self):
self._test_slave_index() self._test_slave_index()
return self.settings.getproperties(self.opt, self.path, index=self.index, obj=False) return self.settings.getproperties(self.opt,
self.path,
index=self.index,
obj=False)
def set(self, properties): def set(self, properties):
"""set properties for a specified option""" """set properties for a specified option"""
@ -189,11 +217,19 @@ class TiramisuOptionPermissive(CommonTiramisu):
allow_unrestraint = True allow_unrestraint = True
slave_need_index = False slave_need_index = False
def __init__(self, opt, path, index, config, force_permissive, force_unrestraint): def __init__(self,
opt,
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint):
super(TiramisuOptionPermissive, self).__init__(opt, super(TiramisuOptionPermissive, self).__init__(opt,
path, path,
index, index,
config, config,
setting_properties,
force_permissive, force_permissive,
force_unrestraint) force_unrestraint)
if config: if config:
@ -201,8 +237,7 @@ class TiramisuOptionPermissive(CommonTiramisu):
def get(self): def get(self):
"""get permissive value for a specified path""" """get permissive value for a specified path"""
setting_properties = self.settings.getproperties(None, None, obj=False) return self.settings.getpermissive(self.setting_properties, self.path)
return self.settings.getpermissive(setting_properties, self.path)
def set(self, permissive): def set(self, permissive):
self.settings.setpermissive(permissive, opt=self.opt, path=self.path) self.settings.setpermissive(permissive, opt=self.opt, path=self.path)
@ -217,25 +252,28 @@ class TiramisuOptionPermissive(CommonTiramisu):
class TiramisuOptionValue(CommonTiramisu): class TiramisuOptionValue(CommonTiramisu):
"""manager option's value""" """manager option's value"""
def __init__(self, opt, path, index, config, force_permissive, force_unrestraint): def __init__(self,
opt,
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint):
super(TiramisuOptionValue, self).__init__(opt, super(TiramisuOptionValue, self).__init__(opt,
path, path,
index, index,
config, config,
setting_properties,
force_permissive, force_permissive,
force_unrestraint) force_unrestraint)
def append(self, value=undefined):
if not self.opt.impl_is_master_slaves('master'):
raise APIError('append is only allowed for a master')
multi = self.config.getattr(self.path,
force_permissive=self.force_permissive)
multi.append(value)
self.set(multi)
def get(self): def get(self):
settings = self.config.cfgimpl_get_settings()
value = self.config.getattr(self.path, value = self.config.getattr(self.path,
index=self.index, index=self.index,
setting_properties=self.setting_properties,
force_permissive=self.force_permissive) force_permissive=self.force_permissive)
if isinstance(value, Multi): if isinstance(value, Multi):
value = list(value) value = list(value)
@ -247,45 +285,53 @@ class TiramisuOptionValue(CommonTiramisu):
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.opt,
self.path, self.path,
True, idx)
idx,
undefined,
True)
else: else:
if value == undefined: if value == undefined:
value = values._getdefaultvalue(self.opt, value = values.getdefaultvalue(self.opt,
self.path, self.path,
True, self.index)
self.index,
undefined,
True)
self.config.setattr(self.path, self.config.setattr(self.path,
value, value,
index=self.index, index=self.index,
force_permissive=self.force_permissive) force_permissive=self.force_permissive)
def pop(self, index):
"""pop value for a specified master values
"""
self.config.delattr(self.path,
index=index,
setting_properties=self.setting_properties,
force_permissive=self.force_permissive)
def reset(self): def reset(self):
"""reset value for a value""" """reset value for a value"""
if self.index is None: self.config.delattr(self.path,
self.config.cfgimpl_get_values().reset(self.opt, index=self.index,
path=self.path, setting_properties=self.setting_properties,
force_permissive=self.force_permissive) force_permissive=self.force_permissive)
else:
#FIXME ... _p_ ...
self.config.cfgimpl_get_values()._p_.resetvalue_index(self.path, self.index)
class TiramisuOption(object): class TiramisuOption(object):
icon = '\u2937' icon = '\u2937'
tmpl_help = ' {} {}: {}' tmpl_help = ' {} {}: {}'
def __init__(self, opt, path, index, config, force_permissive=False, force_unrestraint=False): def __init__(self,
opt,
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint):
self.opt = opt self.opt = opt
self.path = path self.path = path
self.index = index self.index = index
self.config = config self.config = config
self.setting_properties = setting_properties
self.force_permissive = force_permissive self.force_permissive = force_permissive
self.force_unrestraint = force_unrestraint self.force_unrestraint = force_unrestraint
self.registers = {} self.registers = {}
@ -310,6 +356,7 @@ class TiramisuOption(object):
self.path, self.path,
self.index, self.index,
self.config, self.config,
self.setting_properties,
self.force_permissive, self.force_permissive,
self.force_unrestraint) self.force_unrestraint)
elif subfunc == 'help': elif subfunc == 'help':
@ -322,18 +369,25 @@ class TiramisuAPI(object):
icon = '\u2937' icon = '\u2937'
tmpl_help = ' {} {}: {}' tmpl_help = ' {} {}: {}'
def __init__(self, config, force_permissive=False, force_unrestraint=False): def __init__(self,
config,
force_permissive=False,
force_unrestraint=False):
self.config = config self.config = config
self.force_permissive = force_permissive self.force_permissive = force_permissive
self.force_unrestraint = force_unrestraint self.force_unrestraint = force_unrestraint
settings = self.config.cfgimpl_get_settings()
#FIXME ? #FIXME ?
self.config.read_write() self.config.read_write()
self.config.cfgimpl_get_settings().setpermissive(('hidden',)) settings.setpermissive(('hidden',))
#/FIXME ? #/FIXME ?
def option(self, path, index=None): def option(self, path, index=None):
validate = not self.force_unrestraint validate = not self.force_unrestraint
settings = self.config.cfgimpl_get_settings()
setting_properties = settings.getcontextproperties()
opt = self.config.unwrap_from_path(path, opt = self.config.unwrap_from_path(path,
setting_properties=setting_properties,
validate=validate, validate=validate,
validate_properties=validate, validate_properties=validate,
force_permissive=self.force_permissive, force_permissive=self.force_permissive,
@ -344,14 +398,19 @@ class TiramisuAPI(object):
path, path,
index, index,
self.config, self.config,
force_permissive=self.force_permissive, setting_properties,
force_unrestraint=self.force_unrestraint) self.force_permissive,
self.force_unrestraint)
def __getattr__(self, subfunc): def __getattr__(self, subfunc):
if subfunc == 'forcepermissive': if subfunc == 'forcepermissive':
return TiramisuAPI(self.config, force_permissive=True, force_unrestraint=self.force_unrestraint) return TiramisuAPI(self.config,
force_permissive=True,
force_unrestraint=self.force_unrestraint)
elif subfunc == 'unrestraint': elif subfunc == 'unrestraint':
return TiramisuAPI(self.config, force_permissive=self.force_permissive, force_unrestraint=True) return TiramisuAPI(self.config,
force_permissive=self.force_permissive,
force_unrestraint=True)
elif subfunc == 'help': elif subfunc == 'help':
return self._help() return self._help()
else: else:

View File

@ -31,7 +31,7 @@ from .option import OptionDescription, Option, SymLinkOption, \
from .option.baseoption import valid_name from .option.baseoption import valid_name
from .setting import groups, Settings, default_encoding, undefined from .setting import groups, Settings, default_encoding, undefined
from .storage import get_storages, set_storage, 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 _
@ -45,9 +45,19 @@ class SubConfig(object):
on-demand. A Config is also a SubConfig. on-demand. A Config is also a SubConfig.
Root Config is call context below Root Config is call context below
""" """
__slots__ = ('_impl_context', '_impl_descr', '_impl_path') __slots__ = ('_impl_context',
'_impl_descr',
'_impl_path',
'_impl_setting_properties',
'_impl_length')
def __init__(self, descr, context, subpath=None): def __init__(self,
descr,
context,
setting_properties,
validate,
force_permissive,
subpath=None):
""" Configuration option management master class """ Configuration option management master class
:param descr: describes the configuration schema :param descr: describes the configuration schema
@ -63,13 +73,19 @@ class SubConfig(object):
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}'
).format(type(descr))) ).format(type(descr)))
self._impl_descr = descr self._impl_descr = descr
# sub option descriptions # sub option descriptions
if not isinstance(context, weakref.ReferenceType): # pragma: optional cover if not isinstance(context, weakref.ReferenceType): # pragma: optional cover
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:
self._impl_setting_properties = setting_properties
if descr.impl_get_group_type() == groups.master:
self._impl_length = descr.get_length(context().cfgimpl_get_values(),
validate=validate,
force_permissive=force_permissive)
def cfgimpl_reset_cache(self, def cfgimpl_reset_cache(self,
only_expired=False, only_expired=False,
@ -144,17 +160,20 @@ class SubConfig(object):
else: else:
reset_all_cache() reset_all_cache()
def cfgimpl_get_home_by_path(self, path, force_permissive=False, def cfgimpl_get_home_by_path(self,
returns_raise=False, _setting_properties=undefined, path,
validate_properties=True): setting_properties,
validate_properties=True,
force_permissive=False,
returns_raise=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]:
self = self.getattr(step, self = self.getattr(step,
force_permissive=force_permissive, force_permissive=force_permissive,
returns_raise=returns_raise,
validate_properties=validate_properties, validate_properties=validate_properties,
_setting_properties=_setting_properties) returns_raise=returns_raise,
setting_properties=setting_properties)
if isinstance(self, Exception): if isinstance(self, Exception):
return self, None return self, None
return self, path[-1] return self, path[-1]
@ -269,62 +288,111 @@ class SubConfig(object):
# attribute methods # attribute methods
def __setattr__(self, name, value): def __setattr__(self, name, value):
"attribute notation mechanism for the setting of the value of an option" "attribute notation mechanism for the setting of the value of an option"
self.setattr(name, value) self.setattr(name,
value)
def _setattr(self, name, value, force_permissive=False, not_raises=False): def setattr(self,
"""use setattr instead of _setattr name,
""" value,
self.setattr(name, value, force_permissive=force_permissive, force_permissive=False,
not_raises=not_raises) not_raises=False,
index=None,
setting_properties=undefined,
_commit=True):
def setattr(self, name, value, force_permissive=False, not_raises=False, index=None,
_setting_properties=undefined, _commit=True):
if name.startswith('_impl_'): if name.startswith('_impl_'):
return object.__setattr__(self, name, value) return object.__setattr__(self,
name,
value)
context = self._cfgimpl_get_context() context = self._cfgimpl_get_context()
if _setting_properties is undefined: if setting_properties is undefined:
_setting_properties = context.cfgimpl_get_settings()._getproperties(read_write=True) setting_properties = context.cfgimpl_get_settings()._getproperties(read_write=True)
if '.' in name: # pragma: optional cover if '.' in name: # pragma: optional cover
homeconfig, name = self.cfgimpl_get_home_by_path(name, self, name = self.cfgimpl_get_home_by_path(name,
force_permissive=force_permissive, force_permissive=force_permissive,
_setting_properties=_setting_properties) setting_properties=setting_properties)
return homeconfig.setattr(name, value, force_permissive,
not_raises, index=index,
_setting_properties=_setting_properties,
_commit=_commit)
child = self.cfgimpl_get_description().__getattr__(name, child = self.cfgimpl_get_description().__getattr__(name,
context=context) context=context)
if isinstance(child, OptionDescription) or isinstance(child, SynDynOptionDescription): if isinstance(child, (OptionDescription, 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._is_symlinkoption() and \ elif child._is_symlinkoption() and \
not isinstance(child, DynSymLinkOption): # pragma: no dynoptiondescription cover not isinstance(child, DynSymLinkOption): # pragma: no dynoptiondescription cover
path = context.cfgimpl_get_description().impl_get_path_by_opt( raise TypeError(_("can't assign to a SymlinkOption"))
child._impl_getopt())
context.setattr(path, value, force_permissive, not_raises, index=index,
_setting_properties=_setting_properties,
_commit=_commit)
else: else:
msg = self.cfgimpl_get_description().impl_validate_value(child, value, self)
if msg is not None:
if not_raises:
return msg
else:
raise msg
subpath = self._get_subpath(name) subpath = self._get_subpath(name)
ret = self.cfgimpl_get_values().setitem(child, value, subpath, return self.cfgimpl_get_values().setitem(child,
force_permissive=force_permissive, value,
not_raises=not_raises, index=index, subpath,
_setting_properties=_setting_properties, force_permissive,
_commit=_commit) not_raises,
if ret is not None: index,
return ret setting_properties,
_commit)
def __delattr__(self, name): def __delattr__(self, name):
self.delattr(name)
def delattr(self,
name,
index=None,
force_permissive=False,
setting_properties=undefined,
validate=True,
not_raises=False):
context = self._cfgimpl_get_context() context = self._cfgimpl_get_context()
child = self.cfgimpl_get_description().__getattr__(name, context) if setting_properties is undefined:
self.cfgimpl_get_values().__delitem__(child) setting_properties = context.cfgimpl_get_settings()._getproperties(read_write=True)
if '.' in name: # pragma: optional cover
self, name = self.cfgimpl_get_home_by_path(name,
force_permissive=force_permissive,
setting_properties=setting_properties)
child = self.cfgimpl_get_description().__getattr__(name,
context=context)
if isinstance(child, (OptionDescription, SynDynOptionDescription)):
raise TypeError(_("can't delete an OptionDescription")) # pragma: optional cover
elif child._is_symlinkoption() and \
not isinstance(child, DynSymLinkOption): # pragma: no dynoptiondescription cover
raise TypeError(_("can't delete a SymlinkOption"))
else:
subpath = self._get_subpath(name)
values = self.cfgimpl_get_values()
if index is not None:
if child.impl_is_master_slaves('master'):
ret = values.reset_master(self,
child,
subpath,
index,
force_permissive,
setting_properties)
elif child.impl_is_master_slaves('slave'):
ret = values.reset_slave(child,
subpath,
index,
setting_properties,
force_permissive=force_permissive,
validate=validate)
else:
raise ValueError(_("can delete value with index only with a master or a slave"))
else:
ret = values.reset(child,
subpath,
setting_properties,
force_permissive=force_permissive,
validate=validate)
if ret:
if not_raises:
return ret
raise ret
def __getattr__(self, name): def __getattr__(self, name):
return self.getattr(name) setting_properties = self.cfgimpl_get_context().cfgimpl_get_settings().getcontextproperties()
return self.getattr(name, setting_properties)
def _getattr(self, name, force_permissive=False, validate=True): # pragma: optional cover
"""use getattr instead of _getattr
"""
return self.getattr(name, force_permissive, validate)
def _get_subpath(self, name): def _get_subpath(self, name):
if self._impl_path is None: if self._impl_path is None:
@ -333,10 +401,15 @@ class SubConfig(object):
subpath = self._impl_path + '.' + name subpath = self._impl_path + '.' + name
return subpath return subpath
def getattr(self, name, force_permissive=False, validate=True, def getattr(self,
_setting_properties=undefined, _self_properties=undefined, index=None, name,
returns_raise=False, returns_option=False, setting_properties,
validate_properties=True): force_permissive=False,
validate=True,
validate_properties=True,
index=None,
returns_raise=False,
returns_option=False):
""" """
attribute notation mechanism for accessing the value of an option attribute notation mechanism for accessing the value of an option
:param name: attribute name :param name: attribute name
@ -346,51 +419,51 @@ class SubConfig(object):
# attribute access by passing a path, # attribute access by passing a path,
# for instance getattr(self, "creole.general.family.adresse_ip_eth0") # for instance getattr(self, "creole.general.family.adresse_ip_eth0")
context = self._cfgimpl_get_context() context = self._cfgimpl_get_context()
if _setting_properties is undefined:
_setting_properties = context.cfgimpl_get_settings()._getproperties(read_write=True)
if '.' in name: if '.' in name:
homeconfig, name = self.cfgimpl_get_home_by_path( homeconfig, name = self.cfgimpl_get_home_by_path(name,
name, force_permissive=force_permissive, force_permissive=force_permissive,
validate_properties=validate_properties, validate_properties=validate_properties,
returns_raise=returns_raise, _setting_properties=_setting_properties) returns_raise=returns_raise,
setting_properties=setting_properties)
if isinstance(homeconfig, Exception): if isinstance(homeconfig, Exception):
cfg = homeconfig cfg = homeconfig
else: else:
cfg = homeconfig.getattr(name, force_permissive=force_permissive, cfg = homeconfig.getattr(name,
force_permissive=force_permissive,
validate=validate, validate=validate,
_setting_properties=_setting_properties, validate_properties=validate_properties,
_self_properties=_self_properties, setting_properties=setting_properties,
index=index, returns_raise=returns_raise, index=index,
validate_properties=validate_properties) returns_raise=returns_raise)
else: else:
option = self.cfgimpl_get_description().__getattr__(name, option = self.cfgimpl_get_description().__getattr__(name,
context=context) context=context)
subpath = self._get_subpath(name) subpath = self._get_subpath(name)
if isinstance(option, DynSymLinkOption): if isinstance(option, DynSymLinkOption):
cfg = self.cfgimpl_get_values()._get_cached_value( cfg = self.cfgimpl_get_values().get_cached_value(option,
option, path=subpath, path=subpath,
validate=validate, validate=validate,
force_permissive=force_permissive, validate_properties=validate_properties,
setting_properties=_setting_properties, force_permissive=force_permissive,
self_properties=_self_properties, setting_properties=setting_properties,
validate_properties=validate_properties, index=index)
index=index)
elif option._is_symlinkoption(): # pragma: no dynoptiondescription cover elif option._is_symlinkoption(): # pragma: no dynoptiondescription cover
path = context.cfgimpl_get_description().impl_get_path_by_opt( path = context.cfgimpl_get_description().impl_get_path_by_opt(option._impl_getopt())
option._impl_getopt()) cfg = context.getattr(path,
cfg = context.getattr(path, validate=validate, validate=validate,
force_permissive=force_permissive,
_setting_properties=_setting_properties,
_self_properties=_self_properties,
validate_properties=validate_properties, validate_properties=validate_properties,
index=index, returns_raise=True) force_permissive=force_permissive,
setting_properties=setting_properties,
index=index,
returns_raise=True)
elif option.impl_is_optiondescription(): elif option.impl_is_optiondescription():
if validate_properties: if setting_properties:
props = self.cfgimpl_get_settings().validate_properties( props = self.cfgimpl_get_settings().validate_properties(option,
option, True, False, path=subpath, True,
force_permissive=force_permissive, False,
self_properties=_self_properties, path=subpath,
setting_properties=_setting_properties) force_permissive=force_permissive,
setting_properties=setting_properties)
if props: if props:
if returns_raise: if returns_raise:
return props return props
@ -398,25 +471,29 @@ class SubConfig(object):
raise props raise props
if returns_option is True: if returns_option is True:
return option return option
return SubConfig(option, self._impl_context, subpath) return SubConfig(option,
self._impl_context,
setting_properties,
validate,
force_permissive,
subpath)
else: else:
if validate: if validate:
ret = self.cfgimpl_get_description().impl_validate(context, ret = self.cfgimpl_get_description().impl_validate(context,
force_permissive, force_permissive,
_setting_properties) setting_properties)
if ret: if ret:
if returns_raise: if returns_raise:
return ret return ret
else: else:
raise ret raise ret
cfg = self.cfgimpl_get_values()._get_cached_value( cfg = self.cfgimpl_get_values().get_cached_value(option,
option, path=subpath, path=subpath,
validate=validate, validate=validate,
force_permissive=force_permissive, validate_properties=validate_properties,
setting_properties=_setting_properties, force_permissive=force_permissive,
self_properties=_self_properties, setting_properties=setting_properties,
validate_properties=validate_properties, index=index)
index=index)
if not returns_raise and isinstance(cfg, Exception): if not returns_raise and isinstance(cfg, Exception):
raise cfg raise cfg
if returns_option is True: if returns_option is True:
@ -473,13 +550,13 @@ class SubConfig(object):
if byvalue is undefined: if byvalue is undefined:
return True return True
value = self.getattr(path, force_permissive=force_permissive, value = self.getattr(path, force_permissive=force_permissive,
_setting_properties=setting_properties, setting_properties=setting_properties,
returns_raise=True) returns_raise=True)
if isinstance(value, Exception): if isinstance(value, Exception):
if isinstance(value, PropertiesOptionError): if isinstance(value, PropertiesOptionError):
return False return False
raise value # pragma: no cover raise value # pragma: no cover
elif isinstance(value, Multi): elif isinstance(value, list):
return byvalue in value return byvalue in value
else: else:
return value == byvalue return value == byvalue
@ -506,7 +583,7 @@ class SubConfig(object):
if byvalue is undefined and check_properties: if byvalue is undefined and check_properties:
value = self.getattr(path, value = self.getattr(path,
force_permissive=force_permissive, force_permissive=force_permissive,
_setting_properties=setting_properties, setting_properties=setting_properties,
returns_raise=True) returns_raise=True)
if isinstance(value, Exception): if isinstance(value, Exception):
if isinstance(value, PropertiesOptionError): if isinstance(value, PropertiesOptionError):
@ -533,9 +610,14 @@ class SubConfig(object):
else: else:
return find_results return find_results
def make_dict(self, flatten=False, _currpath=None, withoption=None, def make_dict(self,
withvalue=undefined, force_permissive=False, flatten=False,
setting_properties=undefined, fullpath=False): _currpath=None,
withoption=None,
withvalue=undefined,
force_permissive=False,
setting_properties=undefined,
fullpath=False):
"""exports the whole config into a `dict`, for example: """exports the whole config into a `dict`, for example:
>>> print cfg.make_dict() >>> print cfg.make_dict()
@ -579,17 +661,20 @@ class SubConfig(object):
raise ValueError(_("make_dict can't filtering with value without " raise ValueError(_("make_dict can't filtering with value without "
"option")) "option"))
if setting_properties is undefined: if setting_properties is undefined:
setting_properties = self.cfgimpl_get_settings()._getproperties( setting_properties = self.cfgimpl_get_settings()._getproperties(read_write=False)
read_write=False)
if withoption is not None: if withoption is not None:
context = self._cfgimpl_get_context() context = self._cfgimpl_get_context()
for path in context._find(bytype=None, byname=withoption, for path in context._find(bytype=None,
byvalue=withvalue, first=False, byname=withoption,
type_='path', _subpath=self.cfgimpl_get_path(False), byvalue=withvalue,
first=False,
type_='path',
_subpath=self.cfgimpl_get_path(False),
force_permissive=force_permissive, force_permissive=force_permissive,
setting_properties=setting_properties): setting_properties=setting_properties):
path = '.'.join(path.split('.')[:-1]) path = '.'.join(path.split('.')[:-1])
opt = context.unwrap_from_path(path, force_permissive=True) opt = context.unwrap_from_path(path,
orce_permissive=True)
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:
@ -624,7 +709,7 @@ class SubConfig(object):
setting_properties, force_permissive=False, fullpath=False): setting_properties, force_permissive=False, fullpath=False):
value = self.getattr(path, value = self.getattr(path,
force_permissive=force_permissive, force_permissive=force_permissive,
_setting_properties=setting_properties, setting_properties=setting_properties,
returns_raise=True) returns_raise=True)
if isinstance(value, Exception): if isinstance(value, Exception):
if not isinstance(value, PropertiesOptionError): # pragma: no cover if not isinstance(value, PropertiesOptionError): # pragma: no cover
@ -689,30 +774,52 @@ class _CommonConfig(SubConfig):
return self.cfgimpl_get_values().getowner(opt, index=index, return self.cfgimpl_get_values().getowner(opt, index=index,
force_permissive=force_permissive) force_permissive=force_permissive)
def unwrap_from_path(self, path, force_permissive=False, index=None, def unwrap_from_path(self,
validate_properties=True, validate=True, path,
_setting_properties=undefined): setting_properties=undefined,
force_permissive=False,
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
:returns: Option() :returns: Option()
""" """
if _setting_properties is undefined:
context = self._cfgimpl_get_context()
_setting_properties = context.cfgimpl_get_settings()._getproperties(read_write=True)
if '.' in path: if '.' in path:
self, path = self.cfgimpl_get_home_by_path(path, self, path = self.cfgimpl_get_home_by_path(path,
validate_properties=validate_properties,
force_permissive=force_permissive, force_permissive=force_permissive,
_setting_properties=_setting_properties) validate_properties=validate_properties,
return self.getattr(path, setting_properties=setting_properties)
validate_properties=validate_properties, if not validate_properties:
validate=validate, return self.cfgimpl_get_description().__getattr__(path,
force_permissive=force_permissive, context=self._cfgimpl_get_context())
index=index, else:
_setting_properties=_setting_properties, option = self.cfgimpl_get_description().__getattr__(path,
returns_option=True) context=self._cfgimpl_get_context())
if not validate_properties:
return option
else:
if index is None and option.impl_is_master_slaves('slave'):
subpath = self._get_subpath(path)
props = self.cfgimpl_get_settings().validate_properties(option,
True,
False,
path=subpath,
force_permissive=force_permissive,
setting_properties=setting_properties)
if props:
raise props
return option
else:
return self.getattr(path,
validate=validate,
force_permissive=force_permissive,
index=index,
setting_properties=setting_properties,
validate_properties=validate_properties,
returns_option=True)
def cfgimpl_get_path(self, dyn=True): def cfgimpl_get_path(self, dyn=True):
return None return None
@ -743,19 +850,17 @@ class _CommonConfig(SubConfig):
def __getstate__(self): def __getstate__(self):
raise NotImplementedError() raise NotImplementedError()
def _gen_fake_values(self, session): def _gen_fake_values(self):
fake_config = Config(self._impl_descr, persistent=False, fake_config = Config(self._impl_descr, persistent=False,
force_values=get_default_values_storages(), force_values=get_default_values_storages(),
force_settings=self.cfgimpl_get_settings()) force_settings=self.cfgimpl_get_settings())
fake_config.cfgimpl_get_values()._p_.importation(self.cfgimpl_get_values()._p_.exportation(session, fake=True)) fake_config.cfgimpl_get_values()._p_.importation(self.cfgimpl_get_values()._p_.exportation(fake=True))
return fake_config return fake_config
def duplicate(self, force_values=None, force_settings=None): def duplicate(self, force_values=None, force_settings=None):
config = Config(self._impl_descr, _duplicate=True, force_values=force_values, config = Config(self._impl_descr, _duplicate=True, force_values=force_values,
force_settings=force_settings) force_settings=force_settings)
session = self.cfgimpl_get_values()._p_.getsession() config.cfgimpl_get_values()._p_.importation(self.cfgimpl_get_values()._p_.exportation())
config.cfgimpl_get_values()._p_.importation(self.cfgimpl_get_values()._p_.exportation(
session))
config.cfgimpl_get_settings()._p_.set_modified_properties(self.cfgimpl_get_settings( config.cfgimpl_get_settings()._p_.set_modified_properties(self.cfgimpl_get_settings(
)._p_.get_modified_properties()) )._p_.get_modified_properties())
config.cfgimpl_get_settings()._pp_.set_modified_permissives(self.cfgimpl_get_settings( config.cfgimpl_get_settings()._pp_.set_modified_permissives(self.cfgimpl_get_settings(
@ -795,7 +900,7 @@ class Config(_CommonConfig):
raise ValueError(_("invalid session ID: {0} for config").format(session_id)) raise ValueError(_("invalid session ID: {0} for config").format(session_id))
self._impl_settings = Settings(self, properties, permissives) self._impl_settings = Settings(self, properties, permissives)
self._impl_values = Values(self, values) self._impl_values = Values(self, values)
super(Config, self).__init__(descr, weakref.ref(self)) super(Config, self).__init__(descr, weakref.ref(self), undefined, True, False)
self._impl_meta = None 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
@ -926,21 +1031,25 @@ class GroupConfig(_CommonConfig):
__repr__ = __str__ __repr__ = __str__
def getattr(self, name, force_permissive=False, validate=True, def getattr(self,
_setting_properties=undefined, _self_properties=undefined, index=None, name,
returns_raise=False, returns_option=False, setting_properties,
validate_properties=True): force_permissive=False,
validate=True,
index=None,
returns_raise=False,
validate_properties=True,
returns_option=False):
for child in self._impl_children: for child in self._impl_children:
if name == child._impl_name: if name == child._impl_name:
return child return child
return super(GroupConfig, self).getattr(name, force_permissive, return super(GroupConfig, self).getattr(name, force_permissive,
validate, validate,
_self_properties=_self_properties,
index=index, index=index,
_setting_properties=_setting_properties, setting_properties=setting_properties,
returns_raise=returns_raise, returns_raise=returns_raise,
returns_option=False, validate_properties=validate_properties,
validate_properties=validate_properties) returns_option=False)
class MetaConfig(GroupConfig): class MetaConfig(GroupConfig):
@ -1000,22 +1109,30 @@ class MetaConfig(GroupConfig):
else: else:
child_value = child.getattr(path) child_value = child.getattr(path)
if force_default or value == child_value: if force_default or value == child_value:
child.cfgimpl_get_values().reset(opt, path=path, child.cfgimpl_get_values().reset(opt,
path,
setting_properties,
validate=False, validate=False,
_setting_properties=setting_properties,
_commit=False) _commit=False)
continue continue
if force_dont_change_value: if force_dont_change_value:
child_value = child.getattr(path, _setting_properties=setting_properties, child_value = child.getattr(path,
setting_properties=setting_properties,
returns_raise=True) returns_raise=True)
if isinstance(child_value, Exception): if isinstance(child_value, Exception):
ret.append(child_value) ret.append(child_value)
elif value != child_value: elif value != child_value:
childret = child.setattr(path, child_value, _commit=False, not_raises=True) childret = child.setattr(path,
child_value,
_commit=False,
not_raises=True)
if childret is not None: # pragma: no cover if childret is not None: # pragma: no cover
ret.append(childret) ret.append(childret)
setret = self.setattr(path, value, _commit=_commit, not_raises=True) setret = self.setattr(path,
value,
_commit=_commit,
not_raises=True)
if setret is not None: if setret is not None:
ret.append(setret) ret.append(setret)
return ret return ret
@ -1024,13 +1141,15 @@ class MetaConfig(GroupConfig):
opt = self.cfgimpl_get_description().impl_get_opt_by_path(path) opt = self.cfgimpl_get_description().impl_get_opt_by_path(path)
setting_properties = self.cfgimpl_get_settings()._getproperties(read_write=False) setting_properties = self.cfgimpl_get_settings()._getproperties(read_write=False)
for child in self._impl_children: for child in self._impl_children:
child.cfgimpl_get_values().reset(opt, path=path, child.cfgimpl_get_values().reset(opt,
path,
setting_properties,
validate=False, validate=False,
_setting_properties=setting_properties,
_commit=False) _commit=False)
self.cfgimpl_get_values().reset(opt, path=path, self.cfgimpl_get_values().reset(opt,
validate=False, path,
_setting_properties=setting_properties) setting_properties,
validate=False)
def new_config(self, session_id, persistent=False): def new_config(self, session_id, persistent=False):
config = Config(self._impl_descr, session_id=session_id, config = Config(self._impl_descr, session_id=session_id,

View File

@ -135,7 +135,7 @@ class Base(object):
def __init__(self, name, doc, requires=None, properties=None, is_multi=False): def __init__(self, name, doc, requires=None, properties=None, is_multi=False):
if not valid_name(name): if not valid_name(name):
raise ValueError(_("invalid name: {0} for option").format(name)) raise ValueError(_('invalid name: "{0}" for option').format(name))
if requires is not None: if requires is not None:
calc_properties, requires = validate_requires_arg(self, is_multi, calc_properties, requires = validate_requires_arg(self, is_multi,
requires, name) requires, name)
@ -654,13 +654,18 @@ class DynSymLinkOption(object):
else: else:
return base_path + '.' + self._dyn return base_path + '.' + self._dyn
def impl_validate(self, value, context=undefined, validate=True, def impl_validate(self,
force_index=None, force_submulti_index=None, is_multi=None, value,
display_error=True, display_warnings=True, multi=None, context=undefined,
validate=True,
force_index=None,
is_multi=None,
display_error=True,
display_warnings=True,
multi=None,
setting_properties=undefined): setting_properties=undefined):
return self._impl_getopt().impl_validate(value, context, validate, return self._impl_getopt().impl_validate(value, context, validate,
force_index, force_index,
force_submulti_index,
current_opt=self, current_opt=self,
is_multi=is_multi, is_multi=is_multi,
display_error=display_error, display_error=display_error,

View File

@ -112,12 +112,23 @@ class Option(OnlyOption):
super(Option, self).__init__(name, doc, requires=requires, super(Option, self).__init__(name, doc, requires=requires,
properties=properties, is_multi=is_multi) properties=properties, is_multi=is_multi)
if is_multi and default_multi is not None: if is_multi and default_multi is not None:
err = self._validate(default_multi) def test_multi_value(value):
if err: err = self._validate(value)
raise ValueError(_("invalid default_multi value {0} " if err:
"for option {1}: {2}").format( raise ValueError(_("invalid default_multi value {0} "
str(default_multi), "for option {1}: {2}").format(
self.impl_getname(), str(err))) str(value),
self.impl_getname(), str(err)))
if _multi is submulti:
if not isinstance(default_multi, list):
raise ValueError(_("invalid default_multi value {0} "
"for option {1}: must be a list for a submulti").format(
str(default_multi),
self.impl_getname()))
for value in default_multi:
test_multi_value(value)
else:
test_multi_value(default_multi)
_setattr(self, '_default_multi', default_multi) _setattr(self, '_default_multi', default_multi)
if unique is not undefined: if unique is not undefined:
_setattr(self, '_unique', unique) _setattr(self, '_unique', unique)
@ -239,10 +250,17 @@ class Option(OnlyOption):
ret_val = val ret_val = val
return ret_val return ret_val
def impl_validate(self, value, context=undefined, validate=True, def impl_validate(self,
force_index=None, force_submulti_index=None, value,
current_opt=undefined, is_multi=None, context=undefined,
display_error=True, display_warnings=True, multi=None, validate=True,
force_index=None,
force_submulti_index=None,
current_opt=undefined,
is_multi=None,
display_error=True,
display_warnings=True,
multi=None,
setting_properties=undefined): setting_properties=undefined):
""" """
:param value: the option's value :param value: the option's value
@ -290,7 +308,8 @@ class Option(OnlyOption):
else: else:
validator_params_ = {'': (val,)} validator_params_ = {'': (val,)}
# Raise ValueError if not valid # Raise ValueError if not valid
value = carry_out_calculation(current_opt, context=context, value = carry_out_calculation(current_opt,
context=context,
callback=validator, callback=validator,
callback_params=validator_params_, callback_params=validator_params_,
index=_index, index=_index,
@ -304,11 +323,14 @@ class Option(OnlyOption):
else: else:
if display_error: if display_error:
# option validation # option validation
err = self._validate(_value, context, current_opt) err = self._validate(_value,
context,
current_opt)
if err: if 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}, '
'submulti_index: {2}'.format(_value, _index, 'submulti_index: {2}'.format(_value,
_index,
submulti_index), submulti_index),
exc_info=True) exc_info=True)
err_msg = '{0}'.format(err) err_msg = '{0}'.format(err)
@ -342,8 +364,12 @@ class Option(OnlyOption):
if error is None: if error is None:
# if context launch consistency validation # if context launch consistency validation
#if context is not undefined: #if context is not undefined:
ret = self._valid_consistency(current_opt, _value, context, ret = self._valid_consistency(current_opt,
_index, submulti_index, display_warnings, _value,
context,
_index,
submulti_index,
display_warnings,
display_error) display_error)
if isinstance(ret, ValueError): if isinstance(ret, ValueError):
error = ret error = ret
@ -421,8 +447,13 @@ class Option(OnlyOption):
err = do_validation(val, idx, force_submulti_index) err = do_validation(val, idx, force_submulti_index)
if err: if err:
return err return err
return self._valid_consistency(current_opt, None, context, return self._valid_consistency(current_opt,
None, None, display_warnings, display_error) None,
context,
None,
None,
display_warnings,
display_error)
def impl_is_dynsymlinkoption(self): def impl_is_dynsymlinkoption(self):
return False return False
@ -596,7 +627,11 @@ class Option(OnlyOption):
def impl_getdefault_multi(self): def impl_getdefault_multi(self):
"accessing the default value for a multi" "accessing the default value for a multi"
return getattr(self, '_default_multi', None) if self.impl_is_submulti():
default_value = []
else:
default_value = None
return getattr(self, '_default_multi', default_value)
def _validate_callback(self, callback, callback_params): def _validate_callback(self, callback, callback_params):
"""callback_params: """callback_params:
@ -605,7 +640,7 @@ class Option(OnlyOption):
""" """
if callback is None: if callback is None:
return return
default_multi = self.impl_getdefault_multi() default_multi = getattr(self, '_default_multi', None)
is_multi = self.impl_is_multi() is_multi = self.impl_is_multi()
default = self.impl_getdefault() default = self.impl_getdefault()
if (not is_multi and (default is not None or default_multi is not None)) or \ if (not is_multi and (default is not None or default_multi is not None)) or \

View File

@ -163,11 +163,11 @@ class CacheOptionDescription(BaseOption):
raise ConfigError(_('a dynoption ({0}) cannot have ' raise ConfigError(_('a dynoption ({0}) cannot have '
'force_store_value property').format(subpath)) 'force_store_value property').format(subpath))
if force_store_values and not config._impl_values._p_.hasvalue(subpath, session): if force_store_values and not config._impl_values._p_.hasvalue(subpath, session):
value = config.cfgimpl_get_values()._get_cached_value(option, value = config.cfgimpl_get_values().get_cached_value(option,
path=subpath, path=subpath,
validate=False, validate=False,
trusted_cached_properties=False, trusted_cached_properties=False,
validate_properties=True) validate_properties=True)
value_set = True value_set = True
config._impl_values._p_.setvalue(subpath, value, config._impl_values._p_.setvalue(subpath, value,
owners.forced, None, session, False) owners.forced, None, session, False)
@ -497,6 +497,9 @@ class OptionDescription(OptionDescriptionWalk):
raise ValueError(_("invalid suffix: {0} for option").format(val)) raise ValueError(_("invalid suffix: {0} for option").format(val))
return values return values
def impl_validate_value(self, option, value, context):
pass
class DynOptionDescription(OptionDescription): class DynOptionDescription(OptionDescription):
def __init__(self, name, doc, children, requires=None, properties=None, def __init__(self, name, doc, children, requires=None, properties=None,
@ -561,9 +564,13 @@ class SynDynOptionDescription(object):
class MasterSlaves(OptionDescription): class MasterSlaves(OptionDescription):
__slots__ = ('master', 'slaves') __slots__ = ('master', 'slaves')
def __init__(self, name, doc, children, requires=None, properties=None): def __init__(self,
#if master (same name has group) is set name,
#for collect all slaves doc,
children,
requires=None,
properties=None):
super(MasterSlaves, self).__init__(name, super(MasterSlaves, self).__init__(name,
doc, doc,
children, children,
@ -572,10 +579,6 @@ class MasterSlaves(OptionDescription):
self._group_type = groups.master self._group_type = groups.master
slaves = [] slaves = []
master = children[0] master = children[0]
if master.impl_getname() != name:
raise ValueError(_('master group with wrong'
' master name for {0}'
).format(name))
for child in children[1:]: for child in children[1:]:
if child.impl_getdefault() != []: if child.impl_getdefault() != []:
raise ValueError(_("not allowed default value for option {0} " raise ValueError(_("not allowed default value for option {0} "
@ -604,8 +607,6 @@ class MasterSlaves(OptionDescription):
raise ValueError(_("callback of master's option shall " raise ValueError(_("callback of master's option shall "
"not refered a slave's ones")) "not refered a slave's ones"))
#everything is ok, store references #everything is ok, store references
#self.master = master
#self.slaves = tuple(slaves)
for child in children: for child in children:
child._master_slaves = self child._master_slaves = self
master._add_dependency(self) master._add_dependency(self)
@ -644,41 +645,74 @@ class MasterSlaves(OptionDescription):
c_opt = opt c_opt = opt
return c_opt in self._children[1] return c_opt in self._children[1]
def reset(self, opt, values, setting_properties, _commit=True, force_permissive=False): def reset(self,
for slave in self.getslaves(opt): opt,
values.reset(slave, validate=False, _setting_properties=setting_properties, values,
_commit=_commit, force_permissive=force_permissive) setting_properties,
_commit=True,
force_permissive=False):
def pop(self, opt, values, index):
for slave in self.getslaves(opt): for slave in self.getslaves(opt):
slave_path = slave.impl_getpath(values._getcontext()) slave_path = slave.impl_getpath(values._getcontext())
slavelen = values._p_.get_max_length(slave_path, None) values.reset(slave,
# just for raise if needed slave_path,
if not values.is_default_owner(slave, validate_properties=False, setting_properties,
validate_meta=False, index=index): validate=False,
multi = values._get_cached_value(slave, validate=False, _commit=_commit,
validate_properties=False, force_permissive=force_permissive)
)
if isinstance(multi, Exception): def pop(self,
raise multi opt,
path,
values,
index):
for slave in self.getslaves(opt):
slave_path = slave.impl_getpath(values._getcontext())
slavelen = values._p_.get_max_length(slave_path)
if not values.is_default_owner(slave,
validate_properties=False,
validate_meta=False,
index=index):
#FIXME # just for raise if needed
#multi = values.get_cached_value(slave,
# validate=False,
# validate_properties=False,
# )
#if isinstance(multi, Exception):
# raise multi
if slavelen > index: if slavelen > index:
values._p_.resetvalue_index(slave_path, index) values._p_.resetvalue_index(slave_path,
index)
if slavelen > index + 1: if slavelen > index + 1:
for idx in xrange(index + 1, slavelen): for idx in xrange(index + 1, slavelen):
values._p_.reduce_index(slave_path, idx) values._p_.reduce_index(slave_path,
idx)
def getitem(self, values, opt, path, validate, force_permissive, def getitem(self,
trusted_cached_properties, validate_properties, values,
slave_path=undefined, slave_value=undefined, opt,
setting_properties=undefined, self_properties=undefined, index=None, path,
validate,
force_permissive,
trusted_cached_properties,
validate_properties,
setting_properties=undefined,
self_properties=undefined,
index=None,
check_frozen=False): check_frozen=False):
if self.is_master(opt): if self.is_master(opt):
return self._getmaster(values, opt, path, validate, return self._getmaster(values,
opt,
path,
validate,
force_permissive, force_permissive,
validate_properties, slave_path, validate_properties,
slave_value, self_properties, index, self_properties,
setting_properties, check_frozen) index,
setting_properties,
check_frozen)
else: else:
return self._getslave(values, opt, path, validate, return self._getslave(values, opt, path, validate,
force_permissive, trusted_cached_properties, force_permissive, trusted_cached_properties,
@ -686,17 +720,26 @@ class MasterSlaves(OptionDescription):
self_properties, index, self_properties, index,
check_frozen) check_frozen)
def _getmaster(self, values, opt, path, validate, force_permissive, def _getmaster(self,
validate_properties, c_slave_path, values,
c_slave_value, self_properties, index, opt,
setting_properties, check_frozen): path,
return values._get_cached_value(opt, path=path, validate=validate, validate,
force_permissive=force_permissive, force_permissive,
validate_properties=validate_properties, validate_properties,
self_properties=self_properties, self_properties,
from_masterslave=True, index=index, index,
setting_properties=setting_properties, setting_properties,
check_frozen=check_frozen) check_frozen):
return values.get_cached_value(opt,
path=path,
validate=validate,
force_permissive=force_permissive,
validate_properties=validate_properties,
self_properties=self_properties,
index=index,
setting_properties=setting_properties,
check_frozen=check_frozen)
def _getslave(self, values, opt, path, validate, force_permissive, def _getslave(self, values, opt, path, validate, force_permissive,
trusted_cached_properties, validate_properties, setting_properties, trusted_cached_properties, validate_properties, setting_properties,
@ -725,20 +768,20 @@ class MasterSlaves(OptionDescription):
master = self.getmaster(opt) master = self.getmaster(opt)
context = values._getcontext() context = values._getcontext()
masterp = master.impl_getpath(context) masterp = master.impl_getpath(context)
mastervalue = values._get_cached_value(master, path=masterp, validate=validate, mastervalue = values.get_cached_value(master, path=masterp, validate=validate,
force_permissive=force_permissive, force_permissive=force_permissive,
validate_properties=validate_properties, validate_properties=validate_properties,
self_properties=self_properties, self_properties=self_properties,
from_masterslave=True, from_masterslave=True,
setting_properties=setting_properties, setting_properties=setting_properties,
check_frozen=check_frozen) check_frozen=check_frozen)
if isinstance(mastervalue, Exception): if isinstance(mastervalue, Exception):
if isinstance(mastervalue, PropertiesOptionError): if isinstance(mastervalue, PropertiesOptionError):
mastervalue.set_orig_opt(opt) mastervalue.set_orig_opt(opt)
return mastervalue return mastervalue
masterlen = len(mastervalue) masterlen = len(mastervalue)
master_is_meta = values._is_meta(master, masterp, force_permissive=force_permissive) #self._master_is_meta = values._is_meta(master, masterp, force_permissive=force_permissive)
multi = values._get_multi(opt, path) multi = list() # values._get_multi(opt, path)
if validate_properties: if validate_properties:
props = context.cfgimpl_get_settings().validate_properties(opt, False, props = context.cfgimpl_get_settings().validate_properties(opt, False,
check_frozen, check_frozen,
@ -748,68 +791,84 @@ class MasterSlaves(OptionDescription):
setting_properties=setting_properties) setting_properties=setting_properties)
if props: if props:
return props return props
#FIXME shouldn't have index!!!
if index is None: if index is None:
indexes = xrange(0, masterlen) indexes = xrange(0, masterlen)
else: else:
indexes = [index] indexes = [index]
for idx in indexes: for idx in indexes:
value = values._get_cached_value(opt, path, validate, value = values.get_cached_value(opt, path, validate,
force_permissive, force_permissive,
trusted_cached_properties, trusted_cached_properties,
validate_properties, validate_properties,
with_meta=master_is_meta, index=idx,
index=idx, # not self_properties,
# not self_properties, # depends to index
# depends to index #self_properties=self_properties,
#self_properties=self_properties, setting_properties=setting_properties,
setting_properties=setting_properties, from_masterslave=True,
masterlen=masterlen, check_frozen=check_frozen)
from_masterslave=True,
check_frozen=check_frozen)
if isinstance(value, Exception): if isinstance(value, Exception):
if isinstance(value, PropertiesOptionError): if isinstance(value, PropertiesOptionError):
err = value err = value
if index is None: if index is None:
multi.append_properties_error(value) multi.append(value)
else: else:
multi = value multi = value
else: else:
return value return value
elif index is None: elif index is None:
multi.append(value, setitem=False, force=True, validate=False, multi.append(value)
force_permissive=force_permissive)
else: else:
multi = value multi = value
return multi return multi
def validate(self, values, opt, index, path, setitem): def validate(self,
values,
opt,
index,
path,
setitem):
if self.is_master(opt): if self.is_master(opt):
#for regen slave path #for regen slave path
base_path = '.'.join(path.split('.')[:-1]) + '.' base_path = '.'.join(path.split('.')[:-1]) + '.'
for slave in self.getslaves(opt): for slave in self.getslaves(opt):
slave_path = base_path + slave.impl_getname() slave_path = base_path + slave.impl_getname()
slavelen = values._p_.get_max_length(slave_path) slavelen = values._p_.get_max_length(slave_path)
self.validate_slave_length(index, slavelen, slave.impl_getname(), opt) self.validate_slave_length(index,
slavelen,
slave.impl_getname(),
opt)
else: else:
val_len = self.get_length(values, opt, slave_path=path) val_len = self.get_length(values)
if isinstance(val_len, Exception): if isinstance(val_len, Exception):
return val_len return val_len
self.validate_slave_length(val_len, index, self.validate_slave_length(val_len,
opt.impl_getname(), opt, setitem=setitem) index,
opt.impl_getname(),
opt,
setitem=setitem)
def get_length(self, values, opt, validate=True, slave_path=undefined, def get_length(self,
slave_value=undefined, force_permissive=False, master=None, values,
masterp=None, setting_properties=undefined): validate=True,
force_permissive=False,
master=None,
masterp=None,
setting_properties=undefined):
"""get master len with slave option""" """get master len with slave option"""
if master is None: if master is None:
master = self.getmaster(None) master = self.getmaster(None)
if masterp is None: if masterp is None:
masterp = master.impl_getpath(self._getcontext()) masterp = master.impl_getpath(values._getcontext())
if slave_value is undefined: value = self.getitem(values,
slave_path = undefined master,
value = self.getitem(values, master, masterp, validate, masterp,
force_permissive, None, True, slave_path=slave_path, validate,
slave_value=slave_value, setting_properties=setting_properties) force_permissive,
None,
True,
setting_properties=setting_properties)
if isinstance(value, Exception): if isinstance(value, Exception):
return value return value
return len(value) return len(value)
@ -843,10 +902,9 @@ class MasterSlaves(OptionDescription):
master = self.getmaster(opt) master = self.getmaster(opt)
masterp = master.impl_getpath(context) masterp = master.impl_getpath(context)
mastervalue = values._get_cached_value(master, path=masterp, mastervalue = values.get_cached_value(master, path=masterp,
force_permissive=force_permissive, force_permissive=force_permissive,
from_masterslave=True, setting_properties=setting_properties)
setting_properties=setting_properties)
if isinstance(mastervalue, Exception): if isinstance(mastervalue, Exception):
return mastervalue return mastervalue
masterlen = len(mastervalue) masterlen = len(mastervalue)
@ -857,9 +915,15 @@ class MasterSlaves(OptionDescription):
else: else:
for slave in self.getslaves(master): for slave in self.getslaves(master):
slave_path = slave.impl_getpath(context) slave_path = slave.impl_getpath(context)
slavelen = values._p_.get_max_length(slave_path, None) slavelen = values._p_.get_max_length(slave_path)
self.validate_slave_length(masterlen, slavelen, slave.impl_getname(), master) self.validate_slave_length(masterlen, slavelen, slave.impl_getname(), master)
def impl_validate_value(self, option, value, context):
if option.impl_is_master_slaves('master') and isinstance(value, list):
if len(value) < context._impl_length:
return ValueError(_('cannot reduce length of master "{}"'
'').format(option.impl_get_display_name()))
def _impl_getpaths(klass, include_groups, _currpath): def _impl_getpaths(klass, include_groups, _currpath):
"""returns a list of all paths in klass, recursively """returns a list of all paths in klass, recursively

View File

@ -353,15 +353,25 @@ class Settings(object):
path = opt.impl_getpath(self._getcontext()) path = opt.impl_getpath(self._getcontext())
return self.getproperties(opt, path) return self.getproperties(opt, path)
def getproperties(self, opt, path, setting_properties=undefined, index=None, obj=True): def getproperties(self,
opt,
path,
setting_properties=undefined,
index=None,
obj=True):
"""get properties for a specified option """get properties for a specified option
""" """
properties = self._getproperties(opt, path, index=index, properties = self._getproperties(opt,
path,
index=index,
setting_properties=setting_properties) setting_properties=setting_properties)
if obj: if obj:
return Property(self, properties, opt, path) return Property(self, properties, opt, path)
return properties return properties
def getcontextproperties(self):
return self._getproperties()
def __setitem__(self, opt, value): # pragma: optional cover def __setitem__(self, opt, value): # pragma: optional cover
raise ValueError(_('you should only append/remove properties')) raise ValueError(_('you should only append/remove properties'))
@ -377,9 +387,13 @@ class Settings(object):
self._p_.delproperties(_path) self._p_.delproperties(_path)
self._getcontext().cfgimpl_reset_cache(opt=opt, path=_path, only=('settings', 'values')) self._getcontext().cfgimpl_reset_cache(opt=opt, path=_path, only=('settings', 'values'))
def _getproperties(self, opt=None, path=None, def _getproperties(self,
setting_properties=undefined, read_write=True, opt=None,
apply_requires=True, index=None): path=None,
setting_properties=undefined,
read_write=True,
apply_requires=True,
index=None):
""" """
""" """
if opt is None: if opt is None:

View File

@ -67,7 +67,7 @@ class Values(Cache):
return vidx return vidx
# value # value
def setvalue(self, path, value, owner, index, session, commit): def setvalue(self, path, value, owner, index, commit):
"""set value for a path """set value for a path
a specified value must be associated to an owner a specified value must be associated to an owner
""" """
@ -137,7 +137,7 @@ class Values(Cache):
_resetvalue_index(3) _resetvalue_index(3)
self._values = tuple(values) self._values = tuple(values)
def resetvalue(self, path, session, commit): def resetvalue(self, path, commit):
"""remove value means delete value in storage """remove value means delete value in storage
""" """
def _resetvalue(nb): def _resetvalue(nb):
@ -174,7 +174,7 @@ class Values(Cache):
return values return values
# owner # owner
def setowner(self, path, owner, session, index=None): def setowner(self, path, owner, index=None):
"""change owner for a path """change owner for a path
""" """
idx = self._values[0].index(path) idx = self._values[0].index(path)
@ -188,14 +188,14 @@ class Values(Cache):
lst[3] = tuple(values[0]) lst[3] = tuple(values[0])
self._values = tuple(lst) self._values = tuple(lst)
def get_max_length(self, path, session): def get_max_length(self, path):
if path in self._values[0]: if path in self._values[0]:
idx = self._values[0].index(path) idx = self._values[0].index(path)
else: else:
return 0 return 0
return max(self._values[1][idx]) + 1 return max(self._values[1][idx]) + 1
def getowner(self, path, default, session, index=None, only_default=False, def getowner(self, path, default, index=None, only_default=False,
with_value=False): with_value=False):
"""get owner for a path """get owner for a path
return: owner object return: owner object
@ -271,11 +271,11 @@ class Values(Cache):
if raises: if raises:
raise ValueError(_("information's item not found {0}").format(key)) raise ValueError(_("information's item not found {0}").format(key))
def exportation(self, session, fake=False): def exportation(self, fake=False):
return self._values return self._values
def importation(self, export): def importation(self, export):
self._values = export self._values = export
def delete_session(session_id, session): def delete_session(session_id):
raise ValueError(_('a dictionary cannot be persistent')) raise ValueError(_('a dictionary cannot be persistent'))

View File

@ -15,6 +15,12 @@
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# ____________________________________________________________ # ____________________________________________________________
FIXME = 0
def POUET(obj):
return(obj.__class__.__name__.lower())
DEBUG = False
#DEBUG = True
class Cache(object): class Cache(object):
@ -29,17 +35,41 @@ class Cache(object):
"""add val in cache for a specified path """add val in cache for a specified path
if slave, add index if slave, add index
""" """
if DEBUG:
global FIXME
FIXME += 1
print('ca set cache', path, val, POUET(self), FIXME)
#if path is not None and (path.startswith('od.st.') or path.startswith('od.dod.')):
# raise Exception('mais ... mais ... mais')
#if FIXME == 111:
# raise Exception('rah')
self._cache.setdefault(path, {})[index] = (val, time) self._cache.setdefault(path, {})[index] = (val, time)
def getcache(self, path, exp, index): def getcache(self, path, exp, index):
value, created = self._cache[path][index] value, created = self._cache[path][index]
if created is None or exp <= created: if created is None or exp <= created:
if DEBUG:
global FIXME
FIXME += 1
print('ca trouve dans le cache', path, value, POUET(self), FIXME)
#if path is not None and (path.startswith('od.st.') or path.startswith('od.dod.')):
# raise Exception('mais ... mais ... mais')
#if FIXME == 45:
# raise Exception('rah')
return True, value return True, value
return False, None # pragma: no cover return False, None # pragma: no cover
def delcache(self, path): def delcache(self, path):
"""remove cache for a specified path """remove cache for a specified path
""" """
if DEBUG:
global FIXME
FIXME += 1
print('ca del cache', path, POUET(self), FIXME)
#if path is not None and (path.startswith('od.st.') or path.startswith('od.dod.')):
# raise Exception('mais ... mais ... mais')
#if FIXME == 23:
# raise Exception('rah')
if path in self._cache: if path in self._cache:
del self._cache[path] del self._cache[path]
@ -48,6 +78,8 @@ class Cache(object):
:param path: the path's option :param path: the path's option
""" """
if DEBUG:
print('ca cherche dans le cache', path, POUET(self))
return path in self._cache and index in self._cache[path] return path in self._cache and index in self._cache[path]
def reset_expired_cache(self, exp): def reset_expired_cache(self, exp):
@ -63,6 +95,8 @@ class Cache(object):
def reset_all_cache(self): def reset_all_cache(self):
"empty the cache" "empty the cache"
if DEBUG:
print('bzzzzzzzzzzzz delete tout le cache', POUET(self))
self._cache.clear() self._cache.clear()
def get_cached(self): def get_cached(self):

View File

@ -54,76 +54,129 @@ class Values(object):
raise ConfigError(_('the context does not exist anymore')) raise ConfigError(_('the context does not exist anymore'))
return context return context
def _get_multi(self, opt, path): def getdefaultvalue(self,
return Multi([], self.context, opt, path) opt,
path,
index=None):
"""get default value:
- get meta config value or
- get calculated value or
- get default value
:param opt: the `option.Option()` object
:param path: path for `option.Option()` object
:type path: str
:param index: index of a multi/submulti
:type index: int
:returns: default value
"""
return self._getdefaultvalue(opt,
path,
index,
True,
self._getcontext())
def _getdefaultvalue(self, opt, path, with_meta, index, submulti_index, validate, def _getdefaultvalue(self,
_orig_context=undefined): opt,
if _orig_context is undefined: path,
_orig_context = self._getcontext() index,
validate,
_orig_context):
def _reset_cache():
# calculated value could be a new value, so reset cache
_orig_context.cfgimpl_reset_cache(opt=opt,
path=path,
only=('values', 'properties'))
#FIXME with_meta should be calculated here...
with_meta = True
if with_meta: if with_meta:
meta = self._getcontext().cfgimpl_get_meta() meta = self._getcontext().cfgimpl_get_meta()
if meta is not None: if meta is not None:
value = meta.cfgimpl_get_values( # retrieved value from meta config
)._get_cached_value(opt, path, index=index, submulti_index=submulti_index, value = meta.cfgimpl_get_values().get_cached_value(opt,
from_masterslave=True, _orig_context=_orig_context) path,
index=index,
_orig_context=_orig_context)
if isinstance(value, Exception): if isinstance(value, Exception):
# if properties error, return an other default value
if not isinstance(value, PropertiesOptionError): # pragma: no cover if not isinstance(value, PropertiesOptionError): # pragma: no cover
# unexpected error, should not happened
raise value raise value
else: else:
if isinstance(value, Multi):
new_value = []
for val in value:
if isinstance(val, SubMulti):
val = list(val)
new_value.append(val)
value = new_value
del new_value
return value return value
# if value has callback and is not set
if opt.impl_has_callback(): if opt.impl_has_callback():
# if value has callback, calculate value
callback, callback_params = opt.impl_get_callback() callback, callback_params = opt.impl_get_callback()
value = carry_out_calculation(opt, context=_orig_context, value = carry_out_calculation(opt,
context=_orig_context,
callback=callback, callback=callback,
callback_params=callback_params, callback_params=callback_params,
index=index, validate=validate) index=index,
_orig_context.cfgimpl_reset_cache(opt=opt, path=path, only=('values', 'properties')) validate=validate)
if isinstance(value, list) and index is not None: if isinstance(value, list) and index is not None:
#if return a list and index is set, return value only if # if value is a list and index is set
#it's a submulti without submulti_index and without list of list if opt.impl_is_submulti() and (value == [] or not isinstance(value[0], list)):
if opt.impl_is_submulti() and submulti_index is undefined and \ # return value only if it's a submulti and not a list of list
(len(value) == 0 or not isinstance(value[0], list)): _reset_cache()
return value return value
if not opt.impl_is_submulti() and len(value) > index:
if len(value) > index:
# return the value for specified index if found
_reset_cache()
return value[index] return value[index]
else: # there is no calculate value for this index,
# so return an other default value
elif isinstance(value, list):
# value is a list, but no index specified
_reset_cache()
if opt.impl_is_submulti() and (value == [] or not isinstance(value[0], list)):
# if submulti, return a list of value
return [value]
# otherwise just return the value
return value return value
# now try to get default value elif index is not None:
# if not list but with index
_reset_cache()
if opt.impl_is_submulti():
# if submulti, return a list of value
return [value]
# otherwise just return the value
return value
else:
_reset_cache()
# not a list or index is None
if opt.impl_is_submulti():
# return a list of list for a submulti
return [[value]]
elif opt.impl_is_multi():
# return a list for a multi
return [value]
# not a list, return value
return value
# now try to get default value:
# - if opt is a submulti, return a list a list
# - if opt is a multi, return a list
# - default value
value = opt.impl_getdefault() value = opt.impl_getdefault()
if opt.impl_is_multi() and index is not None: if opt.impl_is_multi() and index is not None:
if value == []: # if index, must return good value for this index
value = opt.impl_getdefault_multi() if len(value) > index:
if submulti_index is undefined and opt.impl_is_submulti(): value = value[index]
if value is None:
value = []
elif not isinstance(value, list):
value = [value]
else: else:
if len(value) > index: # no value for this index, retrieve default multi value
value = value[index] # default_multi is already a list for submulti
else: value = opt.impl_getdefault_multi()
value = opt.impl_getdefault_multi()
if submulti_index is undefined and opt.impl_is_submulti():
if value is None:
value = []
elif not isinstance(value, list):
value = [value]
if opt.impl_is_submulti() and not isinstance(value, list) and submulti_index is undefined:
value = [value]
return value return value
def _getvalue(self, opt, path, self_properties, index, submulti_index, def _getvalue(self,
with_meta, masterlen, session, validate, _orig_context): opt,
path,
self_properties,
index,
validate,
_orig_context):
"""actually retrieves the value """actually retrieves the value
:param opt: the `option.Option()` object :param opt: the `option.Option()` object
@ -136,8 +189,11 @@ class Values(object):
_index = None _index = None
else: else:
_index = index _index = index
owner, value = self._p_.getowner(path, owners.default, session, only_default=True, owner, value = self._p_.getowner(path,
index=_index, with_value=True) owners.default,
only_default=True,
index=_index,
with_value=True)
is_default = owner == owners.default is_default = owner == owners.default
if not is_default and not force_default: if not is_default and not force_default:
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'):
@ -147,8 +203,11 @@ class Values(object):
#so return default value #so return default value
else: else:
return value return value
return self._getdefaultvalue(opt, path, with_meta, index, return self._getdefaultvalue(opt,
submulti_index, validate, _orig_context) path,
index,
validate,
_orig_context)
def get_modified_values(self): def get_modified_values(self):
return self._p_.get_modified_values() return self._p_.get_modified_values()
@ -163,55 +222,129 @@ class Values(object):
path = opt.impl_getpath(self._getcontext()) path = opt.impl_getpath(self._getcontext())
return self._contains(path) return self._contains(path)
def _contains(self, path, session=None): def _contains(self, path):
if session is None: return self._p_.hasvalue(path)
session = self._p_.getsession()
return self._p_.hasvalue(path, session)
def __delitem__(self, opt): def reset(self,
"""overrides the builtins `del()` instructions""" opt,
self.reset(opt) path,
setting_properties,
def reset(self, opt, path=None, validate=True, _setting_properties=None, _commit=True, validate=True,
_commit=True,
force_permissive=False): force_permissive=False):
context = self._getcontext() context = self._getcontext()
setting = context.cfgimpl_get_settings() setting = context.cfgimpl_get_settings()
if path is None: hasvalue = self._contains(path)
path = opt.impl_getpath(context)
if _setting_properties is None:
_setting_properties = setting._getproperties(read_write=False)
session = self._p_.getsession()
hasvalue = self._contains(path, session)
if validate and hasvalue and 'validator' in _setting_properties: if validate and hasvalue and 'validator' in setting_properties:
session = context.cfgimpl_get_values()._p_.getsession() fake_context = context._gen_fake_values()
fake_context = context._gen_fake_values(session)
fake_value = fake_context.cfgimpl_get_values() fake_value = fake_context.cfgimpl_get_values()
fake_value.reset(opt, path, validate=False) fake_value.reset(opt,
ret = fake_value._get_cached_value(opt, path, path,
setting_properties=_setting_properties, setting_properties,
check_frozen=True, validate=False)
force_permissive=force_permissive) ret = fake_value.get_cached_value(opt,
path,
setting_properties=setting_properties,
check_frozen=True,
force_permissive=force_permissive)
if isinstance(ret, Exception): if isinstance(ret, Exception):
raise ret raise ret
if opt.impl_is_master_slaves('master'): if opt.impl_is_master_slaves('master'):
opt.impl_get_master_slaves().reset(opt, self, _setting_properties, _commit=_commit, opt.impl_get_master_slaves().reset(opt,
self,
setting_properties,
_commit=_commit,
force_permissive=force_permissive) force_permissive=force_permissive)
if hasvalue: if hasvalue:
if 'force_store_value' in setting._getproperties(opt=opt, if 'force_store_value' in setting._getproperties(opt=opt,
path=path, path=path,
setting_properties=_setting_properties, setting_properties=setting_properties,
read_write=False, read_write=False,
apply_requires=False): apply_requires=False):
value = self._getdefaultvalue(opt, path, True, undefined, undefined, validate) value = self._getdefaultvalue(opt,
path,
True,
undefined,
validate,
context)
if isinstance(value, Exception): # pragma: no cover if isinstance(value, Exception): # pragma: no cover
raise value raise value
self._setvalue(opt, path, value, force_owner=owners.forced, commit=_commit) self._setvalue(opt,
path,
value,
owners.forced,
None,
commit=_commit)
else: else:
self._p_.resetvalue(path, session, _commit) self._p_.resetvalue(path,
context.cfgimpl_reset_cache(opt=opt, path=path, only=('values', 'properties')) _commit)
context.cfgimpl_reset_cache(opt=opt,
path=path,
only=('values', 'properties'))
def _isempty(self, opt, value, force_allow_empty_list=False, index=None): def reset_slave(self,
opt,
path,
index,
setting_properties,
validate=True,
force_permissive=False):
context = self._getcontext()
if validate and 'validator' in setting_properties:
fake_context = context._gen_fake_values()
fake_value = fake_context.cfgimpl_get_values()
fake_value.reset_slave(opt,
path,
index,
setting_properties,
validate=False)
ret = fake_value.get_cached_value(opt,
path,
index=index,
setting_properties=setting_properties,
check_frozen=True,
force_permissive=force_permissive)
if isinstance(ret, Exception):
raise ret
self._p_.resetvalue_index(path, index)
def reset_master(self,
subconfig,
opt,
path,
index,
force_permissive,
setting_properties):
current_value = self.get_cached_value(opt,
path,
setting_properties=setting_properties,
check_frozen=True,
force_permissive=force_permissive)
current_value.pop(index)
ret = self.setitem(opt,
current_value,
path,
force_permissive=force_permissive,
not_raises=True,
index=None,
setting_properties=setting_properties,
_commit=True)
if ret:
return ret
subconfig.cfgimpl_get_description().pop(opt,
path,
self,
index)
def _isempty(self,
opt,
value,
force_allow_empty_list=False,
index=None):
"convenience method to know if an option is empty" "convenience method to know if an option is empty"
if value is undefined: if value is undefined:
return False return False
@ -235,15 +368,21 @@ class Values(object):
def __getitem__(self, opt): def __getitem__(self, opt):
"enables us to use the pythonic dictionary-like access to values" "enables us to use the pythonic dictionary-like access to values"
return self._get_cached_value(opt) return self.get_cached_value(opt)
def _get_cached_value(self, opt, path=None, validate=True, def get_cached_value(self,
force_permissive=False, trusted_cached_properties=True, opt,
validate_properties=True, path=None,
setting_properties=undefined, self_properties=undefined, validate=True,
index=None, submulti_index=undefined, from_masterslave=False, force_permissive=False,
with_meta=True, masterlen=undefined, check_frozen=False, trusted_cached_properties=True,
session=None, display_warnings=True, _orig_context=undefined): validate_properties=True,
setting_properties=undefined,
self_properties=undefined,
index=None,
check_frozen=False,
display_warnings=True,
_orig_context=undefined):
context = self._getcontext() context = self._getcontext()
settings = context.cfgimpl_get_settings() settings = context.cfgimpl_get_settings()
if path is None: if path is None:
@ -252,7 +391,8 @@ class Values(object):
if setting_properties is undefined: if setting_properties is undefined:
setting_properties = settings._getproperties(read_write=False) setting_properties = settings._getproperties(read_write=False)
if self_properties is undefined: if self_properties is undefined:
self_properties = settings._getproperties(opt, path, self_properties = settings._getproperties(opt,
path,
read_write=False, read_write=False,
setting_properties=setting_properties, setting_properties=setting_properties,
index=index) index=index)
@ -264,11 +404,14 @@ class Values(object):
if index: if index:
value = value[index] value = value[index]
if is_cached: if is_cached:
if opt.impl_is_multi() and not isinstance(value, Multi) and index is None: #if opt.impl_is_multi() and not isinstance(value, Multi) and index is None:
value = Multi(value, self.context, opt, path) # value = Multi(value, self.context, opt, path)
if not trusted_cached_properties: if not trusted_cached_properties:
# revalidate properties (because of not default properties) # revalidate properties (because of not default properties)
props = settings.validate_properties(opt, False, False, value=value, props = settings.validate_properties(opt,
False,
False,
value=value,
path=path, path=path,
force_permissive=force_permissive, force_permissive=force_permissive,
setting_properties=setting_properties, setting_properties=setting_properties,
@ -277,38 +420,35 @@ class Values(object):
if props: if props:
return props return props
return value return value
if session is None: #if not from_masterslave and opt.impl_is_master_slaves():
session = self._p_.getsession() # val = opt.impl_get_master_slaves().getitem(self, opt, path,
if not from_masterslave and opt.impl_is_master_slaves(): # validate,
val = opt.impl_get_master_slaves().getitem(self, opt, path, # force_permissive,
validate, # trusted_cached_properties,
force_permissive, # validate_properties,
trusted_cached_properties, # setting_properties=setting_properties,
validate_properties, # index=index,
session, # self_properties=self_properties,
setting_properties=setting_properties, # check_frozen=check_frozen)
index=index, #else:
self_properties=self_properties, if _orig_context is not undefined:
check_frozen=check_frozen) _context = _orig_context
else: else:
val = self._get_validated_value(opt, path, validate, _context = context
force_permissive, val = self._get_validated_value(opt,
validate_properties, path,
setting_properties, validate,
self_properties, force_permissive,
with_meta=with_meta, validate_properties,
masterlen=masterlen, setting_properties,
index=index, self_properties,
submulti_index=submulti_index, index=index,
check_frozen=check_frozen, check_frozen=check_frozen,
session=session, display_warnings=display_warnings,
display_warnings=display_warnings, _orig_context=_context)
_orig_context=_orig_context)
if isinstance(val, Exception): if isinstance(val, Exception):
return val return val
# cache doesn't work with SubMulti yet if index is None and 'cache' in setting_properties and \
if not from_masterslave and index is None and not isinstance(val, SubMulti) and \
'cache' in setting_properties and \
validate and validate_properties and force_permissive is False \ validate and validate_properties and force_permissive is False \
and trusted_cached_properties is True and _orig_context is undefined: and trusted_cached_properties is True and _orig_context is undefined:
if 'expire' in setting_properties: if 'expire' in setting_properties:
@ -318,14 +458,17 @@ class Values(object):
self._p_.setcache(path, val, ntime, None) self._p_.setcache(path, val, ntime, None)
return val return val
def _get_validated_value(self, opt, path, validate, force_permissive, def _get_validated_value(self,
validate_properties, setting_properties, opt,
path,
validate,
force_permissive,
validate_properties,
setting_properties,
self_properties, self_properties,
index=None, submulti_index=undefined, index=None,
with_meta=True,
masterlen=undefined,
check_frozen=False, check_frozen=False,
session=None, display_warnings=True, display_warnings=True,
_orig_context=undefined): _orig_context=undefined):
"""same has getitem but don't touch the cache """same has getitem but don't touch the cache
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 []
@ -333,10 +476,12 @@ class Values(object):
context = self._getcontext() context = self._getcontext()
setting = context.cfgimpl_get_settings() setting = context.cfgimpl_get_settings()
config_error = None config_error = None
if session is None: value = self._getvalue(opt,
session = self._p_.getsession() path,
value = self._getvalue(opt, path, self_properties, index, submulti_index, self_properties,
with_meta, masterlen, session, validate, _orig_context) index,
validate,
_orig_context)
if isinstance(value, Exception): if isinstance(value, Exception):
value_error = True value_error = True
if isinstance(value, ConfigError): if isinstance(value, ConfigError):
@ -355,22 +500,11 @@ class Values(object):
raise value raise value
else: else:
value_error = False value_error = False
if opt.impl_is_multi():
if index is None:
value = Multi(value, self.context, opt, path)
elif opt.impl_is_submulti() and submulti_index is undefined:
value = SubMulti(value, self.context, opt, path,
index)
if validate: if validate:
if submulti_index is undefined: err = opt.impl_validate(value,
force_submulti_index = None context,
else:
force_submulti_index = submulti_index
err = opt.impl_validate(value, context,
'validator' in setting_properties, 'validator' in setting_properties,
force_index=index, force_index=index,
force_submulti_index=force_submulti_index,
display_error=True, display_error=True,
display_warnings=False, display_warnings=False,
setting_properties=setting_properties) setting_properties=setting_properties)
@ -385,7 +519,10 @@ class Values(object):
val_props = undefined val_props = undefined
else: else:
val_props = value val_props = value
props = setting.validate_properties(opt, False, check_frozen, value=val_props, props = setting.validate_properties(opt,
False,
check_frozen,
value=val_props,
path=path, path=path,
force_permissive=force_permissive, force_permissive=force_permissive,
setting_properties=setting_properties, setting_properties=setting_properties,
@ -394,10 +531,10 @@ class Values(object):
if props: if props:
return props return props
if not value_error and validate and display_warnings: if not value_error and validate and display_warnings:
opt.impl_validate(value, context, opt.impl_validate(value,
context,
'validator' in setting_properties, 'validator' in setting_properties,
force_index=index, force_index=index,
force_submulti_index=force_submulti_index,
display_error=False, display_error=False,
display_warnings=display_warnings, display_warnings=display_warnings,
setting_properties=setting_properties) setting_properties=setting_properties)
@ -405,122 +542,116 @@ class Values(object):
return config_error return config_error
return value return value
def __setitem__(self, opt, value): def setitem(self,
raise ConfigError(_('you should only set value with config')) opt,
value,
path,
force_permissive,
not_raises,
index,
setting_properties,
_commit):
def setitem(self, opt, value, path, force_permissive=False,
check_frozen=True, not_raises=False, index=None,
_setting_properties=undefined, _commit=True):
# check_frozen is, for example, used with "force_store_value"
# user didn't change value, so not write
# valid opt
context = self._getcontext() context = self._getcontext()
if 'validator' in _setting_properties: owner = context.cfgimpl_get_settings().getowner()
session = context.cfgimpl_get_values()._p_.getsession() if 'validator' in setting_properties:
if opt._has_consistencies(): if opt._has_consistencies():
fake_context = context._gen_fake_values(session) # set value to a fake config when option has dependency
fake_values = fake_context.cfgimpl_get_values() # validation will be complet in this case (consistency, ...)
fake_values._setvalue(opt, path, value, index=index) tested_context = context._gen_fake_values()
tested_values = tested_context.cfgimpl_get_values()
tested_values._setvalue(opt,
path,
value,
index=index,
owner=owner)
else: else:
fake_context = context tested_context = context
fake_values = self tested_values = self
props = fake_values.validate(opt, value, path, props = tested_values.validate_setitem(opt,
check_frozen=check_frozen, value,
force_permissive=force_permissive, path,
setting_properties=_setting_properties, force_permissive,
session=session, not_raises=not_raises, setting_properties,
index=index, setitem=True) index)
if props and not_raises: if props:
if not not_raises:
raise props
return props return props
err = opt.impl_validate(value, fake_context, display_warnings=False, force_index=index,
setting_properties=_setting_properties)
if err:
if not_raises:
return err
raise err
opt.impl_validate(value, fake_context, display_error=False,
setting_properties=_setting_properties)
self._setvalue(opt, path, value, index=index, commit=_commit)
def _setvalue(self, opt, path, value, force_owner=undefined, index=None, commit=True): self._setvalue(opt,
path,
value,
owner,
index=index,
commit=_commit)
def validate_setitem(self,
opt,
value,
path,
force_permissive,
setting_properties,
index):
context = self._getcontext() context = self._getcontext()
context.cfgimpl_reset_cache(opt=opt, path=path, only=('values', 'properties')) # First validate properties with this value
if force_owner is undefined: props = context.cfgimpl_get_settings().validate_properties(opt,
owner = context.cfgimpl_get_settings().getowner() False,
else: True,
owner = force_owner value=value,
# in storage, value must not be a multi path=path,
if isinstance(value, Multi): force_permissive=force_permissive,
if not opt.impl_is_master_slaves('slave') or index is None: setting_properties=setting_properties,
value = list(value) index=index)
if opt.impl_is_submulti():
for idx, val in enumerate(value):
if isinstance(val, SubMulti):
value[idx] = list(val)
else:
value = value[index]
session = self._p_.getsession()
#FIXME pourquoi là et pas dans masterslaves ??
if opt.impl_is_master_slaves('slave'):
if index is not None:
self._p_.setvalue(path, value, owner, index, session, commit)
else:
self._p_.resetvalue(path, session, commit)
for idx, val in enumerate(value):
self._p_.setvalue(path, val, owner, idx, session, commit)
else:
self._p_.setvalue(path, value, owner, None, session, commit)
del(session)
def validate(self, opt, value, path, check_frozen=True, force_permissive=False,
setting_properties=undefined, valid_masterslave=True,
not_raises=False, session=None, index=None, setitem=False):
if valid_masterslave and opt.impl_is_master_slaves():
if session is None:
session = self._p_.getsession()
setitem = True
if opt.impl_is_master_slaves('master'):
masterlen = len(value)
slavelen = None
elif index is not None:
masterlen = None
slavelen = index
setitem = False
else:
masterlen = None
slavelen = len(value)
opt.impl_get_master_slaves().impl_validate(self._getcontext(), force_permissive,
setting_properties, masterlen=masterlen,
slavelen=slavelen, opt=opt, setitem=setitem)
#val = opt.impl_get_master_slaves().impl_validate(self, opt, len_value, path, session, setitem=setitem)
#if isinstance(val, Exception):
# return val
props = self._getcontext().cfgimpl_get_settings().validate_properties(opt,
False,
check_frozen,
value=value,
path=path,
force_permissive=force_permissive,
setting_properties=setting_properties,
index=index)
if props: if props:
if not_raises: return props
return props # Value must be valid for option
raise props err = opt.impl_validate(value,
context,
display_warnings=False,
force_index=index,
setting_properties=setting_properties)
if err:
return err
# No error found so emit warnings
opt.impl_validate(value,
context,
display_error=False,
force_index=index,
setting_properties=setting_properties)
def _is_meta(self, opt, path, session=None, force_permissive=False): def _setvalue(self,
opt,
path,
value,
owner,
index=None,
commit=True):
self._getcontext().cfgimpl_reset_cache(opt=opt,
path=path,
only=('values', 'properties'))
if isinstance(value, list):
# copy
value = list(value)
self._p_.setvalue(path,
value,
owner,
index,
commit)
def _is_meta(self, opt, path, force_permissive=False):
context = self._getcontext() context = self._getcontext()
if context.cfgimpl_get_meta() is None: if context.cfgimpl_get_meta() is None:
return False return False
setting = context.cfgimpl_get_settings() setting = context.cfgimpl_get_settings()
self_properties = setting._getproperties(opt, path, read_write=False) self_properties = setting._getproperties(opt, path, read_write=False)
if session is None:
session = self._p_.getsession()
return self.is_default_owner(opt, path=path, validate_properties=True, return self.is_default_owner(opt, path=path, validate_properties=True,
validate_meta=False, index=None, validate_meta=False, index=None,
force_permissive=force_permissive) force_permissive=force_permissive)
def getowner(self, opt, index=None, force_permissive=False, session=None): def getowner(self, opt, index=None, force_permissive=False):
""" """
retrieves the option's owner retrieves the option's owner
@ -533,16 +664,22 @@ class Values(object):
not isinstance(opt, DynSymLinkOption): not isinstance(opt, DynSymLinkOption):
opt = opt._impl_getopt() opt = opt._impl_getopt()
path = opt.impl_getpath(self._getcontext()) path = opt.impl_getpath(self._getcontext())
return self._getowner(opt, path, session, index=index, force_permissive=force_permissive) return self._getowner(opt,
path,
index=index,
force_permissive=force_permissive)
def _getowner(self, opt, path, session, validate_properties=True, def _getowner(self,
force_permissive=False, validate_meta=undefined, opt,
self_properties=undefined, only_default=False, path,
validate_properties=True,
force_permissive=False,
validate_meta=undefined,
self_properties=undefined,
only_default=False,
index=None): index=None):
"""get owner of an option """get owner of an option
""" """
if session is None:
session = self._p_.getsession()
if not isinstance(opt, Option) and not isinstance(opt, if not isinstance(opt, Option) and not isinstance(opt,
DynSymLinkOption): DynSymLinkOption):
raise ConfigError(_('owner only avalaible for an option')) raise ConfigError(_('owner only avalaible for an option'))
@ -553,28 +690,32 @@ class Values(object):
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 validate_properties: if validate_properties:
value = self._get_cached_value(opt, path=path, force_permissive=force_permissive, value = self.get_cached_value(opt,
self_properties=self_properties, session=session, path=path,
index=index) force_permissive=force_permissive,
self_properties=self_properties,
index=index)
if isinstance(value, Exception): if isinstance(value, Exception):
raise value raise value
owner = self._p_.getowner(path, owners.default, session, only_default=only_default, index=index) owner = self._p_.getowner(path, owners.default, only_default=only_default, index=index)
if validate_meta is undefined: if validate_meta is undefined:
if opt.impl_is_master_slaves('slave'): if opt.impl_is_master_slaves('slave'):
master = opt.impl_get_master_slaves().getmaster(opt) master = opt.impl_get_master_slaves().getmaster(opt)
masterp = master.impl_getpath(context) masterp = master.impl_getpath(context)
validate_meta = self._is_meta(master, masterp, session) validate_meta = self._is_meta(master, masterp)
else: else:
validate_meta = True validate_meta = True
if validate_meta and owner is owners.default: if validate_meta and owner is owners.default:
meta = context.cfgimpl_get_meta() meta = context.cfgimpl_get_meta()
if meta is not None: if meta is not None:
owner = meta.cfgimpl_get_values()._getowner(opt, path, session, owner = meta.cfgimpl_get_values()._getowner(opt,
path,
validate_properties=validate_properties, validate_properties=validate_properties,
force_permissive=force_permissive, force_permissive=force_permissive,
self_properties=self_properties, self_properties=self_properties,
only_default=only_default, index=index) only_default=only_default,
index=index)
return owner return owner
def setowner(self, opt, owner, index=None, force_permissive=False): def setowner(self, opt, owner, index=None, force_permissive=False):
@ -588,7 +729,6 @@ class Values(object):
raise TypeError(_("invalid generic owner {0}").format(str(owner))) raise TypeError(_("invalid generic owner {0}").format(str(owner)))
path = opt.impl_getpath(self._getcontext()) path = opt.impl_getpath(self._getcontext())
session = self._p_.getsession()
props = self._getcontext().cfgimpl_get_settings().validate_properties(opt, props = self._getcontext().cfgimpl_get_settings().validate_properties(opt,
False, False,
True, True,
@ -597,10 +737,10 @@ class Values(object):
force_permissive=force_permissive) force_permissive=force_permissive)
if props: if props:
raise props raise props
if not self._p_.hasvalue(path, session): 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._p_.setowner(path, owner, session, index=index) self._p_.setowner(path, owner, index=index)
def is_default_owner(self, opt, path=None, validate_properties=True, def is_default_owner(self, opt, path=None, validate_properties=True,
validate_meta=True, index=None, validate_meta=True, index=None,
@ -612,19 +752,30 @@ class Values(object):
""" """
if path is None: if path is None:
path = opt.impl_getpath(self._getcontext()) path = opt.impl_getpath(self._getcontext())
return self._is_default_owner(opt, path, session=None, return self._is_default_owner(opt,
path,
validate_properties=validate_properties, validate_properties=validate_properties,
validate_meta=validate_meta, index=index, validate_meta=validate_meta,
index=index,
force_permissive=force_permissive) force_permissive=force_permissive)
def _is_default_owner(self, opt, path, session, validate_properties=True, def _is_default_owner(self,
validate_meta=True, self_properties=undefined, opt,
index=None, force_permissive=False): path,
d = self._getowner(opt, path, session, validate_properties=validate_properties, validate_properties=True,
validate_meta=validate_meta, validate_meta=True,
self_properties=self_properties, only_default=True, self_properties=undefined,
index=index, force_permissive=force_permissive) index=None,
return d == owners.default force_permissive=False):
owner = self._getowner(opt,
path,
validate_properties=validate_properties,
validate_meta=validate_meta,
self_properties=self_properties,
only_default=True,
index=index,
force_permissive=force_permissive)
return owner == owners.default
# information # information
def set_information(self, key, value): def set_information(self, key, value):
@ -688,13 +839,13 @@ class Values(object):
read_write=False, read_write=False,
setting_properties=setting_properties) setting_properties=setting_properties)
if 'mandatory' in self_properties or 'empty' in self_properties: if 'mandatory' in self_properties or 'empty' in self_properties:
err = self._get_cached_value(opt, path=path, err = self.get_cached_value(opt, path=path,
trusted_cached_properties=False, trusted_cached_properties=False,
force_permissive=True, force_permissive=True,
setting_properties=setting_properties, setting_properties=setting_properties,
self_properties=self_properties, self_properties=self_properties,
validate=True, validate=True,
display_warnings=False) display_warnings=False)
if opt.impl_is_master_slaves('slave') and isinstance(err, list): if opt.impl_is_master_slaves('slave') and isinstance(err, list):
for val in err: for val in err:
ret = _is_properties_option(val, path) ret = _is_properties_option(val, path)
@ -723,277 +874,3 @@ class Values(object):
err = context.getattr(path, returns_raise=True) err = context.getattr(path, returns_raise=True)
if isinstance(err, Exception) and not isinstance(err, PropertiesOptionError): # pragma: no cover if isinstance(err, Exception) and not isinstance(err, PropertiesOptionError): # pragma: no cover
raise err raise err
# ____________________________________________________________
# multi types
class Multi(list):
"""multi options values container
that support item notation for the values of multi options"""
__slots__ = ('opt', 'path', 'context', '__weakref__')
def __init__(self, value, context, opt, path):
"""
:param value: the Multi wraps a list value
:param context: the home config that has the values
:param opt: the option object that have this Multi value
:param path: path of the option
"""
if value is None:
value = []
if not opt.impl_is_submulti() and isinstance(value, Multi):
raise ValueError(_('{0} is already a Multi ').format(
opt.impl_getname()))
self.opt = opt
self.path = path
if not isinstance(context, weakref.ReferenceType):
raise ValueError('context must be a Weakref')
self.context = context
if not isinstance(value, list):
if not '_index' in self.__slots__ and opt.impl_is_submulti():
value = [[value]]
else:
value = [value]
elif value != [] and not '_index' in self.__slots__ and \
opt.impl_is_submulti() and not isinstance(value[0], list):
value = [value]
super(Multi, self).__init__(value)
if opt.impl_is_submulti():
if not '_index' in self.__slots__:
for idx, val in enumerate(self):
if not isinstance(val, SubMulti):
super(Multi, self).__setitem__(idx, SubMulti(val,
context,
opt, path,
idx))
self[idx].refmulti = weakref.ref(self)
def _getcontext(self):
"""context could be None, we need to test it
context is None only if all reference to `Config` object is deleted
(for example we delete a `Config` and we manipulate a reference to
old `SubConfig`, `Values`, `Multi` or `Settings`)
"""
context = self.context()
if context is None:
raise ConfigError(_('the context does not exist anymore'))
return context
def __setitem__(self, index, value):
self._setitem(index, value)
def _setitem(self, index, value, validate=True):
context = self._getcontext()
setting = context.cfgimpl_get_settings()
setting_properties = setting._getproperties(read_write=False)
if index < 0:
index = self.__len__() + index
if 'validator' in setting_properties and validate:
session = context.cfgimpl_get_values()._p_.getsession()
fake_context = context._gen_fake_values(session)
fake_multi = Multi(list(self), weakref.ref(fake_context), self.opt, self.path)
fake_multi._setitem(index, value, validate=False)
self._validate(value, fake_context, index, True)
#assume not checking mandatory property
super(Multi, self).__setitem__(index, value)
self._store(index=index)
#def __repr__(self, *args, **kwargs):
# return super(Multi, self).__repr__(*args, **kwargs)
def __getitem__(self, index):
value = super(Multi, self).__getitem__(index)
if isinstance(value, PropertiesOptionError):
raise value
return value
def __delitem__(self, index):
return self.pop(index)
def _getdefaultvalue(self, index):
values = self._getcontext().cfgimpl_get_values()
value = values._getdefaultvalue(self.opt, self.path, True, index,
undefined, True)
if self.opt.impl_is_submulti():
value = SubMulti(value, self.context, self.opt, self.path, index)
return value
def append(self, value=undefined, force=False, setitem=True, validate=True,
force_permissive=False):
"""the list value can be updated (appened)
only if the option is a master
"""
if not force and self.opt.impl_is_master_slaves('slave'):
raise SlaveError(_("cannot append a value on a multi option {0}"
" which is a slave").format(self.opt.impl_getname()))
index = self.__len__()
if value is undefined:
value = self._getdefaultvalue(index)
if validate and value not in [None, undefined]:
context = self._getcontext()
setting = context.cfgimpl_get_settings()
setting_properties = setting._getproperties(read_write=False)
if 'validator' in setting_properties:
session = context.cfgimpl_get_values()._p_.getsession()
fake_context = context._gen_fake_values(session)
fake_multi = Multi(list(self), weakref.ref(fake_context), self.opt, self.path)
fake_multi.append(value, validate=False, force=True,
setitem=setitem)
self._validate(value, fake_context, index, True)
if not '_index' in self.__slots__ and self.opt.impl_is_submulti():
if not isinstance(value, SubMulti):
value = SubMulti(value, self.context, self.opt, self.path, index)
value.refmulti = weakref.ref(self)
super(Multi, self).append(value)
if setitem:
self._store(force=force)
def append_properties_error(self, err):
super(Multi, self).append(err)
def sort(self, cmp=None, key=None, reverse=False):
if self.opt.impl_is_master_slaves():
raise SlaveError(_("cannot sort multi option {0} if master or slave"
"").format(self.opt.impl_getname()))
if sys.version_info[0] >= 3: # pragma: no cover
if cmp is not None:
raise ValueError(_('cmp is not permitted in python v3 or '
'greater'))
super(Multi, self).sort(key=key, reverse=reverse)
else:
super(Multi, self).sort(cmp=cmp, key=key, reverse=reverse)
self._store()
def reverse(self):
if self.opt.impl_is_master_slaves():
raise SlaveError(_("cannot reverse multi option {0} if master or "
"slave").format(self.opt.impl_getname()))
super(Multi, self).reverse()
self._store()
def insert(self, index, value, validate=True):
if self.opt.impl_is_master_slaves():
raise SlaveError(_("cannot insert multi option {0} if master or "
"slave").format(self.opt.impl_getname()))
context = self._getcontext()
setting = setting = context.cfgimpl_get_settings()
setting_properties = setting._getproperties(read_write=False)
if 'validator' in setting_properties and validate and value is not None:
session = context.cfgimpl_get_values()._p_.getsession()
fake_context = context._gen_fake_values(session)
fake_multi = Multi(list(self), weakref.ref(fake_context), self.opt, self.path)
fake_multi.insert(index, value, validate=False)
self._validate(value, fake_context, index, True)
super(Multi, self).insert(index, value)
self._store()
def extend(self, iterable, validate=True):
if self.opt.impl_is_master_slaves():
raise SlaveError(_("cannot extend multi option {0} if master or "
"slave").format(self.opt.impl_getname()))
index = getattr(self, '_index', None)
context = self._getcontext()
setting = context.cfgimpl_get_settings()
setting_properties = setting._getproperties(read_write=False)
if 'validator' in setting_properties and validate:
session = context.cfgimpl_get_values()._p_.getsession()
fake_context = context._gen_fake_values(session)
fake_multi = Multi(list(self), weakref.ref(fake_context), self.opt, self.path)
if index is None:
fake_multi.extend(iterable, validate=False)
self._validate(fake_multi, fake_context, index)
else:
fake_multi[index].extend(iterable, validate=False)
self._validate(fake_multi[index], fake_context, index)
super(Multi, self).extend(iterable)
self._store()
def _validate(self, value, fake_context, force_index, submulti=False):
err = self.opt.impl_validate(value, context=fake_context,
force_index=force_index,
multi=self)
if err:
raise err
def pop(self, index, force=False):
"""the list value can be updated (poped)
only if the option is a master
:param index: remove item a index
:type index: int
:param force: force pop item (without check master/slave)
:type force: boolean
:returns: item at index
"""
context = self._getcontext()
if not force:
if self.opt.impl_is_master_slaves('slave'):
raise SlaveError(_("cannot pop a value on a multi option {0}"
" which is a slave").format(self.opt.impl_getname()))
if self.opt.impl_is_master_slaves('master'):
self.opt.impl_get_master_slaves().pop(self.opt,
context.cfgimpl_get_values(), index)
#set value without valid properties
ret = super(Multi, self).pop(index)
self._store(force=force)
return ret
def remove(self, value):
idx = self.index(value)
return self.pop(idx)
def _store(self, force=False, index=None):
values = self._getcontext().cfgimpl_get_values()
if not force:
#FIXME could get properties an pass it
values.validate(self.opt, self, self.path, valid_masterslave=False)
values._setvalue(self.opt, self.path, self, index=index)
class SubMulti(Multi):
__slots__ = ('_index', 'refmulti')
def __init__(self, value, context, opt, path, index):
"""
:param index: index (only for slave with submulti)
:type index: `int`
"""
self._index = index
super(SubMulti, self).__init__(value, context, opt, path)
def append(self, value=undefined):
super(SubMulti, self).append(value, force=True)
def pop(self, index):
return super(SubMulti, self).pop(index, force=True)
def __setitem__(self, index, value):
self._setitem(index, value)
def _store(self, force=False, index=None):
#force is unused here
values = self._getcontext().cfgimpl_get_values()
values.validate(self.opt, self, self.path, valid_masterslave=False)
multi = self.refmulti()
if multi is None:
multi = values._get_cached_value(self.opt, path=self.path)
multi[self._index] = self
values._setvalue(self.opt, self.path, multi)
def _validate(self, value, fake_context, force_index, submulti=False):
if value is not None:
if submulti is False:
super(SubMulti, self)._validate(value, fake_context,
force_index, submulti)
else:
err = self.opt.impl_validate(value, context=fake_context,
force_index=self._index,
force_submulti_index=force_index,
multi=self)
if err:
raise err
def _getdefaultvalue(self, index):
values = self._getcontext().cfgimpl_get_values()
return values._getdefaultvalue(self.opt, self.path, True, index,
self._index, True)