use python-coverage to delete dead part of code
authorEmmanuel Garette <egarette@cadoles.com>
Tue, 24 Nov 2015 09:58:19 +0000 (10:58 +0100)
committerEmmanuel Garette <egarette@cadoles.com>
Tue, 24 Nov 2015 09:58:19 +0000 (10:58 +0100)
16 files changed:
test/test_choice_option.py
test/test_config.py
test/test_config_domain.py
test/test_config_ip.py
test/test_dyn_optiondescription.py
test/test_metaconfig.py
test/test_option_calculation.py
test/test_option_consistency.py
test/test_submulti.py
tiramisu/autolib.py
tiramisu/config.py
tiramisu/option/baseoption.py
tiramisu/option/option.py
tiramisu/option/optiondescription.py
tiramisu/storage/dictionary/option.py
tiramisu/value.py

index 9b3d504..f636acc 100644 (file)
@@ -5,6 +5,7 @@ do_autopath()
 from tiramisu.setting import owners
 from tiramisu.option import ChoiceOption, StrOption, OptionDescription
 from tiramisu.config import Config
+from tiramisu.error import ConfigError
 
 from py.test import raises
 
@@ -86,3 +87,18 @@ def test_choiceoption_calc_opt_multi_function():
     assert cfg.getowner(ch) == owners.default
     #
     raises(ValueError, "cfg.ch2")
+
+
+def test_choiceoption_calc_invalid():
+    st = StrOption('st', '', ['val1'], multi=True)
+    st
+    raises(ValueError, "ch = ChoiceOption('ch', '', default_multi='val2', values=[1, 2, 3], values_params={'': ((st, False),)}, multi=True)")
+
+
+def test_choiceoption_calc_not_list():
+    st = StrOption('st', '', 'val1')
+    ch = ChoiceOption('ch', "", default_multi='val2', values=return_val, values_params={'': ((st, False),)}, multi=True)
+    od = OptionDescription('od', '', [st, ch])
+    cfg = Config(od)
+    cfg.read_write()
+    raises(ConfigError, "cfg.ch = ['val1']")
index d71c709..28e5ee9 100644 (file)
@@ -49,6 +49,14 @@ def test_base_config():
     assert dm.impl_getname() == 'dummy'
 
 
+def test_base_config_name():
+    gcdummy = BoolOption('dummy', 'dummy', default=False)
+    descr = OptionDescription('tiramisu', '', [gcdummy])
+    cfg = Config(descr, name='cfg')
+    cfg.impl_getname() == 'cfg'
+    raises(ValueError, "Config(descr, name='unvalid name')")
+
+
 def test_not_config():
     assert raises(TypeError, "Config('str')")
 
@@ -324,6 +332,15 @@ def test_delete_config_with_subconfig():
     raises(ConfigError, 'sub.make_dict()')
 
 
+def test_subconfig():
+    i = IntOption('i', '')
+    o = OptionDescription('val', '', [i])
+    o2 = OptionDescription('val', '', [o])
+    c = Config(o2)
+    raises(TypeError, "SubConfig(i, weakref.ref(c))")
+    pass
+
+
 def test_config_weakref():
     o = OptionDescription('val', '', [])
     o2 = OptionDescription('val', '', [o])
index ed8dac8..3c0fb8f 100644 (file)
@@ -85,7 +85,7 @@ def test_domainname_warning():
     raises(ValueError, "c.f = 'domainnametoolongthathavemorethanmaximumsizeforatruedomainnamean'")
     c.f = 'domainnametoolongthathavemorethanmaximumsizeforatruedomainnamea.nd'
     c.f = 'domainnametoolongthathavemorethanmaximumsizeforatruedomainnamea.nditsnoteasytogeneratesolongdomainnamewithoutrepeatdomainnameto.olongthathavemorethanmaximumsizeforatruedomainnameanditsnoteas.ytogeneratesolongdomainnamewithoutrepeatbutimnotabletodoitnowie'
-    raises(ValueError, "c.f = 'domainnametoolongthathavemorethanmaximumsizeforatruedomainnamea.nditsnoteasytogeneratesolongdomainnamewithoutrepeatdomainnameto.olongthathavemorethanmaximumsizeforatruedomainnameanditsnoteas.ytogeneratesolongdomainnamewithoutrepeatbutimnotabletodoitnowien'")
+    raises(ValueError, "c.f = 'domainnametoolongthathavemorethanmaximumsizeforatruedomainname.nditsnoteasytogeneratesolongdomainnamewithoutrepeatdomainnamet.olongthathavemorethanmaximumsizeforatruedomainnameanditsnotea.ytogeneratesolongdomainnamewithoutrepeatbutimnotabletodoitnowie.xxxx'")
     c.f = 'd'
     c.f = 'd.t'
     #
index b4359f4..c5c61b9 100644 (file)
@@ -1,16 +1,20 @@
 from autopath import do_autopath
 do_autopath()
 
+import warnings
 from py.test import raises
 from tiramisu.config import Config
 from tiramisu.option import IPOption, NetworkOption, NetmaskOption, \
     PortOption, OptionDescription
+from tiramisu.error import ValueWarning
 
 
 def test_ip():
     a = IPOption('a', '')
     b = IPOption('b', '', private_only=True)
-    od = OptionDescription('od', '', [a, b])
+    d = IPOption('d', '', warnings_only=True, private_only=True)
+    warnings.simplefilter("always", ValueWarning)
+    od = OptionDescription('od', '', [a, b, d])
     c = Config(od)
     c.a = '192.168.1.1'
     c.a = '192.168.1.0'
@@ -24,10 +28,9 @@ def test_ip():
     raises(ValueError, "c.b = '255.255.255.0'")
 
     raises(ValueError, "IPOption('a', 'ip', default='192.000.023.01')")
-    d = IPOption('a', 'ip', default='192.0.23.1')
-    od = OptionDescription('od', '', [d])
-    c = Config(od)
-    raises(ValueError, "c.a = '192.000.023.01'")
+    with warnings.catch_warnings(record=True) as w:
+        c.d = '88.88.88.88'
+    assert len(w) == 1
 
 
 def test_ip_default():
@@ -40,21 +43,31 @@ def test_ip_default():
 def test_ip_reserved():
     a = IPOption('a', '')
     b = IPOption('b', '', allow_reserved=True)
-    od = OptionDescription('od', '', [a, b])
-    c = Config(od)
-    raises(ValueError, "c.a = '226.94.1.1'")
-    c.b = '226.94.1.1'
+    c = IPOption('c', '', warnings_only=True)
+    od = OptionDescription('od', '', [a, b, c])
+    warnings.simplefilter("always", ValueWarning)
+    cfg = Config(od)
+    raises(ValueError, "cfg.a = '226.94.1.1'")
+    cfg.b = '226.94.1.1'
+    with warnings.catch_warnings(record=True) as w:
+        cfg.c = '226.94.1.1'
+    assert len(w) == 1
 
 
 def test_network():
     a = NetworkOption('a', '')
-    od = OptionDescription('od', '', [a])
+    b = NetworkOption('b', '', warnings_only=True)
+    od = OptionDescription('od', '', [a, b])
+    warnings.simplefilter("always", ValueWarning)
     c = Config(od)
     c.a = '192.168.1.1'
     c.a = '192.168.1.0'
     c.a = '88.88.88.88'
     c.a = '0.0.0.0'
     raises(ValueError, "c.a = '255.255.255.0'")
+    with warnings.catch_warnings(record=True) as w:
+        c.b = '255.255.255.0'
+    assert len(w) == 1
 
 
 def test_netmask():
index 381bfd6..b82a4e8 100644 (file)
@@ -707,6 +707,88 @@ def test_consistency_dyndescription():
     raises(ValueError, "cfg.od.dodval2.stval2 = 'yes'")
 
 
+def test_consistency_dyndescription_default():
+    st = StrOption('st', '', 'yes')
+    st2 = StrOption('st2', '')
+    dod = DynOptionDescription('dod', '', [st, st2], callback=return_list)
+    od = OptionDescription('od', '', [dod])
+    st.impl_add_consistency('not_equal', st2)
+    od2 = OptionDescription('od', '', [od])
+    cfg = Config(od2)
+    cfg
+    raises(ValueError, "cfg.od.dodval1.st2val1 = 'yes'")
+    raises(ValueError, "cfg.od.dodval2.st2val2 = 'yes'")
+
+
+def test_consistency_dyndescription_multi():
+    st = StrOption('st', '', multi=True)
+    st2 = StrOption('st2', '', multi=True)
+    dod = DynOptionDescription('dod', '', [st, st2], callback=return_list)
+    od = OptionDescription('od', '', [dod])
+    st.impl_add_consistency('not_equal', st2)
+    od2 = OptionDescription('od', '', [od])
+    cfg = Config(od2)
+    cfg.od.dodval1.stval1.append('yes')
+    raises(ValueError, "cfg.od.dodval1.st2val1.append('yes')")
+    cfg.od.dodval2.stval2.append('yes')
+    raises(ValueError, "cfg.od.dodval2.st2val2.append('yes')")
+    raises(ValueError, "cfg.od.dodval1.st2val1.append('yes')")
+    del(cfg.od.dodval2.stval2)
+    raises(ValueError, "cfg.od.dodval1.st2val1.append('yes')")
+    cfg.od.dodval2.st2val2.append('yes')
+    raises(ValueError, "cfg.od.dodval2.stval2.append('yes')")
+
+
+def test_consistency_dyndescription_default_multi():
+    st = StrOption('st', '', ['yes'], multi=True)
+    st2 = StrOption('st2', '', multi=True)
+    dod = DynOptionDescription('dod', '', [st, st2], callback=return_list)
+    od = OptionDescription('od', '', [dod])
+    st.impl_add_consistency('not_equal', st2)
+    od2 = OptionDescription('od', '', [od])
+    cfg = Config(od2)
+    raises(ValueError, "cfg.od.dodval1.st2val1.append('yes')")
+    raises(ValueError, "cfg.od.dodval1.st2val1.append('yes')")
+    cfg.od.dodval1.stval1.append('yes')
+
+
+def test_consistency_dyndescription_default_multi2():
+    st = StrOption('st', '', ['yes'], multi=True)
+    st2 = StrOption('st2', '', ['yes'], multi=True)
+    dod = DynOptionDescription('dod', '', [st, st2], callback=return_list)
+    dod
+    raises(ValueError, "st.impl_add_consistency('not_equal', st2)")
+
+
+def test_consistency_only_one_dyndescription():
+    st = StrOption('st', '')
+    st
+    st2 = StrOption('st2', '')
+    DynOptionDescription('dod', '', [st2], callback=return_list)
+    raises(ConfigError, "st.impl_add_consistency('not_equal', st2)")
+    raises(ConfigError, "st2.impl_add_consistency('not_equal', st)")
+
+
+def test_consistency_became_dyndescription():
+    st = StrOption('st', '')
+    st2 = StrOption('st2', '')
+    st2.impl_add_consistency('not_equal', st)
+    od = DynOptionDescription('dod', '', [st2], callback=return_list)
+    od2 = OptionDescription('od', '', [od, st])
+    od2
+    raises(ConfigError, "c = Config(od2)")
+
+
+def test_consistency_became_dyndescription2():
+    st = StrOption('st', '')
+    st2 = StrOption('st2', '')
+    st.impl_add_consistency('not_equal', st2)
+    od = DynOptionDescription('dod', '', [st2], callback=return_list)
+    od2 = OptionDescription('od', '', [od, st])
+    od2
+    raises(ConfigError, "c = Config(od2)")
+
+
 def test_consistency_external_dyndescription():
     st = StrOption('st', '')
     st1 = StrOption('st1', '')
index b9487fb..69c4087 100644 (file)
@@ -24,7 +24,7 @@ def make_description():
     conf2 = Config(od2, name='conf2')
     conf1.read_write()
     conf2.read_write()
-    meta = MetaConfig([conf1, conf2])
+    meta = MetaConfig([conf1, conf2], name='meta')
     meta.cfgimpl_get_settings().setowner(owners.meta)
     return meta
 
@@ -168,6 +168,9 @@ def test_meta_meta_set():
     raises(AttributeError, "meta2.find_firsts(byname='i1', byvalue=10)")
     raises(AttributeError, "meta2.find_firsts(byname='not', byvalue=10)")
     raises(AttributeError, "meta2.find_firsts(byname='i6')")
+    raises(ValueError, "meta2.set_value('od1.i6', 7, only_config=True, force_default=True)")
+    raises(ValueError, "meta2.set_value('od1.i6', 7, only_config=True, force_default_if_same=True)")
+    raises(ValueError, "meta2.set_value('od1.i6', 7, only_config=True, force_dont_change_value=True)")
 
 
 def test_not_meta():
@@ -200,6 +203,21 @@ def test_group_find_firsts():
     assert [conf1, conf2] == grp.find_firsts(byname='i1').cfgimpl_get_children()
 
 
+def test_group_group():
+    i1 = IntOption('i1', '')
+    od1 = OptionDescription('od1', '', [i1])
+    od2 = OptionDescription('od2', '', [od1])
+    conf1 = Config(od2, name='conf1')
+    conf2 = Config(od2, name='conf2')
+    grp = GroupConfig([conf1, conf2])
+    raises(ValueError, "GroupConfig([grp])")
+    grp = GroupConfig([conf1, conf2], 'grp')
+    grp2 = GroupConfig([grp])
+    grp2.set_value('od1.i1', 2)
+    assert grp2.grp.conf1.od1.i1 == 2
+    assert grp2.grp.conf1.getowner(i1) == owners.user
+
+
 def test_meta_path():
     meta = make_description()
     assert meta._impl_path is None
index a269702..021f6e4 100644 (file)
@@ -869,3 +869,10 @@ def test_masterslaves_callback_description():
     assert cfg.od.st.st1.st1 == ['yes']
     assert cfg.od.st.st1.st2 == ['yes']
     assert cfg.getowner(st1) == owner
+
+
+def test_re_set_callback():
+    st1 = StrOption('st1', "", multi=True)
+    st2 = StrOption('st2', "", multi=True)
+    st2.impl_set_callback(return_value, {'': ((st1, False),)})
+    raises(ConfigError, "st2.impl_set_callback(return_value, {'': ((st1, False),)})")
index c6a0f09..323f6e4 100644 (file)
@@ -6,7 +6,7 @@ from py.test import raises
 from tiramisu.setting import owners, groups
 from tiramisu.config import Config
 from tiramisu.option import IPOption, NetworkOption, NetmaskOption, IntOption,\
-    BroadcastOption, SymLinkOption, OptionDescription
+    BroadcastOption, SymLinkOption, OptionDescription, submulti
 from tiramisu.error import ConfigError, ValueWarning, PropertiesOptionError
 import warnings
 
@@ -14,7 +14,6 @@ import warnings
 def test_consistency():
     a = IntOption('a', '')
     b = IntOption('b', '')
-    od = OptionDescription('od', '', [a, b])
     a.impl_add_consistency('not_equal', b)
     #consistency to itself
     raises(ConfigError, "a.impl_add_consistency('not_equal', a)")
@@ -25,17 +24,26 @@ def test_consistency():
 def test_consistency_not_exists():
     a = IntOption('a', '')
     b = IntOption('b', '')
-    od = OptionDescription('od', '', [a, b])
+    a, b
     raises(ConfigError, "a.impl_add_consistency('not_exists', b)")
 
 
 def test_consistency_unknown_params():
     a = IntOption('a', '')
     b = IntOption('b', '')
-    od = OptionDescription('od', '', [a, b])
+    a, b
     raises(ValueError, "a.impl_add_consistency('not_equal', b, unknown=False)")
 
 
+def test_consistency_warnings_only_default():
+    a = IntOption('a', '', 1)
+    b = IntOption('b', '', 1)
+    warnings.simplefilter("always", ValueWarning)
+    with warnings.catch_warnings(record=True) as w:
+        a.impl_add_consistency('not_equal', b, warnings_only=True)
+    assert w != []
+
+
 def test_consistency_warnings_only():
     a = IntOption('a', '')
     b = IntOption('b', '')
@@ -99,8 +107,8 @@ def test_consistency_not_in_config_1():
     b = IntOption('b', '')
     a.impl_add_consistency('not_equal', b)
     od1 = OptionDescription('od1', '', [a])
-    od2 = OptionDescription('od2', '', [b])
     od = OptionDescription('root', '', [od1])
+    od
     raises(ConfigError, "Config(od)")
 
 
@@ -121,6 +129,7 @@ def test_consistency_not_in_config_3():
     od1 = OptionDescription('od1', '', [a])
     od2 = OptionDescription('od2', '', [b])
     od = OptionDescription('root', '', [od1, od2])
+    od
     #with subconfig
     raises(ConfigError, "Config(od.od1)")
 
@@ -145,6 +154,34 @@ def test_consistency_not_equal_symlink():
     assert set(od._cache_consistencies.keys()) == set([a, b])
 
 
+def test_consistency_not_equal_submulti():
+    a = IntOption('a', '', multi=submulti)
+    b = IntOption('b', '', multi=submulti)
+    od = OptionDescription('od', '', [a, b])
+    a.impl_add_consistency('not_equal', b)
+    c = Config(od)
+    assert c.a == []
+    assert c.b == []
+    c.a = [[1]]
+    del(c.a)
+    c.a = [[1]]
+    raises(ValueError, "c.b = [[1]]")
+    c.a = [[1, 2]]
+    c.b = [[3]]
+    c.b = [[3, 1]]
+    c.b = [[3]]
+    c.b[0].append(1)
+    c.b = [[3], [1]]
+
+
+def test_consistency_not_equal_default_submulti():
+    a = IntOption('a', '', [[1, 2]], multi=submulti)
+    b = IntOption('b', '', [[1]], multi=submulti)
+    od = OptionDescription('od', '', [a, b])
+    od
+    raises(ValueError, "a.impl_add_consistency('not_equal', b)")
+
+
 def test_consistency_not_equal_multi():
     a = IntOption('a', '', multi=True)
     b = IntOption('b', '', multi=True)
@@ -160,9 +197,25 @@ def test_consistency_not_equal_multi():
     c.b = [2]
 
 
+def test_consistency_not_equal_multi_default():
+    a = IntOption('a', '', multi=True)
+    b = IntOption('b', '', multi=True, default_multi=1)
+    od = OptionDescription('od', '', [a, b])
+    a.impl_add_consistency('not_equal', b)
+    c = Config(od)
+    assert c.a == []
+    assert c.b == []
+    c.a = [1]
+    del(c.a)
+    c.a = [1]
+    raises(ValueError, "c.b = [1]")
+    c.b = [2]
+
+
 def test_consistency_default():
     a = IntOption('a', '', 1)
     b = IntOption('b', '', 1)
+    a, b
     raises(ValueError, "a.impl_add_consistency('not_equal', b)")
 
 
@@ -170,6 +223,7 @@ def test_consistency_default_multi():
     a = IntOption('a', '', [2, 1], multi=True)
     b = IntOption('b', '', [1, 1], multi=True)
     c = IntOption('c', '', [1, 2], multi=True)
+    b
     raises(ValueError, "a.impl_add_consistency('not_equal', b)")
     a.impl_add_consistency('not_equal', c)
 
@@ -221,8 +275,11 @@ def test_consistency_ip_in_network():
     a = NetworkOption('a', '')
     b = NetmaskOption('b', '')
     c = IPOption('c', '')
-    od = OptionDescription('od', '', [a, b, c])
+    d = IPOption('d', '')
+    od = OptionDescription('od', '', [a, b, c, d])
     c.impl_add_consistency('in_network', a, b)
+    d.impl_add_consistency('in_network', a, b, warnings_only=True)
+    warnings.simplefilter("always", ValueWarning)
     cfg = Config(od)
     cfg.a = '192.168.1.0'
     cfg.b = '255.255.255.0'
@@ -230,6 +287,9 @@ def test_consistency_ip_in_network():
     raises(ValueError, "cfg.c = '192.168.2.1'")
     raises(ValueError, "cfg.c = '192.168.1.0'")
     raises(ValueError, "cfg.c = '192.168.1.255'")
+    with warnings.catch_warnings(record=True) as w:
+        cfg.d = '192.168.2.1'
+    assert len(w) == 1
 
 
 def test_consistency_ip_in_network_len_error():
@@ -239,6 +299,7 @@ def test_consistency_ip_in_network_len_error():
     od = OptionDescription('od', '', [a, b, c])
     c.impl_add_consistency('in_network', a)
     cfg = Config(od)
+    cfg
     raises(ConfigError, "cfg.a = '192.168.2.0'")
 
 
@@ -257,7 +318,7 @@ def test_consistency_ip_netmask_network_error():
 def test_consistency_ip_netmask_error_multi():
     a = IPOption('a', '', multi=True)
     b = NetmaskOption('b', '')
-    od = OptionDescription('od', '', [a, b])
+    OptionDescription('od', '', [a, b])
     raises(ConfigError, "b.impl_add_consistency('ip_netmask', a)")
 
 
@@ -449,17 +510,17 @@ def test_consistency_broadcast_default_1():
     a = NetworkOption('a', '', '192.168.1.0')
     b = NetmaskOption('b', '', '255.255.255.128')
     c = BroadcastOption('c', '', '192.168.2.127')
-    d = BroadcastOption('d', '', '192.168.1.127')
     od = OptionDescription('a', '', [a, b, c])
+    od
     raises(ValueError, "c.impl_add_consistency('broadcast', a, b)")
 
 
 def test_consistency_broadcast_default_2():
     a = NetworkOption('a', '', '192.168.1.0')
     b = NetmaskOption('b', '', '255.255.255.128')
-    c = BroadcastOption('c', '', '192.168.2.127')
     d = BroadcastOption('d', '', '192.168.1.127')
     od2 = OptionDescription('a', '', [a, b, d])
+    od2
     d.impl_add_consistency('broadcast', a, b)
 
 
index b97ec2a..d43035e 100644 (file)
@@ -11,8 +11,11 @@ from tiramisu.error import SlaveError
 from py.test import raises
 
 
-def return_val():
-    return 'val'
+def return_val(val=None):
+    if val is None:
+        return 'val'
+    else:
+        return val
 
 
 def return_list(value=None):
@@ -319,6 +322,8 @@ def test_callback_submulti_list():
     cfg.multi.append()
     assert cfg.getowner(multi) == owner
     assert cfg.multi == [['val', 'val'], ['val', 'val']]
+    cfg.multi.append()
+    assert cfg.multi == [['val', 'val'], ['val', 'val'], ['val', 'val']]
     del(cfg.multi)
     assert cfg.getowner(multi) == owners.default
     cfg.multi[0].append()
@@ -342,6 +347,8 @@ def test_callback_submulti_list_list():
     cfg.multi[0].append()
     assert cfg.getowner(multi) == owner
     assert cfg.multi == [['val', 'val', None]]
+    del(cfg.multi)
+    cfg.multi.append()
 
 
 #FIXME multi sur une master
@@ -639,3 +646,20 @@ def test__master_is_submulti():
     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"]')
+
+
+def test_callback_submulti():
+    multi = StrOption('multi', '', multi=submulti)
+    multi2 = StrOption('multi2', '', multi=submulti, callback=return_val, callback_params={'': ((multi, False),)})
+    od = OptionDescription('multi', '', [multi, multi2])
+    cfg = Config(od)
+    cfg.read_write()
+    owner = cfg.cfgimpl_get_settings().getowner()
+    assert cfg.getowner(multi) == owners.default
+    assert cfg.multi == []
+    assert cfg.multi2 == []
+    cfg.multi.append(['val'])
+    assert cfg.getowner(multi) == owner
+    assert cfg.getowner(multi2) == owners.default
+    assert cfg.multi == [['val']]
+    assert cfg.multi2 == [['val']]
index 73a8503..acb342b 100644 (file)
@@ -139,7 +139,6 @@ def carry_out_calculation(option, context, callback, callback_params,
     # if callback_params has a callback, launch several time calculate()
     master_slave = False
     # multi's option should have same value for all option
-    len_multi = None
     try:
         if option._is_subdyn():
             tcparams[''] = [(option.impl_getsuffix(), False)]
@@ -182,7 +181,6 @@ def carry_out_calculation(option, context, callback, callback_params,
 
                     if opt.impl_is_master_slaves() and \
                             opt.impl_get_master_slaves().in_same_group(option):
-                        len_multi = len(value)
                         master_slave = True
                         is_multi = True
                     else:
@@ -197,32 +195,20 @@ def carry_out_calculation(option, context, callback, callback_params,
     # if no index, return a list
     if master_slave:
         ret = []
-        if index is not undefined:
-            # for example if append master and get a no default slave without
-            # getting master
-            range_ = [index]
-        else:
-            range_ = range(len_multi)
-        for incr in range_:
-            args = []
-            kwargs = {}
-            for key, couples in tcparams.items():
-                for couple in couples:
-                    value, ismulti = couple
-                    if ismulti:
-                        val = value[incr]
-                    else:
-                        val = value
-                    if key == '':
-                        args.append(val)
-                    else:
-                        kwargs[key] = val
-            calc = calculate(callback, args, kwargs)
-            if index is not undefined:
-                ret = calc
-            else:
-                ret.append(calc)
-        return ret
+        args = []
+        kwargs = {}
+        for key, couples in tcparams.items():
+            for couple in couples:
+                value, ismulti = couple
+                if ismulti:
+                    val = value[index]
+                else:
+                    val = value
+                if key == '':
+                    args.append(val)
+                else:
+                    kwargs[key] = val
+        return calculate(callback, args, kwargs)
     else:
         # no value is multi
         # return a single value
@@ -236,15 +222,9 @@ def carry_out_calculation(option, context, callback, callback_params,
                 else:
                     kwargs[key] = couple[0]
         ret = calculate(callback, args, kwargs)
-        if callback_params != {}:
-            if isinstance(ret, list) and index is not undefined:
-                if option.impl_is_master_slaves('slave'):
-                    raise SlaveError(_("callback cannot return a list for a "
-                                       "slave option ({0})").format(path))
-                if len(ret) < index + 1:
-                    ret = None
-                else:
-                    ret = ret[index]
+        if callback_params != {} and isinstance(ret, list) and index is not undefined:
+            raise SlaveError(_("callback cannot return a list for a "
+                               "slave option ({0})").format(path))
         return ret
 
 
index d7dd69f..8e3eb47 100644 (file)
@@ -669,9 +669,6 @@ class Config(_CommonConfig):
     def impl_getname(self):
         return self._impl_name
 
-    def impl_setname(self, name):
-        self._impl_name = name
-
 
 class GroupConfig(_CommonConfig):
     __slots__ = ('__weakref__', '_impl_children', '_impl_name')
@@ -684,12 +681,10 @@ class GroupConfig(_CommonConfig):
         for child in children:
             if not isinstance(child, _CommonConfig):
                 raise ValueError(_("groupconfig's children must be Config, MetaConfig or GroupConfig"))
-            name = child._impl_name
-            if name is None:
+            name_ = child._impl_name
+            if name_ is None:
                 raise ValueError(_('name must be set to config before creating groupconfig'))
-            #if name in names:
-            #    raise ValueError(_('config name must be uniq in groupconfig'))
-            names.append(name)
+            names.append(name_)
         if len(names) != len(set(names)):
             for idx in xrange(1, len(names) + 1):
                 name = names.pop(0)
@@ -827,6 +822,9 @@ class MetaConfig(GroupConfig):
     def set_value(self, path, value, force_default=False,
                   force_dont_change_value=False, force_default_if_same=False,
                   only_config=False):
+        """only_config: could be set if you want modify value in all Config included in
+                        this MetaConfig
+        """
         if only_config:
             if force_default or force_default_if_same or force_dont_change_value:
                 raise ValueError(_('force_default, force_default_if_same or '
index 3f1867e..8629672 100644 (file)
@@ -140,6 +140,7 @@ class Base(StorageBase):
             default = []
         self.impl_validate(default)
         self._set_default_values(default, default_multi)
+        #callback is False in optiondescription
         if callback is not False:
             self.impl_set_callback(callback, callback_params)
         self.commit()
@@ -184,7 +185,7 @@ class BaseOption(Base):
         :param load: `True` if we are at the init of the option description
         :type load: bool
         """
-        if not load and self.impl_getrequires() is None:
+        if not load and self.impl_getrequires() == []:
             self._state_requires = None
         elif load and self._state_requires is None:
             del(self._state_requires)
@@ -215,7 +216,7 @@ class BaseOption(Base):
         if self.__class__.__name__ == 'OptionDescription' or \
                 isinstance(self, SymLinkOption):
             return
-        if not load and self.impl_get_callback() is None:
+        if not load and self.impl_get_callback() == (None, {}):
             self._state_callback = None
             self._state_callback_params = {}
         elif load and self._state_callback is None:
@@ -228,22 +229,19 @@ class BaseOption(Base):
             else:
                 callback, callback_params = self.impl_get_callback()
                 self._state_callback_params = {}
-            if callback_params is not None:
-                cllbck_prms = {}
-                for key, values in callback_params.items():
-                    vls = []
-                    for value in values:
-                        if isinstance(value, tuple) and value[0] is not None:
-                            if load:
-                                value = (descr.impl_get_opt_by_path(value[0]),
-                                         value[1])
-                            else:
-                                value = (descr.impl_get_path_by_opt(value[0]),
-                                         value[1])
-                        vls.append(value)
-                    cllbck_prms[key] = tuple(vls)
-            else:
-                cllbck_prms = None
+            cllbck_prms = {}
+            for key, values in callback_params.items():
+                vls = []
+                for value in values:
+                    if isinstance(value, tuple) and value[0] is not None:
+                        if load:
+                            value = (descr.impl_get_opt_by_path(value[0]),
+                                     value[1])
+                        else:
+                            value = (descr.impl_get_path_by_opt(value[0]),
+                                     value[1])
+                    vls.append(value)
+                cllbck_prms[key] = tuple(vls)
 
             if load:
                 del(self._state_callback)
@@ -354,12 +352,7 @@ class BaseOption(Base):
                 except (KeyError, AttributeError):
                     pass
             elif name == '_opt':
-                try:
-                    if self._impl_getopt() is not None:
-                        #so _opt is already set
-                        is_readonly = True
-                except (KeyError, AttributeError):
-                    pass
+                pass
             elif name != '_readonly':
                 is_readonly = self.impl_is_readonly()
             if is_readonly:  # pragma: optional cover
@@ -470,21 +463,10 @@ class Option(OnlyOption):
                     try:
                         all_cons_vals.append(opt_value[index])
                     except IndexError, err:
-                        log.debug('indexerror in _launch_consistency: {0}'.format(err))
                         #value is not already set, could be higher index
                         #so return if no value and not default_value
-                        if context is not undefined:
-                            if isinstance(opt, DynSymLinkOption):
-                                path = opt.impl_getpath(context)
-                            else:
-                                path = descr.impl_get_path_by_opt(opt)
-                            default_value = context.cfgimpl_get_values()._getvalue(opt, path, True, index=index)
-                        else:
-                            default_value = opt.impl_getdefault_multi()
-                        if default_value is not None:
-                            all_cons_vals.append(default_value)
-                        else:
-                            return
+                        log.debug('indexerror in _launch_consistency: {0}'.format(err))
+                        return
             except PropertiesOptionError as err:
                 log.debug('propertyerror in _launch_consistency: {0}'.format(err))
                 if transitive:
@@ -563,16 +545,12 @@ class Option(OnlyOption):
                 if self._is_warnings_only():
                     warning = error
                     error = None
-            except ValueWarning as warning:
-                log.debug(_('do_validation for {0}: warning in value').format(
-                    self.impl_getname()), exc_info=True)
-                pass
             if error is None and warning is None:
                 try:
                     # if context launch consistency validation
-                    if context is not undefined:
-                        descr._valid_consistency(current_opt, _value, context,
-                                                 _index, submulti_index)
+                    #if context is not undefined:
+                    self._valid_consistency(current_opt, _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)
@@ -584,7 +562,7 @@ class Option(OnlyOption):
             if warning:
                 msg = _("warning on the value of the option {0}: {1}").format(
                     self.impl_getname(), warning)
-                if context is None or 'warnings' in \
+                if context is undefined or 'warnings' in \
                         context.cfgimpl_get_settings():
                     warnings.warn_explicit(ValueWarning(msg, self),
                                            ValueWarning,
@@ -594,8 +572,8 @@ class Option(OnlyOption):
                     self.impl_getname(), error))
 
         # generic calculation
-        if context is not undefined:
-            descr = context.cfgimpl_get_description()
+        #if context is not undefined:
+        #    descr = context.cfgimpl_get_description()
 
         if not self.impl_is_multi():
             do_validation(value, None, None)
@@ -656,33 +634,7 @@ class Option(OnlyOption):
         "accesses the Option's doc"
         return self.impl_get_information('doc')
 
-    #def impl_getkey(self, value):
-    #    return value
-
-    def impl_add_consistency(self, func, *other_opts, **params):
-        """Add consistency means that value will be validate with other_opts
-        option's values.
-
-        :param func: function's name
-        :type func: `str`
-        :param other_opts: options used to validate value
-        :type other_opts: `list` of `tiramisu.option.Option`
-        :param params: extra params (warnings_only and transitive are allowed)
-        """
-        if self.impl_is_readonly():  # pragma: optional cover
-            raise AttributeError(_("'{0}' ({1}) cannot add consistency, option is"
-                                   " read-only").format(
-                                       self.__class__.__name__,
-                                       self.impl_getname()))
-        warnings_only = False
-        transitive = True
-        for key, value in params.items():
-            if key == 'warnings_only':
-                warnings_only = value
-            elif key == 'transitive':
-                transitive = value
-            else:
-                raise ValueError(_('unknow parameter {0} in consistency').format(key))
+    def _valid_consistencies(self, other_opts):
         if self._is_subdyn():
             dynod = self._impl_getsubdyn()
         else:
@@ -706,31 +658,75 @@ class Option(OnlyOption):
             if self.impl_is_multi() != opt.impl_is_multi():  # pragma: optional cover
                 raise ConfigError(_('every options in consistency must be '
                                     'multi or none'))
+
+    def impl_add_consistency(self, func, *other_opts, **params):
+        """Add consistency means that value will be validate with other_opts
+        option's values.
+
+        :param func: function's name
+        :type func: `str`
+        :param other_opts: options used to validate value
+        :type other_opts: `list` of `tiramisu.option.Option`
+        :param params: extra params (warnings_only and transitive are allowed)
+        """
+        if self.impl_is_readonly():  # pragma: optional cover
+            raise AttributeError(_("'{0}' ({1}) cannot add consistency, option is"
+                                   " read-only").format(
+                                       self.__class__.__name__,
+                                       self.impl_getname()))
+        self._valid_consistencies(other_opts)
         func = '_cons_{0}'.format(func)
         if func not in dir(self):
             raise ConfigError(_('consistency {0} not available for this option').format(func))
         all_cons_opts = tuple([self] + list(other_opts))
-        value = self.impl_getdefault()
-        if value is not None:
-            if self.impl_is_multi():
-                for idx, val in enumerate(value):
-                    if not self.impl_is_submulti():
-                        self._launch_consistency(func, self, val, undefined, idx,
-                                                 None, all_cons_opts,
-                                                 warnings_only, transitive)
-                    else:
-                        for slave_idx, val in enumerate(value):
-                            self._launch_consistency(func, self, val, None,
-                                                     idx, slave_idx,
-                                                     all_cons_opts,
-                                                     warnings_only, transitive)
-            else:
-                self._launch_consistency(func, self, value, undefined, None,
-                                         None, all_cons_opts, warnings_only,
-                                         transitive)
+        unknown_params = set(params.keys()) - set(['warnings_only', 'transitive'])
+        if unknown_params != set():
+            raise ValueError(_('unknow parameter {0} in consistency').format(unknown_params))
         self._add_consistency(func, all_cons_opts, params)
-        #re validate default value when add consistency
-        self.impl_validate(self.impl_getdefault())
+        #validate default value when add consistency
+        try:
+            self.impl_validate(self.impl_getdefault())
+        except ValueError, err:
+            self._del_consistency()
+            raise err
+
+    def _valid_consistency(self, option, value, context, index, submulti_idx):
+        if context is not undefined:
+            descr = context.cfgimpl_get_description()
+            if descr._cache_consistencies is None:
+                return True
+            #consistencies is something like [('_cons_not_equal', (opt1, opt2))]
+            if isinstance(option, DynSymLinkOption):
+                consistencies = descr._cache_consistencies.get(option._impl_getopt())
+            else:
+                consistencies = descr._cache_consistencies.get(option)
+        else:
+            consistencies = option._get_consistencies()
+        if consistencies is not None:
+            for func, all_cons_opts, params in consistencies:
+                warnings_only = params.get('warnings_only', False)
+                transitive = params.get('transitive', True)
+                #all_cons_opts[0] is the option where func is set
+                if isinstance(option, DynSymLinkOption):
+                    subpath = '.'.join(option._dyn.split('.')[:-1])
+                    namelen = len(option._impl_getopt().impl_getname())
+                    suffix = option.impl_getname()[namelen:]
+                    opts = []
+                    for opt in all_cons_opts:
+                        name = opt.impl_getname() + suffix
+                        path = subpath + '.' + name
+                        opts.append(opt._impl_to_dyn(name, path))
+                else:
+                    opts = all_cons_opts
+                try:
+                    opts[0]._launch_consistency(func, option, value, context,
+                                                index, submulti_idx, opts,
+                                                warnings_only, transitive)
+                except ValueError as err:
+                    if warnings_only:
+                        raise ValueWarning(err.message, option)
+                    else:
+                        raise err
 
     def _cons_not_equal(self, opts, vals, warnings_only):
         for idx_inf, val_inf in enumerate(vals):
@@ -740,6 +736,7 @@ class Option(OnlyOption):
                         msg = _("same value for {0} and {1}, should be different")
                     else:
                         msg = _("same value for {0} and {1}, must be different")
+                    log.debug('_cons_not_equal: {0} and {1} are not different'.format(val_inf, val_sup))
                     raise ValueError(msg.format(opts[idx_inf].impl_getname(),
                                                 opts[idx_inf + idx_sup + 1].impl_getname()))
 
@@ -753,7 +750,7 @@ class Option(OnlyOption):
         :param load: `True` if we are at the init of the option description
         :type load: bool
         """
-        if not load and self._get_consistencies() is None:
+        if not load and self._get_consistencies() == ():
             self._state_consistencies = None
         elif load and self._state_consistencies is None:
             del(self._state_consistencies)
@@ -787,10 +784,7 @@ class Option(OnlyOption):
     def _validate_callback(self, callback, callback_params):
         if callback is None:
             return
-        try:
-            default_multi = self.impl_getdefault_multi()
-        except AttributeError:
-            default_multi = None
+        default_multi = self.impl_getdefault_multi()
         if (not self.impl_is_multi() and (self.impl_getdefault() is not None or
             default_multi is not None)) or \
             (self.impl_is_multi() and (self.impl_getdefault() != [] or
@@ -808,8 +802,6 @@ def validate_requires_arg(requires, name):
                      know more about
                      the description of the requires dictionary
     """
-    if requires is None:
-        return None, None
     ret_requires = {}
     config_action = {}
 
index 7b430c8..623f668 100644 (file)
@@ -173,13 +173,9 @@ class IPOption(Option):
         # sometimes an ip term starts with a zero
         # but this does not fit in some case, for example bind does not like it
         self._impl_valid_unicode(value)
-        try:
-            for val in value.split('.'):
-                if val.startswith("0") and len(val) > 1:
-                    raise ValueError(_('invalid IP'))  # pragma: optional cover
-        except AttributeError:  # pragma: optional cover
-            #if integer for example
-            raise ValueError(_('invalid IP'))
+        for val in value.split('.'):
+            if val.startswith("0") and len(val) > 1:
+                raise ValueError(_('invalid IP'))  # pragma: optional cover
         # 'standard' validation
         try:
             IP('{0}/32'.format(value))
@@ -432,6 +428,7 @@ class DomainnameOption(Option):
 
     def _validate(self, value, context=undefined):
         self._impl_valid_unicode(value)
+
         def _valid_length(val):
             if len(val) < 1:
                 raise ValueError(_("invalid domainname's length (min 1)"))
index 8a3831e..05ef6ef 100644 (file)
@@ -24,10 +24,9 @@ import re
 
 from tiramisu.i18n import _
 from tiramisu.setting import groups, undefined  # , log
-from .baseoption import BaseOption, DynSymLinkOption, SymLinkOption, \
-    allowed_character
+from .baseoption import BaseOption, SymLinkOption, allowed_character
 from . import MasterSlaves
-from tiramisu.error import ConfigError, ConflictError, ValueWarning
+from tiramisu.error import ConfigError, ConflictError
 from tiramisu.storage import get_storages_option
 from tiramisu.autolib import carry_out_calculation
 
@@ -103,6 +102,7 @@ class OptionDescription(BaseOption, StorageOptionDescription):
             cache_option.append(option._get_id())
             if not isinstance(option, OptionDescription):
                 for func, all_cons_opts, params in option._get_consistencies():
+                    all_cons_opts[0]._valid_consistencies(all_cons_opts[1:])
                     for opt in all_cons_opts:
                         _consistencies.setdefault(opt,
                                                   []).append((func,
@@ -162,40 +162,6 @@ class OptionDescription(BaseOption, StorageOptionDescription):
             raise ValueError(_('group_type: {0}'
                                ' not allowed').format(group_type))
 
-    def _valid_consistency(self, option, value, context, index, submulti_idx):
-        if self._cache_consistencies is None:
-            return True
-        #consistencies is something like [('_cons_not_equal', (opt1, opt2))]
-        if isinstance(option, DynSymLinkOption):
-            consistencies = self._cache_consistencies.get(option._impl_getopt())
-        else:
-            consistencies = self._cache_consistencies.get(option)
-        if consistencies is not None:
-            for func, all_cons_opts, params in consistencies:
-                warnings_only = params.get('warnings_only', False)
-                transitive = params.get('transitive', True)
-                #all_cons_opts[0] is the option where func is set
-                if isinstance(option, DynSymLinkOption):
-                    subpath = '.'.join(option._dyn.split('.')[:-1])
-                    namelen = len(option._impl_getopt().impl_getname())
-                    suffix = option.impl_getname()[namelen:]
-                    opts = []
-                    for opt in all_cons_opts:
-                        name = opt.impl_getname() + suffix
-                        path = subpath + '.' + name
-                        opts.append(opt._impl_to_dyn(name, path))
-                else:
-                    opts = all_cons_opts
-                try:
-                    opts[0]._launch_consistency(func, option, value, context,
-                                                index, submulti_idx, opts,
-                                                warnings_only, transitive)
-                except ValueError as err:
-                    if warnings_only:
-                        raise ValueWarning(err.message, option)
-                    else:
-                        raise err
-
     def _impl_getstate(self, descr=None):
         """enables us to export into a dict
         :param descr: parent :class:`tiramisu.option.OptionDescription`
@@ -317,12 +283,15 @@ class DynOptionDescription(OptionDescription):
         for child in children:
             if isinstance(child, OptionDescription):
                 if child.impl_get_group_type() != groups.master:
-                    raise ConfigError(_('cannot set optiondescription in an '
+                    raise ConfigError(_('cannot set optiondescription in a '
                                         'dynoptiondescription'))
                 for chld in child._impl_getchildren():
                     chld._impl_setsubdyn(self)
             if isinstance(child, SymLinkOption):
-                raise ConfigError(_('cannot set symlinkoption in an '
+                raise ConfigError(_('cannot set symlinkoption in a '
+                                    'dynoptiondescription'))
+            if isinstance(child, SymLinkOption):
+                raise ConfigError(_('cannot set symlinkoption in a '
                                     'dynoptiondescription'))
             child._impl_setsubdyn(self)
         self.impl_set_callback(callback, callback_params)
index b3c135d..f7d22b1 100644 (file)
@@ -145,6 +145,9 @@ class StorageBase(object):
         except AttributeError:
             self._consistencies = [cons]
 
+    def _del_consistency(self):
+        self._consistencies.pop(-1)
+
     def _get_consistencies(self):
         try:
             return self._consistencies
index aa8b5cc..2e0deb3 100644 (file)
@@ -57,7 +57,7 @@ class Values(object):
     def _get_multi(self, opt, path):
         return Multi([], self.context, opt, path)
 
-    def _getdefaultvalue(self, opt, path, with_meta, index):
+    def _getdefaultvalue(self, opt, path, with_meta, index, submulti_index):
         # if value has callback and is not set
         if opt.impl_has_callback():
             callback, callback_params = opt.impl_get_callback()
@@ -65,18 +65,14 @@ class Values(object):
                                           callback=callback,
                                           callback_params=callback_params,
                                           index=index)
-            try:
-                if isinstance(value, list) and index is not undefined:
-                    #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]
+            if isinstance(value, list) and index is not undefined:
+                #if return a list and index is set, return value only if
+                #it's a submulti without submulti_index and without list of list
+                if opt.impl_is_submulti() and submulti_index is undefined and \
+                        (len(value) == 0 or not isinstance(value[0], list)):
+                    return value
+            else:
                 return value
-            except IndexError:
-                pass
         if with_meta:
             meta = self._getcontext().cfgimpl_get_meta()
             if meta is not None:
@@ -94,7 +90,7 @@ class Values(object):
         # now try to get default value
         value = opt.impl_getdefault()
         if opt.impl_is_multi() and index is not undefined:
-            if value is None:
+            if value == []:
                 value = opt.impl_getdefault_multi()
             else:
                 try:
@@ -103,43 +99,20 @@ class Values(object):
                     value = opt.impl_getdefault_multi()
         return value
 
-    def _getvalue(self, opt, path, is_default, index=undefined,
-                  with_meta=True, self_properties=undefined,
+    def _getvalue(self, opt, path, is_default, self_properties,
+                  index=undefined, submulti_index=undefined, with_meta=True,
                   masterlen=undefined):
         """actually retrieves the value
 
         :param opt: the `option.Option()` object
         :returns: the option's value (or the default value if not set)
         """
-        if opt.impl_is_optiondescription():  # pragma: optional cover
-            raise ValueError(_('optiondescription has no value'))
-
-        if self_properties is undefined:
-            self_properties = self._getcontext().cfgimpl_get_settings()._getproperties(
-                opt, path, read_write=False)
         force_default = 'frozen' in self_properties and \
             'force_default_on_freeze' in self_properties
+        # not default value
         if not is_default and not force_default:
             if opt.impl_is_master_slaves('slave'):
-            #if masterlen is not undefined:
-                if index is undefined:
-                    value = []
-                    vals = self._p_.getvalue(path)
-                    length = max(masterlen, len(vals))
-                    for idx in xrange(0, length):
-                        try:
-                            if vals[idx] is undefined:
-                                value.append(self._getdefaultvalue(opt, path, with_meta, idx))
-                            else:
-                                value.append(vals[idx])
-                        except IndexError:
-                            try:
-                                value.append(self._getdefaultvalue(opt, path, with_meta, idx))
-                            except IndexError:
-                                value.append(None)
-                else:
-                    value = self._p_.getvalue(path, index)
-                return value
+                return self._p_.getvalue(path, index)
             else:
                 value = self._p_.getvalue(path)
                 if index is not undefined:
@@ -151,7 +124,7 @@ class Values(object):
                         pass
                 else:
                     return value
-        return self._getdefaultvalue(opt, path, with_meta, index)
+        return self._getdefaultvalue(opt, path, with_meta, index, submulti_index)
 
     def get_modified_values(self):
         context = self._getcontext()
@@ -316,13 +289,9 @@ class Values(object):
                                             self_properties=self_properties,
                                             index=index)
         try:
-            if index is None:
-                gv_index = undefined
-            else:
-                gv_index = index
-            value = self._getvalue(opt, path, is_default, index=gv_index,
+            value = self._getvalue(opt, path, is_default, self_properties,
+                                   index=index, submulti_index=submulti_index,
                                    with_meta=with_meta,
-                                   self_properties=self_properties,
                                    masterlen=masterlen)
             config_error = None
         except ConfigError as err:
@@ -344,9 +313,6 @@ class Values(object):
             else:
                 force_index = index
             if opt.impl_is_multi():
-                #for slave is a multi
-                if index is None and not isinstance(value, list):
-                    value = []
                 if force_index is None:
                     value = Multi(value, self.context, opt, path)
                 elif opt.impl_is_submulti() and submulti_index is undefined:
@@ -773,10 +739,7 @@ class Multi(list):
                                " which is a slave").format(self.opt.impl_getname()))
         index = self.__len__()
         if value is undefined:
-            try:
-                value = self._get_validated_value(index)
-            except IndexError:
-                value = None
+            value = self._get_validated_value(index)
         context = self._getcontext()
         setting = context.cfgimpl_get_settings()
         setting_properties = setting._getproperties(read_write=False)