Merge branch 'master' into orm
authorEmmanuel Garette <egarette@cadoles.com>
Sun, 2 Feb 2014 17:52:13 +0000 (18:52 +0100)
committerEmmanuel Garette <egarette@cadoles.com>
Sun, 2 Feb 2014 17:52:13 +0000 (18:52 +0100)
Conflicts:
test/test_dereference.py
test/test_state.py
tiramisu/config.py
tiramisu/value.py

1  2 
test/test_dereference.py
test/test_option_calculation.py
test/test_state.py
tiramisu/autolib.py
tiramisu/config.py
tiramisu/value.py

@@@ -117,5 -108,32 +117,33 @@@ def test_deref_optiondescription_config
      del(o)
      assert w() is not None
      del(c)
 -    assert w() is None
 +    #FIXME
 +    #assert w() is None
+ def test_deref_groupconfig():
+     i1 = IntOption('i1', '')
+     od1 = OptionDescription('od1', '', [i1])
+     od2 = OptionDescription('od2', '', [od1])
+     conf1 = Config(od2)
+     conf2 = Config(od2)
+     meta = GroupConfig([conf1, conf2])
+     w = weakref.ref(conf1)
+     del(conf1)
+     assert w() is not None
+     del(meta)
+     assert w() is None
+ def test_deref_metaconfig():
+     i1 = IntOption('i1', '')
+     od1 = OptionDescription('od1', '', [i1])
+     od2 = OptionDescription('od2', '', [od1])
+     conf1 = Config(od2)
+     conf2 = Config(od2)
+     meta = MetaConfig([conf1, conf2])
+     w = weakref.ref(conf1)
+     del(conf1)
+     assert w() is not None
+     del(meta)
+     assert w() is None
Simple merge
 -from tiramisu.option import BoolOption, UnicodeOption, SymLinkOption, \
 -    IntOption, OptionDescription
 -from tiramisu.config import Config, GroupConfig, MetaConfig
 -from tiramisu.setting import owners
 -from tiramisu.storage import delete_session
 -from tiramisu.error import ConfigError
 -from pickle import dumps, loads
 -from py.test import raises
 -
 -
 -def return_value(value=None):
 -        return value
 -
 -
 -def _get_slots(opt):
 -    slots = set()
 -    for subclass in opt.__class__.__mro__:
 -        if subclass is not object:
 -            slots.update(subclass.__slots__)
 -    return slots
 -
 -
 -def _no_state(opt):
 -    for attr in _get_slots(opt):
 -        if 'state' in attr:
 -            try:
 -                getattr(opt, attr)
 -            except:
 -                pass
 -            else:
 -                raise Exception('opt should have already attribute {0}'.format(attr))
 -
 -
 -def _diff_opt(opt1, opt2):
 -    attr1 = set(_get_slots(opt1))
 -    attr2 = set(_get_slots(opt2))
 -    diff1 = attr1 - attr2
 -    diff2 = attr2 - attr1
 -    if diff1 != set():
 -        raise Exception('more attribute in opt1 {0}'.format(list(diff1)))
 -    if diff2 != set():
 -        raise Exception('more attribute in opt2 {0}'.format(list(diff2)))
 -    for attr in attr1:
 -        if attr in ['_cache_paths', '_cache_consistencies']:
 -            continue
 -        err1 = False
 -        err2 = False
 -        val1 = None
 -        val2 = None
 -        try:
 -            val1 = getattr(opt1, attr)
 -        except:
 -            err1 = True
 -
 -        try:
 -            val2 = getattr(opt2, attr)
 -        except:
 -            err2 = True
 -        assert err1 == err2
 -        if val1 is None:
 -            assert val1 == val2
 -        elif attr == '_children':
 -            assert val1[0] == val2[0]
 -            for index, _opt in enumerate(val1[1]):
 -                assert _opt._name == val2[1][index]._name
 -        elif attr == '_requires':
 -            assert val1[0][0][0]._name == val2[0][0][0]._name
 -            assert val1[0][0][1:] == val2[0][0][1:]
 -        elif attr == '_opt':
 -            assert val1._name == val2._name
 -        elif attr == '_consistencies':
 -            # dict is only a cache
 -            if isinstance(val1, list):
 -                for index, consistency in enumerate(val1):
 -                    assert consistency[0] == val2[index][0]
 -                    for idx, opt in enumerate(consistency[1]):
 -                        assert opt._name == val2[index][1][idx]._name
 -        elif attr == '_callback':
 -            assert val1[0] == val2[0]
 -            if val1[1] is not None:
 -                for key, values in val1[1].items():
 -                    for idx, value in enumerate(values):
 -                        if isinstance(value, tuple):
 -                            assert val1[1][key][idx][0]._name == val2[1][key][idx][0]._name
 -                            assert val1[1][key][idx][1] == val2[1][key][idx][1]
 -                        else:
 -                            assert val1[1][key][idx] == val2[1][key][idx]
 -            else:
 -                assert val1[1] == val2[1]
 -        else:
 -            assert val1 == val2
 -
 -
 -def _diff_conf(cfg1, cfg2):
 -    attr1 = set(_get_slots(cfg1))
 -    attr2 = set(_get_slots(cfg2))
 -    diff1 = attr1 - attr2
 -    diff2 = attr2 - attr1
 -    if diff1 != set():
 -        raise Exception('more attribute in cfg1 {0}'.format(list(diff1)))
 -    if diff2 != set():
 -        raise Exception('more attribute in cfg2 {0}'.format(list(diff2)))
 -    for attr in attr1:
 -        if attr in ('_impl_context', '__weakref__'):
 -            continue
 -        err1 = False
 -        err2 = False
 -        val1 = None
 -        val2 = None
 -        try:
 -            val1 = getattr(cfg1, attr)
 -        except:
 -            err1 = True
 -
 -        try:
 -            val2 = getattr(cfg2, attr)
 -        except:
 -            err2 = True
 -        assert err1 == err2
 -        if val1 is None:
 -            assert val1 == val2
 -        elif attr == '_impl_values':
 -            assert cfg1.cfgimpl_get_values().get_modified_values() == cfg2.cfgimpl_get_values().get_modified_values()
 -        elif attr == '_impl_settings':
 -            assert cfg1.cfgimpl_get_settings().get_modified_properties() == cfg2.cfgimpl_get_settings().get_modified_properties()
 -            assert cfg1.cfgimpl_get_settings().get_modified_permissives() == cfg2.cfgimpl_get_settings().get_modified_permissives()
 -        elif attr == '_impl_descr':
 -            _diff_opt(cfg1.cfgimpl_get_description(), cfg2.cfgimpl_get_description())
 -        else:
 -            assert val1 == val2
 -
 -
 -def test_diff_opt():
 -    b = BoolOption('b', '')
 -    u = UnicodeOption('u', '', requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}])
 -    #u.impl_add_consistency('not_equal', b)
 -    s = SymLinkOption('s', u)
 -    o = OptionDescription('o', '', [b, u, s])
 -    o1 = OptionDescription('o1', '', [o])
 -
 -    a = dumps(o1)
 -    q = loads(a)
 -    _diff_opt(o1, q)
 -    _diff_opt(o1.o, q.o)
 -    _diff_opt(o1.o.b, q.o.b)
 -    _diff_opt(o1.o.u, q.o.u)
 -    _diff_opt(o1.o.s, q.o.s)
 -
 -
 -def test_diff_opt_cache():
 -    b = BoolOption('b', '')
 -    u = UnicodeOption('u', '', requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}])
 -    u.impl_add_consistency('not_equal', b)
 -    s = SymLinkOption('s', u)
 -    o = OptionDescription('o', '', [b, u, s])
 -    o1 = OptionDescription('o1', '', [o])
 -    o1.impl_build_cache()
 -
 -    a = dumps(o1)
 -    q = loads(a)
 -    _diff_opt(o1, q)
 -    _diff_opt(o1.o, q.o)
 -    _diff_opt(o1.o.b, q.o.b)
 -    _diff_opt(o1.o.u, q.o.u)
 -    _diff_opt(o1.o.s, q.o.s)
 -
 -
 -def test_diff_opt_callback():
 -    b = BoolOption('b', '', callback=return_value)
 -    b2 = BoolOption('b2', '', callback=return_value, callback_params={'': ('yes',)})
 -    b3 = BoolOption('b3', '', callback=return_value, callback_params={'': ('yes', (b, False)), 'value': ('no',)})
 -    o = OptionDescription('o', '', [b, b2, b3])
 -    o1 = OptionDescription('o1', '', [o])
 -    o1.impl_build_cache()
 -
 -    a = dumps(o1)
 -    q = loads(a)
 -    _diff_opt(o1, q)
 -    _diff_opt(o1.o, q.o)
 -    _diff_opt(o1.o.b, q.o.b)
 -    _diff_opt(o1.o.b2, q.o.b2)
 -    _diff_opt(o1.o.b3, q.o.b3)
 -
 -
 -def test_no_state_attr():
 -    # all _state_xxx attributes should be deleted
 -    b = BoolOption('b', '')
 -    u = UnicodeOption('u', '', requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}])
 -    s = SymLinkOption('s', u)
 -    o = OptionDescription('o', '', [b, u, s])
 -    o1 = OptionDescription('o1', '', [o])
 -
 -    a = dumps(o1)
 -    q = loads(a)
 -    _no_state(q)
 -    _no_state(q.o)
 -    _no_state(q.o.b)
 -    _no_state(q.o.u)
 -    _no_state(q.o.s)
 -
 -
 -def test_state_config():
 -    val1 = BoolOption('val1', "")
 -    maconfig = OptionDescription('rootconfig', '', [val1])
 -    try:
 -        cfg = Config(maconfig, persistent=True, session_id='29090931')
 -    except ValueError:
 -        cfg = Config(maconfig, session_id='29090931')
 -        cfg._impl_test = True
 -    a = dumps(cfg)
 -    q = loads(a)
 -    _diff_conf(cfg, q)
 -    try:
 -        delete_session('29090931')
 -    except ConfigError:
 -        pass
 -
 -
 -def test_state_properties():
 -    val1 = BoolOption('val1', "")
 -    maconfig = OptionDescription('rootconfig', '', [val1])
 -    try:
 -        cfg = Config(maconfig, persistent=True, session_id='29090932')
 -    except ValueError:
 -        cfg = Config(maconfig, session_id='29090932')
 -        cfg._impl_test = True
 -    cfg.read_write()
 -    cfg.cfgimpl_get_settings()[val1].append('test')
 -    a = dumps(cfg)
 -    q = loads(a)
 -    _diff_conf(cfg, q)
 -    try:
 -        delete_session('29090932')
 -    except ConfigError:
 -        pass
 -
 -
 -def test_state_values():
 -    val1 = BoolOption('val1', "")
 -    maconfig = OptionDescription('rootconfig', '', [val1])
 -    try:
 -        cfg = Config(maconfig, persistent=True, session_id='29090933')
 -    except ValueError:
 -        cfg = Config(maconfig, session_id='29090933')
 -        cfg._impl_test = True
 -    cfg.val1 = True
 -    a = dumps(cfg)
 -    q = loads(a)
 -    _diff_conf(cfg, q)
 -    q.val1 = False
 -    #assert cfg.val1 is True
 -    assert q.val1 is False
 -    try:
 -        delete_session('29090933')
 -    except ConfigError:
 -        pass
 -
 -
 -def test_state_values_owner():
 -    val1 = BoolOption('val1', "")
 -    maconfig = OptionDescription('rootconfig', '', [val1])
 -    try:
 -        cfg = Config(maconfig, persistent=True, session_id='29090934')
 -    except ValueError:
 -        cfg = Config(maconfig, session_id='29090934')
 -        cfg._impl_test = True
 -    owners.addowner('newowner')
 -    cfg.cfgimpl_get_settings().setowner(owners.newowner)
 -    cfg.val1 = True
 -    a = dumps(cfg)
 -    q = loads(a)
 -    _diff_conf(cfg, q)
 -    q.val1 = False
 -    nval1 = q.cfgimpl_get_description().val1
 -    assert q.getowner(nval1) == owners.newowner
 -    try:
 -        delete_session('29090934')
 -    except ConfigError:
 -        pass
 -
 -
 -def test_state_metaconfig():
 -    i1 = IntOption('i1', '')
 -    od1 = OptionDescription('od1', '', [i1])
 -    od2 = OptionDescription('od2', '', [od1])
 -    conf1 = Config(od2, session_id='29090935')
 -    conf1._impl_test = True
 -    conf2 = Config(od2, session_id='29090936')
 -    conf2._impl_test = True
 -    meta = MetaConfig([conf1, conf2], session_id='29090937')
 -    meta._impl_test = True
 -    raises(ConfigError, "dumps(meta)")
 -    try:
 -        delete_session('29090935')
 -        delete_session('29090936')
 -        delete_session('29090937')
 -    except ConfigError:
 -        pass
 -
 -
 -def test_state_groupconfig():
 -    i1 = IntOption('i1', '')
 -    od1 = OptionDescription('od1', '', [i1])
 -    od2 = OptionDescription('od2', '', [od1])
 -    conf1 = Config(od2, session_id='29090935')
 -    conf1._impl_test = True
 -    conf2 = Config(od2, session_id='29090936')
 -    conf2._impl_test = True
 -    meta = GroupConfig([conf1, conf2], session_id='29090937')
 -    meta._impl_test = True
 -    a = dumps(meta)
 -    q = loads(a)
 -    _diff_conf(meta, q)
 -    try:
 -        delete_session('29090935')
 -        delete_session('29090936')
 -        delete_session('29090937')
 -    except ConfigError:
 -        pass
 -
 -
 -def test_state_unkown_setting_owner():
 -    """load an unknow _owner, should create it"""
 -    assert not 'supernewuser' in owners.__dict__
 -    loads("""ccopy_reg
 -_reconstructor
 -p0
 -(ctiramisu.setting
 -Settings
 -p1
 -c__builtin__
 -object
 -p2
 -Ntp3
 -Rp4
 -(dp5
 -S'_owner'
 -p6
 -S'supernewuser'
 -p7
 -sS'_p_'
 -p8
 -g0
 -(ctiramisu.storage.dictionary.setting
 -Settings
 -p9
 -g2
 -Ntp10
 -Rp11
 -(dp12
 -S'_cache'
 -p13
 -(dp14
 -sS'_permissives'
 -p15
 -(dp16
 -sS'_properties'
 -p17
 -(dp18
 -sbsb.
 -.""")
 -    assert 'supernewuser' in owners.__dict__
 +#from tiramisu.option import BoolOption, UnicodeOption, SymLinkOption, \
- #    OptionDescription
- #from tiramisu.config import Config
++#    IntOption, OptionDescription
++#from tiramisu.config import Config, GroupConfig, MetaConfig
 +#from tiramisu.setting import owners
 +#from tiramisu.storage import delete_session
 +#from tiramisu.error import ConfigError
 +#from pickle import dumps, loads
++#from py.test import raises
 +#
 +#
 +#def return_value(value=None):
 +#        return value
 +#
 +#
 +#def _get_slots(opt):
 +#    slots = set()
 +#    for subclass in opt.__class__.__mro__:
 +#        if subclass is not object:
 +#            slots.update(subclass.__slots__)
 +#    return slots
 +#
 +#
 +#def _no_state(opt):
 +#    for attr in _get_slots(opt):
 +#        if 'state' in attr:
 +#            try:
 +#                getattr(opt, attr)
 +#            except:
 +#                pass
 +#            else:
 +#                raise Exception('opt should have already attribute {0}'.format(attr))
 +#
 +#
 +#def _diff_opt(opt1, opt2):
 +#    attr1 = set(_get_slots(opt1))
 +#    attr2 = set(_get_slots(opt2))
 +#    diff1 = attr1 - attr2
 +#    diff2 = attr2 - attr1
 +#    if diff1 != set():
 +#        raise Exception('more attribute in opt1 {0}'.format(list(diff1)))
 +#    if diff2 != set():
 +#        raise Exception('more attribute in opt2 {0}'.format(list(diff2)))
 +#    for attr in attr1:
 +#        if attr in ['_cache_paths', '_cache_consistencies']:
 +#            continue
 +#        err1 = False
 +#        err2 = False
 +#        val1 = None
 +#        val2 = None
 +#        try:
 +#            val1 = getattr(opt1, attr)
 +#        except:
 +#            err1 = True
 +#
 +#        try:
 +#            val2 = getattr(opt2, attr)
 +#        except:
 +#            err2 = True
 +#        assert err1 == err2
 +#        if val1 is None:
 +#            assert val1 == val2
 +#        elif attr == '_children':
 +#            assert val1[0] == val2[0]
 +#            for index, _opt in enumerate(val1[1]):
 +#                assert _opt._name == val2[1][index]._name
 +#        elif attr == '_requires':
 +#            assert val1[0][0][0]._name == val2[0][0][0]._name
 +#            assert val1[0][0][1:] == val2[0][0][1:]
 +#        elif attr == '_opt':
 +#            assert val1._name == val2._name
 +#        elif attr == '_consistencies':
 +#            # dict is only a cache
 +#            if isinstance(val1, list):
 +#                for index, consistency in enumerate(val1):
 +#                    assert consistency[0] == val2[index][0]
 +#                    for idx, opt in enumerate(consistency[1]):
 +#                        assert opt._name == val2[index][1][idx]._name
 +#        elif attr == '_callback':
 +#            assert val1[0] == val2[0]
 +#            if val1[1] is not None:
 +#                for key, values in val1[1].items():
 +#                    for idx, value in enumerate(values):
 +#                        if isinstance(value, tuple):
 +#                            assert val1[1][key][idx][0]._name == val2[1][key][idx][0]._name
 +#                            assert val1[1][key][idx][1] == val2[1][key][idx][1]
 +#                        else:
 +#                            assert val1[1][key][idx] == val2[1][key][idx]
 +#            else:
 +#                assert val1[1] == val2[1]
 +#        else:
 +#            assert val1 == val2
 +#
 +#
++#def _diff_conf(cfg1, cfg2):
++#    attr1 = set(_get_slots(cfg1))
++#    attr2 = set(_get_slots(cfg2))
++#    diff1 = attr1 - attr2
++#    diff2 = attr2 - attr1
++#    if diff1 != set():
++#        raise Exception('more attribute in cfg1 {0}'.format(list(diff1)))
++#    if diff2 != set():
++#        raise Exception('more attribute in cfg2 {0}'.format(list(diff2)))
++#    for attr in attr1:
++#        if attr in ('_impl_context', '__weakref__'):
++#            continue
++#        err1 = False
++#        err2 = False
++#        val1 = None
++#        val2 = None
++#        try:
++#            val1 = getattr(cfg1, attr)
++#        except:
++#            err1 = True
++#
++#        try:
++#            val2 = getattr(cfg2, attr)
++#        except:
++#            err2 = True
++#        assert err1 == err2
++#        if val1 is None:
++#            assert val1 == val2
++#        elif attr == '_impl_values':
++#            assert cfg1.cfgimpl_get_values().get_modified_values() == cfg2.cfgimpl_get_values().get_modified_values()
++#        elif attr == '_impl_settings':
++#            assert cfg1.cfgimpl_get_settings().get_modified_properties() == cfg2.cfgimpl_get_settings().get_modified_properties()
++#            assert cfg1.cfgimpl_get_settings().get_modified_permissives() == cfg2.cfgimpl_get_settings().get_modified_permissives()
++#        elif attr == '_impl_descr':
++#            _diff_opt(cfg1.cfgimpl_get_description(), cfg2.cfgimpl_get_description())
++#        else:
++#            assert val1 == val2
++#
++#
 +#def test_diff_opt():
 +#    b = BoolOption('b', '')
 +#    u = UnicodeOption('u', '', requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}])
 +#    #u.impl_add_consistency('not_equal', b)
 +#    s = SymLinkOption('s', u)
 +#    o = OptionDescription('o', '', [b, u, s])
 +#    o1 = OptionDescription('o1', '', [o])
 +#
 +#    a = dumps(o1)
 +#    q = loads(a)
 +#    _diff_opt(o1, q)
 +#    _diff_opt(o1.o, q.o)
 +#    _diff_opt(o1.o.b, q.o.b)
 +#    _diff_opt(o1.o.u, q.o.u)
 +#    _diff_opt(o1.o.s, q.o.s)
 +#
 +#
 +#def test_diff_opt_cache():
 +#    b = BoolOption('b', '')
 +#    u = UnicodeOption('u', '', requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}])
 +#    u.impl_add_consistency('not_equal', b)
 +#    s = SymLinkOption('s', u)
 +#    o = OptionDescription('o', '', [b, u, s])
 +#    o1 = OptionDescription('o1', '', [o])
 +#    o1.impl_build_cache()
 +#
 +#    a = dumps(o1)
 +#    q = loads(a)
 +#    _diff_opt(o1, q)
 +#    _diff_opt(o1.o, q.o)
 +#    _diff_opt(o1.o.b, q.o.b)
 +#    _diff_opt(o1.o.u, q.o.u)
 +#    _diff_opt(o1.o.s, q.o.s)
 +#
 +#
 +#def test_diff_opt_callback():
 +#    b = BoolOption('b', '', callback=return_value)
 +#    b2 = BoolOption('b2', '', callback=return_value, callback_params={'': ('yes',)})
 +#    b3 = BoolOption('b3', '', callback=return_value, callback_params={'': ('yes', (b, False)), 'value': ('no',)})
 +#    o = OptionDescription('o', '', [b, b2, b3])
 +#    o1 = OptionDescription('o1', '', [o])
 +#    o1.impl_build_cache()
 +#
 +#    a = dumps(o1)
 +#    q = loads(a)
 +#    _diff_opt(o1, q)
 +#    _diff_opt(o1.o, q.o)
 +#    _diff_opt(o1.o.b, q.o.b)
 +#    _diff_opt(o1.o.b2, q.o.b2)
 +#    _diff_opt(o1.o.b3, q.o.b3)
 +#
 +#
 +#def test_no_state_attr():
 +#    # all _state_xxx attributes should be deleted
 +#    b = BoolOption('b', '')
 +#    u = UnicodeOption('u', '', requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}])
 +#    s = SymLinkOption('s', u)
 +#    o = OptionDescription('o', '', [b, u, s])
 +#    o1 = OptionDescription('o1', '', [o])
 +#
 +#    a = dumps(o1)
 +#    q = loads(a)
 +#    _no_state(q)
 +#    _no_state(q.o)
 +#    _no_state(q.o.b)
 +#    _no_state(q.o.u)
 +#    _no_state(q.o.s)
 +#
 +#
 +#def test_state_config():
 +#    val1 = BoolOption('val1', "")
 +#    maconfig = OptionDescription('rootconfig', '', [val1])
 +#    try:
 +#        cfg = Config(maconfig, persistent=True, session_id='29090931')
 +#    except ValueError:
 +#        cfg = Config(maconfig, session_id='29090931')
 +#        cfg._impl_test = True
 +#    a = dumps(cfg)
 +#    q = loads(a)
- #    _diff_opt(maconfig, q.cfgimpl_get_description())
- #    assert cfg.cfgimpl_get_values().get_modified_values() == q.cfgimpl_get_values().get_modified_values()
- #    assert cfg.cfgimpl_get_settings().get_modified_properties() == q.cfgimpl_get_settings().get_modified_properties()
- #    assert cfg.cfgimpl_get_settings().get_modified_permissives() == q.cfgimpl_get_settings().get_modified_permissives()
++#    _diff_conf(cfg, q)
 +#    try:
 +#        delete_session('29090931')
 +#    except ConfigError:
 +#        pass
 +#
 +#
 +#def test_state_properties():
 +#    val1 = BoolOption('val1', "")
 +#    maconfig = OptionDescription('rootconfig', '', [val1])
 +#    try:
 +#        cfg = Config(maconfig, persistent=True, session_id='29090932')
 +#    except ValueError:
 +#        cfg = Config(maconfig, session_id='29090932')
 +#        cfg._impl_test = True
 +#    cfg.read_write()
 +#    cfg.cfgimpl_get_settings()[val1].append('test')
 +#    a = dumps(cfg)
 +#    q = loads(a)
- #    _diff_opt(maconfig, q.cfgimpl_get_description())
- #    assert cfg.cfgimpl_get_values().get_modified_values() == q.cfgimpl_get_values().get_modified_values()
- #    assert cfg.cfgimpl_get_settings().get_modified_properties() == q.cfgimpl_get_settings().get_modified_properties()
- #    assert cfg.cfgimpl_get_settings().get_modified_permissives() == q.cfgimpl_get_settings().get_modified_permissives()
++#    _diff_conf(cfg, q)
 +#    try:
- #        delete_session('29090931')
++#        delete_session('29090932')
 +#    except ConfigError:
 +#        pass
 +#
 +#
 +#def test_state_values():
 +#    val1 = BoolOption('val1', "")
 +#    maconfig = OptionDescription('rootconfig', '', [val1])
 +#    try:
 +#        cfg = Config(maconfig, persistent=True, session_id='29090933')
 +#    except ValueError:
 +#        cfg = Config(maconfig, session_id='29090933')
 +#        cfg._impl_test = True
 +#    cfg.val1 = True
 +#    a = dumps(cfg)
 +#    q = loads(a)
- #    _diff_opt(maconfig, q.cfgimpl_get_description())
- #    assert cfg.cfgimpl_get_values().get_modified_values() == q.cfgimpl_get_values().get_modified_values()
- #    assert cfg.cfgimpl_get_settings().get_modified_properties() == q.cfgimpl_get_settings().get_modified_properties()
- #    assert cfg.cfgimpl_get_settings().get_modified_permissives() == q.cfgimpl_get_settings().get_modified_permissives()
++#    _diff_conf(cfg, q)
 +#    q.val1 = False
 +#    #assert cfg.val1 is True
 +#    assert q.val1 is False
 +#    try:
- #        delete_session('29090931')
++#        delete_session('29090933')
 +#    except ConfigError:
 +#        pass
 +#
 +#
 +#def test_state_values_owner():
 +#    val1 = BoolOption('val1', "")
 +#    maconfig = OptionDescription('rootconfig', '', [val1])
 +#    try:
 +#        cfg = Config(maconfig, persistent=True, session_id='29090934')
 +#    except ValueError:
 +#        cfg = Config(maconfig, session_id='29090934')
 +#        cfg._impl_test = True
 +#    owners.addowner('newowner')
 +#    cfg.cfgimpl_get_settings().setowner(owners.newowner)
 +#    cfg.val1 = True
 +#    a = dumps(cfg)
 +#    q = loads(a)
- #    _diff_opt(maconfig, q.cfgimpl_get_description())
- #    assert cfg.cfgimpl_get_values().get_modified_values() == q.cfgimpl_get_values().get_modified_values()
- #    assert cfg.cfgimpl_get_settings().get_modified_properties() == q.cfgimpl_get_settings().get_modified_properties()
- #    assert cfg.cfgimpl_get_settings().get_modified_permissives() == q.cfgimpl_get_settings().get_modified_permissives()
++#    _diff_conf(cfg, q)
 +#    q.val1 = False
 +#    nval1 = q.cfgimpl_get_description().val1
 +#    assert q.getowner(nval1) == owners.newowner
 +#    try:
- #        delete_session('29090931')
++#        delete_session('29090934')
++#    except ConfigError:
++#        pass
++#
++#
++#def test_state_metaconfig():
++#    i1 = IntOption('i1', '')
++#    od1 = OptionDescription('od1', '', [i1])
++#    od2 = OptionDescription('od2', '', [od1])
++#    conf1 = Config(od2, session_id='29090935')
++#    conf1._impl_test = True
++#    conf2 = Config(od2, session_id='29090936')
++#    conf2._impl_test = True
++#    meta = MetaConfig([conf1, conf2], session_id='29090937')
++#    meta._impl_test = True
++#    raises(ConfigError, "dumps(meta)")
++#    try:
++#        delete_session('29090935')
++#        delete_session('29090936')
++#        delete_session('29090937')
++#    except ConfigError:
++#        pass
++#
++#
++#def test_state_groupconfig():
++#    i1 = IntOption('i1', '')
++#    od1 = OptionDescription('od1', '', [i1])
++#    od2 = OptionDescription('od2', '', [od1])
++#    conf1 = Config(od2, session_id='29090935')
++#    conf1._impl_test = True
++#    conf2 = Config(od2, session_id='29090936')
++#    conf2._impl_test = True
++#    meta = GroupConfig([conf1, conf2], session_id='29090937')
++#    meta._impl_test = True
++#    a = dumps(meta)
++#    q = loads(a)
++#    _diff_conf(meta, q)
++#    try:
++#        delete_session('29090935')
++#        delete_session('29090936')
++#        delete_session('29090937')
 +#    except ConfigError:
 +#        pass
++#
++#
++#def test_state_unkown_setting_owner():
++#    """load an unknow _owner, should create it"""
++#    assert not 'supernewuser' in owners.__dict__
++#    loads("""ccopy_reg
++#_reconstructor
++#p0
++#(ctiramisu.setting
++#Settings
++#p1
++#c__builtin__
++#object
++#p2
++#Ntp3
++#Rp4
++#(dp5
++#S'_owner'
++#p6
++#S'supernewuser'
++#p7
++#sS'_p_'
++#p8
++#g0
++#(ctiramisu.storage.dictionary.setting
++#Settings
++#p9
++#g2
++#Ntp10
++#Rp11
++#(dp12
++#S'_cache'
++#p13
++#(dp14
++#sS'_permissives'
++#p15
++#(dp16
++#sS'_properties'
++#p17
++#(dp18
++#sbsb.
++#.""")
++#    assert 'supernewuser' in owners.__dict__
Simple merge
@@@ -459,15 -477,12 +459,15 @@@ class SubConfig(object)
          return context_descr.impl_get_path_by_opt(descr)
  
  
- class CommonConfig(SubConfig):
-     "abstract base class for the Config and the MetaConfig"
-     __slots__ = ('_impl_values', '_impl_settings', '_impl_meta')
+ class _CommonConfig(SubConfig):
+     "abstract base class for the Config, GroupConfig and the MetaConfig"
+     __slots__ = ('_impl_values', '_impl_settings', '_impl_meta', '_impl_test')
  
 -    def _impl_build_all_paths(self):
 -        self.cfgimpl_get_description().impl_build_cache()
 +    def _impl_build_all_caches(self):
 +        if not self.cfgimpl_get_description().impl_already_build_caches():
 +            self.cfgimpl_get_description().impl_build_cache_consistency()
 +            self.cfgimpl_get_description().impl_validate_options()
 +            self.cfgimpl_get_description().impl_build_cache_option()
  
      def read_only(self):
          "read only is a global config's setting, see `settings.py`"
          storage = get_storage(test=self._impl_test, **state['_storage'])
          self._impl_values._impl_setstate(storage)
          self._impl_settings._impl_setstate(storage)
 -    __slots__ = ('__weakref__',)
+         self._impl_meta = None
+ # ____________________________________________________________
+ class Config(_CommonConfig):
+     "main configuration management entry"
 -        self._impl_build_all_paths()
++    __slots__ = ('__weakref__', '_impl_test')
+     def __init__(self, descr, session_id=None, persistent=False):
+         """ Configuration option management master class
+         :param descr: describes the configuration schema
+         :type descr: an instance of ``option.OptionDescription``
+         :param context: the current root config
+         :type context: `Config`
+         :param session_id: session ID is import with persistent Config to
+         retrieve good session
+         :type session_id: `str`
+         :param persistent: if persistent, don't delete storage when leaving
+         :type persistent: `boolean`
+         """
+         settings, values = get_storages(self, session_id, persistent)
+         self._impl_settings = Settings(self, settings)
+         self._impl_values = Values(self, values)
+         super(Config, self).__init__(descr, weakref.ref(self))
++        self._impl_build_all_caches()
+         self._impl_meta = None
+         #undocumented option used only in test script
+         self._impl_test = False
+     def cfgimpl_reset_cache(self,
+                             only_expired=False,
+                             only=('values', 'settings')):
+         if 'values' in only:
+             self.cfgimpl_get_values().reset_cache(only_expired=only_expired)
+         if 'settings' in only:
+             self.cfgimpl_get_settings().reset_cache(only_expired=only_expired)
+ class GroupConfig(_CommonConfig):
+     __slots__ = ('_impl_children', '__weakref__')
  
+     def __init__(self, children, session_id=None, persistent=False,
+                  _descr=None):
+         if not isinstance(children, list):
+             raise ValueError(_("metaconfig's children must be a list"))
+         self._impl_children = children
+         settings, values = get_storages(self, session_id, persistent)
+         self._impl_settings = Settings(self, settings)
+         self._impl_values = Values(self, values)
+         super(GroupConfig, self).__init__(_descr, weakref.ref(self))
+         self._impl_meta = None
+         #undocumented option used only in test script
+         self._impl_test = False
+     def cfgimpl_get_children(self):
+         return self._impl_children
+     #def cfgimpl_get_context(self):
+     #    "a meta config is a config which has a setting, that is itself"
+     #    return self
+     #
      def cfgimpl_reset_cache(self,
                              only_expired=False,
                              only=('values', 'settings')):
@@@ -433,15 -453,13 +453,13 @@@ class Multi(list)
          values = context.cfgimpl_get_values()
          masterp = context.cfgimpl_get_description().impl_get_path_by_opt(
              self.opt.impl_get_master_slaves())
-         mastervalue = getattr(context, masterp)
+         mastervalue = context._getattr(masterp, validate=False)
          masterlen = len(mastervalue)
          valuelen = len(value)
-         is_default_owner = not values._is_default_owner(self.path) or setitem
-         if valuelen > masterlen or (valuelen < masterlen and
-                                     is_default_owner):
+         if valuelen > masterlen or (valuelen < masterlen and setitem):
              raise SlaveError(_("invalid len for the slave: {0}"
                                 " which has {1} as master").format(
 -                                   self.opt._name, masterp))
 +                                   self.opt.impl_getname(), masterp))
          elif valuelen < masterlen:
              for num in range(0, masterlen - valuelen):
                  if self.opt.impl_has_callback():