separate value in slave

This commit is contained in:
Emmanuel Garette 2015-11-19 22:25:00 +01:00
parent a248508498
commit 54ca54e505
16 changed files with 409 additions and 416 deletions

View file

@ -10,7 +10,7 @@ Sun Jul 26 19:09:29 2015 +0200 Emmanuel Garette <egarette@cadoles.com>
Fri Jul 24 18:03:59 2015 +0200 Emmanuel Garette <egarette@cadoles.com>
* add duplicate option to Config, to generate new Config with same
value, properties, Option. Option are not duplication.
value, properties, Option. Option are not duplicated.
Mon Apr 20 14:44:15 2015 +0200 Emmanuel Garette <egarette@cadoles.com>
* if option is multi, the properties disallow [None] for a multi but
@ -44,7 +44,7 @@ Sun Dec 7 14:37:32 2014 +0200 Emmanuel Garette <egarette@cadoles.com>
Mon Dec 1 22:58:13 2014 +0200 Emmanuel Garette <egarette@cadoles.com>
* propertyerror are transitive in consistency, now it's possible to set
non-transitive consistency
* if consistency with multiple option return if transitive
* support transitive in consistency with multiple option return
* can reset slave value in all case when deleting master value
* in_network's consistency now verify that IP is not network or
broadcast's IP + ip_netmask's consistency now verify that IP is not
@ -52,11 +52,11 @@ Mon Dec 1 22:58:13 2014 +0200 Emmanuel Garette <egarette@cadoles.com>
Sun Oct 26 08:50:38 2014 +0200 Emmanuel Garette <egarette@cadoles.com>
* if option is frozen with force_default_on_freeze property, owner
must be 'default' check property when tried to change owner
must be 'default', check property when tried to change owner
* bad characters in DomainnameOption could be in warning level
* frozen with force_default_on_freeze can change owner
* add force_permissive to config __iter__
* pass force_permissive to slave for a master or to master for a slave
* add force_permissive to slave for a master or to master for a slave
* remove mandatory_warnings in config.py
* add force_permissive in mandatory_warnings
@ -78,13 +78,13 @@ Thu Jun 19 23:20:29 2014 +0200 Emmanuel Garette <egarette@cadoles.com>
Sun Apr 27 10:32:40 2014 +0200 Emmanuel Garette <egarette@cadoles.com>
* behavior change in ChoiceOption:
remove open_values, that no sens (no type validation is possible) if
remove open_values, that no sens (we cannot validate type) if
you want something like open_values, please use a typed option and
add impl_(s|g)et_information to add proposed values and use it in your
code
* add dynamic ChoiceOption:
we can have dynamic ChoiceOption. Parameter values can be a function
and as callback, we can add values_params
and, as callback, we can add values_params
Fri Apr 25 22:57:08 2014 +0200 Emmanuel Garette <egarette@cadoles.com>
@ -99,8 +99,8 @@ Sat Apr 12 11:37:27 2014 +0200 Emmanuel Garette <egarette@cadoles.com>
* tiramisu/config.py (in cfgimpl_get_home_by_path and getattr) and
tiramisu/value.py (in getitem): arity change, remove force_properties
* tiramisu/option.py: split into tiramisu/option directory
* tiramisu/option/masterslave.py: master/slaves have no a special
object MasterSlaves for all code related to master/slaves options
* tiramisu/option/masterslave.py: master and slaves values (length,
consistency, ...) are now check every time
* tiramisu/option/masterslave.py: add special object MasterSlaves for
all code related to master/slaves options
* tiramisu/option/masterslave.py: check every time master and slaves
values (length, consistency, ...)
* change None to undefined when needed

View file

@ -904,8 +904,8 @@ def test_masterslaves_dyndescription():
assert cfg.od.stval2.st1val2.st2val2 == []
assert cfg.getowner(st1val1) == owner
assert cfg.getowner(st1val2) == owners.default
assert cfg.getowner(st2val1) == owner
assert cfg.getowner(st2val2) == owners.default
assert cfg.getowner(st2val1, 0) == owner
# assert cfg.getowner(st2val2) == owners.default
#
cfg.od.stval1.st1val1.st1val1.pop(0)
assert cfg.od.stval1.st1val1.st1val1 == []
@ -914,18 +914,18 @@ def test_masterslaves_dyndescription():
assert cfg.od.stval2.st1val2.st2val2 == []
assert cfg.getowner(st1val1) == owner
assert cfg.getowner(st1val2) == owners.default
assert cfg.getowner(st2val1) == owner
assert cfg.getowner(st2val2) == owners.default
# assert cfg.getowner(st2val1) == owner
# assert cfg.getowner(st2val2) == owners.default
#
cfg.od.stval1.st1val1.st1val1 = ['yes']
cfg.od.stval1.st1val1.st2val1 = ['yes']
assert cfg.getowner(st1val1) == owner
assert cfg.getowner(st2val1) == owner
assert cfg.getowner(st2val1, 0) == owner
del(cfg.od.stval1.st1val1.st2val1)
assert cfg.getowner(st1val1) == owner
assert cfg.getowner(st1val2) == owners.default
assert cfg.getowner(st2val1) == owners.default
assert cfg.getowner(st2val2) == owners.default
# assert cfg.getowner(st2val1) == owners.default
# assert cfg.getowner(st2val2) == owners.default
#
cfg.od.stval1.st1val1.st1val1 = ['yes']
cfg.od.stval1.st1val1.st2val1 = ['yes']
@ -1012,8 +1012,8 @@ def test_masterslaves_submulti_dyndescription():
assert cfg.od.stval2.st1val2.st2val2 == []
assert cfg.getowner(st1val1) == owner
assert cfg.getowner(st1val2) == owners.default
assert cfg.getowner(st2val1) == owner
assert cfg.getowner(st2val2) == owners.default
assert cfg.getowner(st2val1, 0) == owner
# assert cfg.getowner(st2val2) == owners.default
def test_masterslaves_consistency_ip_dyndescription():
@ -1085,8 +1085,8 @@ def test_masterslaves_callback_dyndescription():
assert cfg.od.stval2.st1val2.st2val2 == []
assert cfg.getowner(st1val1) == owner
assert cfg.getowner(st1val2) == owners.default
assert cfg.getowner(st2val1) == owner
assert cfg.getowner(st2val2) == owners.default
assert cfg.getowner(st2val1, 0) == owner
# assert cfg.getowner(st2val2) == owners.default
#
cfg.od.stval1.st1val1.st1val1.pop(0)
assert cfg.od.stval1.st1val1.st1val1 == []
@ -1095,13 +1095,13 @@ def test_masterslaves_callback_dyndescription():
assert cfg.od.stval2.st1val2.st2val2 == []
assert cfg.getowner(st1val1) == owner
assert cfg.getowner(st1val2) == owners.default
assert cfg.getowner(st2val1) == owner
assert cfg.getowner(st2val2) == owners.default
# assert cfg.getowner(st2val1) == owner
# assert cfg.getowner(st2val2) == owners.default
#
cfg.od.stval1.st1val1.st1val1 = ['yes']
cfg.od.stval1.st1val1.st2val1 = ['yes']
assert cfg.getowner(st1val1) == owner
assert cfg.getowner(st2val1) == owner
assert cfg.getowner(st2val1, 0) == owner
del(cfg.od.stval1.st1val1.st2val1)
assert cfg.getowner(st1val1) == owner
assert cfg.getowner(st1val2) == owners.default
@ -1159,31 +1159,6 @@ def test_masterslaves_callback_nomulti_dyndescription():
assert cfg.od.stval1.st1val1.st2val1 == ['val']
def test_masterslaves_callback_multi_dyndescription():
v1 = StrOption('v1', '', multi=True)
st1 = StrOption('st1', "", multi=True)
st2 = StrOption('st2', "", multi=True, callback=return_dynval, callback_params={'': ((v1, False),)})
stm = OptionDescription('st1', '', [st1, st2])
stm.impl_set_group_type(groups.master)
st = DynOptionDescription('st', '', [stm], callback=return_list)
od = OptionDescription('od', '', [st])
od2 = OptionDescription('od', '', [od, v1])
cfg = Config(od2)
assert cfg.od.stval1.st1val1.st1val1 == []
assert cfg.od.stval1.st1val1.st2val1 == []
cfg.od.stval1.st1val1.st1val1.append('yes')
assert cfg.od.stval1.st1val1.st1val1 == ['yes']
assert cfg.od.stval1.st1val1.st2val1 == [None]
cfg.od.stval1.st1val1.st2val1 = ['no']
cfg.v1 = ['no', 'no', 'no']
cfg.od.stval1.st1val1.st1val1.append('yes')
assert cfg.od.stval1.st1val1.st1val1 == ['yes', 'yes']
assert cfg.od.stval1.st1val1.st2val1 == ['no', 'no']
cfg.od.stval1.st1val1.st1val1.pop(1)
assert cfg.od.stval1.st1val1.st1val1 == ['yes']
assert cfg.od.stval1.st1val1.st2val1 == ['no']
def test_masterslaves_callback_samegroup_dyndescription():
st1 = StrOption('st1', "", multi=True)
st2 = StrOption('st2', "", multi=True)
@ -1242,11 +1217,11 @@ def test_masterslaves_callback_samegroup_dyndescription():
'od.stval2.st1val2.st2val2': [],
'od.stval2.st1val2.st3val2': []}
assert cfg.getowner(st1val1) == owner
assert cfg.getowner(st2val1, 0) == owner
assert cfg.getowner(st3val1, 0) == owners.default
assert cfg.getowner(st1val2) == owners.default
assert cfg.getowner(st2val1) == owner
assert cfg.getowner(st2val2) == owners.default
assert cfg.getowner(st3val1) == owners.default
assert cfg.getowner(st3val2) == owners.default
#assert cfg.getowner(st2val2) == owners.default
#assert cfg.getowner(st3val2) == owners.default
def test_state_config():

View file

@ -295,13 +295,13 @@ def test_meta_master_slaves_owners():
assert meta.conf1.getowner(netmask_admin_eth0) == owners.default
meta.netmask_admin_eth0 = ['255.255.255.0']
assert meta.conf1.getowner(ip_admin_eth0) == owners.meta
assert meta.conf1.getowner(netmask_admin_eth0) == owners.meta
assert meta.conf1.getowner(netmask_admin_eth0, 0) == owners.meta
meta.netmask_admin_eth0 = ['255.255.0.0']
assert meta.conf1.getowner(ip_admin_eth0) == owners.meta
assert meta.conf1.getowner(netmask_admin_eth0) == owners.meta
assert meta.conf1.getowner(netmask_admin_eth0, 0) == owners.meta
meta.conf1.ip_admin_eth0 = ['192.168.1.1']
assert meta.conf1.getowner(ip_admin_eth0) == owners.user
assert meta.conf1.getowner(netmask_admin_eth0) == owners.default
assert meta.conf1.getowner(netmask_admin_eth0, 0) == owners.default
def test_meta_force_default():

View file

@ -6,6 +6,7 @@ from tiramisu.value import Multi
from tiramisu.option import IntOption, StrOption, OptionDescription
from tiramisu.config import Config
from tiramisu.error import ConfigError, PropertiesOptionError
from tiramisu.setting import groups
import weakref
from py.test import raises

View file

@ -548,33 +548,6 @@ def test_callback_master_and_slaves_slave_cal():
assert cfg.val1.val2 == ['val1', 'val2', 'val']
def test_callback_master_and_slaves_slave_cal2():
val3 = StrOption('val3', "", ['val', 'val'], multi=True)
val1 = StrOption('val1', "", multi=True, callback=return_value, callback_params={'': ((val3, False),)})
val2 = StrOption('val2', "", ['val2', 'val2'], multi=True)
interface1 = OptionDescription('val1', '', [val1, val2])
interface1.impl_set_group_type(groups.master)
maconfig = OptionDescription('rootconfig', '', [interface1, val3])
cfg = Config(maconfig)
cfg.read_write()
assert cfg.val3 == ['val', 'val']
assert cfg.val1.val1 == ['val', 'val']
assert cfg.val1.val2 == ['val2', 'val2']
cfg.val3.pop(1)
# cannot remove slave's value because master is calculated
# so raise
raises(SlaveError, "cfg.val1.val1")
raises(SlaveError, "cfg.val1.val2")
cfg.val3 = ['val', 'val']
assert cfg.val3 == ['val', 'val']
assert cfg.val1.val1 == ['val', 'val']
assert cfg.val1.val2 == ['val2', 'val2']
raises(SlaveError, "cfg.val1.val1 = ['val']")
assert cfg.val3 == ['val', 'val']
assert cfg.val1.val1 == ['val', 'val']
assert cfg.val1.val2 == ['val2', 'val2']
def test_callback_master_and_slaves_master_disabled():
#properties must be transitive
val1 = StrOption('val1', "", multi=True, properties=('disabled',))
@ -643,35 +616,16 @@ def test_callback_master_and_slaves_slave_callback_disabled():
cfg = Config(maconfig)
cfg.read_write()
assert cfg.val1.val1 == []
raises(ConfigError, "cfg.val1.val2")
assert cfg.val1.val2 == []
cfg.val1.val1.append('yes')
assert cfg.val1.val1 == ['yes']
cfg.cfgimpl_get_settings().remove('disabled')
assert cfg.val1.val2 == [None]
raises(SlaveError, "cfg.val1.val2")
cfg.val1.val2 = ['no']
cfg.val1.val1.append('yes1')
cfg.val1.val2[1] = 'no1'
cfg.cfgimpl_get_settings().append('disabled')
cfg.val1.val1.pop(0)
assert cfg.val1.val1 == ['yes1']
assert cfg.val1.val2 == ['no1']
def test_callback_master_and_slaves_slave_list():
val1 = StrOption('val1', "", multi=True)
val2 = StrOption('val2', "", multi=True, callback=return_list)
interface1 = OptionDescription('val1', '', [val1, val2])
interface1.impl_set_group_type(groups.master)
maconfig = OptionDescription('rootconfig', '', [interface1])
cfg = Config(maconfig)
cfg.read_write()
#len is equal to 2 for slave and 0 for master
raises(SlaveError, "cfg.val1.val2")
cfg.val1.val1 = ['val1', 'val2']
assert cfg.val1.val1 == ['val1', 'val2']
assert cfg.val1.val2 == ['val', 'val']
#wrong len
raises(SlaveError, "cfg.val1.val1 = ['val1']")
cfg.cfgimpl_get_settings().append('disabled')
raises(ConfigError, "cfg.val1.val1.pop(0)")
def test_callback_master_and_slaves_value():
@ -687,35 +641,40 @@ def test_callback_master_and_slaves_value():
cfg = Config(maconfig)
cfg.read_write()
cfg.val4 == ['val10', 'val11']
raises(SlaveError, "cfg.val1.val1")
raises(SlaveError, "cfg.val1.val2")
raises(SlaveError, "cfg.val1.val3")
raises(SlaveError, "cfg.val1.val5")
raises(SlaveError, "cfg.val1.val6")
assert cfg.val1.val1 == []
assert cfg.val1.val2 == []
assert cfg.val1.val3 == []
assert cfg.val1.val5 == []
assert cfg.val1.val6 == []
#raises(SlaveError, "cfg.val1.val1")
#raises(SlaveError, "cfg.val1.val2")
#raises(SlaveError, "cfg.val1.val3")
#raises(SlaveError, "cfg.val1.val5")
#raises(SlaveError, "cfg.val1.val6")
#
#default calculation has greater length
raises(SlaveError, "cfg.val1.val1 = ['val1']")
#raises(SlaveError, "cfg.val1.val1 = ['val1']")
#
cfg.val1.val1 = ['val1', 'val2']
assert cfg.val1.val1 == ['val1', 'val2']
assert cfg.val1.val2 == ['val1', 'val2']
assert cfg.val1.val3 == ['yes', 'yes']
assert cfg.val1.val5 == ['val10', 'val11']
assert cfg.val1.val6 == ['val10', 'val11']
raises(SlaveError, "cfg.val1.val5")
raises(SlaveError, "cfg.val1.val6")
#
cfg.val1.val1.append('val3')
assert cfg.val1.val1 == ['val1', 'val2', 'val3']
assert cfg.val1.val2 == ['val1', 'val2', 'val3']
assert cfg.val1.val3 == ['yes', 'yes', 'yes']
assert cfg.val1.val5 == ['val10', 'val11', None]
assert cfg.val1.val6 == ['val10', 'val11', None]
raises(SlaveError, "cfg.val1.val5")
raises(SlaveError, "cfg.val1.val6")
#
cfg.val1.val1.pop(2)
assert cfg.val1.val1 == ['val1', 'val2']
assert cfg.val1.val2 == ['val1', 'val2']
assert cfg.val1.val3 == ['yes', 'yes']
assert cfg.val1.val5 == ['val10', 'val11']
assert cfg.val1.val6 == ['val10', 'val11']
raises(SlaveError, "cfg.val1.val5")
raises(SlaveError, "cfg.val1.val6")
#
cfg.val1.val2 = ['val2', 'val2']
cfg.val1.val3 = ['val2', 'val2']
@ -728,121 +687,16 @@ def test_callback_master_and_slaves_value():
cfg.val1.val1.append('val3')
assert cfg.val1.val2 == ['val2', 'val2', 'val3']
assert cfg.val1.val3 == ['val2', 'val2', 'yes']
assert cfg.val1.val5 == ['val2', 'val2', None]
assert cfg.val1.val6 == ['val2', 'val2', None]
raises(SlaveError, "cfg.val1.val5")
raises(SlaveError, "cfg.val1.val6")
cfg.cfgimpl_get_settings().remove('cache')
cfg.val4 = ['val10', 'val11', 'val12']
#if value is already set, not updated !
cfg.val1.val1.pop(2)
cfg.val1.val1.append('val3')
cfg.val1.val1 = ['val1', 'val2', 'val3']
assert cfg.val1.val5 == ['val2', 'val2', 'val12']
assert cfg.val1.val6 == ['val2', 'val2', 'val12']
def test_callback_master_and_slaves_disabled():
val = BoolOption('val', '', multi=True)
val1 = StrOption('val1', "", multi=True)
val2 = StrOption('val2', "", multi=True, callback=return_value, callback_params={'': ((val, False),)})
interface1 = OptionDescription('val1', '', [val1, val2])
interface1.impl_set_group_type(groups.master)
maconfig = OptionDescription('rootconfig', '', [val, interface1])
cfg = Config(maconfig)
cfg.read_write()
#
assert cfg.val == []
assert cfg.val1.val1 == []
assert cfg.val1.val2 == []
cfg.val1.val1.append('val1')
assert cfg.val == []
assert cfg.val1.val1 == ['val1']
assert cfg.val1.val2 == [None]
#
cfg.val.append(True)
cfg.cfgimpl_get_settings()[cfg.cfgimpl_get_description().val1.val2].append('disabled')
assert cfg.val == [True]
assert cfg.val1.val1 == ['val1']
raises(PropertiesOptionError, 'cfg.val1.val2')
#
cfg.val1.val1.append('val1_1')
assert cfg.val == [True]
assert cfg.val1.val1 == ['val1', 'val1_1']
raises(PropertiesOptionError, 'cfg.val1.val2')
#
cfg.cfgimpl_get_settings()[cfg.cfgimpl_get_description().val1.val2].remove('disabled')
assert cfg.val == [True]
assert cfg.val1.val1 == ['val1', 'val1_1']
raises(ValueError, 'cfg.val1.val2')
#
cfg.val = []
assert cfg.val1.val1 == ['val1', 'val1_1']
assert cfg.val1.val2 == [None, None]
#
cfg.val1.val2 = [None, None]
cfg.val = [True, True]
cfg.cfgimpl_get_settings()[cfg.cfgimpl_get_description().val1.val2].append('disabled')
cfg.val1.val1.pop(1)
assert cfg.val == [True, True]
assert cfg.val1.val1 == ['val1']
raises(PropertiesOptionError, 'cfg.val1.val2')
#
cfg.val1.val1.append('val1_2')
assert cfg.val == [True, True]
assert cfg.val1.val1 == ['val1', 'val1_2']
raises(PropertiesOptionError, 'cfg.val1.val2')
#
cfg.cfgimpl_get_settings()[cfg.cfgimpl_get_description().val1.val2].remove('disabled')
assert cfg.val == [True, True]
assert cfg.val1.val1 == ['val1', 'val1_2']
#[None, None] + pop() + append() => [None, True]
raises(ValueError, 'assert cfg.val1.val2')
def test_callback_master_and_slaves_requires():
val = StrOption('val', '', 'val')
valreq = StrOption('valreq', '', 'val')
val1 = StrOption('val1', "", multi=True)
val2 = StrOption('val2', "", multi=True, callback=return_value, callback_params={'': ((val1, False),)})
val3 = StrOption('val3', "", multi=True, callback=return_value, callback_params={'': ('yes',)})
val4 = StrOption('val4', '', multi=True, default=[])
val5 = StrOption('val5', "", multi=True, callback=return_value, callback_params={'': ((val4, False),)})
val6 = StrOption('val6', "", multi=True, callback=return_value, callback_params={'': ((val, False),)},
requires=({'option': valreq, 'expected': 'val_disabled', 'action': 'disabled'},))
interface1 = OptionDescription('val1', '', [val1, val2, val3, val5, val6])
interface1.impl_set_group_type(groups.master)
maconfig = OptionDescription('rootconfig', '', [val, valreq, interface1, val4])
cfg = Config(maconfig)
cfg.read_write()
assert cfg.val1.val1 == []
assert cfg.val1.val2 == []
assert cfg.val1.val3 == []
assert cfg.val1.val5 == []
assert cfg.val1.val6 == []
#
cfg.val1.val1 = ['val1']
assert cfg.val1.val1 == ['val1']
assert cfg.val1.val2 == ['val1']
assert cfg.val1.val3 == ['yes']
assert cfg.val1.val5 == [None]
assert cfg.val1.val6 == ['val']
cfg.val4 = ['val10']
assert cfg.val1.val5 == ['val10']
#
cfg.valreq = 'val_disabled'
assert cfg.val1.val1 == ['val1']
assert cfg.val1.val2 == ['val1']
assert cfg.val1.val3 == ['yes']
assert cfg.val1.val5 == ['val10']
raises(PropertiesOptionError, 'cfg.val1.val6')
assert cfg.make_dict() == {'val1.val2': ['val1'], 'val1.val3': ['yes'], 'val1.val1': ['val1'], 'val1.val5': ['val10'], 'val': 'val', 'valreq': 'val_disabled', 'val4': ['val10']}
#
cfg.cfgimpl_get_settings()[cfg.cfgimpl_get_description().val].append('disabled')
cfg.cfgimpl_get_settings()[cfg.cfgimpl_get_description().val1.val3].append('disabled')
raises(PropertiesOptionError, 'cfg.val1.val6')
assert cfg.make_dict() == {'val1.val2': ['val1'], 'val1.val1': ['val1'], 'val1.val5': ['val10'], 'val4': ['val10'], 'valreq': 'val_disabled'}
#
cfg.valreq = 'val'
raises(ConfigError, 'cfg.val1.val6')
raises(SlaveError, "cfg.val1.val5")
raises(SlaveError, "cfg.val1.val6")
def test_callback_master():
@ -853,42 +707,6 @@ def test_callback_master():
raises(ValueError, "interface1.impl_set_group_type(groups.master)")
def test_callback_master_and_other_master_slave():
val1 = StrOption('val1', "", multi=True)
val2 = StrOption('val2', "", multi=True)
val3 = StrOption('val3', "", multi=True)
val4 = StrOption('val4', '', multi=True, default=['val10', 'val11'])
val5 = StrOption('val5', "", multi=True, callback=return_value, callback_params={'': ((val1, False),)})
val6 = StrOption('val6', "", multi=True, callback=return_value, callback_params={'': ((val2, False),)})
interface1 = OptionDescription('val1', '', [val1, val2, val3])
interface1.impl_set_group_type(groups.master)
interface2 = OptionDescription('val4', '', [val4, val5, val6])
interface2.impl_set_group_type(groups.master)
maconfig = OptionDescription('rootconfig', '', [interface1, interface2])
cfg = Config(maconfig)
cfg.read_write()
assert cfg.val4.val4 == ['val10', 'val11']
assert cfg.val4.val5 == [None, None]
assert cfg.val4.val6 == [None, None]
cfg.val1.val1 = ['yes']
assert cfg.val4.val4 == ['val10', 'val11']
assert cfg.val4.val5 == ['yes', None]
assert cfg.val4.val6 == [None, None]
cfg.val1.val2 = ['no']
assert cfg.val4.val4 == ['val10', 'val11']
assert cfg.val4.val5 == ['yes', None]
assert cfg.val4.val6 == ['no', None]
cfg.val1.val1 = ['yes', 'yes', 'yes']
cfg.val1.val2 = ['no', 'no', 'no']
raises(SlaveError, "cfg.val4.val4")
raises(SlaveError, "cfg.val4.val5")
raises(SlaveError, "cfg.val4.val6")
cfg.val4.getattr('val4', validate=False).append('val12')
assert cfg.val4.val4 == ['val10', 'val11', 'val12']
assert cfg.val4.val5 == ['yes', 'yes', 'yes']
assert cfg.val4.val6 == ['no', 'no', 'no']
#FIXME: slave est un symlink

View file

@ -361,16 +361,16 @@ def test_reset_values_with_master_and_slaves_default():
cfg.ip_admin_eth0.ip_admin_eth0[0] = "192.168.230.146"
cfg.ip_admin_eth0.netmask_admin_eth0[0] = "255.255.255.0"
assert cfg.getowner(ip_admin_eth0) == owner
assert cfg.getowner(netmask_admin_eth0) == owner
assert cfg.getowner(netmask_admin_eth0, 0) == owner
del(cfg.ip_admin_eth0.ip_admin_eth0)
assert cfg.getowner(ip_admin_eth0) == owners.default
assert cfg.getowner(netmask_admin_eth0) == owners.default
assert cfg.getowner(netmask_admin_eth0, 0) == owners.default
assert cfg.ip_admin_eth0.ip_admin_eth0 == ['192.168.230.145']
assert cfg.ip_admin_eth0.netmask_admin_eth0 == [None]
cfg.ip_admin_eth0.netmask_admin_eth0[0] = "255.255.255.0"
assert cfg.getowner(ip_admin_eth0) == owners.default
assert cfg.getowner(netmask_admin_eth0) == owner
assert cfg.getowner(netmask_admin_eth0, 0) == owner
del(cfg.ip_admin_eth0.ip_admin_eth0)
assert cfg.getowner(ip_admin_eth0) == owners.default
assert cfg.getowner(netmask_admin_eth0) == owners.default

View file

@ -417,10 +417,10 @@ def test_reset_values_with_master_and_slaves_submulti():
cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
cfg.ip_admin_eth0.netmask_admin_eth0[0].append('255.255.255.0')
assert cfg.getowner(ip_admin_eth0) == owner
assert cfg.getowner(netmask_admin_eth0) == owner
assert cfg.getowner(netmask_admin_eth0, 0) == owner
del(cfg.ip_admin_eth0.ip_admin_eth0)
assert cfg.getowner(ip_admin_eth0) == owners.default
assert cfg.getowner(netmask_admin_eth0) == owners.default
# assert cfg.getowner(netmask_admin_eth0) == owners.default
assert cfg.ip_admin_eth0.ip_admin_eth0 == []
assert cfg.ip_admin_eth0.netmask_admin_eth0 == []

View file

@ -18,7 +18,8 @@
# the whole pypy projet is under MIT licence
# ____________________________________________________________
"enables us to carry out a calculation and return an option's value"
from tiramisu.error import PropertiesOptionError, ConfigError, ContextError
from tiramisu.error import PropertiesOptionError, ConfigError, ContextError, \
SlaveError
from tiramisu.i18n import _
from tiramisu.setting import undefined
# ____________________________________________________________
@ -237,6 +238,9 @@ def carry_out_calculation(option, context, callback, callback_params,
ret = calculate(callback, args, kwargs)
if callback_params != {}:
if isinstance(ret, list) and index is not undefined:
if option.impl_is_master_slaves('slave'):
raise SlaveError(_("callback cannot return a list for a "
"slave option ({0})").format(path))
if len(ret) < index + 1:
ret = None
else:

View file

@ -518,7 +518,7 @@ class _CommonConfig(SubConfig):
"read write is a global config's setting, see `settings.py`"
self.cfgimpl_get_settings().read_write()
def getowner(self, opt, force_permissive=False):
def getowner(self, opt, index=None, force_permissive=False):
"""convenience method to retrieve an option's owner
from the config itself
"""
@ -527,7 +527,7 @@ class _CommonConfig(SubConfig):
not isinstance(opt, DynSymLinkOption): # pragma: optional cover
raise TypeError(_('opt in getowner must be an option not {0}'
'').format(type(opt)))
return self.cfgimpl_get_values().getowner(opt,
return self.cfgimpl_get_values().getowner(opt, index=index,
force_permissive=force_permissive)
def unwrap_from_path(self, path, force_permissive=False):
@ -608,12 +608,12 @@ class _CommonConfig(SubConfig):
fake_config = Config(self._impl_descr, persistent=False,
force_values=get_storages_validation(),
force_settings=self.cfgimpl_get_settings())
fake_config.cfgimpl_get_values()._p_._values = self.cfgimpl_get_values()._p_.get_modified_values()
fake_config.cfgimpl_get_values()._p_._values = self.cfgimpl_get_values()._p_._values
return fake_config
def duplicate(self):
config = Config(self._impl_descr)
config.cfgimpl_get_values()._p_._values = self.cfgimpl_get_values()._p_.get_modified_values()
config.cfgimpl_get_values()._p_._values = self.cfgimpl_get_values()._p_._values
config.cfgimpl_get_settings()._p_._properties = self.cfgimpl_get_settings()._p_.get_modified_properties()
config.cfgimpl_get_settings()._p_._permissives = self.cfgimpl_get_settings()._p_.get_modified_permissives()
return config

View file

@ -98,7 +98,8 @@ class Base(StorageBase):
def __init__(self, name, doc, default=None, default_multi=None,
requires=None, multi=False, callback=None,
callback_params=None, validator=None, validator_params=None,
properties=None, warnings_only=False, extra=None, allow_empty_list=undefined):
properties=None, warnings_only=False, extra=None,
allow_empty_list=undefined):
if not valid_name(name): # pragma: optional cover
raise ValueError(_("invalid name: {0} for option").format(name))
if requires is not None:
@ -108,7 +109,7 @@ class Base(StorageBase):
calc_properties = frozenset()
requires = undefined
if not multi and default_multi is not None: # pragma: optional cover
raise ValueError(_("a default_multi is set whereas multi is False"
raise ValueError(_("default_multi is set whereas multi is False"
" in option: {0}").format(name))
if multi is True:
_multi = 0
@ -133,7 +134,8 @@ class Base(StorageBase):
'requirement {0}'.format(
list(set_forbidden_properties)))
StorageBase.__init__(self, name, _multi, warnings_only, doc, extra,
calc_properties, requires, properties, allow_empty_list)
calc_properties, requires, properties,
allow_empty_list)
if multi is not False and default is None:
default = []
self.impl_validate(default)

View file

@ -48,6 +48,10 @@ class MasterSlaves(object):
if child.impl_getname() == name:
self.master = child
else:
if child.impl_getdefault() != []:
raise ValueError(_("not allowed default value for option {0} "
"in group {1}").format(child.impl_getname(),
name))
slaves.append(child)
if self.master is None: # pragma: optional cover
raise ValueError(_('master group with wrong'
@ -107,7 +111,7 @@ class MasterSlaves(object):
def pop(self, opt, values, index):
for slave in self.getslaves(opt):
if not values.is_default_owner(slave, validate_properties=False,
validate_meta=False):
validate_meta=False, index=index):
values._get_cached_item(slave, validate=False,
validate_properties=False
).pop(index, force=True)
@ -139,17 +143,19 @@ class MasterSlaves(object):
for slave in self.getslaves(opt):
try:
slave_path = slave.impl_getpath(values._getcontext())
if c_slave_path == slave_path:
slave_value = c_slave_value
else:
slave_value = values._get_validated_value(slave,
slave_path,
False,
False,
None, False,
None,
self_properties=self_properties)
slavelen = len(slave_value)
slavelen = values._p_.get_max_length(slave_path)
#if c_slave_path == slave_path:
# slave_value = c_slave_value
#else:
# slave_value = values._get_validated_value(slave,
# slave_path,
# False,
# False,
# None, False,
# None,
# self_properties=self_properties,
# masterlen=masterlen)
#slavelen = len(slave_value)
self.validate_slave_length(masterlen, slavelen, slave.impl_getname(), opt)
except ConfigError: # pragma: optional cover
pass
@ -186,39 +192,44 @@ class MasterSlaves(object):
undefined, force_permissive,
master=master)
master_is_meta = values._is_meta(opt, masterp)
value = values._get_validated_value(opt, path, validate,
force_permissive,
force_properties,
validate_properties,
None, # not undefined
with_meta=master_is_meta,
self_properties=self_properties)
#value = values._get_validated_value(opt, path, validate,
# force_permissive,
# force_properties,
# validate_properties,
# None, # not undefined
# with_meta=master_is_meta,
# self_properties=self_properties)
#if slave, had values until master's one
path = opt.impl_getpath(context)
valuelen = len(value)
if validate:
self.validate_slave_length(masterlen, valuelen,
opt.impl_getname(), opt)
if valuelen < masterlen:
for num in range(0, masterlen - valuelen):
index = valuelen + num
value.append(values._get_validated_value(opt, path, True,
False, None,
validate_properties=False,
with_meta=master_is_meta,
index=index,
self_properties=self_properties),
setitem=False,
force=True,
validate=validate)
if validate_properties:
context.cfgimpl_get_settings().validate_properties(opt, False,
False,
value=value,
path=path,
force_permissive=force_permissive,
force_properties=force_properties,
setting_properties=setting_properties)
#path = opt.impl_getpath(context)
#valuelen = len(value)
#if validate:
# self.validate_slave_length(masterlen, valuelen,
# opt.impl_getname(), opt)
#if valuelen < masterlen:
#FIXME voir si pas de plus grande valeur !
value = values._get_multi(opt, path)
for index in range(0, masterlen):
#index = valuelen + num
value.append(values._get_validated_value(opt, path, validate,
force_permissive, force_properties,
validate_properties,
with_meta=master_is_meta,
index=index,
self_properties=self_properties,
masterlen=masterlen),
setitem=False,
force=True,
validate=validate)
#FIXME hu?
if validate_properties:
context.cfgimpl_get_settings().validate_properties(opt, False,
False,
value=value,
path=path,
force_permissive=force_permissive,
force_properties=force_properties,
setting_properties=setting_properties)
return value
def setitem(self, values, opt, value, path):
@ -228,14 +239,17 @@ class MasterSlaves(object):
base_path = '.'.join(path.split('.')[:-1]) + '.'
for slave in self.getslaves(opt):
slave_path = base_path + slave.impl_getname()
slave_value = values._get_validated_value(slave,
slave_path,
False,
False,
None, False,
None) # not undefined
slavelen = len(slave_value)
slavelen = values._p_.get_max_length(slave_path)
self.validate_slave_length(masterlen, slavelen, slave.impl_getname(), opt)
#slave_value = values._get_validated_value(slave,
# slave_path,
# False,
# False,
# None, False,
# None,
# masterlen=masterlen) # not undefined
#slavelen = len(slave_value)
#self.validate_slave_length(masterlen, slavelen, slave.impl_getname(), opt)
else:
self.validate_slave_length(self.get_length(values, opt,
slave_path=path), len(value),

View file

@ -433,7 +433,8 @@ class Settings(object):
value=None, force_permissive=False,
force_properties=None,
setting_properties=undefined,
self_properties=undefined):
self_properties=undefined,
index=None):
"""
validation upon the properties related to `opt_or_descr`
@ -480,7 +481,7 @@ class Settings(object):
else:
if 'mandatory' in properties and \
not self._getcontext().cfgimpl_get_values()._isempty(
opt_or_descr, value):
opt_or_descr, value, index=index):
properties.remove('mandatory')
elif opt_or_descr.impl_is_multi() and \
not is_write and 'empty' in forced_properties and \

View file

@ -47,7 +47,7 @@ class StorageBase(object):
'_master_slaves',
'_choice_values',
'_choice_values_params',
#autre
#other
'_state_master_slaves',
'_state_callback',
'_state_callback_params',

View file

@ -15,8 +15,8 @@
# 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/>.
# ____________________________________________________________
from copy import copy
from ..util import Cache
from tiramisu.setting import undefined
class Values(Cache):
@ -25,52 +25,167 @@ class Values(Cache):
def __init__(self, storage):
"""init plugin means create values storage
"""
self._values = {}
self._values = (tuple(), tuple(), tuple(), tuple())
self._informations = {}
# should init cache too
super(Values, self).__init__(storage)
# value
def setvalue(self, path, value, owner):
def setvalue(self, path, value, owner, index):
"""set value for a path
a specified value must be associated to an owner
"""
self._values[path] = (owner, value)
values = []
vidx = None
def getvalue(self, path):
def _setvalue_info(nb, idx, value, vidx):
lst = list(self._values[nb])
if idx is None:
if index is None or nb == 0:
lst.append(value)
else:
lst.append([value])
else:
if index is None or nb == 0:
lst[idx] = value
else:
if nb == 1:
try:
vidx = lst[idx].index(index)
except ValueError:
vidx = None
if vidx is None:
lst[idx].append(value)
elif nb != 1:
lst[idx][vidx] = value
values.append(tuple(lst))
return vidx
try:
idx = self._values[0].index(path)
except ValueError:
idx = None
vidx = _setvalue_info(0, idx, path, vidx)
vidx = _setvalue_info(1, idx, index, vidx)
vidx = _setvalue_info(2, idx, value, vidx)
_setvalue_info(3, idx, owner, vidx)
self._values = tuple(values)
def getvalue(self, path, index=None):
"""get value for a path
return: only value, not the owner
"""
return self._values[path][1]
return self._getvalue(path, 2, index)
def hasvalue(self, path):
def hasvalue(self, path, index=None):
"""if path has a value
return: boolean
"""
return path in self._values
return path in self._values[0]
def resetvalue(self, path):
"""remove value means delete value in storage
"""
del(self._values[path])
def _resetvalue(nb):
lst = list(self._values[nb])
lst.pop(idx)
values.append(tuple(lst))
values = []
idx = self._values[0].index(path)
_resetvalue(0)
_resetvalue(1)
_resetvalue(2)
_resetvalue(3)
self._values = tuple(values)
def get_modified_values(self):
"""return all values in a dictionary
example: {'path1': (owner, 'value1'), 'path2': (owner, 'value2')}
"""
return copy(self._values)
values = {}
for idx, path in enumerate(self._values[0]):
values[path] = (self._values[3][idx], self._values[2][idx])
return values
# owner
def setowner(self, path, owner):
def setowner(self, path, owner, index=None):
"""change owner for a path
"""
self._values[path] = (owner, self._values[path][1])
idx = self._values[0].index(path)
if isinstance(self._values[3][idx], list):
if index is None:
raise ValueError('list but no index')
owner = list(self._values[3][idx])[index] = owner
elif index is not None:
raise ValueError('index set but not a list')
lst = list(self._values[3])
lst[idx] = owner
values = list(self._values)
values[3] = tuple(lst)
self._values = tuple(values)
def getowner(self, path, default):
def get_max_length(self, path):
try:
idx = self._values[0].index(path)
except ValueError:
return 0
return max(self._values[1][idx]) + 1
def getowner(self, path, default, index=None, only_default=False):
"""get owner for a path
return: owner object
"""
return self._values.get(path, (default, None))[0]
if index is None:
if only_default:
if path in self._values[0]:
return None
else:
return default
val = self._getvalue(path, 3, index)
if val is None:
return default
return val
else:
value = self._getvalue(path, 3, index)
if value is None:
return default
else:
return value
def _getvalue(self, path, nb, index):
"""
_values == ((path1, path2), ((value1_1, value1_2), value2), ((owner1_1, owner1_2), owner2), ((idx1_1, idx1_2), None))
"""
try:
idx = self._values[0].index(path)
except ValueError:
value = None
else:
if isinstance(self._values[1][idx], list):
if index is None:
raise ValueError('list but no index')
elif index is not None:
raise ValueError('index set but not a list')
if self._values[1][idx] is None:
if index is None:
value = self._values[nb][idx]
else:
value = self._values[nb][idx][index]
else:
if index is not None:
try:
subidx = self._values[1][idx].index(index)
value = self._values[nb][idx][subidx]
except ValueError:
value = None
else:
value = []
for i in xrange(0, max(self._values[1][idx])):
if i in self._values[1][idx]:
value.append(self._values[nb][idx][self._values[1][idx].index(i)])
else:
value.append(undefined)
return value
def set_information(self, key, value):
"""updates the information's attribute

View file

@ -47,11 +47,20 @@ class Cache(object):
value = getattr(self, slot)
#value has owners object, need 'str()' it
if slot == '_values':
_value = {}
for key, values in value.items():
vals = list(values)
vals[0] = str(vals[0])
_value[key] = tuple(vals)
_value = []
_value.append(value[0])
_value.append(value[1])
str_owner = []
_value.append(value[2])
for owner in value[3]:
if isinstance(owner, list):
str_owners = []
for subowner in owner:
str_owners.append(str(subowner))
str_owner.append(str_owners)
else:
str_owner.append(str(owner))
_value.append(str_owner)
states[slot] = _value
else:
states[slot] = value
@ -60,19 +69,32 @@ class Cache(object):
return states
def __setstate__(self, states):
def convert_owner(owner):
try:
owner = getattr(owners, owner)
except AttributeError:
owners.addowner(owner)
owner = getattr(owners, owner)
return owner
for key, value in states.items():
#value has owners object, need to reconstruct it
if key == '_values':
_value = {}
for key_, values_ in value.items():
vals = list(values_)
try:
vals[0] = getattr(owners, vals[0])
except AttributeError:
owners.addowner(vals[0])
vals[0] = getattr(owners, vals[0])
_value[key_] = tuple(vals)
value = _value
_value = []
_value.append(value[0])
_value.append(value[1])
_value.append(value[2])
obj_owner = []
for owner in value[3]:
if isinstance(owner, list):
obj_owners = []
for subowner in owner:
obj_owners.append(convert_owner(subowner))
obj_owner.append(tuple(obj_owners))
else:
obj_owner.append(convert_owner(owner))
_value.append(tuple(obj_owner))
value = tuple(_value)
setattr(self, key, value)
def setcache(self, path, val, time):

View file

@ -54,33 +54,10 @@ class Values(object):
raise ConfigError(_('the context does not exist anymore'))
return context
def _getvalue(self, opt, path, is_default, index=undefined,
with_meta=True, self_properties=undefined):
"""actually retrieves the value
def _get_multi(self, opt, path):
return Multi([], self.context, opt, path)
:param opt: the `option.Option()` object
:returns: the option's value (or the default value if not set)
"""
if opt.impl_is_optiondescription(): # pragma: optional cover
raise ValueError(_('optiondescription has no value'))
if self_properties is undefined:
self_properties = self._getcontext().cfgimpl_get_settings()._getproperties(
opt, path, read_write=False)
force_default = 'frozen' in self_properties and \
'force_default_on_freeze' in self_properties
if not is_default and not force_default:
value = self._p_.getvalue(path)
if index is not undefined:
try:
return value[index]
except IndexError:
#value is smaller than expected
#so return default value
pass
else:
return value
#so default value
def _getdefaultvalue(self, opt, path, with_meta, index):
# if value has callback and is not set
if opt.impl_has_callback():
callback, callback_params = opt.impl_get_callback()
@ -126,6 +103,56 @@ class Values(object):
value = opt.impl_getdefault_multi()
return value
def _getvalue(self, opt, path, is_default, index=undefined,
with_meta=True, self_properties=undefined,
masterlen=undefined):
"""actually retrieves the value
:param opt: the `option.Option()` object
:returns: the option's value (or the default value if not set)
"""
if opt.impl_is_optiondescription(): # pragma: optional cover
raise ValueError(_('optiondescription has no value'))
if self_properties is undefined:
self_properties = self._getcontext().cfgimpl_get_settings()._getproperties(
opt, path, read_write=False)
force_default = 'frozen' in self_properties and \
'force_default_on_freeze' in self_properties
if not is_default and not force_default:
if opt.impl_is_master_slaves('slave'):
#if masterlen is not undefined:
if index is undefined:
value = []
vals = self._p_.getvalue(path)
length = max(masterlen, len(vals))
for idx in xrange(0, length):
try:
if vals[idx] is undefined:
value.append(self._getdefaultvalue(opt, path, with_meta, idx))
else:
value.append(vals[idx])
except IndexError:
try:
value.append(self._getdefaultvalue(opt, path, with_meta, idx))
except IndexError:
value.append(None)
else:
value = self._p_.getvalue(path, index)
return value
else:
value = self._p_.getvalue(path)
if index is not undefined:
try:
return value[index]
except IndexError:
#value is smaller than expected
#so return default value
pass
else:
return value
return self._getdefaultvalue(opt, path, with_meta, index)
def get_modified_values(self):
context = self._getcontext()
if context._impl_descr is not None:
@ -175,13 +202,13 @@ class Values(object):
if hasvalue:
self._p_.resetvalue(path)
def _isempty(self, opt, value, force_allow_empty_list=False):
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
else:
empty = opt._empty
if opt.impl_is_multi():
if index in [None, undefined] and opt.impl_is_multi():
if force_allow_empty_list:
allow_empty_list = True
else:
@ -273,7 +300,7 @@ class Values(object):
force_properties, validate_properties,
index=undefined, submulti_index=undefined,
with_meta=True, setting_properties=undefined,
self_properties=undefined):
self_properties=undefined, masterlen=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 []
"""
@ -286,7 +313,8 @@ class Values(object):
is_default = self._is_default_owner(opt, path,
validate_properties=False,
validate_meta=False,
self_properties=self_properties)
self_properties=self_properties,
index=index)
try:
if index is None:
gv_index = undefined
@ -294,7 +322,8 @@ class Values(object):
gv_index = index
value = self._getvalue(opt, path, is_default, index=gv_index,
with_meta=with_meta,
self_properties=self_properties)
self_properties=self_properties,
masterlen=masterlen)
config_error = None
except ConfigError as err:
# For calculating properties, we need value (ie for mandatory
@ -309,8 +338,7 @@ class Values(object):
# value is not set, for 'undefined' (cannot set None because of
# mandatory property)
value = undefined
if config_error is None:
else:
if index is undefined:
force_index = None
else:
@ -358,7 +386,8 @@ class Values(object):
force_permissive=force_permissive,
force_properties=force_properties,
setting_properties=setting_properties,
self_properties=self_properties)
self_properties=self_properties,
index=index)
if config_error is not None:
raise config_error
return value
@ -394,7 +423,7 @@ class Values(object):
def _setvalue(self, opt, path, value, force_permissive=False,
is_write=True, validate_properties=True,
setting_properties=undefined):
setting_properties=undefined, index=None):
context = self._getcontext()
context.cfgimpl_reset_cache()
if validate_properties:
@ -410,7 +439,15 @@ class Values(object):
if isinstance(val, SubMulti):
value[idx] = list(val)
owner = context.cfgimpl_get_settings().getowner()
self._p_.setvalue(path, value, owner)
if opt.impl_is_master_slaves('slave') and index is None:
try:
self._p_.resetvalue(path)
except ValueError:
pass
for idx, val in enumerate(value):
self._p_.setvalue(path, val, owner, idx)
else:
self._p_.setvalue(path, value, owner, index)
def _is_meta(self, opt, path):
context = self._getcontext()
@ -418,13 +455,13 @@ class Values(object):
self_properties = setting._getproperties(opt, path, read_write=False)
if 'frozen' in self_properties and 'force_default_on_freeze' in self_properties:
return False
if self._p_.getowner(path, owners.default) is not owners.default:
if self._p_.getowner(path, owners.default, only_default=True) is not owners.default:
return False
if context.cfgimpl_get_meta() is not None:
return True
return False
def getowner(self, opt, force_permissive=False):
def getowner(self, opt, index=None, force_permissive=False):
"""
retrieves the option's owner
@ -437,11 +474,12 @@ class Values(object):
not isinstance(opt, DynSymLinkOption):
opt = opt._impl_getopt()
path = opt.impl_getpath(self._getcontext())
return self._getowner(opt, path, force_permissive=force_permissive)
return self._getowner(opt, path, index=index, force_permissive=force_permissive)
def _getowner(self, opt, path, validate_properties=True,
force_permissive=False, validate_meta=undefined,
self_properties=undefined):
self_properties=undefined, only_default=False,
index=None):
"""get owner of an option
"""
if not isinstance(opt, Option) and not isinstance(opt,
@ -456,7 +494,7 @@ class Values(object):
if validate_properties:
self._getitem(opt, path, True, force_permissive, None, True,
self_properties=self_properties)
owner = self._p_.getowner(path, owners.default)
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)
@ -467,7 +505,11 @@ class Values(object):
if validate_meta:
meta = context.cfgimpl_get_meta()
if owner is owners.default and meta is not None:
owner = meta.cfgimpl_get_values()._getowner(opt, path)
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)
return owner
def setowner(self, opt, owner):
@ -481,9 +523,6 @@ class Values(object):
raise TypeError(_("invalid generic owner {0}").format(str(owner)))
path = opt.impl_getpath(self._getcontext())
self._setowner(opt, path, owner)
def _setowner(self, opt, path, owner):
if not self._p_.hasvalue(path): # pragma: optional cover
raise ConfigError(_('no value for {0} cannot change owner to {1}'
'').format(path, owner))
@ -495,7 +534,7 @@ class Values(object):
self._p_.setowner(path, owner)
def is_default_owner(self, opt, validate_properties=True,
validate_meta=True):
validate_meta=True, index=None):
"""
:param config: *must* be only the **parent** config
(not the toplevel config)
@ -504,14 +543,18 @@ class Values(object):
path = opt.impl_getpath(self._getcontext())
return self._is_default_owner(opt, path,
validate_properties=validate_properties,
validate_meta=validate_meta)
validate_meta=validate_meta, index=index)
def _is_default_owner(self, opt, path, validate_properties=True,
validate_meta=True, self_properties=undefined):
return self._getowner(opt, path, validate_properties,
validate_meta=validate_meta,
self_properties=self_properties) == \
owners.default
validate_meta=True, self_properties=undefined,
index=None):
if not opt.impl_is_master_slaves('slave'):
index = None
d = self._getowner(opt, path, validate_properties,
validate_meta=validate_meta,
self_properties=self_properties, only_default=True,
index=index)
return d == owners.default
def reset_cache(self, only_expired):
"""
@ -640,7 +683,6 @@ class Values(object):
# ____________________________________________________________
# multi types
class Multi(list):
"""multi options values container
that support item notation for the values of multi options"""
@ -708,7 +750,7 @@ class Multi(list):
self._validate(value, fake_context, index, True)
#assume not checking mandatory property
super(Multi, self).__setitem__(index, value)
context.cfgimpl_get_values()._setvalue(self.opt, self.path, self, setting_properties=setting_properties)
self._store()
#def __repr__(self, *args, **kwargs):
# return super(Multi, self).__repr__(*args, **kwargs)
@ -750,7 +792,7 @@ class Multi(list):
value.submulti = weakref.ref(self)
super(Multi, self).append(value)
if setitem:
self._store(force)
self._store(force=force)
def sort(self, cmp=None, key=None, reverse=False):
if self.opt.impl_is_master_slaves():
@ -773,7 +815,6 @@ class Multi(list):
self._store()
def insert(self, index, value, validate=True):
#FIXME value should be undefined
if self.opt.impl_is_master_slaves():
raise SlaveError(_("cannot insert multi option {0} if master or "
"slave").format(self.opt.impl_getname()))
@ -833,7 +874,7 @@ class Multi(list):
context.cfgimpl_get_values(), index)
#set value without valid properties
ret = super(Multi, self).pop(index)
self._store(force)
self._store(force=force)
return ret
def _store(self, force=False):