add SubMulti
This commit is contained in:
parent
b6a0f188b2
commit
9112a8c5b0
13 changed files with 909 additions and 86 deletions
|
@ -1,3 +1,8 @@
|
|||
XXXXXXXXXXXXX Emmanuel Garette <egarette@cadoles.com>
|
||||
|
||||
* add SubMulti:
|
||||
a SubMulti is a multi in a multi variable
|
||||
|
||||
Sat Apr 12 11:37:27 CEST 2014 Emmanuel Garette <egarette@cadoles.com>
|
||||
|
||||
* behavior change in master/slave part of code:
|
||||
|
|
|
@ -3,7 +3,7 @@ import autopath
|
|||
#from py.test import raises
|
||||
|
||||
from tiramisu.config import Config, GroupConfig, MetaConfig
|
||||
from tiramisu.option import BoolOption, IntOption, OptionDescription
|
||||
from tiramisu.option import BoolOption, IntOption, StrOption, OptionDescription, submulti
|
||||
import weakref
|
||||
|
||||
|
||||
|
@ -137,3 +137,21 @@ def test_deref_metaconfig():
|
|||
assert w() is not None
|
||||
del(meta)
|
||||
assert w() is None
|
||||
|
||||
|
||||
def test_deref_submulti():
|
||||
multi = StrOption('multi', '', multi=submulti)
|
||||
od = OptionDescription('od', '', [multi])
|
||||
cfg = Config(od)
|
||||
cfg.cfgimpl_get_settings().remove('cache')
|
||||
w = weakref.ref(cfg.multi)
|
||||
assert w() is None
|
||||
cfg.multi.append([])
|
||||
w = weakref.ref(cfg.multi)
|
||||
assert w() is None
|
||||
m = cfg.multi
|
||||
w = weakref.ref(m)
|
||||
z = weakref.ref(w()[0])
|
||||
del(m)
|
||||
assert w() is None
|
||||
assert z() is None
|
||||
|
|
|
@ -438,8 +438,9 @@ def test_callback_multi_callback():
|
|||
cfg = Config(maconfig)
|
||||
cfg.read_write()
|
||||
assert cfg.val1.val1 == ['val']
|
||||
cfg.val1.val1 = ['val1']
|
||||
cfg.val1.val1.append()
|
||||
assert cfg.val1.val1 == ['val', 'val']
|
||||
assert cfg.val1.val1 == ['val1', 'val']
|
||||
|
||||
|
||||
def test_callback_master_and_slaves_master():
|
||||
|
|
|
@ -355,6 +355,7 @@ def test_multi_insert():
|
|||
c.var.insert(0, 'nok')
|
||||
assert c.var == ['nok', 'ok']
|
||||
assert c.getowner(var) != owners.default
|
||||
raises(ValueError, 'c.var.insert(0, 1)')
|
||||
|
||||
|
||||
def test_multi_insert_master():
|
||||
|
@ -427,6 +428,7 @@ def test_multi_extend():
|
|||
c.var.extend(['pok'])
|
||||
assert c.var == ['ok', 'nok', 'pok']
|
||||
assert c.getowner(var) != owners.default
|
||||
raises(ValueError, 'c.var.extend([1])')
|
||||
|
||||
|
||||
def test_multi_extend_master():
|
||||
|
|
639
test/test_submulti.py
Normal file
639
test/test_submulti.py
Normal file
|
@ -0,0 +1,639 @@
|
|||
# coding: utf-8
|
||||
import autopath
|
||||
from tiramisu.setting import groups, owners
|
||||
from tiramisu.config import Config
|
||||
from tiramisu.option import StrOption, OptionDescription, submulti
|
||||
from tiramisu.value import SubMulti, Multi
|
||||
from tiramisu.error import SlaveError
|
||||
|
||||
from py.test import raises
|
||||
|
||||
|
||||
def return_val():
|
||||
return 'val'
|
||||
|
||||
|
||||
def return_list(value=None):
|
||||
return ['val', 'val']
|
||||
|
||||
|
||||
def return_list2(value=None):
|
||||
return [['val', 'val']]
|
||||
|
||||
|
||||
def test_submulti():
|
||||
multi = StrOption('multi', '', multi=submulti)
|
||||
multi2 = StrOption('multi2', '', default_multi='yes', multi=submulti)
|
||||
multi3 = StrOption('multi3', '', default=[['yes']], multi=submulti)
|
||||
od = OptionDescription('od', '', [multi, multi2, multi3])
|
||||
cfg = Config(od)
|
||||
assert cfg.getowner(multi) == owners.default
|
||||
assert cfg.multi == []
|
||||
assert cfg.getowner(multi) == owners.default
|
||||
assert cfg.getowner(multi) == owners.default
|
||||
assert cfg.multi3 == [['yes']]
|
||||
assert cfg.multi3[0] == ['yes']
|
||||
assert cfg.multi3[0][0] == 'yes'
|
||||
cfg.multi3[0]
|
||||
assert cfg.getowner(multi) == owners.default
|
||||
|
||||
|
||||
def test_append_submulti():
|
||||
multi = StrOption('multi', '', multi=submulti)
|
||||
multi2 = StrOption('multi2', '', default_multi='yes', multi=submulti)
|
||||
multi3 = StrOption('multi3', '', default=[['yes']], multi=submulti)
|
||||
od = OptionDescription('od', '', [multi, multi2, multi3])
|
||||
cfg = Config(od)
|
||||
owner = cfg.cfgimpl_get_settings().getowner()
|
||||
assert cfg.multi == []
|
||||
assert cfg.getowner(multi) == owners.default
|
||||
cfg.multi.append()
|
||||
assert cfg.getowner(multi) == owner
|
||||
assert cfg.multi == [[]]
|
||||
cfg.multi.append(['no'])
|
||||
assert cfg.multi == [[], ['no']]
|
||||
#
|
||||
assert cfg.multi2 == []
|
||||
assert cfg.getowner(multi2) == owners.default
|
||||
cfg.multi2.append()
|
||||
assert cfg.getowner(multi2) == owner
|
||||
assert cfg.multi2 == [['yes']]
|
||||
cfg.multi2.append(['no'])
|
||||
assert cfg.multi2 == [['yes'], ['no']]
|
||||
#
|
||||
assert cfg.multi3 == [['yes']]
|
||||
assert cfg.getowner(multi3) == owners.default
|
||||
cfg.multi3.append()
|
||||
assert cfg.getowner(multi3) == owner
|
||||
assert cfg.multi3 == [['yes'], []]
|
||||
cfg.multi3.append(['no'])
|
||||
assert cfg.multi3 == [['yes'], [], ['no']]
|
||||
|
||||
|
||||
def test_append_unvalide_submulti():
|
||||
multi = StrOption('multi', '', multi=submulti)
|
||||
multi2 = StrOption('multi2', '', default_multi='yes', multi=submulti)
|
||||
multi3 = StrOption('multi3', '', default=[['yes']], multi=submulti)
|
||||
od = OptionDescription('od', '', [multi, multi2, multi3])
|
||||
cfg = Config(od)
|
||||
assert cfg.multi == []
|
||||
assert cfg.getowner(multi) == owners.default
|
||||
raises(ValueError, "cfg.multi.append(1)")
|
||||
assert cfg.multi == []
|
||||
assert cfg.getowner(multi) == owners.default
|
||||
#
|
||||
assert cfg.multi2 == []
|
||||
raises(ValueError, "cfg.multi2.append('no')")
|
||||
assert cfg.getowner(multi) == owners.default
|
||||
assert cfg.multi2 == []
|
||||
#
|
||||
assert cfg.multi3 == [['yes']]
|
||||
assert cfg.getowner(multi3) == owners.default
|
||||
raises(ValueError, "cfg.multi3[0].append(1)")
|
||||
assert cfg.multi3 == [['yes']]
|
||||
assert cfg.getowner(multi3) == owners.default
|
||||
raises(ValueError, "cfg.multi3[0].append([])")
|
||||
assert cfg.multi3 == [['yes']]
|
||||
assert cfg.getowner(multi3) == owners.default
|
||||
|
||||
|
||||
def test_pop_submulti():
|
||||
multi = StrOption('multi', '', multi=submulti)
|
||||
multi2 = StrOption('multi2', '', default_multi='yes', multi=submulti)
|
||||
multi3 = StrOption('multi3', '', default=[['yes']], multi=submulti)
|
||||
od = OptionDescription('od', '', [multi, multi2, multi3])
|
||||
cfg = Config(od)
|
||||
owner = cfg.cfgimpl_get_settings().getowner()
|
||||
assert cfg.multi == []
|
||||
assert cfg.getowner(multi3) == owners.default
|
||||
cfg.multi = [['no', 'yes'], ['peharps']]
|
||||
assert cfg.getowner(multi) == owner
|
||||
assert cfg.multi == [['no', 'yes'], ['peharps']]
|
||||
cfg.multi[0].pop(1)
|
||||
assert cfg.multi == [['no'], ['peharps']]
|
||||
cfg.multi[0].pop(0)
|
||||
assert cfg.multi == [[], ['peharps']]
|
||||
cfg.multi.pop(1)
|
||||
assert cfg.multi == [[]]
|
||||
cfg.multi.pop(0)
|
||||
assert cfg.multi == []
|
||||
#
|
||||
assert cfg.multi3 == [['yes']]
|
||||
assert cfg.getowner(multi3) == owners.default
|
||||
cfg.multi3.pop(0)
|
||||
assert cfg.getowner(multi) == owner
|
||||
assert cfg.multi3 == []
|
||||
del(cfg.multi3)
|
||||
assert cfg.getowner(multi3) == owners.default
|
||||
cfg.multi3[0].pop(0)
|
||||
assert cfg.getowner(multi3) == owner
|
||||
assert cfg.multi3 == [[]]
|
||||
|
||||
|
||||
def test_sort_submulti():
|
||||
multi = StrOption('multi', '', multi=submulti)
|
||||
multi2 = StrOption('multi2', '', default_multi='yes', multi=submulti)
|
||||
multi3 = StrOption('multi3', '', default=[['yes']], multi=submulti)
|
||||
od = OptionDescription('od', '', [multi, multi2, multi3])
|
||||
cfg = Config(od)
|
||||
owner = cfg.cfgimpl_get_settings().getowner()
|
||||
assert cfg.multi == []
|
||||
assert cfg.getowner(multi) == owners.default
|
||||
cfg.multi.sort()
|
||||
assert cfg.getowner(multi) == owner
|
||||
cfg.multi = [['no', 'yes'], ['peharps']]
|
||||
cfg.multi.sort()
|
||||
assert cfg.multi == [['no', 'yes'], ['peharps']]
|
||||
cfg.multi.sort(reverse=True)
|
||||
assert cfg.multi == [['peharps'], ['no', 'yes']]
|
||||
cfg.multi[1].sort(reverse=True)
|
||||
assert cfg.multi == [['peharps'], ['yes', 'no']]
|
||||
cfg.multi[1].sort()
|
||||
assert cfg.multi == [['peharps'], ['no', 'yes']]
|
||||
#
|
||||
assert cfg.multi3 == [['yes']]
|
||||
assert cfg.getowner(multi3) == owners.default
|
||||
cfg.multi3.sort()
|
||||
assert cfg.getowner(multi) == owner
|
||||
assert cfg.multi3 == [['yes']]
|
||||
del(cfg.multi3)
|
||||
assert cfg.getowner(multi3) == owners.default
|
||||
cfg.multi3[0].sort()
|
||||
assert cfg.getowner(multi) == owner
|
||||
assert cfg.multi3 == [['yes']]
|
||||
|
||||
|
||||
def test_reverse_submulti():
|
||||
multi = StrOption('multi', '', multi=submulti)
|
||||
multi2 = StrOption('multi2', '', default_multi='yes', multi=submulti)
|
||||
multi3 = StrOption('multi3', '', default=[['yes']], multi=submulti)
|
||||
od = OptionDescription('od', '', [multi, multi2, multi3])
|
||||
cfg = Config(od)
|
||||
owner = cfg.cfgimpl_get_settings().getowner()
|
||||
assert cfg.multi == []
|
||||
assert cfg.getowner(multi) == owners.default
|
||||
cfg.multi.reverse()
|
||||
assert cfg.getowner(multi) == owner
|
||||
cfg.multi = [['no', 'yes'], ['peharps']]
|
||||
cfg.multi.reverse()
|
||||
assert cfg.multi == [['peharps'], ['no', 'yes']]
|
||||
cfg.multi[1].reverse()
|
||||
assert cfg.multi == [['peharps'], ['yes', 'no']]
|
||||
#
|
||||
assert cfg.multi3 == [['yes']]
|
||||
assert cfg.getowner(multi3) == owners.default
|
||||
cfg.multi3.reverse()
|
||||
assert cfg.getowner(multi) == owner
|
||||
assert cfg.multi3 == [['yes']]
|
||||
del(cfg.multi3)
|
||||
assert cfg.getowner(multi3) == owners.default
|
||||
cfg.multi3[0].reverse()
|
||||
assert cfg.getowner(multi) == owner
|
||||
assert cfg.multi3 == [['yes']]
|
||||
|
||||
|
||||
def test_insert_submulti():
|
||||
multi = StrOption('multi', '', multi=submulti)
|
||||
multi2 = StrOption('multi2', '', default_multi='yes', multi=submulti)
|
||||
multi3 = StrOption('multi3', '', default=[['yes']], multi=submulti)
|
||||
od = OptionDescription('od', '', [multi, multi2, multi3])
|
||||
cfg = Config(od)
|
||||
owner = cfg.cfgimpl_get_settings().getowner()
|
||||
assert cfg.multi == []
|
||||
assert cfg.getowner(multi) == owners.default
|
||||
cfg.multi.insert(0, ['no'])
|
||||
assert cfg.getowner(multi) == owner
|
||||
assert cfg.multi == [['no']]
|
||||
assert isinstance(cfg.multi, Multi)
|
||||
assert isinstance(cfg.multi[0], SubMulti)
|
||||
#
|
||||
assert cfg.multi3 == [['yes']]
|
||||
assert cfg.getowner(multi3) == owners.default
|
||||
cfg.multi3.insert(1, [])
|
||||
assert cfg.getowner(multi3) == owner
|
||||
assert cfg.multi3 == [['yes'], []]
|
||||
cfg.multi3.insert(0, ['no'])
|
||||
assert cfg.multi3 == [['no'], ['yes'], []]
|
||||
del(cfg.multi3)
|
||||
assert cfg.getowner(multi3) == owners.default
|
||||
cfg.multi3[0].insert(0, 'no')
|
||||
assert cfg.getowner(multi3) == owner
|
||||
assert cfg.multi3 == [['no', 'yes']]
|
||||
|
||||
|
||||
def test_insert_unvalide_submulti():
|
||||
multi = StrOption('multi', '', multi=submulti)
|
||||
multi2 = StrOption('multi2', '', default_multi='yes', multi=submulti)
|
||||
multi3 = StrOption('multi3', '', default=[['yes']], multi=submulti)
|
||||
od = OptionDescription('od', '', [multi, multi2, multi3])
|
||||
cfg = Config(od)
|
||||
assert cfg.multi == []
|
||||
assert cfg.getowner(multi) == owners.default
|
||||
raises(ValueError, "cfg.multi.insert(0, 1)")
|
||||
assert cfg.multi == []
|
||||
assert cfg.getowner(multi) == owners.default
|
||||
#
|
||||
assert cfg.multi3 == [['yes']]
|
||||
assert cfg.getowner(multi3) == owners.default
|
||||
raises(ValueError, "cfg.multi3[0].insert(0, 1)")
|
||||
assert cfg.multi3 == [['yes']]
|
||||
assert cfg.getowner(multi3) == owners.default
|
||||
|
||||
|
||||
def test_extend_submulti():
|
||||
multi = StrOption('multi', '', multi=submulti)
|
||||
multi2 = StrOption('multi2', '', default_multi='yes', multi=submulti)
|
||||
multi3 = StrOption('multi3', '', default=[['yes']], multi=submulti)
|
||||
od = OptionDescription('od', '', [multi, multi2, multi3])
|
||||
cfg = Config(od)
|
||||
owner = cfg.cfgimpl_get_settings().getowner()
|
||||
assert cfg.multi == []
|
||||
assert cfg.getowner(multi) == owners.default
|
||||
cfg.multi.extend([['no']])
|
||||
assert cfg.getowner(multi) == owner
|
||||
assert cfg.multi == [['no']]
|
||||
assert isinstance(cfg.multi, Multi)
|
||||
assert isinstance(cfg.multi[0], SubMulti)
|
||||
#
|
||||
assert cfg.multi3 == [['yes']]
|
||||
assert cfg.getowner(multi3) == owners.default
|
||||
cfg.multi3.extend([[]])
|
||||
assert cfg.getowner(multi3) == owner
|
||||
assert cfg.multi3 == [['yes'], []]
|
||||
cfg.multi3.extend([['no']])
|
||||
assert cfg.multi3 == [['yes'], [], ['no']]
|
||||
del(cfg.multi3)
|
||||
assert cfg.getowner(multi3) == owners.default
|
||||
cfg.multi3[0].extend(['no'])
|
||||
assert cfg.getowner(multi3) == owner
|
||||
assert cfg.multi3 == [['yes', 'no']]
|
||||
|
||||
|
||||
def test_extend_unvalide_submulti():
|
||||
multi = StrOption('multi', '', multi=submulti)
|
||||
multi2 = StrOption('multi2', '', default_multi='yes', multi=submulti)
|
||||
multi3 = StrOption('multi3', '', default=[['yes']], multi=submulti)
|
||||
od = OptionDescription('od', '', [multi, multi2, multi3])
|
||||
cfg = Config(od)
|
||||
assert cfg.multi == []
|
||||
assert cfg.getowner(multi) == owners.default
|
||||
raises(ValueError, "cfg.multi.extend([[1]])")
|
||||
assert cfg.multi == []
|
||||
assert cfg.getowner(multi) == owners.default
|
||||
#
|
||||
assert cfg.multi3 == [['yes']]
|
||||
assert cfg.getowner(multi3) == owners.default
|
||||
raises(ValueError, "cfg.multi3[0].extend([1])")
|
||||
assert cfg.multi3 == [['yes']]
|
||||
assert cfg.getowner(multi3) == owners.default
|
||||
|
||||
|
||||
def test_callback_submulti_str():
|
||||
multi = StrOption('multi', '', multi=submulti, callback=return_val)
|
||||
od = OptionDescription('od', '', [multi])
|
||||
cfg = Config(od)
|
||||
cfg.read_write()
|
||||
owner = cfg.cfgimpl_get_settings().getowner()
|
||||
assert cfg.getowner(multi) == owners.default
|
||||
assert cfg.multi == [['val']]
|
||||
cfg.multi.append()
|
||||
assert cfg.getowner(multi) == owner
|
||||
assert cfg.multi == [['val'], ['val']]
|
||||
del(cfg.multi)
|
||||
assert cfg.getowner(multi) == owners.default
|
||||
cfg.multi[0].append()
|
||||
assert cfg.getowner(multi) == owner
|
||||
assert cfg.multi == [['val', 'val']]
|
||||
|
||||
|
||||
def test_callback_submulti_list():
|
||||
multi = StrOption('multi', '', multi=submulti, callback=return_list)
|
||||
od = OptionDescription('od', '', [multi])
|
||||
cfg = Config(od)
|
||||
cfg.read_write()
|
||||
owner = cfg.cfgimpl_get_settings().getowner()
|
||||
assert cfg.multi == [['val', 'val']]
|
||||
assert cfg.getowner(multi) == owners.default
|
||||
cfg.multi.append()
|
||||
assert cfg.getowner(multi) == owner
|
||||
assert cfg.multi == [['val', 'val'], ['val', 'val']]
|
||||
del(cfg.multi)
|
||||
assert cfg.getowner(multi) == owners.default
|
||||
cfg.multi[0].append()
|
||||
assert cfg.getowner(multi) == owner
|
||||
assert cfg.multi == [['val', 'val', None]]
|
||||
|
||||
|
||||
def test_callback_submulti_list_list():
|
||||
multi = StrOption('multi', '', multi=submulti, callback=return_list2)
|
||||
od = OptionDescription('od', '', [multi])
|
||||
cfg = Config(od)
|
||||
cfg.read_write()
|
||||
owner = cfg.cfgimpl_get_settings().getowner()
|
||||
assert cfg.multi == [['val', 'val']]
|
||||
assert cfg.getowner(multi) == owners.default
|
||||
cfg.multi.append()
|
||||
assert cfg.getowner(multi) == owner
|
||||
assert cfg.multi == [['val', 'val'], []]
|
||||
del(cfg.multi)
|
||||
assert cfg.getowner(multi) == owners.default
|
||||
cfg.multi[0].append()
|
||||
assert cfg.getowner(multi) == owner
|
||||
assert cfg.multi == [['val', 'val', None]]
|
||||
|
||||
|
||||
#FIXME multi sur une master
|
||||
|
||||
|
||||
def test_groups_with_master_submulti():
|
||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=submulti)
|
||||
interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||
interface1.impl_set_group_type(groups.master)
|
||||
assert interface1.impl_get_group_type() == groups.master
|
||||
|
||||
|
||||
def test_groups_with_master_in_config_submulti():
|
||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=submulti)
|
||||
interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||
interface1.impl_set_group_type(groups.master)
|
||||
Config(interface1)
|
||||
assert interface1.impl_get_group_type() == groups.master
|
||||
|
||||
|
||||
def test_values_with_master_and_slaves_submulti():
|
||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=submulti)
|
||||
interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||
interface1.impl_set_group_type(groups.master)
|
||||
maconfig = OptionDescription('toto', '', [interface1])
|
||||
cfg = Config(maconfig)
|
||||
cfg.read_write()
|
||||
owner = cfg.cfgimpl_get_settings().getowner()
|
||||
assert interface1.impl_get_group_type() == groups.master
|
||||
assert cfg.getowner(ip_admin_eth0) == owners.default
|
||||
assert cfg.getowner(netmask_admin_eth0) == owners.default
|
||||
assert cfg.ip_admin_eth0.netmask_admin_eth0 == []
|
||||
cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
|
||||
assert cfg.ip_admin_eth0.ip_admin_eth0 == ["192.168.230.145"]
|
||||
assert cfg.ip_admin_eth0.netmask_admin_eth0 == [[]]
|
||||
assert cfg.getowner(ip_admin_eth0) == owner
|
||||
assert cfg.getowner(netmask_admin_eth0) == owners.default
|
||||
cfg.ip_admin_eth0.ip_admin_eth0 = ["192.168.230.145", "192.168.230.147"]
|
||||
assert cfg.ip_admin_eth0.netmask_admin_eth0 == [[], []]
|
||||
raises(SlaveError, 'cfg.ip_admin_eth0.netmask_admin_eth0.append(None)')
|
||||
raises(SlaveError, 'cfg.ip_admin_eth0.netmask_admin_eth0.pop(0)')
|
||||
cfg.ip_admin_eth0.netmask_admin_eth0[0].append('255.255.255.0')
|
||||
assert cfg.ip_admin_eth0.netmask_admin_eth0 == [['255.255.255.0'], []]
|
||||
cfg.ip_admin_eth0.netmask_admin_eth0[0].pop(0)
|
||||
assert cfg.ip_admin_eth0.netmask_admin_eth0 == [[], []]
|
||||
raises(ValueError, 'cfg.ip_admin_eth0.netmask_admin_eth0 = ["255.255.255.0", "255.255.255.0"]')
|
||||
|
||||
|
||||
def test_reset_values_with_master_and_slaves_submulti():
|
||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=submulti)
|
||||
interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||
interface1.impl_set_group_type(groups.master)
|
||||
maconfig = OptionDescription('toto', '', [interface1])
|
||||
cfg = Config(maconfig)
|
||||
cfg.read_write()
|
||||
owner = cfg.cfgimpl_get_settings().getowner()
|
||||
assert interface1.impl_get_group_type() == groups.master
|
||||
assert cfg.getowner(ip_admin_eth0) == owners.default
|
||||
assert cfg.getowner(netmask_admin_eth0) == owners.default
|
||||
cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
|
||||
assert cfg.getowner(ip_admin_eth0) == owner
|
||||
assert cfg.getowner(netmask_admin_eth0) == owners.default
|
||||
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.ip_admin_eth0.ip_admin_eth0 == []
|
||||
assert cfg.ip_admin_eth0.netmask_admin_eth0 == []
|
||||
#
|
||||
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
|
||||
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.ip_admin_eth0.ip_admin_eth0 == []
|
||||
assert cfg.ip_admin_eth0.netmask_admin_eth0 == []
|
||||
|
||||
|
||||
def test_values_with_master_and_slaves_slave_submulti():
|
||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=submulti)
|
||||
interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||
interface1.impl_set_group_type(groups.master)
|
||||
maconfig = OptionDescription('toto', '', [interface1])
|
||||
cfg = Config(maconfig)
|
||||
cfg.read_write()
|
||||
assert cfg.ip_admin_eth0.netmask_admin_eth0 == []
|
||||
raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0 = [['255.255.255.0']]")
|
||||
cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
|
||||
cfg.ip_admin_eth0.netmask_admin_eth0 = [['255.255.255.0']]
|
||||
cfg.ip_admin_eth0.netmask_admin_eth0[0] = ['255.255.255.0']
|
||||
cfg.ip_admin_eth0.netmask_admin_eth0[0][0] = '255.255.255.0'
|
||||
raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0 = [['255.255.255.0'], ['255.255.255.0']]")
|
||||
raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0 = []")
|
||||
del(cfg.ip_admin_eth0.netmask_admin_eth0)
|
||||
cfg.ip_admin_eth0.netmask_admin_eth0 = [['255.255.255.0']]
|
||||
cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
|
||||
assert cfg.ip_admin_eth0.netmask_admin_eth0 == [['255.255.255.0'], []]
|
||||
cfg.ip_admin_eth0.netmask_admin_eth0 = [['255.255.255.0'], ['255.255.255.0']]
|
||||
raises(SlaveError, 'cfg.ip_admin_eth0.netmask_admin_eth0.pop(1)')
|
||||
|
||||
|
||||
def test_values_with_master_and_slaves_master_submulti():
|
||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=submulti)
|
||||
interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||
interface1.impl_set_group_type(groups.master)
|
||||
maconfig = OptionDescription('toto', '', [interface1])
|
||||
cfg = Config(maconfig)
|
||||
cfg.read_write()
|
||||
cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
|
||||
cfg.ip_admin_eth0.ip_admin_eth0 = ["192.168.230.145"]
|
||||
cfg.ip_admin_eth0.ip_admin_eth0 = ["192.168.230.145", "192.168.230.145"]
|
||||
cfg.ip_admin_eth0.netmask_admin_eth0 = [['255.255.255.0'], ['255.255.255.0']]
|
||||
raises(SlaveError, 'cfg.ip_admin_eth0.ip_admin_eth0 = ["192.168.230.145"]')
|
||||
assert cfg.ip_admin_eth0.netmask_admin_eth0 == [['255.255.255.0'], ['255.255.255.0']]
|
||||
cfg.ip_admin_eth0.ip_admin_eth0.pop(1)
|
||||
assert cfg.ip_admin_eth0.ip_admin_eth0 == ["192.168.230.145"]
|
||||
assert cfg.ip_admin_eth0.netmask_admin_eth0 == [['255.255.255.0']]
|
||||
del(cfg.ip_admin_eth0.ip_admin_eth0)
|
||||
assert cfg.ip_admin_eth0.ip_admin_eth0 == []
|
||||
assert cfg.ip_admin_eth0.netmask_admin_eth0 == []
|
||||
|
||||
|
||||
def test_values_with_master_and_slaves_master_error_submulti():
|
||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=submulti)
|
||||
interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||
interface1.impl_set_group_type(groups.master)
|
||||
maconfig = OptionDescription('toto', '', [interface1])
|
||||
cfg = Config(maconfig)
|
||||
cfg.read_write()
|
||||
cfg.ip_admin_eth0.ip_admin_eth0 = ["192.168.230.145", "192.168.230.145"]
|
||||
raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0 = [['255.255.255.0']]")
|
||||
raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0 = [['255.255.255.0'], ['255.255.255.0'], ['255.255.255.0']]")
|
||||
cfg.ip_admin_eth0.netmask_admin_eth0 = [['255.255.255.0'], ['255.255.255.0']]
|
||||
raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0 = [['255.255.255.0']]")
|
||||
raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0 = [['255.255.255.0'], ['255.255.255.0'], ['255.255.255.0']]")
|
||||
|
||||
|
||||
def test_values_with_master_owner_submulti():
|
||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=submulti)
|
||||
interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||
interface1.impl_set_group_type(groups.master)
|
||||
maconfig = OptionDescription('toto', '', [interface1])
|
||||
cfg = Config(maconfig)
|
||||
cfg.read_write()
|
||||
owner = cfg.cfgimpl_get_settings().getowner()
|
||||
assert cfg.getowner(ip_admin_eth0) == owners.default
|
||||
assert cfg.getowner(netmask_admin_eth0) == owners.default
|
||||
cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
|
||||
assert cfg.getowner(ip_admin_eth0) == owner
|
||||
assert cfg.getowner(netmask_admin_eth0) == owners.default
|
||||
cfg.ip_admin_eth0.ip_admin_eth0.pop(0)
|
||||
assert cfg.getowner(ip_admin_eth0) == owner
|
||||
assert cfg.getowner(netmask_admin_eth0) == owners.default
|
||||
|
||||
|
||||
def test_values_with_master_disabled_submulti():
|
||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=submulti)
|
||||
interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||
interface1.impl_set_group_type(groups.master)
|
||||
maconfig = OptionDescription('toto', '', [interface1])
|
||||
cfg = Config(maconfig)
|
||||
cfg.read_write()
|
||||
cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
|
||||
cfg.ip_admin_eth0.ip_admin_eth0.pop(0)
|
||||
cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
|
||||
cfg.ip_admin_eth0.netmask_admin_eth0 = [["192.168.230.145"]]
|
||||
cfg.ip_admin_eth0.ip_admin_eth0.pop(0)
|
||||
del(cfg.ip_admin_eth0.netmask_admin_eth0)
|
||||
cfg.cfgimpl_get_settings()[netmask_admin_eth0].append('disabled')
|
||||
cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
|
||||
cfg.ip_admin_eth0.ip_admin_eth0.pop(0)
|
||||
|
||||
#delete with value in disabled var
|
||||
cfg.cfgimpl_get_settings()[netmask_admin_eth0].remove('disabled')
|
||||
cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
|
||||
cfg.ip_admin_eth0.netmask_admin_eth0 = [["192.168.230.145"]]
|
||||
cfg.cfgimpl_get_settings()[netmask_admin_eth0].append('disabled')
|
||||
cfg.ip_admin_eth0.ip_admin_eth0.pop(0)
|
||||
|
||||
#append with value in disabled var
|
||||
cfg.cfgimpl_get_settings()[netmask_admin_eth0].remove('disabled')
|
||||
cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
|
||||
cfg.ip_admin_eth0.netmask_admin_eth0 = [["192.168.230.145"]]
|
||||
cfg.cfgimpl_get_settings()[netmask_admin_eth0].append('disabled')
|
||||
cfg.ip_admin_eth0.ip_admin_eth0.append('192.168.230.43')
|
||||
|
||||
|
||||
def test_multi_insert_master_submulti():
|
||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=submulti)
|
||||
interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||
interface1.impl_set_group_type(groups.master)
|
||||
maconfig = OptionDescription('toto', '', [interface1])
|
||||
cfg = Config(maconfig)
|
||||
cfg.read_write()
|
||||
raises(SlaveError, "cfg.ip_admin_eth0.ip_admin_eth0.insert(0, 'nok')")
|
||||
raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0.insert(0, 'nok')")
|
||||
cfg.ip_admin_eth0.ip_admin_eth0.append('192.168.1.1')
|
||||
raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0[0].insert(0, 'nok')")
|
||||
|
||||
|
||||
def test_multi_sort_master_submulti():
|
||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=submulti)
|
||||
interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||
interface1.impl_set_group_type(groups.master)
|
||||
maconfig = OptionDescription('toto', '', [interface1])
|
||||
cfg = Config(maconfig)
|
||||
cfg.read_write()
|
||||
raises(SlaveError, "cfg.ip_admin_eth0.ip_admin_eth0.sort()")
|
||||
raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0.sort()")
|
||||
cfg.ip_admin_eth0.ip_admin_eth0.append('192.168.1.1')
|
||||
raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0[0].sort()")
|
||||
|
||||
|
||||
def test_multi_reverse_master_submulti():
|
||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=submulti)
|
||||
interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||
interface1.impl_set_group_type(groups.master)
|
||||
maconfig = OptionDescription('toto', '', [interface1])
|
||||
cfg = Config(maconfig)
|
||||
cfg.read_write()
|
||||
raises(SlaveError, "cfg.ip_admin_eth0.ip_admin_eth0.reverse()")
|
||||
raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0.reverse()")
|
||||
cfg.ip_admin_eth0.ip_admin_eth0.append('192.168.1.1')
|
||||
raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0[0].reverse()")
|
||||
|
||||
|
||||
def test_multi_extend_master_submulti():
|
||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=submulti)
|
||||
interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||
interface1.impl_set_group_type(groups.master)
|
||||
maconfig = OptionDescription('toto', '', [interface1])
|
||||
cfg = Config(maconfig)
|
||||
cfg.read_write()
|
||||
raises(SlaveError, "cfg.ip_admin_eth0.ip_admin_eth0.extend(['ok'])")
|
||||
raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0.extend(['ok'])")
|
||||
cfg.ip_admin_eth0.ip_admin_eth0.append('192.168.1.1')
|
||||
raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0[0].extend(['ok'])")
|
||||
|
||||
|
||||
def test_slave_submulti():
|
||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=submulti)
|
||||
interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||
interface1.impl_set_group_type(groups.master)
|
||||
maconfig = OptionDescription('toto', '', [interface1])
|
||||
cfg = Config(maconfig)
|
||||
cfg.read_write()
|
||||
assert cfg.ip_admin_eth0.ip_admin_eth0.__class__.__name__ == 'Multi'
|
||||
assert cfg.ip_admin_eth0.netmask_admin_eth0.__class__.__name__ == 'Multi'
|
||||
cfg.ip_admin_eth0.ip_admin_eth0.append('192.168.1.1')
|
||||
assert cfg.ip_admin_eth0.ip_admin_eth0.__class__.__name__ == 'Multi'
|
||||
assert cfg.ip_admin_eth0.netmask_admin_eth0.__class__.__name__ == 'Multi'
|
||||
assert cfg.ip_admin_eth0.ip_admin_eth0[0].__class__.__name__ == 'str'
|
||||
assert cfg.ip_admin_eth0.netmask_admin_eth0[0].__class__.__name__ == 'SubMulti'
|
||||
|
||||
|
||||
def test__master_is_submulti():
|
||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=submulti)
|
||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
|
||||
interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||
interface1.impl_set_group_type(groups.master)
|
||||
maconfig = OptionDescription('toto', '', [interface1])
|
||||
cfg = Config(maconfig)
|
||||
cfg.read_write()
|
||||
owner = cfg.cfgimpl_get_settings().getowner()
|
||||
assert interface1.impl_get_group_type() == groups.master
|
||||
assert cfg.getowner(ip_admin_eth0) == owners.default
|
||||
assert cfg.getowner(netmask_admin_eth0) == owners.default
|
||||
assert cfg.ip_admin_eth0.netmask_admin_eth0 == []
|
||||
cfg.ip_admin_eth0.ip_admin_eth0.append(["192.168.230.145"])
|
||||
assert cfg.ip_admin_eth0.ip_admin_eth0 == [["192.168.230.145"]]
|
||||
assert cfg.ip_admin_eth0.netmask_admin_eth0 == [None]
|
||||
assert cfg.getowner(ip_admin_eth0) == owner
|
||||
assert cfg.getowner(netmask_admin_eth0) == owners.default
|
||||
cfg.ip_admin_eth0.ip_admin_eth0 = [["192.168.230.145"], ["192.168.230.147"]]
|
||||
assert cfg.ip_admin_eth0.netmask_admin_eth0 == [None, None]
|
||||
raises(SlaveError, 'cfg.ip_admin_eth0.netmask_admin_eth0.append(None)')
|
||||
raises(SlaveError, 'cfg.ip_admin_eth0.netmask_admin_eth0.pop(0)')
|
||||
cfg.ip_admin_eth0.ip_admin_eth0[0].append('192.168.1.1')
|
||||
assert cfg.ip_admin_eth0.ip_admin_eth0 == [["192.168.230.145", '192.168.1.1'], ["192.168.230.147"]]
|
||||
cfg.ip_admin_eth0.ip_admin_eth0[0].pop(0)
|
||||
assert cfg.ip_admin_eth0.ip_admin_eth0 == [["192.168.1.1"], ["192.168.230.147"]]
|
||||
raises(ValueError, 'cfg.ip_admin_eth0.ip_admin_eth0 = ["192.168.1.1", "192.168.1.1"]')
|
|
@ -1,6 +1,6 @@
|
|||
from .masterslave import MasterSlaves
|
||||
from .optiondescription import OptionDescription
|
||||
from .baseoption import Option, SymLinkOption
|
||||
from .baseoption import Option, SymLinkOption, submulti
|
||||
from .option import (ChoiceOption, BoolOption, IntOption, FloatOption,
|
||||
StrOption, UnicodeOption, IPOption, PortOption,
|
||||
NetworkOption, NetmaskOption, BroadcastOption,
|
||||
|
@ -13,4 +13,4 @@ __all__ = ('MasterSlaves', 'OptionDescription', 'Option', 'SymLinkOption',
|
|||
'StrOption', 'UnicodeOption', 'IPOption', 'PortOption',
|
||||
'NetworkOption', 'NetmaskOption', 'BroadcastOption',
|
||||
'DomainnameOption', 'EmailOption', 'URLOption', 'UsernameOption',
|
||||
'FilenameOption')
|
||||
'FilenameOption', 'submulti')
|
||||
|
|
|
@ -32,6 +32,14 @@ from tiramisu.storage import get_storages_option
|
|||
|
||||
StorageBase = get_storages_option('base')
|
||||
|
||||
|
||||
class SubMulti(object):
|
||||
pass
|
||||
|
||||
|
||||
submulti = SubMulti()
|
||||
|
||||
|
||||
name_regexp = re.compile(r'^\d+')
|
||||
forbidden_names = ('iter_all', 'iter_group', 'find', 'find_first',
|
||||
'make_dict', 'unwrap_from_path', 'read_only',
|
||||
|
@ -123,7 +131,7 @@ class Base(StorageBase):
|
|||
"for option {1}: {2}").format(
|
||||
str(default_multi), name, err))
|
||||
self._multi = multi
|
||||
if self._multi:
|
||||
if self._multi is not False:
|
||||
if default is None:
|
||||
default = []
|
||||
self._default_multi = default_multi
|
||||
|
@ -414,7 +422,7 @@ class Option(OnlyOption):
|
|||
return self._requires
|
||||
|
||||
def _launch_consistency(self, func, option, value, context, index,
|
||||
all_cons_opts, warnings_only):
|
||||
submulti_index, all_cons_opts, warnings_only):
|
||||
"""Launch consistency now
|
||||
|
||||
:param func: function name, this name should start with _cons_
|
||||
|
@ -452,17 +460,24 @@ class Option(OnlyOption):
|
|||
#append value
|
||||
if not self.impl_is_multi() or option == opt:
|
||||
all_cons_vals.append(opt_value)
|
||||
else:
|
||||
elif self.impl_is_submulti():
|
||||
try:
|
||||
all_cons_vals.append(opt_value[index][submulti_index])
|
||||
except IndexError:
|
||||
#value is not already set, could be higher index
|
||||
#so return if no value
|
||||
return
|
||||
else:
|
||||
try:
|
||||
all_cons_vals.append(opt_value[index])
|
||||
except IndexError:
|
||||
#value is not already set, could be higher index
|
||||
#so return if no value
|
||||
return
|
||||
getattr(self, func)(all_cons_opts, all_cons_vals, warnings_only)
|
||||
|
||||
def impl_validate(self, value, context=None, validate=True,
|
||||
force_index=None):
|
||||
force_index=None, force_submulti_index=None):
|
||||
"""
|
||||
:param value: the option's value
|
||||
:param context: Config's context
|
||||
|
@ -472,6 +487,9 @@ class Option(OnlyOption):
|
|||
:param force_index: if multi, value has to be a list
|
||||
not if force_index is not None
|
||||
:type force_index: integer
|
||||
:param force_submulti_index: if submulti, value has to be a list
|
||||
not if force_submulti_index is not None
|
||||
:type force_submulti_index: integer
|
||||
"""
|
||||
if not validate:
|
||||
return
|
||||
|
@ -496,15 +514,17 @@ class Option(OnlyOption):
|
|||
callback=self._validator,
|
||||
callback_params=validator_params)
|
||||
|
||||
def do_validation(_value, _index=None):
|
||||
def do_validation(_value, _index, submulti_index):
|
||||
if _value is None:
|
||||
return
|
||||
# option validation
|
||||
try:
|
||||
self._validate(_value)
|
||||
except ValueError as err:
|
||||
log.debug('do_validation: value: {0} index: {1}'.format(
|
||||
_value, _index), exc_info=True)
|
||||
log.debug('do_validation: value: {0}, index: {1}, '
|
||||
'submulti_index: {2}'.format(_value, _index,
|
||||
submulti_index),
|
||||
exc_info=True)
|
||||
raise ValueError(_('invalid value for option {0}: {1}'
|
||||
'').format(self.impl_getname(), err))
|
||||
error = None
|
||||
|
@ -514,7 +534,8 @@ class Option(OnlyOption):
|
|||
val_validator(_value)
|
||||
# if not context launch consistency validation
|
||||
if context is not None:
|
||||
descr._valid_consistency(self, _value, context, _index)
|
||||
descr._valid_consistency(self, _value, context, _index,
|
||||
submulti_index)
|
||||
self._second_level_validation(_value, self._warnings_only)
|
||||
except ValueError as error:
|
||||
log.debug(_('do_validation for {0}: error in value').format(
|
||||
|
@ -530,7 +551,8 @@ class Option(OnlyOption):
|
|||
try:
|
||||
# if context launch consistency validation
|
||||
if context is not None:
|
||||
descr._valid_consistency(self, _value, context, _index)
|
||||
descr._valid_consistency(self, _value, context, _index,
|
||||
submulti_index)
|
||||
except ValueError as error:
|
||||
log.debug(_('do_validation for {0}: error in consistency').format(
|
||||
self.impl_getname()), exc_info=True)
|
||||
|
@ -553,13 +575,34 @@ class Option(OnlyOption):
|
|||
if context is not None:
|
||||
descr = context.cfgimpl_get_description()
|
||||
|
||||
if not self._multi or force_index is not None:
|
||||
do_validation(value, force_index)
|
||||
if not self.impl_is_multi():
|
||||
do_validation(value, None, None)
|
||||
elif force_index is not None:
|
||||
if self.impl_is_submulti() and force_submulti_index is None:
|
||||
if not isinstance(value, list):
|
||||
raise ValueError(_("invalid value {0} for option {1} which"
|
||||
" must be a list").format(
|
||||
value, self.impl_getname()))
|
||||
for idx, val in enumerate(value):
|
||||
do_validation(val, force_index, idx)
|
||||
else:
|
||||
do_validation(value, force_index, force_submulti_index)
|
||||
else:
|
||||
if not isinstance(value, list):
|
||||
raise ValueError(_("invalid value {0} for option {1} which must be a list").format(value, self.impl_getname()))
|
||||
for index, val in enumerate(value):
|
||||
do_validation(val, index)
|
||||
raise ValueError(_("invalid value {0} for option {1} which "
|
||||
"must be a list").format(value,
|
||||
self.impl_getname()))
|
||||
for idx, val in enumerate(value):
|
||||
if self.impl_is_submulti() and force_submulti_index is None:
|
||||
if not isinstance(val, list):
|
||||
raise ValueError(_("invalid value {0} for option {1} "
|
||||
"which must be a list of list"
|
||||
"").format(value,
|
||||
self.impl_getname()))
|
||||
for slave_idx, slave_val in enumerate(val):
|
||||
do_validation(slave_val, idx, slave_idx)
|
||||
else:
|
||||
do_validation(val, idx, force_submulti_index)
|
||||
|
||||
def impl_getdefault(self):
|
||||
"accessing the default value"
|
||||
|
@ -615,7 +658,10 @@ class Option(OnlyOption):
|
|||
# return value
|
||||
|
||||
def impl_is_multi(self):
|
||||
return self._multi
|
||||
return self._multi is True or self._multi is submulti
|
||||
|
||||
def impl_is_submulti(self):
|
||||
return self._multi is submulti
|
||||
|
||||
def impl_add_consistency(self, func, *other_opts, **params):
|
||||
"""Add consistency means that value will be validate with other_opts
|
||||
|
@ -647,10 +693,18 @@ class Option(OnlyOption):
|
|||
if value is not None:
|
||||
if self.impl_is_multi():
|
||||
for idx, val in enumerate(value):
|
||||
self._launch_consistency(func, self, val, None,
|
||||
idx, all_cons_opts, warnings_only)
|
||||
if not self.impl_is_submulti():
|
||||
self._launch_consistency(func, self, val, None, idx,
|
||||
None, all_cons_opts,
|
||||
warnings_only)
|
||||
else:
|
||||
self._launch_consistency(func, self, value, None,
|
||||
for slave_idx, val in enumerate(value):
|
||||
self._launch_consistency(func, self, val, None,
|
||||
idx, slave_idx,
|
||||
all_cons_opts,
|
||||
warnings_only)
|
||||
else:
|
||||
self._launch_consistency(func, self, value, None, None,
|
||||
None, all_cons_opts, warnings_only)
|
||||
self._add_consistency(func, all_cons_opts, params)
|
||||
self.impl_validate(self.impl_getdefault())
|
||||
|
@ -808,7 +862,8 @@ def validate_requires_arg(requires, name):
|
|||
'must be an option in option {0}').format(name))
|
||||
if option.impl_is_multi():
|
||||
raise ValueError(_('malformed requirements option {0} '
|
||||
'must not be a multi').format(name))
|
||||
'must not be a multi for {1}').format(
|
||||
option.impl_getname(), name))
|
||||
if expected is not None:
|
||||
try:
|
||||
option._validate(expected)
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
# the whole pypy projet is under MIT licence
|
||||
# ____________________________________________________________
|
||||
from tiramisu.i18n import _
|
||||
from tiramisu.setting import log
|
||||
from tiramisu.setting import log, undefined
|
||||
from tiramisu.error import SlaveError, ConfigError
|
||||
from .baseoption import SymLinkOption, Option
|
||||
|
||||
|
@ -87,18 +87,21 @@ class MasterSlaves(object):
|
|||
pass
|
||||
|
||||
def getitem(self, values, opt, path, validate, force_permissive,
|
||||
force_properties, validate_properties):
|
||||
force_properties, validate_properties, slave_path=undefined,
|
||||
slave_value=undefined):
|
||||
if opt == self.master:
|
||||
return self._getmaster(values, opt, path, validate,
|
||||
force_permissive, force_properties,
|
||||
validate_properties)
|
||||
validate_properties, slave_path,
|
||||
slave_value)
|
||||
else:
|
||||
return self._getslave(values, opt, path, validate,
|
||||
force_permissive, force_properties,
|
||||
validate_properties)
|
||||
|
||||
def _getmaster(self, values, opt, path, validate, force_permissive,
|
||||
force_properties, validate_properties):
|
||||
force_properties, validate_properties, c_slave_path,
|
||||
c_slave_value):
|
||||
value = values._get_validated_value(opt, path, validate,
|
||||
force_permissive,
|
||||
force_properties,
|
||||
|
@ -108,6 +111,9 @@ class MasterSlaves(object):
|
|||
for slave in self.slaves:
|
||||
try:
|
||||
slave_path = values._get_opt_path(slave)
|
||||
if c_slave_path == slave_path:
|
||||
slave_value = c_slave_value
|
||||
else:
|
||||
slave_value = values._get_validated_value(slave,
|
||||
slave_path,
|
||||
False,
|
||||
|
@ -146,10 +152,11 @@ class MasterSlaves(object):
|
|||
self.validate_slave_length(self.get_length(values), len(value),
|
||||
opt._name, setitem=True)
|
||||
|
||||
def get_length(self, values, validate=True):
|
||||
def get_length(self, values, validate=True, slave_path=undefined,
|
||||
slave_value=undefined):
|
||||
masterp = values._get_opt_path(self.master)
|
||||
return len(self.getitem(values, self.master, masterp, validate, False,
|
||||
None, True))
|
||||
None, True, slave_path, slave_value))
|
||||
|
||||
def validate_slave_length(self, masterlen, valuelen, name, setitem=False):
|
||||
if valuelen > masterlen or (valuelen < masterlen and setitem):
|
||||
|
@ -183,11 +190,11 @@ class MasterSlaves(object):
|
|||
list is greater than master: raise SlaveError
|
||||
"""
|
||||
#if slave, had values until master's one
|
||||
masterlen = self.get_length(values, validate)
|
||||
path = values._get_opt_path(opt)
|
||||
masterlen = self.get_length(values, validate, path, value)
|
||||
valuelen = len(value)
|
||||
if validate:
|
||||
self.validate_slave_length(masterlen, valuelen, opt._name)
|
||||
path = values._get_opt_path(opt)
|
||||
if valuelen < masterlen:
|
||||
for num in range(0, masterlen - valuelen):
|
||||
index = valuelen + num
|
||||
|
|
|
@ -134,7 +134,8 @@ class IPOption(Option):
|
|||
callback_params=None, validator=None, validator_params=None,
|
||||
properties=None, private_only=False, allow_reserved=False,
|
||||
warnings_only=False):
|
||||
self._extra = {'_private_only': private_only, '_allow_reserved': allow_reserved}
|
||||
self._extra = {'_private_only': private_only,
|
||||
'_allow_reserved': allow_reserved}
|
||||
super(IPOption, self).__init__(name, doc, default=default,
|
||||
default_multi=default_multi,
|
||||
callback=callback,
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
from copy import copy
|
||||
|
||||
from tiramisu.i18n import _
|
||||
from tiramisu.setting import groups, log
|
||||
from tiramisu.setting import groups # , log
|
||||
from .baseoption import BaseOption
|
||||
from . import MasterSlaves
|
||||
from tiramisu.error import ConfigError, ConflictError, ValueWarning
|
||||
|
@ -162,7 +162,7 @@ class OptionDescription(BaseOption, StorageOptionDescription):
|
|||
def impl_get_group_type(self):
|
||||
return self._group_type
|
||||
|
||||
def _valid_consistency(self, option, value, context, index):
|
||||
def _valid_consistency(self, option, value, context, index, submulti_idx):
|
||||
if self._cache_consistencies is None:
|
||||
return True
|
||||
#consistencies is something like [('_cons_not_equal', (opt1, opt2))]
|
||||
|
@ -175,6 +175,7 @@ class OptionDescription(BaseOption, StorageOptionDescription):
|
|||
all_cons_opts[0]._launch_consistency(func, option,
|
||||
value,
|
||||
context, index,
|
||||
submulti_idx,
|
||||
all_cons_opts,
|
||||
warnings_only)
|
||||
except ValueError as err:
|
||||
|
|
|
@ -223,7 +223,7 @@ populate_owners()
|
|||
|
||||
|
||||
# ____________________________________________________________
|
||||
class Undefined():
|
||||
class Undefined(object):
|
||||
pass
|
||||
|
||||
|
||||
|
|
|
@ -28,8 +28,8 @@ class Base(object):
|
|||
__slots__ = ('_name', '_requires', '_properties', '_readonly',
|
||||
'_calc_properties', '_informations',
|
||||
'_state_readonly', '_state_requires', '_stated',
|
||||
'_multi', '_validator', '_validator_params', '_default',
|
||||
'_default_multi', '_state_callback', '_callback',
|
||||
'_multi', '_validator', '_validator_params',
|
||||
'_default', '_default_multi', '_state_callback', '_callback',
|
||||
'_state_callback_params', '_callback_params', '_multitype',
|
||||
'_consistencies', '_warnings_only', '_master_slaves',
|
||||
'_state_consistencies', '_extra', '__weakref__')
|
||||
|
|
|
@ -86,7 +86,13 @@ class Values(object):
|
|||
index=index)
|
||||
try:
|
||||
if isinstance(value, list) and index is not undefined:
|
||||
return value[index]
|
||||
#if submulti and return a list of list, just return list
|
||||
if opt.impl_is_submulti():
|
||||
val = value[index]
|
||||
if isinstance(val, list):
|
||||
value = val
|
||||
else:
|
||||
value = value[index]
|
||||
return value
|
||||
except IndexError:
|
||||
pass
|
||||
|
@ -219,9 +225,10 @@ class Values(object):
|
|||
|
||||
def _get_validated_value(self, opt, path, validate, force_permissive,
|
||||
force_properties, validate_properties,
|
||||
index=undefined):
|
||||
"""same has getitem but don't touch the cache"""
|
||||
#FIXME expliquer la différence entre index == undefined et index == None
|
||||
index=undefined, submulti_index=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 []
|
||||
"""
|
||||
context = self._getcontext()
|
||||
setting = context.cfgimpl_get_settings()
|
||||
is_default = self._is_default_owner(opt, path,
|
||||
|
@ -254,13 +261,24 @@ class Values(object):
|
|||
else:
|
||||
force_index = index
|
||||
if opt.impl_is_multi():
|
||||
#for slave is a multi
|
||||
if index is None and not isinstance(value, list):
|
||||
value = []
|
||||
if force_index is None:
|
||||
value = Multi(value, self.context, opt, path)
|
||||
elif opt.impl_is_submulti() and submulti_index is undefined:
|
||||
value = SubMulti(value, self.context, opt, path,
|
||||
force_index)
|
||||
|
||||
if validate:
|
||||
if submulti_index is undefined:
|
||||
force_submulti_index = None
|
||||
else:
|
||||
force_submulti_index = submulti_index
|
||||
|
||||
opt.impl_validate(value, context, 'validator' in setting,
|
||||
force_index=force_index)
|
||||
force_index=force_index,
|
||||
force_submulti_index=force_submulti_index)
|
||||
#FIXME pas de test avec les metas ...
|
||||
#FIXME et les symlinkoption ...
|
||||
if is_default and 'force_store_value' in setting[opt]:
|
||||
|
@ -291,7 +309,7 @@ class Values(object):
|
|||
opt.impl_validate(value, context,
|
||||
'validator' in context.cfgimpl_get_settings())
|
||||
if opt.impl_is_multi():
|
||||
value = Multi(value, self.context, opt, path)
|
||||
#value = Multi(value, self.context, opt, path)
|
||||
if opt.impl_is_master_slaves():
|
||||
opt.impl_get_master_slaves().setitem(self, opt, value, path)
|
||||
self._setvalue(opt, path, value, force_permissive=force_permissive,
|
||||
|
@ -309,6 +327,10 @@ class Values(object):
|
|||
owner = context.cfgimpl_get_settings().getowner()
|
||||
if isinstance(value, Multi):
|
||||
value = list(value)
|
||||
if opt.impl_is_submulti():
|
||||
for idx, val in enumerate(value):
|
||||
if isinstance(val, SubMulti):
|
||||
value[idx] = list(val)
|
||||
self._p_.setvalue(path, value, owner)
|
||||
|
||||
def getowner(self, opt, force_permissive=False):
|
||||
|
@ -471,28 +493,47 @@ class Values(object):
|
|||
# ____________________________________________________________
|
||||
# multi types
|
||||
|
||||
|
||||
class Multi(list):
|
||||
"""multi options values container
|
||||
that support item notation for the values of multi options"""
|
||||
__slots__ = ('opt', 'path', 'context')
|
||||
__slots__ = ('opt', 'path', 'context', '__weakref__')
|
||||
|
||||
def __init__(self, value, context, opt, path):
|
||||
"""
|
||||
:param value: the Multi wraps a list value
|
||||
:param context: the home config that has the values
|
||||
:param opt: the option object that have this Multi value
|
||||
:param path: path of the option
|
||||
"""
|
||||
if isinstance(value, Multi):
|
||||
raise ValueError(_('{0} is already a Multi ').format(opt.impl_getname()))
|
||||
if value is None:
|
||||
value = []
|
||||
if not opt.impl_is_submulti() and isinstance(value, Multi):
|
||||
raise ValueError(_('{0} is already a Multi ').format(
|
||||
opt.impl_getname()))
|
||||
self.opt = opt
|
||||
self.path = path
|
||||
if not isinstance(context, weakref.ReferenceType):
|
||||
raise ValueError('context must be a Weakref')
|
||||
self.context = context
|
||||
if not isinstance(value, list):
|
||||
if not '_index' in self.__slots__ and opt.impl_is_submulti():
|
||||
value = [[value]]
|
||||
else:
|
||||
value = [value]
|
||||
elif value != [] and not '_index' in self.__slots__ and \
|
||||
opt.impl_is_submulti() and not isinstance(value[0], list):
|
||||
value = [value]
|
||||
super(Multi, self).__init__(value)
|
||||
if opt.impl_is_submulti():
|
||||
if not '_index' in self.__slots__:
|
||||
for idx, val in enumerate(self):
|
||||
if not isinstance(val, SubMulti):
|
||||
super(Multi, self).__setitem__(idx, SubMulti(val,
|
||||
context,
|
||||
opt, path,
|
||||
idx))
|
||||
#FIXME weakref ??
|
||||
self[idx].submulti = weakref.ref(self)
|
||||
|
||||
def _getcontext(self):
|
||||
"""context could be None, we need to test it
|
||||
|
@ -506,24 +547,32 @@ class Multi(list):
|
|||
return context
|
||||
|
||||
def __setitem__(self, index, value):
|
||||
self._validate(value, index)
|
||||
self._setitem(index, value)
|
||||
|
||||
def _setitem(self, index, value):
|
||||
self._validate(value, index, True)
|
||||
#assume not checking mandatory property
|
||||
super(Multi, self).__setitem__(index, value)
|
||||
self._getcontext().cfgimpl_get_values()._setvalue(self.opt, self.path,
|
||||
self)
|
||||
|
||||
def __repr__(self, *args, **kwargs):
|
||||
print args, kwargs
|
||||
return super(Multi, self).__repr__(*args, **kwargs)
|
||||
#def __repr__(self, *args, **kwargs):
|
||||
# print args, kwargs
|
||||
# return super(Multi, self).__repr__(*args, **kwargs)
|
||||
|
||||
def __getitem__(self, y):
|
||||
return super(Multi, self).__getitem__(y)
|
||||
#def __getitem__(self, y):
|
||||
# return super(Multi, self).__getitem__(y)
|
||||
|
||||
def _get_validated_value(self, index):
|
||||
values = self._getcontext().cfgimpl_get_values()
|
||||
return values._get_validated_value(self.opt, self.path,
|
||||
True, False, None, True,
|
||||
index=index)
|
||||
|
||||
def append(self, value=undefined, force=False, setitem=True):
|
||||
"""the list value can be updated (appened)
|
||||
only if the option is a master
|
||||
"""
|
||||
values = self._getcontext().cfgimpl_get_values()
|
||||
if not force:
|
||||
if self.opt.impl_is_master_slaves('slave'):
|
||||
raise SlaveError(_("cannot append a value on a multi option {0}"
|
||||
|
@ -531,16 +580,17 @@ class Multi(list):
|
|||
index = self.__len__()
|
||||
if value is undefined:
|
||||
try:
|
||||
value = values._get_validated_value(self.opt, self.path,
|
||||
True, False, None, True,
|
||||
index=index)
|
||||
value = self._get_validated_value(index)
|
||||
except IndexError:
|
||||
value = None
|
||||
self._validate(value, index)
|
||||
self._validate(value, index, True)
|
||||
if not '_index' in self.__slots__ and self.opt.impl_is_submulti():
|
||||
if not isinstance(value, SubMulti):
|
||||
value = SubMulti(value, self.context, self.opt, self.path, index)
|
||||
value.submulti = weakref.ref(self)
|
||||
super(Multi, self).append(value)
|
||||
if setitem:
|
||||
values._setvalue(self.opt, self.path, self,
|
||||
validate_properties=not force)
|
||||
self._store(force)
|
||||
|
||||
def sort(self, cmp=None, key=None, reverse=False):
|
||||
if self.opt.impl_is_master_slaves():
|
||||
|
@ -553,43 +603,40 @@ class Multi(list):
|
|||
super(Multi, self).sort(key=key, reverse=reverse)
|
||||
else:
|
||||
super(Multi, self).sort(cmp=cmp, key=key, reverse=reverse)
|
||||
self._getcontext().cfgimpl_get_values()._setvalue(self.opt, self.path,
|
||||
self)
|
||||
self._store()
|
||||
|
||||
def reverse(self):
|
||||
if self.opt.impl_is_master_slaves():
|
||||
raise SlaveError(_("cannot reverse multi option {0} if master or "
|
||||
"slave").format(self.opt.impl_getname()))
|
||||
super(Multi, self).reverse()
|
||||
self._getcontext().cfgimpl_get_values()._setvalue(self.opt, self.path,
|
||||
self)
|
||||
self._store()
|
||||
|
||||
def insert(self, index, obj):
|
||||
#FIXME obj 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()))
|
||||
self._validate(obj, index, True)
|
||||
super(Multi, self).insert(index, obj)
|
||||
self._getcontext().cfgimpl_get_values()._setvalue(self.opt, self.path,
|
||||
self)
|
||||
self._store()
|
||||
|
||||
def extend(self, iterable):
|
||||
if self.opt.impl_is_master_slaves():
|
||||
raise SlaveError(_("cannot extend multi option {0} if master or "
|
||||
"slave").format(self.opt.impl_getname()))
|
||||
super(Multi, self).extend(iterable)
|
||||
self._getcontext().cfgimpl_get_values()._setvalue(self.opt, self.path,
|
||||
self)
|
||||
|
||||
def _validate(self, value, force_index):
|
||||
if value is not None:
|
||||
try:
|
||||
index = self._index
|
||||
except:
|
||||
index = None
|
||||
self._validate(iterable, index)
|
||||
super(Multi, self).extend(iterable)
|
||||
self._store()
|
||||
|
||||
def _validate(self, value, force_index, submulti=False):
|
||||
if value is not None:
|
||||
self.opt.impl_validate(value, context=self._getcontext(),
|
||||
force_index=force_index)
|
||||
except ValueError as err:
|
||||
raise ValueError(_("invalid value {0} "
|
||||
"for option {1}: {2}"
|
||||
"").format(str(value),
|
||||
self.opt.impl_getname(), err))
|
||||
|
||||
def pop(self, index, force=False):
|
||||
"""the list value can be updated (poped)
|
||||
|
@ -611,6 +658,53 @@ class Multi(list):
|
|||
context.cfgimpl_get_values(), index)
|
||||
#set value without valid properties
|
||||
ret = super(Multi, self).pop(index)
|
||||
context.cfgimpl_get_values()._setvalue(self.opt, self.path, self,
|
||||
validate_properties=not force)
|
||||
self._store(force)
|
||||
return ret
|
||||
|
||||
def _store(self, force=False):
|
||||
self._getcontext().cfgimpl_get_values()._setvalue(self.opt, self.path,
|
||||
self,
|
||||
validate_properties=not force)
|
||||
|
||||
|
||||
class SubMulti(Multi):
|
||||
__slots__ = ('_index', 'submulti')
|
||||
|
||||
def __init__(self, value, context, opt, path, index):
|
||||
"""
|
||||
:param index: index (only for slave with submulti)
|
||||
:type index: `int`
|
||||
"""
|
||||
self._index = index
|
||||
super(SubMulti, self).__init__(value, context, opt, path)
|
||||
|
||||
def append(self, value=undefined):
|
||||
super(SubMulti, self).append(value, force=True)
|
||||
|
||||
def pop(self, index):
|
||||
return super(SubMulti, self).pop(index, force=True)
|
||||
|
||||
def __setitem__(self, index, value):
|
||||
self._setitem(index, value)
|
||||
|
||||
def _store(self, force=False):
|
||||
#force is unused here
|
||||
self._getcontext().cfgimpl_get_values()._setvalue(self.opt,
|
||||
self.path,
|
||||
self.submulti())
|
||||
|
||||
def _validate(self, value, force_index, submulti=False):
|
||||
if value is not None:
|
||||
if submulti is False:
|
||||
super(SubMulti, self)._validate(value, force_index)
|
||||
else:
|
||||
self.opt.impl_validate(value, context=self._getcontext(),
|
||||
force_index=self._index,
|
||||
force_submulti_index=force_index)
|
||||
|
||||
def _get_validated_value(self, index):
|
||||
values = self._getcontext().cfgimpl_get_values()
|
||||
return values._get_validated_value(self.opt, self.path,
|
||||
True, False, None, True,
|
||||
index=index,
|
||||
submulti_index=self._index)
|
||||
|
|
Loading…
Reference in a new issue