separate value in slave
This commit is contained in:
parent
a248508498
commit
54ca54e505
16 changed files with 409 additions and 416 deletions
20
ChangeLog
20
ChangeLog
|
@ -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
|
||||
|
|
|
@ -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():
|
||||
|
|
|
@ -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():
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 == []
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -47,7 +47,7 @@ class StorageBase(object):
|
|||
'_master_slaves',
|
||||
'_choice_values',
|
||||
'_choice_values_params',
|
||||
#autre
|
||||
#other
|
||||
'_state_master_slaves',
|
||||
'_state_callback',
|
||||
'_state_callback_params',
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in a new issue