--- /dev/null
+# 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"]')
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',
"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
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_
#append value
if not self.impl_is_multi() or option == opt:
all_cons_vals.append(opt_value)
+ 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:
- #value is not already set, could be higher index
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
:param validate: if true enables ``self._validator`` validation
:type validate: boolean
: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
+ :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
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
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(
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)
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"
# 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
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:
+ 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,
+ 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())
'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)
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
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,
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]:
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,
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):
# ____________________________________________________________
# 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
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}"
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():
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()))
+ try:
+ index = self._index
+ except:
+ index = None
+ self._validate(iterable, index)
super(Multi, self).extend(iterable)
- self._getcontext().cfgimpl_get_values()._setvalue(self.opt, self.path,
- self)
+ self._store()
- def _validate(self, value, force_index):
+ def _validate(self, value, force_index, submulti=False):
if value is not None:
- try:
- 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))
+ self.opt.impl_validate(value, context=self._getcontext(),
+ force_index=force_index)
def pop(self, index, force=False):
"""the list value can be updated (poped)
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)