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