coverage
authorEmmanuel Garette <egarette@cadoles.com>
Fri, 21 Jul 2017 16:03:34 +0000 (18:03 +0200)
committerEmmanuel Garette <egarette@cadoles.com>
Fri, 21 Jul 2017 16:03:34 +0000 (18:03 +0200)
19 files changed:
test/test_config.py
test/test_dyn_optiondescription.py
test/test_metaconfig.py
test/test_option_consistency.py
test/test_option_setting.py
test/test_permissive.py
test/test_requires.py
tiramisu/config.py
tiramisu/option/baseoption.py
tiramisu/option/optiondescription.py
tiramisu/setting.py
tiramisu/storage/__init__.py
tiramisu/storage/dictionary/option.py
tiramisu/storage/dictionary/setting.py
tiramisu/storage/dictionary/storage.py
tiramisu/storage/dictionary/value.py
tiramisu/storage/sqlite3/setting.py
tiramisu/storage/sqlite3/value.py
tiramisu/value.py

index 43e2714..0eb220f 100644 (file)
@@ -202,6 +202,7 @@ def test_config_impl_get_opt_by_path():
         assert config.cfgimpl_get_description().impl_get_opt_by_path('bool') == boo
         assert config.cfgimpl_get_description().impl_get_opt_by_path('gc.dummy') == dummy
     raises(AttributeError, "config.cfgimpl_get_description().impl_get_opt_by_path('gc.unknown')")
+    raises(ConfigError, "config.gc.cfgimpl_get_description().impl_get_opt_by_path('gc.unknown')")
 
 
 def test_information_display():
index 64c82bf..1c2192c 100644 (file)
@@ -46,6 +46,10 @@ def return_wrong_list():
     return ['---', ' ']
 
 
+def return_raise():
+    raise Exception('error')
+
+
 def test_build_dyndescription():
     st = StrOption('st', '')
     dod = DynOptionDescription('dod', '', [st], callback=return_list)
@@ -57,6 +61,14 @@ def test_build_dyndescription():
     assert str(cfg.dodval2) == "stval2 = None"
 
 
+def test_build_dyndescription_raise():
+    st = StrOption('st', '')
+    dod = DynOptionDescription('dod', '', [st], callback=return_raise)
+    od = OptionDescription('od', '', [dod])
+    cfg = Config(od)
+    raises(ConfigError, "str(cfg)")
+
+
 def test_subpath_dyndescription():
     st = StrOption('st', '')
     dod = DynOptionDescription('dod', '', [st], callback=return_list)
@@ -221,6 +233,14 @@ def test_prop_dyndescription():
     assert str(cfg.cfgimpl_get_settings()[dodval2]) == str([])
 
 
+def test_prop_dyndescription_force_store_value():
+    st = StrOption('st', '', properties=('force_store_value',))
+    dod = DynOptionDescription('dod', '', [st], callback=return_list)
+    od = OptionDescription('od', '', [dod])
+    od2 = OptionDescription('od', '', [od])
+    raises(ConfigError, "Config(od2)")
+
+
 def test_callback_dyndescription():
     st = StrOption('st', '', callback=return_dynval)
     dod = DynOptionDescription('dod', '', [st], callback=return_list)
index e1034bc..ebbc891 100644 (file)
@@ -28,6 +28,11 @@ def make_description():
     i6 = IntOption('i6', '', properties=('disabled',))
     od1 = OptionDescription('od1', '', [i1, i2, i3, i4, i5, i6])
     od2 = OptionDescription('od2', '', [od1])
+    return od2
+
+
+def make_metaconfig():
+    od2 = make_description()
     conf1 = Config(od2, session_id='conf3')
     conf2 = Config(od2, session_id='conf4')
     meta = MetaConfig([conf1, conf2], session_id='meta')
@@ -40,7 +45,7 @@ def make_description():
 #FIXME ne pas mettre 2 OD differents dans un meta
 #FIXME serialization
 def test_none():
-    meta = make_description()
+    meta = make_metaconfig()
     conf1, conf2 = meta.cfgimpl_get_children()
     assert conf1.od1.i3 is conf2.od1.i3 is None
     assert conf1.getowner(conf1.unwrap_from_path('od1.i3')) is conf2.getowner(conf2.unwrap_from_path('od1.i3')) is owners.default
@@ -69,7 +74,7 @@ def test_none():
 
 
 def test_default():
-    meta = make_description()
+    meta = make_metaconfig()
     conf1, conf2 = meta.cfgimpl_get_children()
     assert conf1.od1.i2 == conf2.od1.i2 == 1
     assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.default
@@ -98,18 +103,19 @@ def test_default():
 
 
 def test_contexts():
-    meta = make_description()
+    meta = make_metaconfig()
     conf1, conf2 = meta.cfgimpl_get_children()
     assert conf1.od1.i2 == conf2.od1.i2 == 1
     assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.default
-    meta.set_value('od1.i2', 6, only_config=True)
+    errors = meta.set_value('od1.i2', 6, only_config=True)
     assert meta.od1.i2 == 1
     assert conf1.od1.i2 == conf2.od1.i2 == 6
     assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.user
+    assert len(errors) == 0
 
 
 def test_find():
-    meta = make_description()
+    meta = make_metaconfig()
     i2 = meta.unwrap_from_path('od1.i2')
     assert [i2] == meta.find(byname='i2')
     assert i2 == meta.find_first(byname='i2')
@@ -123,8 +129,11 @@ def test_group_error():
 
 
 def test_meta_meta():
-    meta1 = make_description()
+    meta1 = make_metaconfig()
     meta2 = MetaConfig([meta1])
+    assert str(meta1) == """(conf3)
+(conf4)
+[od1]"""
     meta2.cfgimpl_get_settings().setowner(owners.meta)
     conf1, conf2 = meta1.cfgimpl_get_children()
     assert conf1.od1.i2 == conf2.od1.i2 == 1
@@ -156,14 +165,38 @@ def test_meta_meta():
     assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
 
 
+def test_meta_config_name():
+    od = make_description()
+    meta = MetaConfig(['name1', 'name2'], optiondescription=od)
+    assert len(meta.cfgimpl_get_children()) == 2
+    assert meta.name1
+    assert meta.name2
+
+
+def test_meta_new_config():
+    meta = make_metaconfig()
+    assert len(meta.cfgimpl_get_children()) == 2
+    meta.new_config('newconf1')
+    assert len(meta.cfgimpl_get_children()) == 3
+
+
+def test_meta_new_config_wrong_name():
+    meta = make_metaconfig()
+    assert len(meta.cfgimpl_get_children()) == 2
+    raises(ConflictError, "meta.new_config('conf4')")
+    assert len(meta.cfgimpl_get_children()) == 2
+
+
 def test_meta_meta_set():
-    meta1 = make_description()
+    meta1 = make_metaconfig()
     meta2 = MetaConfig([meta1])
     meta2.cfgimpl_get_settings().setowner(owners.meta)
     meta2.read_write()
     conf1, conf2 = meta1.cfgimpl_get_children()
-    meta2.set_value('od1.i1', 7, only_config=True)
-    meta2.set_value('od1.i6', 7, only_config=True)
+    errors1 = meta2.set_value('od1.i1', 7, only_config=True)
+    errors2 = meta2.set_value('od1.i6', 7, only_config=True)
+    assert len(errors1) == 0
+    assert len(errors2) == 2
     assert conf1.od1.i1 == conf2.od1.i1 == 7
     assert conf1.getowner(conf1.unwrap_from_path('od1.i1')) is conf2.getowner(conf2.unwrap_from_path('od1.i1')) is owners.user
     assert [conf1, conf2] == meta2.find_firsts(byname='i1', byvalue=7).cfgimpl_get_children()
@@ -189,7 +222,7 @@ def test_not_meta():
     conf3 = Config(od2)
     try:
         conf4 = Config(od2, session_id='conf2')
-    except ValueError:
+    except ConflictError:
         pass
     else:
         conf3, conf4
@@ -199,7 +232,8 @@ def test_not_meta():
         grp = GroupConfig([conf1, conf2])
         raises(ConfigError, 'grp.od1.i1')
         conf1, conf2 = grp.cfgimpl_get_children()
-        grp.set_value('od1.i1', 7)
+        errors = grp.set_value('od1.i1', 7)
+        assert len(errors) == 0
         assert grp.conf1.od1.i1 == conf2.od1.i1 == 7
         assert grp.conf1.getowner(grp.conf1.unwrap_from_path('od1.i1')) is grp.conf2.getowner(grp.conf2.unwrap_from_path('od1.i1')) is owners.user
 
@@ -211,6 +245,9 @@ def test_group_find_firsts():
     conf1 = Config(od2, session_id='conf1')
     conf2 = Config(od2, session_id='conf2')
     grp = GroupConfig([conf1, conf2])
+    assert str(grp) == """(conf1)
+(conf2)
+"""
     assert [conf1, conf2] == grp.find_firsts(byname='i1').cfgimpl_get_children()
 
 
@@ -222,13 +259,14 @@ def test_group_group():
     conf2 = Config(od2, session_id='conf10')
     grp = GroupConfig([conf1, conf2], 'grp')
     grp2 = GroupConfig([grp])
-    grp2.set_value('od1.i1', 2)
+    errors = grp2.set_value('od1.i1', 2)
     assert grp2.grp.conf9.od1.i1 == 2
     assert grp2.grp.conf9.getowner(i1) == owners.user
+    assert len(errors) == 0
 
 
 def test_meta_path():
-    meta = make_description()
+    meta = make_metaconfig()
     assert meta._impl_path is None
     assert meta.od1._impl_path == 'od1'
 
@@ -265,6 +303,7 @@ def test_meta_master_slaves():
     conf2 = Config(interface1, session_id='conf2')
     meta = MetaConfig([conf1, conf2])
     meta.read_only()
+    assert [conf1, conf2] == meta.find_firsts(byname='ip_admin_eth0').cfgimpl_get_children()
     assert [conf1, conf2] == meta.find_firsts(byname='netmask_admin_eth0').cfgimpl_get_children()
     meta.read_write()
     raises(AttributeError, "meta.find_firsts(byname='netmask_admin_eth0')")
@@ -361,19 +400,22 @@ def test_meta_force_default():
     assert meta.ip_admin_eth0 == []
     assert meta.conf1.ip_admin_eth0 == []
     assert meta.conf2.ip_admin_eth0 == []
-    meta.set_value('ip_admin_eth0', ['192.168.1.1'])
+    errors = meta.set_value('ip_admin_eth0', ['192.168.1.1'])
+    assert len(errors) == 0
     assert meta.ip_admin_eth0 == ['192.168.1.1']
     assert meta.conf1.ip_admin_eth0 == ['192.168.1.1']
     assert meta.conf2.ip_admin_eth0 == ['192.168.1.1']
-    meta.conf1.ip_admin_eth0 = ['192.168.1.2']
+    errors = meta.conf1.ip_admin_eth0 = ['192.168.1.2']
     assert meta.ip_admin_eth0 == ['192.168.1.1']
     assert meta.conf1.ip_admin_eth0 == ['192.168.1.2']
     assert meta.conf2.ip_admin_eth0 == ['192.168.1.1']
-    meta.set_value('ip_admin_eth0', ['192.168.1.3'])
+    errors = meta.set_value('ip_admin_eth0', ['192.168.1.3'])
+    assert len(errors) == 0
     assert meta.ip_admin_eth0 == ['192.168.1.3']
     assert meta.conf1.ip_admin_eth0 == ['192.168.1.2']
     assert meta.conf2.ip_admin_eth0 == ['192.168.1.3']
-    meta.set_value('ip_admin_eth0', ['192.168.1.4'], force_default=True)
+    errors = meta.set_value('ip_admin_eth0', ['192.168.1.4'], force_default=True)
+    assert len(errors) == 0
     assert meta.ip_admin_eth0 == ['192.168.1.4']
     assert meta.conf1.ip_admin_eth0 == ['192.168.1.4']
     assert meta.conf2.ip_admin_eth0 == ['192.168.1.4']
@@ -399,7 +441,8 @@ def test_meta_force_dont_change_value():
     assert meta.conf2.ip_admin_eth0 == []
     assert conf1.getowner(ip_admin_eth0) is owners.user
     assert conf2.getowner(ip_admin_eth0) is owners.default
-    meta.set_value('ip_admin_eth0', ['192.168.1.4'], force_dont_change_value=True)
+    errors = meta.set_value('ip_admin_eth0', ['192.168.1.4'], force_dont_change_value=True)
+    assert len(errors) == 0
     assert meta.ip_admin_eth0 == ['192.168.1.4']
     assert meta.conf1.ip_admin_eth0 == ['192.168.1.4']
     assert meta.conf2.ip_admin_eth0 == []
@@ -429,7 +472,8 @@ def test_meta_force_default_if_same():
     assert meta.conf2.ip_admin_eth0 == []
     assert conf1.getowner(ip_admin_eth0) is owners.user
     assert conf2.getowner(ip_admin_eth0) is owners.default
-    meta.set_value('ip_admin_eth0', ['192.168.1.4'], force_default_if_same=True)
+    errors = meta.set_value('ip_admin_eth0', ['192.168.1.4'], force_default_if_same=True)
+    assert len(errors) == 0
     assert meta.ip_admin_eth0 == ['192.168.1.4']
     assert meta.conf1.ip_admin_eth0 == ['192.168.1.4']
     assert meta.conf2.ip_admin_eth0 == ['192.168.1.4']
@@ -441,7 +485,8 @@ def test_meta_force_default_if_same():
     assert meta.conf2.ip_admin_eth0 == ['192.168.1.4']
     assert conf1.getowner(ip_admin_eth0) is owners.user
     assert conf2.getowner(ip_admin_eth0) is owners.meta
-    meta.set_value('ip_admin_eth0', ['192.168.1.5'], force_default_if_same=True)
+    errors = meta.set_value('ip_admin_eth0', ['192.168.1.5'], force_default_if_same=True)
+    assert len(errors) == 0
     assert meta.ip_admin_eth0 == ['192.168.1.5']
     assert meta.conf1.ip_admin_eth0 == ['192.168.1.3']
     assert meta.conf2.ip_admin_eth0 == ['192.168.1.5']
@@ -471,7 +516,8 @@ def test_meta_force_default_if_same_and_dont_change():
     assert meta.conf2.ip_admin_eth0 == []
     assert conf1.getowner(ip_admin_eth0) is owners.user
     assert conf2.getowner(ip_admin_eth0) is owners.default
-    meta.set_value('ip_admin_eth0', ['192.168.1.4'], force_default_if_same=True, force_dont_change_value=True)
+    errors = meta.set_value('ip_admin_eth0', ['192.168.1.4'], force_default_if_same=True, force_dont_change_value=True)
+    assert len(errors) == 0
     assert meta.ip_admin_eth0 == ['192.168.1.4']
     assert meta.conf1.ip_admin_eth0 == ['192.168.1.4']
     assert meta.conf2.ip_admin_eth0 == []
@@ -483,7 +529,8 @@ def test_meta_force_default_if_same_and_dont_change():
     assert meta.conf2.ip_admin_eth0 == []
     assert conf1.getowner(ip_admin_eth0) is owners.user
     assert conf2.getowner(ip_admin_eth0) is owners.user
-    meta.set_value('ip_admin_eth0', ['192.168.1.5'], force_default_if_same=True, force_dont_change_value=True)
+    errors = meta.set_value('ip_admin_eth0', ['192.168.1.5'], force_default_if_same=True, force_dont_change_value=True)
+    assert len(errors) == 0
     assert meta.ip_admin_eth0 == ['192.168.1.5']
     assert meta.conf1.ip_admin_eth0 == ['192.168.1.3']
     assert meta.conf2.ip_admin_eth0 == []
@@ -640,3 +687,33 @@ def test_meta_properties_meta_set_value():
     ret = meta.set_value('ip_admin_eth0', '255.255.255.255', force_default_if_same=True)
     assert len(ret) == 1
     assert isinstance(ret[0], ValueError)
+
+
+def test_meta_reset():
+    ip_admin_eth0 = StrOption('ip_admin_eth0', "ip", multi=True)
+    netmask_admin_eth0 = StrOption('netmask_admin_eth0', "mask", multi=True, properties=('hidden',))
+    interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
+    interface1.impl_set_group_type(groups.master)
+    conf1 = Config(interface1, session_id='conf1')
+    conf1.read_write()
+    conf2 = Config(interface1, session_id='conf2')
+    conf2.read_write()
+    meta = MetaConfig([conf1, conf2])
+    meta.read_write()
+    meta.cfgimpl_get_settings().setowner(owners.meta)
+    assert meta.ip_admin_eth0 == []
+    assert meta.conf1.ip_admin_eth0 == []
+    assert meta.conf2.ip_admin_eth0 == []
+    errors = meta.set_value('ip_admin_eth0', ['192.168.1.1'])
+    assert len(errors) == 0
+    assert meta.ip_admin_eth0 == ['192.168.1.1']
+    assert meta.conf1.ip_admin_eth0 == ['192.168.1.1']
+    assert meta.conf2.ip_admin_eth0 == ['192.168.1.1']
+    meta.conf1.ip_admin_eth0 = ['192.168.1.2']
+    assert meta.ip_admin_eth0 == ['192.168.1.1']
+    assert meta.conf1.ip_admin_eth0 == ['192.168.1.2']
+    assert meta.conf2.ip_admin_eth0 == ['192.168.1.1']
+    meta.reset('ip_admin_eth0')
+    assert meta.ip_admin_eth0 == []
+    assert meta.conf1.ip_admin_eth0 == []
+    assert meta.conf2.ip_admin_eth0 == []
index 3761cf2..f46b499 100644 (file)
@@ -215,7 +215,6 @@ def test_consistency_not_equal_submulti():
     a = IntOption('a', '', multi=submulti)
     b = IntOption('b', '', multi=submulti)
     od = OptionDescription('a', '', [a, b])
-    od.impl_set_group_type(groups.master)
     raises(ConfigError, 'a.impl_add_consistency("not_equal", b)')
 
 
@@ -250,6 +249,42 @@ def test_consistency_not_equal_masterslave():
     raises(ValueError, "c.b[1] = 3")
 
 
+def test_consistency_not_equal_masterslave_error_multi1():
+    a = IPOption('a', '', multi=True)
+    b = NetmaskOption('b', '', multi=True)
+    c = NetmaskOption('c', '', multi=True)
+    od = OptionDescription('a', '', [a, b])
+    od.impl_set_group_type(groups.master)
+    od2 = OptionDescription('b', '', [od, c])
+    c.impl_add_consistency('ip_netmask', a)
+    raises(ConfigError, "Config(od2)")
+
+
+def test_consistency_not_equal_masterslave_error_multi2():
+    a = IPOption('a', '', multi=True)
+    b = NetmaskOption('b', '', multi=True)
+    c = IPOption('c', '', multi=True)
+    od = OptionDescription('a', '', [a, b])
+    od.impl_set_group_type(groups.master)
+    od2 = OptionDescription('b', '', [od, c])
+    b.impl_add_consistency('ip_netmask', c)
+    raises(ConfigError, "Config(od2)")
+
+
+def test_consistency_not_equal_masterslave_error_othermaster():
+    a = IPOption('a', '', multi=True)
+    b = NetmaskOption('b', '', multi=True)
+    c = IPOption('c', '', multi=True)
+    d = NetmaskOption('d', '', multi=True)
+    od = OptionDescription('a', '', [a, b])
+    od.impl_set_group_type(groups.master)
+    od2 = OptionDescription('c', '', [c, d])
+    od2.impl_set_group_type(groups.master)
+    od3 = OptionDescription('b', '', [od, od2])
+    d.impl_add_consistency('ip_netmask', a)
+    raises(ConfigError, "Config(od2)")
+
+
 def test_consistency_not_equal_masterslaves_default():
     a = IntOption('a', '', multi=True)
     b = IntOption('b', '', multi=True, default_multi=1)
index 55a6dbd..84f26fd 100644 (file)
@@ -5,7 +5,7 @@ do_autopath()
 from py.test import raises
 
 from tiramisu.i18n import _
-from tiramisu.error import display_list
+from tiramisu.error import display_list, ConfigError
 from tiramisu.setting import owners, groups
 from tiramisu.config import Config
 from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption, \
@@ -431,8 +431,11 @@ def test_append_properties():
     assert tuple(option._properties) == tuple()
     assert not 'test' in setting[option]
     setting[option].append('test')
+    raises(ConfigError, "setting[option].append('force_store_value')")
+    raises(ConfigError, "setting.append('force_store_value')")
     assert tuple(option._properties) == tuple()
     assert 'test' in setting[option]
+    assert setting[option].get() == ('test',)
 
 
 def test_reset_properties():
index 7caf61d..ad82466 100644 (file)
@@ -154,6 +154,65 @@ def test_permissive_option():
     assert props == ['disabled']
 
 
+def test_permissive_option_cache():
+    descr = make_description()
+    u1 = descr.u1
+    config = Config(descr)
+    setting = config.cfgimpl_get_settings()
+    config.read_write()
+    setting.remove('expire')
+
+    props = []
+    try:
+        config.u1
+    except PropertiesOptionError as err:
+        props = err.proptype
+    assert props == ['disabled']
+    props = []
+    try:
+        config.u2
+    except PropertiesOptionError as err:
+        props = err.proptype
+    assert props == ['disabled']
+
+    setting.setpermissive(('disabled',), u1)
+    props = []
+    try:
+        config.u1
+    except PropertiesOptionError as err:
+        props = err.proptype
+    assert props == []
+    props = []
+    try:
+        config.u2
+    except PropertiesOptionError as err:
+        props = err.proptype
+    assert props == ['disabled']
+
+    setting.append('permissive')
+    config.u1
+    props = []
+    try:
+        config.u2
+    except PropertiesOptionError as err:
+        props = err.proptype
+    assert props == ['disabled']
+
+    setting.remove('permissive')
+    props = []
+    try:
+        config.u1
+    except PropertiesOptionError as err:
+        props = err.proptype
+    assert props == []
+    props = []
+    try:
+        config.u2
+    except PropertiesOptionError as err:
+        props = err.proptype
+    assert props == ['disabled']
+
+
 def test_permissive_option_mandatory():
     descr = make_description()
     u1 = descr.u1
index 7dc3ef2..23b310a 100644 (file)
@@ -324,6 +324,30 @@ def test_requires_transitive_hidden_disabled():
     raises(RequirementError, 'c.ip_address_service_web')
 
 
+def test_requires_transitive_hidden_disabled_multiple():
+    a = BoolOption('activate_service', '', True)
+    b = BoolOption('activate_service_web', '', True,
+                   requires=[{'option': a, 'expected': False, 'action': 'hidden'},
+                             {'option': a, 'expected': False, 'action': 'disabled'}])
+    d = IPOption('ip_address_service_web', '',
+                 requires=[{'option': b, 'expected': False, 'action': 'mandatory'}])
+    od = OptionDescription('service', '', [a, b, d])
+    c = Config(od)
+    c.read_write()
+    c.activate_service
+    c.activate_service_web
+    c.ip_address_service_web
+    c.activate_service = False
+    #
+    props = []
+    try:
+        c.activate_service_web
+    except PropertiesOptionError as err:
+        props = err.proptype
+    assert set(props) == {'disabled', 'hidden'}
+    raises(RequirementError, 'c.ip_address_service_web')
+
+
 def test_requires_not_transitive():
     a = BoolOption('activate_service', '', True)
     b = BoolOption('activate_service_web', '', True,
index e76c221..bdcac56 100644 (file)
@@ -35,7 +35,7 @@ from .value import Values, Multi
 from .i18n import _
 
 
-if sys.version_info[0] >= 3:  # pragma: optional cover
+if sys.version_info[0] >= 3:  # pragma: no cover
     xrange = range
 
 
@@ -482,7 +482,7 @@ class SubConfig(object):
         # if value and/or check_properties are set, need all avalaible option
         # If first one has no good value or not good property check second one
         # and so on
-        only_first = first is True and byvalue is None and \
+        only_first = first is True and byvalue is undefined and \
             check_properties is None
         if only_path is not undefined:
             options = [(only_path, only_option)]
@@ -752,7 +752,7 @@ class _CommonConfig(SubConfig):
         self._impl_context = weakref.ref(self)
         self._impl_settings.context = weakref.ref(self)
         self._impl_values.context = weakref.ref(self)
-        storage = get_storage('config', test=self._impl_test, **state['_storage'])
+        storage = get_storage(test=self._impl_test, **state['_storage'])
         self._impl_values._impl_setstate(storage)
         self._impl_settings._impl_setstate(storage)
         self._impl_meta = None
@@ -836,8 +836,6 @@ class GroupConfig(_CommonConfig):
             if not isinstance(child, _CommonConfig):
                 raise ValueError(_("groupconfig's children must be Config, MetaConfig or GroupConfig"))
             name_ = child._impl_name
-            if name_ is None:
-                raise ValueError(_('name must be set to config before creating groupconfig'))
             names.append(name_)
         if len(names) != len(set(names)):
             for idx in xrange(1, len(names) + 1):
@@ -923,16 +921,16 @@ class GroupConfig(_CommonConfig):
         else:
             return GroupConfig(self._find_return_results(ret, raise_if_not_found))
 
-    def __repr__(self):
-        return object.__repr__(self)
-
     def __str__(self):
         ret = ''
         for child in self._impl_children:
             ret += '({0})\n'.format(child._impl_name)
-        ret += super(GroupConfig, self).__str__()
+        if self._impl_descr is not None:
+            ret += super(GroupConfig, self).__str__()
         return ret
 
+    __repr__ = __str__
+
     def getattr(self, name, force_permissive=False, validate=True,
                 _setting_properties=undefined, _self_properties=undefined, index=None,
                 returns_raise=False):
@@ -951,14 +949,14 @@ class MetaConfig(GroupConfig):
     __slots__ = tuple()
 
     def __init__(self, children, session_id=None, persistent=False,
-                 optiondescription=None):
+                 optiondescription=None, _force_store_values=True):
         descr = None
         if optiondescription is not None:
             new_children = []
             for child_session_id in children:
                 #FIXME _force_store_values doit etre a true si inexistant !
-                new_children.append(Config(optiondescription, persistent=True,
-                                           session_id=child_session_id, _force_store_values=False))
+                new_children.append(Config(optiondescription, persistent=persistent,
+                                           session_id=child_session_id, _force_store_values=_force_store_values))
             children = new_children
         for child in children:
             if not isinstance(child, _CommonConfig):
@@ -1004,12 +1002,10 @@ class MetaConfig(GroupConfig):
                         else:
                             child_value = child.getattr(path)
                     if force_default or value == child_value:
-                        childret = child.cfgimpl_get_values().reset(opt, path=path,
-                                                                    validate=False,
-                                                                    _setting_properties=setting_properties,
-                                                                    _commit=False)
-                        if childret is not None:
-                            ret.append(childret)
+                        child.cfgimpl_get_values().reset(opt, path=path,
+                                                         validate=False,
+                                                         _setting_properties=setting_properties,
+                                                         _commit=False)
                         continue
                 if force_dont_change_value:
                     child_value = child.getattr(path, _setting_properties=setting_properties,
@@ -1018,7 +1014,7 @@ class MetaConfig(GroupConfig):
                         ret.append(child_value)
                     elif value != child_value:
                         childret = child.setattr(path, child_value, _commit=False, not_raises=True)
-                        if childret is not None:
+                        if childret is not None:  # pragma: no cover
                             ret.append(childret)
 
         setret = self.setattr(path, value, _commit=_commit, not_raises=True)
@@ -1038,6 +1034,13 @@ class MetaConfig(GroupConfig):
                                         validate=False,
                                         _setting_properties=setting_properties)
 
-    def new_config(self, session_id=None, persistent=False):
-        return Config(self._impl_descr, session_id=session_id,
-                      persistent=persistent)
+    def new_config(self, session_id, persistent=False):
+        config = Config(self._impl_descr, session_id=session_id,
+                        persistent=persistent)
+
+        if config._impl_name in [child._impl_name for child in self._impl_children]:  # pragma: no cover
+            raise ConflictError(_('config name must be uniq in '
+                                  'groupconfig for {0}').format(config._impl_name))
+        config._impl_meta = weakref.ref(self)
+        self._impl_children.append(config)
+        return config
index ff4b4d6..cfb6429 100644 (file)
@@ -554,7 +554,7 @@ class Option(OnlyOption):
                                 return opt_value
                             else:
                                 opt_value = None
-                        else:
+                        else:  # pragma: no cover
                             return opt_value
                 elif index is None:
                     opt_value = opt.impl_getdefault()
@@ -719,7 +719,7 @@ class Option(OnlyOption):
                                         ' must be a list').format(
                                            value, self.impl_get_display_name()))
                 for idx, val in enumerate(value):
-                    if isinstance(val, list):
+                    if isinstance(val, list):  # pragma: no cover
                         return ValueError(_('invalid value "{}" for "{}" '
                                             'which must not be a list').format(val,
                                                                               self.impl_get_display_name()))
index 00f4a4f..c40ff74 100644 (file)
@@ -36,7 +36,7 @@ StorageOptionDescription = get_storages_option('optiondescription')
 name_regexp = re.compile(r'^[a-zA-Z\d\-_]*$')
 
 import sys
-if sys.version_info[0] >= 3:  # pragma: optional cover
+if sys.version_info[0] >= 3:  # pragma: no cover
     xrange = range
 del(sys)
 
@@ -141,18 +141,18 @@ class OptionDescription(BaseOption, StorageOptionDescription):
                     if func not in allowed_const_list and is_multi:
                         is_masterslaves = option.impl_is_master_slaves()
                         if not is_masterslaves:
-                            raise ValueError(_('malformed consistency option "{0}" '
+                            raise ConfigError(_('malformed consistency option "{0}" '
                                                'must be a master/slaves').format(
                                                    option.impl_getname()))
                         masterslaves = option.impl_get_master_slaves()
                     for opt in all_cons_opts:
                         if func not in allowed_const_list and is_multi:
                             if not opt.impl_is_master_slaves():
-                                raise ValueError(_('malformed consistency option "{0}" '
+                                raise ConfigError(_('malformed consistency option "{0}" '
                                                    'must not be a multi for "{1}"').format(
                                                        option.impl_getname(), opt.impl_getname()))
                             elif masterslaves != opt.impl_get_master_slaves():
-                                raise ValueError(_('malformed consistency option "{0}" '
+                                raise ConfigError(_('malformed consistency option "{0}" '
                                                    'must be in same master/slaves for "{1}"').format(
                                                        option.impl_getname(), opt.impl_getname()))
                         _consistencies.setdefault(opt,
@@ -318,8 +318,6 @@ class OptionDescription(BaseOption, StorageOptionDescription):
         values = carry_out_calculation(self, context=context,
                                        callback=callback,
                                        callback_params=callback_params)
-        if isinstance(values, Exception):
-            raise values
         if len(values) > len(set(values)):
             raise ConfigError(_('DynOptionDescription callback return not unique value'))
         for val in values:
@@ -327,16 +325,14 @@ class OptionDescription(BaseOption, StorageOptionDescription):
                 raise ValueError(_("invalid suffix: {0} for option").format(val))
         return values
 
-    def _impl_search_dynchild(self, name=undefined, context=undefined):
+    def _impl_search_dynchild(self, name, context):
         ret = []
         for child in self._impl_st_getchildren(context, only_dyn=True):
             cname = child.impl_getname()
-            if name is undefined or name.startswith(cname):
+            if name.startswith(cname):
                 path = cname
                 for value in child._impl_get_suffixes(context):
-                    if name is undefined:
-                        ret.append(SynDynOptionDescription(child, cname + value, path + value, value))
-                    elif name == cname + value:
+                    if name == cname + value:
                         return SynDynOptionDescription(child, name, path + value, value)
         return ret
 
@@ -388,9 +384,6 @@ class DynOptionDescription(OptionDescription):
             if isinstance(child, SymLinkOption):
                 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 ce8ed05..e302678 100644 (file)
@@ -732,7 +732,7 @@ class Settings(object):
                             # transitive action, force expected
                             value = expected[0]
                             inverse = False
-                        else:
+                        else:  # pragma: no cover
                             raise value
                     else:
                         orig_value = value
index e5dc61c..a6f5d51 100644 (file)
@@ -49,7 +49,7 @@ class StorageType(object):
     mod = None
 
     def set(self, name):  # pragma: optional cover
-        if self.storage_type is not None:
+        if self.storage_type is not None:  # pragma: no cover
             if self.storage_type == name:
                 return
             raise ConfigError(_('storage_type is already set, cannot rebind it'))
@@ -65,7 +65,7 @@ class StorageType(object):
             modulepath = '{0}.storage.{1}'.format(MODULE_PATH, self.storage_type)
             try:
                 mod = __import__(modulepath)
-            except ImportError:
+            except ImportError:  # pragma: no cover
                 raise SystemError(_('cannot import the storage {0}').format(
                     self.default_storage))
             for token in modulepath.split(".")[1:]:
@@ -81,7 +81,7 @@ default_validation = StorageType()
 default_validation.set(DEFAULT_STORAGE)
 
 
-def set_storage(type_, name, **kwargs):  # pragma: optional cover
+def set_storage(type_, name):  # pragma: optional cover
     """Change storage's configuration
 
     :params name: is the storage name. If storage is already set, cannot
@@ -89,19 +89,8 @@ def set_storage(type_, name, **kwargs):  # pragma: optional cover
 
     Other attributes are differents according to the selected storage's name
     """
-    if type_ == 'option':
-        storage_option_type.set(name)
-        setting = storage_option_type.get().setting
-    else:
-        storage_type.set(name)
-        setting = storage_type.get().setting
-    for option, value in kwargs.items():
-        try:
-            getattr(setting, option)
-            setattr(setting, option, value)
-        except AttributeError:
-            raise ValueError(_('option {0} not already exists in storage {1}'
-                               '').format(option, name))
+    storage_type.set(name)
+    setting = storage_type.get().setting
 
 
 def _impl_getstate_setting():
@@ -113,16 +102,10 @@ def _impl_getstate_setting():
     return state
 
 
-def get_storage(type_, session_id, persistent, test):  # pragma: optional cover
+def get_storage(session_id, persistent, test):  # pragma: optional cover
     """all used when __setstate__ a Config
     """
-    #FIXME ca sert ???
-    if type_ == 'option':
-        return storage_option_type.get().Storage(session_id, persistent, test)
-    elif type_ == 'config':
-        return storage_type.get().Storage(session_id, persistent, test)
-    else:
-        return default_validation.get().Storage(session_id, persistent, test)
+    return storage_type.get().Storage(session_id, persistent, test)
 
 
 def get_storages(context, session_id, persistent):
index 4a8799b..f58aedc 100644 (file)
@@ -402,12 +402,6 @@ class StorageOptionDescription(StorageBase):
     __slots__ = ('_children', '_cache_paths', '_cache_consistencies',
                  '_group_type', '_state_group_type', '_cache_force_store_values')
 
-    def __init__(self, name, multi, warnings_only, doc, extra):
-        super(StorageOptionDescription, self).__init__(name, multi,
-                                                       warnings_only, doc,
-                                                       None, undefined,
-                                                       undefined, undefined)
-
     def _add_children(self, child_names, children):
         _setattr = object.__setattr__
         _setattr(self, '_children', (tuple(child_names), tuple(children)))
@@ -550,7 +544,7 @@ class StorageOptionDescription(StorageBase):
                 if _filter(path, option) is False:
                     continue
             if only_first:
-                return find_results[0]
+                return find_results
         return find_results
 
     def _impl_st_getchildren(self, context, only_dyn=False):
index 07f6787..bfa00ff 100644 (file)
@@ -36,9 +36,6 @@ class Properties(Cache):
     def getproperties(self, path, default_properties):
         return self._properties.get(path, set(default_properties))
 
-    def hasproperties(self, path):
-        return path in self._properties
-
     def reset_all_properties(self):
         self._properties.clear()
 
index e356b07..99edeaa 100644 (file)
@@ -15,7 +15,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 # ____________________________________________________________
 from ...i18n import _
-from ...error import ConfigError
+from ...error import ConfigError, ConflictError
 from ..util import SerializeObject
 
 
@@ -45,7 +45,7 @@ class Storage(object):
 
     def __init__(self, session_id, persistent, test=False):
         if not test and session_id in _list_sessions:  # pragma: optional cover
-            raise ValueError(_('session already used'))
+            raise ConflictError(_('session already used'))
         if persistent:  # pragma: optional cover
             raise ValueError(_('a dictionary cannot be persistent'))
         self.session_id = session_id
index 18c2eb2..4cd9c7f 100644 (file)
@@ -85,12 +85,6 @@ class Values(Cache):
         self._setvalue_info(3, idx, owner, values, index, vidx)
         self._values = tuple(values)
 
-    def getvalue(self, path, session, index=None):
-        """get value for a path
-        return: only value, not the owner
-        """
-        return self._getvalue(path, 2, index)
-
     def hasvalue(self, path, index=None):
         """if path has a value
         return: boolean
index 2923538..b39dd1e 100644 (file)
@@ -49,12 +49,6 @@ class Properties(Sqlite3DB):
         else:
             return set(self._sqlite_decode(value[0]))
 
-    def hasproperties(self, path):
-        path = self._sqlite_encode_path(path)
-        return self._storage.select("SELECT properties FROM property WHERE "
-                                    "path = ? AND session_id = ? LIMIT 1", (path, self._session_id)
-                                    ) is not None
-
     def reset_all_properties(self):
         self._storage.execute("DELETE FROM property WHERE session_id = ?", (self._session_id,))
 
index e9f5344..c381976 100644 (file)
@@ -72,16 +72,6 @@ class Values(Sqlite3DB):
                                                    self._session_id),
                                   commit=commit)
 
-    def getvalue(self, path, session, index=None):
-        """get value for an option
-        return: only value, not the owner
-        """
-        path = self._sqlite_encode_path(path)
-        values = self._sqlite_select(path, index)
-        if values is None:
-            return values
-        return self._sqlite_decode(values[0])
-
     def hasvalue(self, path, index=None):
         """if opt has a value
         return: boolean
index 1ea7fb1..52b0d59 100644 (file)
@@ -73,21 +73,13 @@ class Values(object):
                         raise value
                 else:
                     if isinstance(value, Multi):
-                        if index is not None:
-                            value = value[index]
-                            if isinstance(value, SubMulti):
-                                if submulti_index is not undefined:
-                                    value = value[submulti_index]
-                                else:
-                                    value = list(value)
-                        else:
-                            new_value = []
-                            for val in value:
-                                if isinstance(val, SubMulti):
-                                    val = list(val)
-                                new_value.append(val)
-                            value = new_value
-                            del new_value
+                        new_value = []
+                        for val in value:
+                            if isinstance(val, SubMulti):
+                                val = list(val)
+                            new_value.append(val)
+                        value = new_value
+                        del new_value
                     return value
         # if value has callback and is not set
         if opt.impl_has_callback():
@@ -230,12 +222,6 @@ class Values(object):
         "enables us to use the pythonic dictionary-like access to values"
         return self._get_cached_value(opt)
 
-    def getitem(self, opt, validate=True, force_permissive=False):
-        """
-        """
-        return self._get_cached_value(opt, validate=validate,
-                                      force_permissive=force_permissive)
-
     def _get_cached_value(self, opt, path=None, validate=True,
                           force_permissive=False, trusted_cached_properties=True,
                           validate_properties=True,
@@ -411,8 +397,6 @@ class Values(object):
         # user didn't change value, so not write
         # valid opt
         context = self._getcontext()
-        if _setting_properties is undefined:
-            _setting_properties = context.cfgimpl_get_settings()._getproperties(read_write=False)
         if 'validator' in _setting_properties:
             session = context.cfgimpl_get_values()._p_.getsession()
             if opt._has_consistencies():
@@ -476,12 +460,8 @@ class Values(object):
         if valid_masterslave and opt.impl_is_master_slaves():
             if session is None:
                 session = self._p_.getsession()
-            if index is not None:
-                len_value = index
-                setitem = False
-            else:
-                len_value = len(value)
-                setitem = True
+            len_value = len(value)
+            setitem = True
             val = opt.impl_get_master_slaves().validate(self, opt, len_value, path, session, setitem=setitem)
             if isinstance(val, Exception):
                 return val
@@ -502,8 +482,6 @@ class Values(object):
         context = self._getcontext()
         setting = context.cfgimpl_get_settings()
         self_properties = setting._getproperties(opt, path, read_write=False)
-        if 'frozen' in self_properties and 'force_default_on_freeze' in self_properties:
-            return False
         if self._p_.getowner(path, owners.default, session, only_default=True) is not owners.default:
             return False
         if context.cfgimpl_get_meta() is not None:
@@ -834,8 +812,6 @@ class Multi(list):
                 session = context.cfgimpl_get_values()._p_.getsession()
                 fake_context = context._gen_fake_values(session)
                 fake_multi = Multi(list(self), weakref.ref(fake_context), self.opt, self.path)
-                if isinstance(fake_multi, Exception):
-                    raise fake_multi
                 fake_multi.append(value, validate=False, force=True,
                                   setitem=setitem)
                 self._validate(value, fake_context, index, True)