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 ismaster:
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:
#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])
raise Exception('pouet')
else:
api.option(path).value.set(first_value)
else:
if ismaster:
raises(PropertiesOptionError, "api.option(path).value.append(first_value[0])")
raises(PropertiesOptionError, "api.option(path).value.set([first_value[0]])")
elif isslave:
raises(PropertiesOptionError, "api.option(path, 0).value.set(first_value[0])")
else:
@ -180,31 +177,30 @@ def autocheck_value(api, path, **kwargs):
if ismaster:
raises(APIError, "api.unrestraint.option(path).value.set(second_value[1])")
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:
raises(APIError, "api.unrestraint.option(path).value.set(second_value)")
if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False):
if ismaster:
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:
#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])
raise Exception('ca entre ici')
else:
api.option(path).value.set(second_value)
elif kwargs.get('permissive', False):
if ismaster:
api.forcepermissive.option(path).value.append(second_value[0])
api.forcepermissive.option(path).value.append(second_value[1])
api.forcepermissive.option(path).value.set([first_value[0], second_value[1]])
elif isslave:
api.forcepermissive.option(path, 1).value.set(second_value[1])
else:
api.forcepermissive.option(path).value.set(first_value)
else:
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:
raises(PropertiesOptionError, "api.forcepermissive.option(path, 0).value.set(first_value[0])")
else:
@ -240,15 +236,8 @@ def autocheck_value(api, path, **kwargs):
@autocheck
def autocheck_reset_value(api, path, **kwargs):
# check if is a multi, a master or a slave
if not kwargs.get('propertyerror', False):
multi = api.forcepermissive.option(path).option.ismulti()
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()
multi = api.unrestraint.option(path).option.ismulti()
isslave = api.unrestraint.option(path).option.isslave()
# set default value (different if value is multi or not)
if not multi:
@ -337,14 +326,8 @@ def autocheck_property(api, path, **kwargs):
"""get property from path
"""
# check if is a multi or a slave
if not kwargs.get('propertyerror', False):
multi = api.forcepermissive.option(path).option.ismulti()
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()
multi = api.unrestraint.option(path).option.ismulti()
isslave = api.unrestraint.option(path).option.isslave()
# define properties
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, 1).property.get()) == set(default_props)
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
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):
api.option(path).property.set(properties)
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
if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False):
assert set(api.option(path).property.get()) == set(properties)
assert set(api.forcepermissive.option(path).property.get()) == set(properties)
elif kwargs.get('permissive', False):
raises(PropertiesOptionError, "api.option(path).property.get()")
if not isslave:
raises(PropertiesOptionError, "api.option(path).property.get()")
assert set(api.forcepermissive.option(path).property.get()) == set(default_props)
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, 1).property.get()) == set(default_props)
else:
@ -588,7 +578,8 @@ def autocheck_owner_with_value(api, path, **kwargs):
if not isslave:
assert api.forcepermissive.option(path).owner.isdefault() is False
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:
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_option(path):
option_infos = path.split('_')
def make_option(path, option_infos):
#FIXME
option_type = 'str'
option_properties = []
for option_info in option_infos[1:]:
if option_info in OPTIONS_TYPE:
option_type = option_info
elif option_info in PROPERTIES:
option_properties.append(option_info)
else:
raise Exception('unknown {} in {}'.format(option_info, path))
args = [option_infos[0], "{}'s option".format(option_infos[0])]
if option_infos is not None:
for prop in PROPERTIES:
if option_infos.get(prop, False) is True:
option_properties.append(prop)
args = [path, "{}'s option".format(path)]
kwargs = {}
if option_properties != []:
kwargs['properties'] = tuple(option_properties)
@ -794,23 +782,21 @@ def make_api(options, multi):
return tiramisu_option(*args, **kwargs)
def make_optiondescriptions(path, collected):
infos = path.split('_')
name = infos[0]
infos = collected.get('properties', {})
properties = []
kwargs = {}
optiondescription = OptionDescription
for info in infos[1:]:
if info in PROPERTIES:
properties.append(info)
elif info == 'master':
if not multi:
return
optiondescription = MasterSlaves
elif info == 'dyn':
optiondescription = DynOptionDescription
kwargs['callback'] = return_list
else:
raise Exception('unknown {} in {}'.format(info, path))
for prop in PROPERTIES:
if infos.get(prop, False) is True:
properties.append(prop)
if infos.get('master', False) is True:
if not multi:
return
optiondescription = MasterSlaves
if infos.get('dyn', False) is True:
optiondescription = DynOptionDescription
kwargs['callback'] = return_list
options = []
if 'options' in collected:
options.extend(collected['options'])
@ -823,19 +809,20 @@ def make_api(options, multi):
options.append(option)
if 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 = {}
for option in options:
for path, option in options.items():
if option is None:
continue
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 = local_collect_options[optiondescription]
path = '.'.join(option.split('.')[:-1])
option_name = option.split('.')[-1]
local_collect_options.setdefault("options", []).append(make_option(option_name))
local_collect_options['properties'] = option.get(optiondescription, {})
option_name = path.split('.')[-1]
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)
if rootod is None:
@ -846,39 +833,45 @@ def make_api(options, multi):
DICT_PATHS = [
#test a config without optiondescription
OrderedDict([('first', 'first'),
('second', 'second_disabled'),
('third', 'third_hidden')]),
OrderedDict([('first', {}),
('second', {'second': {'disabled': True}}),
('third', {'third': {'hidden': True}})]),
#test a config with an optiondescription
OrderedDict([('subod.first', 'subod.first'),
('subod.second', 'subod.second_disabled'),
('subod.third', 'subod.third_hidden')]),
OrderedDict([('subod.first', {}),
('subod.second', {'second': {'disabled': True}}),
('subod.third', {'third': {'hidden': True}})]),
#test a config with two optiondescription
OrderedDict([('subod.subsubod.first', 'subod.subsubod.first'),
('subod.subsubod.second', 'subod.subsubod.second_disabled'),
('subod.subsubod.third', 'subod.subsubod.third_hidden')]),
OrderedDict([('subod.subsubod.first', {}),
('subod.subsubod.second', {'second': {'disabled': True}}),
('subod.subsubod.third', {'third': {'hidden': True}})]),
#test a config with mix of different optiondescription
OrderedDict([('first', 'first'),
('subod.second', 'subod.second_disabled'),
('subod.subsubod.third', 'subod.subsubod.third_hidden')]),
OrderedDict([('first', {}),
('subod.second', {'second': {'disabled': True}}),
('subod.subsubod.third', {'third': {'hidden': True}})]),
#test a config with masterslaves
OrderedDict([('first.first', 'first_master.first'),
('first.second', 'first_master.second_disabled'),
('first.third', 'first_master.third_hidden')]),
OrderedDict([('odmaster.first', {'odmaster': {'master': True}}),
('odmaster.second', {'second': {'disabled': True}}),
('odmaster.third', {'third': {'hidden': True}})]),
##test a config with dynoption
OrderedDict([('subodval1.firstval1', 'subod_dyn.first'),
('subodval1.secondval1', 'subod_dyn.second_disabled'),
('subodval1.thirdval1', 'subod_dyn.third_hidden'),
OrderedDict([('subod.firstv', {'subod': {'dyn': True}}),
('subod.second', {'second': {'disabled': True}}),
('subod.third', {'third': {'hidden': True}}),
('subodval1.firstval1', None),
('subodval1.secondval1', None),
('subodval1.thirdval1', None),
('subodval2.firstval2', None),
('subodval2.secondval2', None),
('subodval2.thirdval2', None)]),
#test a config with dynoption subdir
OrderedDict([('subod.subodval1.firstval1', 'subod.subod_dyn.first'),
('subod.subodval1.secondval1', 'subod.subod_dyn.second_disabled'),
('subod.subodval1.thirdval1', 'subod.subod_dyn.third_hidden'),
('subod.subodval2.firstval2', None),
('subod.subodval2.secondval2', None),
('subod.subodval2.thirdval2', None)])
OrderedDict([('subod.subsubod.first', {'subod': {'dyn': True}}),
('subod.subsubod.second', {'second': {'disabled': True}}),
('subod.subsubod.third', {'third': {'hidden': True}}),
('subod.subsubodval1.firstval1', None),
('subod.subsubodval1.secondval1', 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):
lpaths = list(paths.keys())
for multi in (False, True):
api = make_api(paths.values(), multi)
api = make_api(paths, multi)
if api is None:
continue
check_all(api, lpaths[0], multi)
@ -908,15 +901,18 @@ def test_options(paths):
DICT_PATHS2 = [
OrderedDict([('subod.subsubod.first', 'subod.subsubod_hidden.first'),
('subod.subsubod.second', 'subod.subsubod_hidden.second'),
('subod.subsubod.third', 'subod.subsubod_hidden.third_hidden')]),
OrderedDict([('subod.subodval1.firstval1', 'subod.subod_dyn_hidden.first'),
('subod.subodval1.secondval1', 'subod.subod_dyn_hidden.second'),
('subod.subodval1.thirdval1', 'subod.subod_dyn_hidden.third_hidden'),
('subod.subodval2.firstval2', None),
('subod.subodval2.secondval2', None),
('subod.subodval2.thirdval2', None)])
OrderedDict([('subod.subsubod.first', {'subsubod': {'hidden': True}}),
('subod.subsubod.second', {}),
('subod.subsubod.third', {})]),
OrderedDict([('subod.subsubod.first', {'subsub': {'dyn': True, 'hidden': True}}),
('subod.subsubod.second', {}),
('subod.subsubod.third', {}),
('subod.subsubodval1.firstval1', None),
('subod.subsubodval1.secondval1', 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
def test_tree_od_permissive(paths2):
"""permissive when optiondescription is hidden
"""
lpaths = list(paths2.keys())
for multi in (False, True):
api = make_api(paths2.values(), multi)
if api is None:
continue
check_all(api, lpaths[0], multi, permissive=True)
check_all(api, lpaths[1], multi, permissive=True)
check_all(api, lpaths[2], multi, permissive=True, extra_properties=['hidden'])
if len(lpaths) == 6:
check_all(api, lpaths[3], multi, permissive=True)
check_all(api, lpaths[4], multi, permissive=True)
check_all(api, lpaths[5], multi, permissive=True, extra_properties=['hidden'])
#FIXME
#def test_tree_od_permissive(paths2):
# """permissive when optiondescription is hidden
# """
# lpaths = list(paths2.keys())
# for multi in (False, True):
# api = make_api(paths2, multi)
# if api is None:
# continue
# check_all(api, lpaths[0], multi, permissive=True)
# check_all(api, lpaths[1], multi, permissive=True)
# check_all(api, lpaths[2], multi, permissive=True, extra_properties=['hidden'])
# if len(lpaths) == 6:
# check_all(api, lpaths[3], multi, permissive=True)
# 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
do_autopath()
from tiramisu.value import Multi
#from tiramisu.value import Multi
from tiramisu.option import IntOption, StrOption, OptionDescription
from tiramisu.config import Config
from tiramisu.error import ConfigError, PropertiesOptionError
@ -12,33 +12,6 @@ import weakref
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():
raises(ValueError, "IntOption('int', '', multi='string')")
raises(ValueError, "IntOption('int', '', multi=True, unique='string')")
@ -46,21 +19,3 @@ def test_non_valid_multi():
def test_non_multi_unique():
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.config import Config, MetaConfig
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 py.test import raises
@ -28,7 +28,7 @@ def return_list2(value=None):
def test_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)
od = OptionDescription('od', '', [multi, multi2, multi3])
cfg = Config(od)
@ -43,314 +43,6 @@ def test_submulti():
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
@ -371,35 +63,6 @@ def test_groups_with_master_in_config_submulti():
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():
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)
@ -663,54 +326,3 @@ def test_callback_submulti():
assert cfg.getowner(multi2) == owners.default
assert cfg.multi == [['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,
index,
config,
setting_properties,
force_permissive,
force_unrestraint):
self.opt = opt
@ -43,6 +44,7 @@ class CommonTiramisu(object):
if self.slave_need_index:
self._test_slave_index()
self.config = config
self.setting_properties = setting_properties
self.force_permissive = force_permissive
self.force_unrestraint = force_unrestraint
if not self.allow_unrestraint:
@ -81,11 +83,19 @@ class TiramisuOptionOption(CommonTiramisu):
allow_unrestraint = True
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,
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint)
if config:
@ -117,11 +127,19 @@ class TiramisuOptionOption(CommonTiramisu):
class TiramisuOptionOwner(CommonTiramisu):
"""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,
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint)
if config:
@ -135,9 +153,8 @@ class TiramisuOptionOwner(CommonTiramisu):
def isdefault(self):
"""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,
index=self.index,
force_permissive=self.force_permissive)
def set(self, owner):
@ -158,11 +175,19 @@ class TiramisuOptionProperty(CommonTiramisu):
#allow_unrestraint = True
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,
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint)
if config:
@ -170,7 +195,10 @@ class TiramisuOptionProperty(CommonTiramisu):
def get(self):
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):
"""set properties for a specified option"""
@ -189,11 +217,19 @@ class TiramisuOptionPermissive(CommonTiramisu):
allow_unrestraint = True
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,
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint)
if config:
@ -201,8 +237,7 @@ class TiramisuOptionPermissive(CommonTiramisu):
def get(self):
"""get permissive value for a specified path"""
setting_properties = self.settings.getproperties(None, None, obj=False)
return self.settings.getpermissive(setting_properties, self.path)
return self.settings.getpermissive(self.setting_properties, self.path)
def set(self, permissive):
self.settings.setpermissive(permissive, opt=self.opt, path=self.path)
@ -217,25 +252,28 @@ class TiramisuOptionPermissive(CommonTiramisu):
class TiramisuOptionValue(CommonTiramisu):
"""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,
path,
index,
config,
setting_properties,
force_permissive,
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):
settings = self.config.cfgimpl_get_settings()
value = self.config.getattr(self.path,
index=self.index,
setting_properties=self.setting_properties,
force_permissive=self.force_permissive)
if isinstance(value, Multi):
value = list(value)
@ -247,45 +285,53 @@ class TiramisuOptionValue(CommonTiramisu):
if isinstance(value, list):
while undefined in value:
idx = value.index(undefined)
value[idx] = values._getdefaultvalue(self.opt,
self.path,
True,
idx,
undefined,
True)
value[idx] = values.getdefaultvalue(self.opt,
self.path,
idx)
else:
if value == undefined:
value = values._getdefaultvalue(self.opt,
self.path,
True,
self.index,
undefined,
True)
value = values.getdefaultvalue(self.opt,
self.path,
self.index)
self.config.setattr(self.path,
value,
index=self.index,
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):
"""reset value for a value"""
if self.index is None:
self.config.cfgimpl_get_values().reset(self.opt,
path=self.path,
force_permissive=self.force_permissive)
else:
#FIXME ... _p_ ...
self.config.cfgimpl_get_values()._p_.resetvalue_index(self.path, self.index)
self.config.delattr(self.path,
index=self.index,
setting_properties=self.setting_properties,
force_permissive=self.force_permissive)
class TiramisuOption(object):
icon = '\u2937'
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.path = path
self.index = index
self.config = config
self.setting_properties = setting_properties
self.force_permissive = force_permissive
self.force_unrestraint = force_unrestraint
self.registers = {}
@ -310,6 +356,7 @@ class TiramisuOption(object):
self.path,
self.index,
self.config,
self.setting_properties,
self.force_permissive,
self.force_unrestraint)
elif subfunc == 'help':
@ -322,18 +369,25 @@ class TiramisuAPI(object):
icon = '\u2937'
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.force_permissive = force_permissive
self.force_unrestraint = force_unrestraint
settings = self.config.cfgimpl_get_settings()
#FIXME ?
self.config.read_write()
self.config.cfgimpl_get_settings().setpermissive(('hidden',))
settings.setpermissive(('hidden',))
#/FIXME ?
def option(self, path, index=None):
validate = not self.force_unrestraint
settings = self.config.cfgimpl_get_settings()
setting_properties = settings.getcontextproperties()
opt = self.config.unwrap_from_path(path,
setting_properties=setting_properties,
validate=validate,
validate_properties=validate,
force_permissive=self.force_permissive,
@ -344,14 +398,19 @@ class TiramisuAPI(object):
path,
index,
self.config,
force_permissive=self.force_permissive,
force_unrestraint=self.force_unrestraint)
setting_properties,
self.force_permissive,
self.force_unrestraint)
def __getattr__(self, subfunc):
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':
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':
return self._help()
else:

View File

@ -31,7 +31,7 @@ from .option import OptionDescription, Option, SymLinkOption, \
from .option.baseoption import valid_name
from .setting import groups, Settings, default_encoding, undefined
from .storage import get_storages, set_storage, get_default_values_storages
from .value import Values, Multi
from .value import Values # , Multi
from .i18n import _
@ -45,9 +45,19 @@ class SubConfig(object):
on-demand. A Config is also a SubConfig.
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
:param descr: describes the configuration schema
@ -63,13 +73,19 @@ class SubConfig(object):
error = True
if error:
raise TypeError(_('descr must be an optiondescription, not {0}'
).format(type(descr)))
).format(type(descr)))
self._impl_descr = descr
# sub option descriptions
if not isinstance(context, weakref.ReferenceType): # pragma: optional cover
raise ValueError('context must be a Weakref')
self._impl_context = context
self._impl_path = subpath
if setting_properties is not undefined:
self._impl_setting_properties = setting_properties
if 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,
only_expired=False,
@ -144,17 +160,20 @@ class SubConfig(object):
else:
reset_all_cache()
def cfgimpl_get_home_by_path(self, path, force_permissive=False,
returns_raise=False, _setting_properties=undefined,
validate_properties=True):
def cfgimpl_get_home_by_path(self,
path,
setting_properties,
validate_properties=True,
force_permissive=False,
returns_raise=False):
""":returns: tuple (config, name)"""
path = path.split('.')
for step in path[:-1]:
self = self.getattr(step,
force_permissive=force_permissive,
returns_raise=returns_raise,
validate_properties=validate_properties,
_setting_properties=_setting_properties)
returns_raise=returns_raise,
setting_properties=setting_properties)
if isinstance(self, Exception):
return self, None
return self, path[-1]
@ -269,62 +288,111 @@ class SubConfig(object):
# attribute methods
def __setattr__(self, name, value):
"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):
"""use setattr instead of _setattr
"""
self.setattr(name, value, force_permissive=force_permissive,
not_raises=not_raises)
def setattr(self,
name,
value,
force_permissive=False,
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_'):
return object.__setattr__(self, name, value)
return object.__setattr__(self,
name,
value)
context = self._cfgimpl_get_context()
if _setting_properties is undefined:
_setting_properties = context.cfgimpl_get_settings()._getproperties(read_write=True)
if setting_properties is undefined:
setting_properties = context.cfgimpl_get_settings()._getproperties(read_write=True)
if '.' in name: # pragma: optional cover
homeconfig, name = self.cfgimpl_get_home_by_path(name,
force_permissive=force_permissive,
_setting_properties=_setting_properties)
return homeconfig.setattr(name, value, force_permissive,
not_raises, index=index,
_setting_properties=_setting_properties,
_commit=_commit)
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) or isinstance(child, SynDynOptionDescription):
if isinstance(child, (OptionDescription, SynDynOptionDescription)):
raise TypeError(_("can't assign to an OptionDescription")) # pragma: optional cover
elif child._is_symlinkoption() and \
not isinstance(child, DynSymLinkOption): # pragma: no dynoptiondescription cover
path = context.cfgimpl_get_description().impl_get_path_by_opt(
child._impl_getopt())
context.setattr(path, value, force_permissive, not_raises, index=index,
_setting_properties=_setting_properties,
_commit=_commit)
raise TypeError(_("can't assign to a SymlinkOption"))
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)
ret = self.cfgimpl_get_values().setitem(child, value, subpath,
force_permissive=force_permissive,
not_raises=not_raises, index=index,
_setting_properties=_setting_properties,
_commit=_commit)
if ret is not None:
return ret
return self.cfgimpl_get_values().setitem(child,
value,
subpath,
force_permissive,
not_raises,
index,
setting_properties,
_commit)
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()
child = self.cfgimpl_get_description().__getattr__(name, context)
self.cfgimpl_get_values().__delitem__(child)
if setting_properties is undefined:
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):
return self.getattr(name)
def _getattr(self, name, force_permissive=False, validate=True): # pragma: optional cover
"""use getattr instead of _getattr
"""
return self.getattr(name, force_permissive, validate)
setting_properties = self.cfgimpl_get_context().cfgimpl_get_settings().getcontextproperties()
return self.getattr(name, setting_properties)
def _get_subpath(self, name):
if self._impl_path is None:
@ -333,10 +401,15 @@ class SubConfig(object):
subpath = self._impl_path + '.' + name
return subpath
def getattr(self, name, force_permissive=False, validate=True,
_setting_properties=undefined, _self_properties=undefined, index=None,
returns_raise=False, returns_option=False,
validate_properties=True):
def getattr(self,
name,
setting_properties,
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
:param name: attribute name
@ -346,51 +419,51 @@ class SubConfig(object):
# attribute access by passing a path,
# for instance getattr(self, "creole.general.family.adresse_ip_eth0")
context = self._cfgimpl_get_context()
if _setting_properties is undefined:
_setting_properties = context.cfgimpl_get_settings()._getproperties(read_write=True)
if '.' in name:
homeconfig, name = self.cfgimpl_get_home_by_path(
name, force_permissive=force_permissive,
validate_properties=validate_properties,
returns_raise=returns_raise, _setting_properties=_setting_properties)
homeconfig, name = self.cfgimpl_get_home_by_path(name,
force_permissive=force_permissive,
validate_properties=validate_properties,
returns_raise=returns_raise,
setting_properties=setting_properties)
if isinstance(homeconfig, Exception):
cfg = homeconfig
else:
cfg = homeconfig.getattr(name, force_permissive=force_permissive,
cfg = homeconfig.getattr(name,
force_permissive=force_permissive,
validate=validate,
_setting_properties=_setting_properties,
_self_properties=_self_properties,
index=index, returns_raise=returns_raise,
validate_properties=validate_properties)
validate_properties=validate_properties,
setting_properties=setting_properties,
index=index,
returns_raise=returns_raise)
else:
option = self.cfgimpl_get_description().__getattr__(name,
context=context)
subpath = self._get_subpath(name)
if isinstance(option, DynSymLinkOption):
cfg = self.cfgimpl_get_values()._get_cached_value(
option, path=subpath,
validate=validate,
force_permissive=force_permissive,
setting_properties=_setting_properties,
self_properties=_self_properties,
validate_properties=validate_properties,
index=index)
cfg = self.cfgimpl_get_values().get_cached_value(option,
path=subpath,
validate=validate,
validate_properties=validate_properties,
force_permissive=force_permissive,
setting_properties=setting_properties,
index=index)
elif option._is_symlinkoption(): # pragma: no dynoptiondescription cover
path = context.cfgimpl_get_description().impl_get_path_by_opt(
option._impl_getopt())
cfg = context.getattr(path, validate=validate,
force_permissive=force_permissive,
_setting_properties=_setting_properties,
_self_properties=_self_properties,
path = context.cfgimpl_get_description().impl_get_path_by_opt(option._impl_getopt())
cfg = context.getattr(path,
validate=validate,
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():
if validate_properties:
props = self.cfgimpl_get_settings().validate_properties(
option, True, False, path=subpath,
force_permissive=force_permissive,
self_properties=_self_properties,
setting_properties=_setting_properties)
if setting_properties:
props = self.cfgimpl_get_settings().validate_properties(option,
True,
False,
path=subpath,
force_permissive=force_permissive,
setting_properties=setting_properties)
if props:
if returns_raise:
return props
@ -398,25 +471,29 @@ class SubConfig(object):
raise props
if returns_option is True:
return option
return SubConfig(option, self._impl_context, subpath)
return SubConfig(option,
self._impl_context,
setting_properties,
validate,
force_permissive,
subpath)
else:
if validate:
ret = self.cfgimpl_get_description().impl_validate(context,
force_permissive,
_setting_properties)
setting_properties)
if ret:
if returns_raise:
return ret
else:
raise ret
cfg = self.cfgimpl_get_values()._get_cached_value(
option, path=subpath,
validate=validate,
force_permissive=force_permissive,
setting_properties=_setting_properties,
self_properties=_self_properties,
validate_properties=validate_properties,
index=index)
cfg = self.cfgimpl_get_values().get_cached_value(option,
path=subpath,
validate=validate,
validate_properties=validate_properties,
force_permissive=force_permissive,
setting_properties=setting_properties,
index=index)
if not returns_raise and isinstance(cfg, Exception):
raise cfg
if returns_option is True:
@ -473,13 +550,13 @@ class SubConfig(object):
if byvalue is undefined:
return True
value = self.getattr(path, force_permissive=force_permissive,
_setting_properties=setting_properties,
setting_properties=setting_properties,
returns_raise=True)
if isinstance(value, Exception):
if isinstance(value, PropertiesOptionError):
return False
raise value # pragma: no cover
elif isinstance(value, Multi):
elif isinstance(value, list):
return byvalue in value
else:
return value == byvalue
@ -506,7 +583,7 @@ class SubConfig(object):
if byvalue is undefined and check_properties:
value = self.getattr(path,
force_permissive=force_permissive,
_setting_properties=setting_properties,
setting_properties=setting_properties,
returns_raise=True)
if isinstance(value, Exception):
if isinstance(value, PropertiesOptionError):
@ -533,9 +610,14 @@ class SubConfig(object):
else:
return find_results
def make_dict(self, flatten=False, _currpath=None, withoption=None,
withvalue=undefined, force_permissive=False,
setting_properties=undefined, fullpath=False):
def make_dict(self,
flatten=False,
_currpath=None,
withoption=None,
withvalue=undefined,
force_permissive=False,
setting_properties=undefined,
fullpath=False):
"""exports the whole config into a `dict`, for example:
>>> print cfg.make_dict()
@ -579,17 +661,20 @@ class SubConfig(object):
raise ValueError(_("make_dict can't filtering with value without "
"option"))
if setting_properties is undefined:
setting_properties = self.cfgimpl_get_settings()._getproperties(
read_write=False)
setting_properties = self.cfgimpl_get_settings()._getproperties(read_write=False)
if withoption is not None:
context = self._cfgimpl_get_context()
for path in context._find(bytype=None, byname=withoption,
byvalue=withvalue, first=False,
type_='path', _subpath=self.cfgimpl_get_path(False),
for path in context._find(bytype=None,
byname=withoption,
byvalue=withvalue,
first=False,
type_='path',
_subpath=self.cfgimpl_get_path(False),
force_permissive=force_permissive,
setting_properties=setting_properties):
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()
if mypath is not None:
if mypath == path:
@ -624,7 +709,7 @@ class SubConfig(object):
setting_properties, force_permissive=False, fullpath=False):
value = self.getattr(path,
force_permissive=force_permissive,
_setting_properties=setting_properties,
setting_properties=setting_properties,
returns_raise=True)
if isinstance(value, Exception):
if not isinstance(value, PropertiesOptionError): # pragma: no cover
@ -689,30 +774,52 @@ class _CommonConfig(SubConfig):
return self.cfgimpl_get_values().getowner(opt, index=index,
force_permissive=force_permissive)
def unwrap_from_path(self, path, force_permissive=False, index=None,
validate_properties=True, validate=True,
_setting_properties=undefined):
def unwrap_from_path(self,
path,
setting_properties=undefined,
force_permissive=False,
index=None,
validate=True,
validate_properties=True):
"""convenience method to extract and Option() object from the Config()
and it is **fast**: finds the option directly in the appropriate
namespace
: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:
self, path = self.cfgimpl_get_home_by_path(path,
validate_properties=validate_properties,
force_permissive=force_permissive,
_setting_properties=_setting_properties)
return self.getattr(path,
validate_properties=validate_properties,
validate=validate,
force_permissive=force_permissive,
index=index,
_setting_properties=_setting_properties,
returns_option=True)
validate_properties=validate_properties,
setting_properties=setting_properties)
if not validate_properties:
return self.cfgimpl_get_description().__getattr__(path,
context=self._cfgimpl_get_context())
else:
option = self.cfgimpl_get_description().__getattr__(path,
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):
return None
@ -743,19 +850,17 @@ class _CommonConfig(SubConfig):
def __getstate__(self):
raise NotImplementedError()
def _gen_fake_values(self, session):
def _gen_fake_values(self):
fake_config = Config(self._impl_descr, persistent=False,
force_values=get_default_values_storages(),
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
def duplicate(self, force_values=None, force_settings=None):
config = Config(self._impl_descr, _duplicate=True, force_values=force_values,
force_settings=force_settings)
session = self.cfgimpl_get_values()._p_.getsession()
config.cfgimpl_get_values()._p_.importation(self.cfgimpl_get_values()._p_.exportation(
session))
config.cfgimpl_get_values()._p_.importation(self.cfgimpl_get_values()._p_.exportation())
config.cfgimpl_get_settings()._p_.set_modified_properties(self.cfgimpl_get_settings(
)._p_.get_modified_properties())
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))
self._impl_settings = Settings(self, properties, permissives)
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
#undocumented option used only in test script
self._impl_test = False
@ -926,21 +1031,25 @@ class GroupConfig(_CommonConfig):
__repr__ = __str__
def getattr(self, name, force_permissive=False, validate=True,
_setting_properties=undefined, _self_properties=undefined, index=None,
returns_raise=False, returns_option=False,
validate_properties=True):
def getattr(self,
name,
setting_properties,
force_permissive=False,
validate=True,
index=None,
returns_raise=False,
validate_properties=True,
returns_option=False):
for child in self._impl_children:
if name == child._impl_name:
return child
return super(GroupConfig, self).getattr(name, force_permissive,
validate,
_self_properties=_self_properties,
index=index,
_setting_properties=_setting_properties,
setting_properties=setting_properties,
returns_raise=returns_raise,
returns_option=False,
validate_properties=validate_properties)
validate_properties=validate_properties,
returns_option=False)
class MetaConfig(GroupConfig):
@ -1000,22 +1109,30 @@ class MetaConfig(GroupConfig):
else:
child_value = child.getattr(path)
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,
_setting_properties=setting_properties,
_commit=False)
continue
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)
if isinstance(child_value, Exception):
ret.append(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
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:
ret.append(setret)
return ret
@ -1024,13 +1141,15 @@ class MetaConfig(GroupConfig):
opt = self.cfgimpl_get_description().impl_get_opt_by_path(path)
setting_properties = self.cfgimpl_get_settings()._getproperties(read_write=False)
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,
_setting_properties=setting_properties,
_commit=False)
self.cfgimpl_get_values().reset(opt, path=path,
validate=False,
_setting_properties=setting_properties)
self.cfgimpl_get_values().reset(opt,
path,
setting_properties,
validate=False)
def new_config(self, session_id, persistent=False):
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):
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:
calc_properties, requires = validate_requires_arg(self, is_multi,
requires, name)
@ -654,13 +654,18 @@ class DynSymLinkOption(object):
else:
return base_path + '.' + self._dyn
def impl_validate(self, value, context=undefined, validate=True,
force_index=None, force_submulti_index=None, is_multi=None,
display_error=True, display_warnings=True, multi=None,
def impl_validate(self,
value,
context=undefined,
validate=True,
force_index=None,
is_multi=None,
display_error=True,
display_warnings=True,
multi=None,
setting_properties=undefined):
return self._impl_getopt().impl_validate(value, context, validate,
force_index,
force_submulti_index,
current_opt=self,
is_multi=is_multi,
display_error=display_error,

View File

@ -112,12 +112,23 @@ class Option(OnlyOption):
super(Option, self).__init__(name, doc, requires=requires,
properties=properties, is_multi=is_multi)
if is_multi and default_multi is not None:
err = self._validate(default_multi)
if err:
raise ValueError(_("invalid default_multi value {0} "
"for option {1}: {2}").format(
str(default_multi),
self.impl_getname(), str(err)))
def test_multi_value(value):
err = self._validate(value)
if err:
raise ValueError(_("invalid default_multi value {0} "
"for option {1}: {2}").format(
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)
if unique is not undefined:
_setattr(self, '_unique', unique)
@ -239,10 +250,17 @@ class Option(OnlyOption):
ret_val = val
return ret_val
def impl_validate(self, value, context=undefined, validate=True,
force_index=None, force_submulti_index=None,
current_opt=undefined, is_multi=None,
display_error=True, display_warnings=True, multi=None,
def impl_validate(self,
value,
context=undefined,
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):
"""
:param value: the option's value
@ -290,7 +308,8 @@ class Option(OnlyOption):
else:
validator_params_ = {'': (val,)}
# Raise ValueError if not valid
value = carry_out_calculation(current_opt, context=context,
value = carry_out_calculation(current_opt,
context=context,
callback=validator,
callback_params=validator_params_,
index=_index,
@ -304,11 +323,14 @@ class Option(OnlyOption):
else:
if display_error:
# option validation
err = self._validate(_value, context, current_opt)
err = self._validate(_value,
context,
current_opt)
if err:
if debug: # pragma: no cover
log.debug('do_validation: value: {0}, index: {1}, '
'submulti_index: {2}'.format(_value, _index,
'submulti_index: {2}'.format(_value,
_index,
submulti_index),
exc_info=True)
err_msg = '{0}'.format(err)
@ -342,8 +364,12 @@ class Option(OnlyOption):
if error is None:
# if context launch consistency validation
#if context is not undefined:
ret = self._valid_consistency(current_opt, _value, context,
_index, submulti_index, display_warnings,
ret = self._valid_consistency(current_opt,
_value,
context,
_index,
submulti_index,
display_warnings,
display_error)
if isinstance(ret, ValueError):
error = ret
@ -421,8 +447,13 @@ class Option(OnlyOption):
err = do_validation(val, idx, force_submulti_index)
if err:
return err
return self._valid_consistency(current_opt, None, context,
None, None, display_warnings, display_error)
return self._valid_consistency(current_opt,
None,
context,
None,
None,
display_warnings,
display_error)
def impl_is_dynsymlinkoption(self):
return False
@ -596,7 +627,11 @@ class Option(OnlyOption):
def impl_getdefault_multi(self):
"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):
"""callback_params:
@ -605,7 +640,7 @@ class Option(OnlyOption):
"""
if callback is None:
return
default_multi = self.impl_getdefault_multi()
default_multi = getattr(self, '_default_multi', None)
is_multi = self.impl_is_multi()
default = self.impl_getdefault()
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 '
'force_store_value property').format(subpath))
if force_store_values and not config._impl_values._p_.hasvalue(subpath, session):
value = config.cfgimpl_get_values()._get_cached_value(option,
path=subpath,
validate=False,
trusted_cached_properties=False,
validate_properties=True)
value = config.cfgimpl_get_values().get_cached_value(option,
path=subpath,
validate=False,
trusted_cached_properties=False,
validate_properties=True)
value_set = True
config._impl_values._p_.setvalue(subpath, value,
owners.forced, None, session, False)
@ -497,6 +497,9 @@ class OptionDescription(OptionDescriptionWalk):
raise ValueError(_("invalid suffix: {0} for option").format(val))
return values
def impl_validate_value(self, option, value, context):
pass
class DynOptionDescription(OptionDescription):
def __init__(self, name, doc, children, requires=None, properties=None,
@ -561,9 +564,13 @@ class SynDynOptionDescription(object):
class MasterSlaves(OptionDescription):
__slots__ = ('master', 'slaves')
def __init__(self, name, doc, children, requires=None, properties=None):
#if master (same name has group) is set
#for collect all slaves
def __init__(self,
name,
doc,
children,
requires=None,
properties=None):
super(MasterSlaves, self).__init__(name,
doc,
children,
@ -572,10 +579,6 @@ class MasterSlaves(OptionDescription):
self._group_type = groups.master
slaves = []
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:]:
if child.impl_getdefault() != []:
raise ValueError(_("not allowed default value for option {0} "
@ -604,8 +607,6 @@ class MasterSlaves(OptionDescription):
raise ValueError(_("callback of master's option shall "
"not refered a slave's ones"))
#everything is ok, store references
#self.master = master
#self.slaves = tuple(slaves)
for child in children:
child._master_slaves = self
master._add_dependency(self)
@ -644,41 +645,74 @@ class MasterSlaves(OptionDescription):
c_opt = opt
return c_opt in self._children[1]
def reset(self, opt, values, setting_properties, _commit=True, force_permissive=False):
for slave in self.getslaves(opt):
values.reset(slave, validate=False, _setting_properties=setting_properties,
_commit=_commit, force_permissive=force_permissive)
def reset(self,
opt,
values,
setting_properties,
_commit=True,
force_permissive=False):
def pop(self, opt, values, index):
for slave in self.getslaves(opt):
slave_path = slave.impl_getpath(values._getcontext())
slavelen = values._p_.get_max_length(slave_path, None)
# just for raise if needed
if not values.is_default_owner(slave, validate_properties=False,
validate_meta=False, index=index):
multi = values._get_cached_value(slave, validate=False,
validate_properties=False,
)
if isinstance(multi, Exception):
raise multi
values.reset(slave,
slave_path,
setting_properties,
validate=False,
_commit=_commit,
force_permissive=force_permissive)
def pop(self,
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:
values._p_.resetvalue_index(slave_path, index)
values._p_.resetvalue_index(slave_path,
index)
if slavelen > index + 1:
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,
trusted_cached_properties, validate_properties,
slave_path=undefined, slave_value=undefined,
setting_properties=undefined, self_properties=undefined, index=None,
def getitem(self,
values,
opt,
path,
validate,
force_permissive,
trusted_cached_properties,
validate_properties,
setting_properties=undefined,
self_properties=undefined,
index=None,
check_frozen=False):
if self.is_master(opt):
return self._getmaster(values, opt, path, validate,
return self._getmaster(values,
opt,
path,
validate,
force_permissive,
validate_properties, slave_path,
slave_value, self_properties, index,
setting_properties, check_frozen)
validate_properties,
self_properties,
index,
setting_properties,
check_frozen)
else:
return self._getslave(values, opt, path, validate,
force_permissive, trusted_cached_properties,
@ -686,17 +720,26 @@ class MasterSlaves(OptionDescription):
self_properties, index,
check_frozen)
def _getmaster(self, values, opt, path, validate, force_permissive,
validate_properties, c_slave_path,
c_slave_value, self_properties, index,
setting_properties, check_frozen):
return values._get_cached_value(opt, path=path, validate=validate,
force_permissive=force_permissive,
validate_properties=validate_properties,
self_properties=self_properties,
from_masterslave=True, index=index,
setting_properties=setting_properties,
check_frozen=check_frozen)
def _getmaster(self,
values,
opt,
path,
validate,
force_permissive,
validate_properties,
self_properties,
index,
setting_properties,
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,
trusted_cached_properties, validate_properties, setting_properties,
@ -725,20 +768,20 @@ class MasterSlaves(OptionDescription):
master = self.getmaster(opt)
context = values._getcontext()
masterp = master.impl_getpath(context)
mastervalue = values._get_cached_value(master, path=masterp, validate=validate,
force_permissive=force_permissive,
validate_properties=validate_properties,
self_properties=self_properties,
from_masterslave=True,
setting_properties=setting_properties,
check_frozen=check_frozen)
mastervalue = values.get_cached_value(master, path=masterp, validate=validate,
force_permissive=force_permissive,
validate_properties=validate_properties,
self_properties=self_properties,
from_masterslave=True,
setting_properties=setting_properties,
check_frozen=check_frozen)
if isinstance(mastervalue, Exception):
if isinstance(mastervalue, PropertiesOptionError):
mastervalue.set_orig_opt(opt)
return mastervalue
masterlen = len(mastervalue)
master_is_meta = values._is_meta(master, masterp, force_permissive=force_permissive)
multi = values._get_multi(opt, path)
#self._master_is_meta = values._is_meta(master, masterp, force_permissive=force_permissive)
multi = list() # values._get_multi(opt, path)
if validate_properties:
props = context.cfgimpl_get_settings().validate_properties(opt, False,
check_frozen,
@ -748,68 +791,84 @@ class MasterSlaves(OptionDescription):
setting_properties=setting_properties)
if props:
return props
#FIXME shouldn't have index!!!
if index is None:
indexes = xrange(0, masterlen)
else:
indexes = [index]
for idx in indexes:
value = values._get_cached_value(opt, path, validate,
force_permissive,
trusted_cached_properties,
validate_properties,
with_meta=master_is_meta,
index=idx,
# not self_properties,
# depends to index
#self_properties=self_properties,
setting_properties=setting_properties,
masterlen=masterlen,
from_masterslave=True,
check_frozen=check_frozen)
value = values.get_cached_value(opt, path, validate,
force_permissive,
trusted_cached_properties,
validate_properties,
index=idx,
# not self_properties,
# depends to index
#self_properties=self_properties,
setting_properties=setting_properties,
from_masterslave=True,
check_frozen=check_frozen)
if isinstance(value, Exception):
if isinstance(value, PropertiesOptionError):
err = value
if index is None:
multi.append_properties_error(value)
multi.append(value)
else:
multi = value
else:
return value
elif index is None:
multi.append(value, setitem=False, force=True, validate=False,
force_permissive=force_permissive)
multi.append(value)
else:
multi = value
return multi
def validate(self, values, opt, index, path, setitem):
def validate(self,
values,
opt,
index,
path,
setitem):
if self.is_master(opt):
#for regen slave path
base_path = '.'.join(path.split('.')[:-1]) + '.'
for slave in self.getslaves(opt):
slave_path = base_path + slave.impl_getname()
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:
val_len = self.get_length(values, opt, slave_path=path)
val_len = self.get_length(values)
if isinstance(val_len, Exception):
return val_len
self.validate_slave_length(val_len, index,
opt.impl_getname(), opt, setitem=setitem)
self.validate_slave_length(val_len,
index,
opt.impl_getname(),
opt,
setitem=setitem)
def get_length(self, values, opt, validate=True, slave_path=undefined,
slave_value=undefined, force_permissive=False, master=None,
masterp=None, setting_properties=undefined):
def get_length(self,
values,
validate=True,
force_permissive=False,
master=None,
masterp=None,
setting_properties=undefined):
"""get master len with slave option"""
if master is None:
master = self.getmaster(None)
if masterp is None:
masterp = master.impl_getpath(self._getcontext())
if slave_value is undefined:
slave_path = undefined
value = self.getitem(values, master, masterp, validate,
force_permissive, None, True, slave_path=slave_path,
slave_value=slave_value, setting_properties=setting_properties)
masterp = master.impl_getpath(values._getcontext())
value = self.getitem(values,
master,
masterp,
validate,
force_permissive,
None,
True,
setting_properties=setting_properties)
if isinstance(value, Exception):
return value
return len(value)
@ -843,10 +902,9 @@ class MasterSlaves(OptionDescription):
master = self.getmaster(opt)
masterp = master.impl_getpath(context)
mastervalue = values._get_cached_value(master, path=masterp,
force_permissive=force_permissive,
from_masterslave=True,
setting_properties=setting_properties)
mastervalue = values.get_cached_value(master, path=masterp,
force_permissive=force_permissive,
setting_properties=setting_properties)
if isinstance(mastervalue, Exception):
return mastervalue
masterlen = len(mastervalue)
@ -857,9 +915,15 @@ class MasterSlaves(OptionDescription):
else:
for slave in self.getslaves(master):
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)
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):
"""returns a list of all paths in klass, recursively

View File

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

View File

@ -67,7 +67,7 @@ class Values(Cache):
return vidx
# value
def setvalue(self, path, value, owner, index, session, commit):
def setvalue(self, path, value, owner, index, commit):
"""set value for a path
a specified value must be associated to an owner
"""
@ -137,7 +137,7 @@ class Values(Cache):
_resetvalue_index(3)
self._values = tuple(values)
def resetvalue(self, path, session, commit):
def resetvalue(self, path, commit):
"""remove value means delete value in storage
"""
def _resetvalue(nb):
@ -174,7 +174,7 @@ class Values(Cache):
return values
# owner
def setowner(self, path, owner, session, index=None):
def setowner(self, path, owner, index=None):
"""change owner for a path
"""
idx = self._values[0].index(path)
@ -188,14 +188,14 @@ class Values(Cache):
lst[3] = tuple(values[0])
self._values = tuple(lst)
def get_max_length(self, path, session):
def get_max_length(self, path):
if path in self._values[0]:
idx = self._values[0].index(path)
else:
return 0
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):
"""get owner for a path
return: owner object
@ -271,11 +271,11 @@ class Values(Cache):
if raises:
raise ValueError(_("information's item not found {0}").format(key))
def exportation(self, session, fake=False):
def exportation(self, fake=False):
return self._values
def importation(self, export):
self._values = export
def delete_session(session_id, session):
def delete_session(session_id):
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
# 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):
@ -29,17 +35,41 @@ class Cache(object):
"""add val in cache for a specified path
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)
def getcache(self, path, exp, index):
value, created = self._cache[path][index]
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 False, None # pragma: no cover
def delcache(self, 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:
del self._cache[path]
@ -48,6 +78,8 @@ class Cache(object):
: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]
def reset_expired_cache(self, exp):
@ -63,6 +95,8 @@ class Cache(object):
def reset_all_cache(self):
"empty the cache"
if DEBUG:
print('bzzzzzzzzzzzz delete tout le cache', POUET(self))
self._cache.clear()
def get_cached(self):

View File

@ -54,76 +54,129 @@ class Values(object):
raise ConfigError(_('the context does not exist anymore'))
return context
def _get_multi(self, opt, path):
return Multi([], self.context, opt, path)
def getdefaultvalue(self,
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,
_orig_context=undefined):
if _orig_context is undefined:
_orig_context = self._getcontext()
def _getdefaultvalue(self,
opt,
path,
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:
meta = self._getcontext().cfgimpl_get_meta()
if meta is not None:
value = meta.cfgimpl_get_values(
)._get_cached_value(opt, path, index=index, submulti_index=submulti_index,
from_masterslave=True, _orig_context=_orig_context)
# retrieved value from meta config
value = meta.cfgimpl_get_values().get_cached_value(opt,
path,
index=index,
_orig_context=_orig_context)
if isinstance(value, Exception):
# if properties error, return an other default value
if not isinstance(value, PropertiesOptionError): # pragma: no cover
# unexpected error, should not happened
raise value
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
# if value has callback and is not set
if opt.impl_has_callback():
# if value has callback, calculate value
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_params=callback_params,
index=index, validate=validate)
_orig_context.cfgimpl_reset_cache(opt=opt, path=path, only=('values', 'properties'))
index=index,
validate=validate)
if isinstance(value, list) and index is not None:
#if return a list and index is set, return value only if
#it's a submulti without submulti_index and without list of list
if opt.impl_is_submulti() and submulti_index is undefined and \
(len(value) == 0 or not isinstance(value[0], list)):
# if value is a list and index is set
if opt.impl_is_submulti() and (value == [] or not isinstance(value[0], list)):
# return value only if it's a submulti and not a list of list
_reset_cache()
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]
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
# 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()
if opt.impl_is_multi() and index is not None:
if value == []:
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 index, must return good value for this index
if len(value) > index:
value = value[index]
else:
if len(value) > index:
value = value[index]
else:
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]
# no value for this index, retrieve default multi value
# default_multi is already a list for submulti
value = opt.impl_getdefault_multi()
return value
def _getvalue(self, opt, path, self_properties, index, submulti_index,
with_meta, masterlen, session, validate, _orig_context):
def _getvalue(self,
opt,
path,
self_properties,
index,
validate,
_orig_context):
"""actually retrieves the value
:param opt: the `option.Option()` object
@ -136,8 +189,11 @@ class Values(object):
_index = None
else:
_index = index
owner, value = self._p_.getowner(path, owners.default, session, only_default=True,
index=_index, with_value=True)
owner, value = self._p_.getowner(path,
owners.default,
only_default=True,
index=_index,
with_value=True)
is_default = owner == owners.default
if not is_default and not force_default:
if index is not None and not opt.impl_is_master_slaves('slave'):
@ -147,8 +203,11 @@ class Values(object):
#so return default value
else:
return value
return self._getdefaultvalue(opt, path, with_meta, index,
submulti_index, validate, _orig_context)
return self._getdefaultvalue(opt,
path,
index,
validate,
_orig_context)
def get_modified_values(self):
return self._p_.get_modified_values()
@ -163,55 +222,129 @@ class Values(object):
path = opt.impl_getpath(self._getcontext())
return self._contains(path)
def _contains(self, path, session=None):
if session is None:
session = self._p_.getsession()
return self._p_.hasvalue(path, session)
def _contains(self, path):
return self._p_.hasvalue(path)
def __delitem__(self, opt):
"""overrides the builtins `del()` instructions"""
self.reset(opt)
def reset(self, opt, path=None, validate=True, _setting_properties=None, _commit=True,
def reset(self,
opt,
path,
setting_properties,
validate=True,
_commit=True,
force_permissive=False):
context = self._getcontext()
setting = context.cfgimpl_get_settings()
if path is None:
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)
hasvalue = self._contains(path)
if validate and hasvalue and 'validator' in _setting_properties:
session = context.cfgimpl_get_values()._p_.getsession()
fake_context = context._gen_fake_values(session)
if validate and hasvalue and 'validator' in setting_properties:
fake_context = context._gen_fake_values()
fake_value = fake_context.cfgimpl_get_values()
fake_value.reset(opt, path, validate=False)
ret = fake_value._get_cached_value(opt, path,
setting_properties=_setting_properties,
check_frozen=True,
force_permissive=force_permissive)
fake_value.reset(opt,
path,
setting_properties,
validate=False)
ret = fake_value.get_cached_value(opt,
path,
setting_properties=setting_properties,
check_frozen=True,
force_permissive=force_permissive)
if isinstance(ret, Exception):
raise ret
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)
if hasvalue:
if 'force_store_value' in setting._getproperties(opt=opt,
path=path,
setting_properties=_setting_properties,
setting_properties=setting_properties,
read_write=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
raise value
self._setvalue(opt, path, value, force_owner=owners.forced, commit=_commit)
self._setvalue(opt,
path,
value,
owners.forced,
None,
commit=_commit)
else:
self._p_.resetvalue(path, session, _commit)
context.cfgimpl_reset_cache(opt=opt, path=path, only=('values', 'properties'))
self._p_.resetvalue(path,
_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"
if value is undefined:
return False
@ -235,15 +368,21 @@ class Values(object):
def __getitem__(self, opt):
"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,
force_permissive=False, trusted_cached_properties=True,
validate_properties=True,
setting_properties=undefined, self_properties=undefined,
index=None, submulti_index=undefined, from_masterslave=False,
with_meta=True, masterlen=undefined, check_frozen=False,
session=None, display_warnings=True, _orig_context=undefined):
def get_cached_value(self,
opt,
path=None,
validate=True,
force_permissive=False,
trusted_cached_properties=True,
validate_properties=True,
setting_properties=undefined,
self_properties=undefined,
index=None,
check_frozen=False,
display_warnings=True,
_orig_context=undefined):
context = self._getcontext()
settings = context.cfgimpl_get_settings()
if path is None:
@ -252,7 +391,8 @@ class Values(object):
if setting_properties is undefined:
setting_properties = settings._getproperties(read_write=False)
if self_properties is undefined:
self_properties = settings._getproperties(opt, path,
self_properties = settings._getproperties(opt,
path,
read_write=False,
setting_properties=setting_properties,
index=index)
@ -264,11 +404,14 @@ class Values(object):
if index:
value = value[index]
if is_cached:
if opt.impl_is_multi() and not isinstance(value, Multi) and index is None:
value = Multi(value, self.context, opt, path)
#if opt.impl_is_multi() and not isinstance(value, Multi) and index is None:
# value = Multi(value, self.context, opt, path)
if not trusted_cached_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,
force_permissive=force_permissive,
setting_properties=setting_properties,
@ -277,38 +420,35 @@ class Values(object):
if props:
return props
return value
if session is None:
session = self._p_.getsession()
if not from_masterslave and opt.impl_is_master_slaves():
val = opt.impl_get_master_slaves().getitem(self, opt, path,
validate,
force_permissive,
trusted_cached_properties,
validate_properties,
session,
setting_properties=setting_properties,
index=index,
self_properties=self_properties,
check_frozen=check_frozen)
#if not from_masterslave and opt.impl_is_master_slaves():
# val = opt.impl_get_master_slaves().getitem(self, opt, path,
# validate,
# force_permissive,
# trusted_cached_properties,
# validate_properties,
# setting_properties=setting_properties,
# index=index,
# self_properties=self_properties,
# check_frozen=check_frozen)
#else:
if _orig_context is not undefined:
_context = _orig_context
else:
val = self._get_validated_value(opt, path, validate,
force_permissive,
validate_properties,
setting_properties,
self_properties,
with_meta=with_meta,
masterlen=masterlen,
index=index,
submulti_index=submulti_index,
check_frozen=check_frozen,
session=session,
display_warnings=display_warnings,
_orig_context=_orig_context)
_context = context
val = self._get_validated_value(opt,
path,
validate,
force_permissive,
validate_properties,
setting_properties,
self_properties,
index=index,
check_frozen=check_frozen,
display_warnings=display_warnings,
_orig_context=_context)
if isinstance(val, Exception):
return val
# cache doesn't work with SubMulti yet
if not from_masterslave and index is None and not isinstance(val, SubMulti) and \
'cache' in setting_properties and \
if index is None and 'cache' in setting_properties and \
validate and validate_properties and force_permissive is False \
and trusted_cached_properties is True and _orig_context is undefined:
if 'expire' in setting_properties:
@ -318,14 +458,17 @@ class Values(object):
self._p_.setcache(path, val, ntime, None)
return val
def _get_validated_value(self, opt, path, validate, force_permissive,
validate_properties, setting_properties,
def _get_validated_value(self,
opt,
path,
validate,
force_permissive,
validate_properties,
setting_properties,
self_properties,
index=None, submulti_index=undefined,
with_meta=True,
masterlen=undefined,
index=None,
check_frozen=False,
session=None, display_warnings=True,
display_warnings=True,
_orig_context=undefined):
"""same has getitem but don't touch the cache
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()
setting = context.cfgimpl_get_settings()
config_error = None
if session is None:
session = self._p_.getsession()
value = self._getvalue(opt, path, self_properties, index, submulti_index,
with_meta, masterlen, session, validate, _orig_context)
value = self._getvalue(opt,
path,
self_properties,
index,
validate,
_orig_context)
if isinstance(value, Exception):
value_error = True
if isinstance(value, ConfigError):
@ -355,22 +500,11 @@ class Values(object):
raise value
else:
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 submulti_index is undefined:
force_submulti_index = None
else:
force_submulti_index = submulti_index
err = opt.impl_validate(value, context,
err = opt.impl_validate(value,
context,
'validator' in setting_properties,
force_index=index,
force_submulti_index=force_submulti_index,
display_error=True,
display_warnings=False,
setting_properties=setting_properties)
@ -385,7 +519,10 @@ class Values(object):
val_props = undefined
else:
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,
force_permissive=force_permissive,
setting_properties=setting_properties,
@ -394,10 +531,10 @@ class Values(object):
if props:
return props
if not value_error and validate and display_warnings:
opt.impl_validate(value, context,
opt.impl_validate(value,
context,
'validator' in setting_properties,
force_index=index,
force_submulti_index=force_submulti_index,
display_error=False,
display_warnings=display_warnings,
setting_properties=setting_properties)
@ -405,122 +542,116 @@ class Values(object):
return config_error
return value
def __setitem__(self, opt, value):
raise ConfigError(_('you should only set value with config'))
def setitem(self,
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()
if 'validator' in _setting_properties:
session = context.cfgimpl_get_values()._p_.getsession()
owner = context.cfgimpl_get_settings().getowner()
if 'validator' in setting_properties:
if opt._has_consistencies():
fake_context = context._gen_fake_values(session)
fake_values = fake_context.cfgimpl_get_values()
fake_values._setvalue(opt, path, value, index=index)
# set value to a fake config when option has dependency
# validation will be complet in this case (consistency, ...)
tested_context = context._gen_fake_values()
tested_values = tested_context.cfgimpl_get_values()
tested_values._setvalue(opt,
path,
value,
index=index,
owner=owner)
else:
fake_context = context
fake_values = self
props = fake_values.validate(opt, value, path,
check_frozen=check_frozen,
force_permissive=force_permissive,
setting_properties=_setting_properties,
session=session, not_raises=not_raises,
index=index, setitem=True)
if props and not_raises:
tested_context = context
tested_values = self
props = tested_values.validate_setitem(opt,
value,
path,
force_permissive,
setting_properties,
index)
if props:
if not not_raises:
raise 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.cfgimpl_reset_cache(opt=opt, path=path, only=('values', 'properties'))
if force_owner is undefined:
owner = context.cfgimpl_get_settings().getowner()
else:
owner = force_owner
# in storage, value must not be a multi
if isinstance(value, Multi):
if not opt.impl_is_master_slaves('slave') or index is None:
value = list(value)
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)
# First validate properties with this value
props = context.cfgimpl_get_settings().validate_properties(opt,
False,
True,
value=value,
path=path,
force_permissive=force_permissive,
setting_properties=setting_properties,
index=index)
if props:
if not_raises:
return props
raise props
return props
# Value must be valid for option
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()
if context.cfgimpl_get_meta() is None:
return False
setting = context.cfgimpl_get_settings()
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,
validate_meta=False, index=None,
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
@ -533,16 +664,22 @@ class Values(object):
not isinstance(opt, DynSymLinkOption):
opt = opt._impl_getopt()
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,
force_permissive=False, validate_meta=undefined,
self_properties=undefined, only_default=False,
def _getowner(self,
opt,
path,
validate_properties=True,
force_permissive=False,
validate_meta=undefined,
self_properties=undefined,
only_default=False,
index=None):
"""get owner of an option
"""
if session is None:
session = self._p_.getsession()
if not isinstance(opt, Option) and not isinstance(opt,
DynSymLinkOption):
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:
return owners.default
if validate_properties:
value = self._get_cached_value(opt, path=path, force_permissive=force_permissive,
self_properties=self_properties, session=session,
index=index)
value = self.get_cached_value(opt,
path=path,
force_permissive=force_permissive,
self_properties=self_properties,
index=index)
if isinstance(value, Exception):
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 opt.impl_is_master_slaves('slave'):
master = opt.impl_get_master_slaves().getmaster(opt)
masterp = master.impl_getpath(context)
validate_meta = self._is_meta(master, masterp, session)
validate_meta = self._is_meta(master, masterp)
else:
validate_meta = True
if validate_meta and owner is owners.default:
meta = context.cfgimpl_get_meta()
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,
force_permissive=force_permissive,
self_properties=self_properties,
only_default=only_default, index=index)
only_default=only_default,
index=index)
return owner
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)))
path = opt.impl_getpath(self._getcontext())
session = self._p_.getsession()
props = self._getcontext().cfgimpl_get_settings().validate_properties(opt,
False,
True,
@ -597,10 +737,10 @@ class Values(object):
force_permissive=force_permissive)
if 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}'
'').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,
validate_meta=True, index=None,
@ -612,19 +752,30 @@ class Values(object):
"""
if path is None:
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_meta=validate_meta, index=index,
validate_meta=validate_meta,
index=index,
force_permissive=force_permissive)
def _is_default_owner(self, opt, path, session, validate_properties=True,
validate_meta=True, self_properties=undefined,
index=None, force_permissive=False):
d = self._getowner(opt, path, session, validate_properties=validate_properties,
validate_meta=validate_meta,
self_properties=self_properties, only_default=True,
index=index, force_permissive=force_permissive)
return d == owners.default
def _is_default_owner(self,
opt,
path,
validate_properties=True,
validate_meta=True,
self_properties=undefined,
index=None,
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
def set_information(self, key, value):
@ -688,13 +839,13 @@ class Values(object):
read_write=False,
setting_properties=setting_properties)
if 'mandatory' in self_properties or 'empty' in self_properties:
err = self._get_cached_value(opt, path=path,
trusted_cached_properties=False,
force_permissive=True,
setting_properties=setting_properties,
self_properties=self_properties,
validate=True,
display_warnings=False)
err = self.get_cached_value(opt, path=path,
trusted_cached_properties=False,
force_permissive=True,
setting_properties=setting_properties,
self_properties=self_properties,
validate=True,
display_warnings=False)
if opt.impl_is_master_slaves('slave') and isinstance(err, list):
for val in err:
ret = _is_properties_option(val, path)
@ -723,277 +874,3 @@ class Values(object):
err = context.getattr(path, returns_raise=True)
if isinstance(err, Exception) and not isinstance(err, PropertiesOptionError): # pragma: no cover
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)