better sqlalchemy integration
authorEmmanuel Garette <egarette@cadoles.com>
Fri, 30 Sep 2016 20:45:33 +0000 (22:45 +0200)
committerEmmanuel Garette <egarette@cadoles.com>
Fri, 30 Sep 2016 20:45:33 +0000 (22:45 +0200)
14 files changed:
test/test_dyn_optiondescription.py
test/test_mandatory.py
test/test_slots.py
test/test_state.py
tiramisu/config.py
tiramisu/option/baseoption.py
tiramisu/option/masterslave.py
tiramisu/option/option.py
tiramisu/option/optiondescription.py
tiramisu/storage/__init__.py
tiramisu/storage/dictionary/__init__.py
tiramisu/storage/dictionary/option.py
tiramisu/storage/sqlalchemy/__init__.py
tiramisu/storage/sqlalchemy/option.py

index d5796a6..12d45b3 100644 (file)
@@ -1293,10 +1293,10 @@ def test_state_config():
     except ValueError:
         cfg = Config(od2, session_id='29090938')
         cfg._impl_test = True
-    a = dumps(cfg)
-    q = loads(a)
-    _diff_opts(cfg.cfgimpl_get_description(), q.cfgimpl_get_description())
-    _diff_conf(cfg, q)
+        a = dumps(cfg)
+        q = loads(a)
+        _diff_opts(cfg.cfgimpl_get_description(), q.cfgimpl_get_description())
+        _diff_conf(cfg, q)
 
     try:
         delete_session('config', '29090938')
index ee04be2..6ed8084 100644 (file)
@@ -82,7 +82,7 @@ def make_description4():
 
 def test_mandatory_ro():
     descr = make_description()
-    config = Config(descr)
+    config = Config(descr, session_id='man001')
     config.read_only()
     prop = []
     try:
@@ -94,21 +94,31 @@ def test_mandatory_ro():
     config.str1 = 'yes'
     config.read_only()
     assert config.str1 == 'yes'
+    try:
+        delete_session('config', config.impl_getsessionid())
+    except ValueError:
+        pass
+    del(config)
 
 
 def test_mandatory_rw():
     descr = make_description()
-    config = Config(descr)
+    config = Config(descr, session_id='man002')
     config.read_write()
     #not mandatory in rw
     config.str1
     config.str1 = 'yes'
     assert config.str1 == 'yes'
+    try:
+        delete_session('config', config.impl_getsessionid())
+    except ValueError:
+        pass
+    del(config)
 
 
 def test_mandatory_default():
     descr = make_description()
-    config = Config(descr)
+    config = Config(descr, session_id='man003')
     config.read_only()
     #not mandatory in rw
     config.str
@@ -125,11 +135,16 @@ def test_mandatory_default():
     except PropertiesOptionError as err:
         prop = err.proptype
     assert 'mandatory' in prop
+    try:
+        delete_session('config', config.impl_getsessionid())
+    except ValueError:
+        pass
+    del(config)
 
 
 def test_mandatory_delete():
     descr = make_description()
-    config = Config(descr)
+    config = Config(descr, session_id='man004')
     config.read_only()
     config.str
     try:
@@ -150,12 +165,17 @@ def test_mandatory_delete():
     assert 'mandatory' in prop
     del(config.str)
     assert config.str1 == 'yes'
+    try:
+        delete_session('config', config.impl_getsessionid())
+    except ValueError:
+        pass
+    del(config)
 
 
 #valeur vide : None, '', u'', ...
 def test_mandatory_none():
     descr = make_description()
-    config = Config(descr)
+    config = Config(descr, session_id='man005')
     config.str1 = None
     assert config.getowner(config.unwrap_from_path('str1')) == 'user'
     config.read_only()
@@ -165,11 +185,16 @@ def test_mandatory_none():
     except PropertiesOptionError as err:
         prop = err.proptype
     assert 'mandatory' in prop
+    try:
+        delete_session('config', config.impl_getsessionid())
+    except ValueError:
+        pass
+    del(config)
 
 
 def test_mandatory_empty():
     descr = make_description()
-    config = Config(descr)
+    config = Config(descr, session_id='man006')
     config.str1 = ''
     assert config.getowner(config.unwrap_from_path('str1')) == 'user'
     config.read_only()
@@ -179,11 +204,16 @@ def test_mandatory_empty():
     except PropertiesOptionError as err:
         prop = err.proptype
     assert 'mandatory' in prop
+    try:
+        delete_session('config', config.impl_getsessionid())
+    except ValueError:
+        pass
+    del(config)
 
 
 def test_mandatory_multi_none():
     descr = make_description()
-    config = Config(descr)
+    config = Config(descr, session_id='man007')
     config.str3 = [None]
     assert config.getowner(config.unwrap_from_path('str3')) == 'user'
     config.read_only()
@@ -203,11 +233,16 @@ def test_mandatory_multi_none():
     except PropertiesOptionError as err:
         prop = err.proptype
     assert 'mandatory' in prop
+    try:
+        delete_session('config', config.impl_getsessionid())
+    except ValueError:
+        pass
+    del(config)
 
 
 def test_mandatory_multi_empty():
     descr = make_description()
-    config = Config(descr)
+    config = Config(descr, session_id='man008')
     config.str3 = []
     assert config.getowner(config.unwrap_from_path('str3')) == 'user'
     config.read_only()
@@ -239,11 +274,16 @@ def test_mandatory_multi_empty():
     except PropertiesOptionError as err:
         prop = err.proptype
     assert 'mandatory' in prop
+    try:
+        delete_session('config', config.impl_getsessionid())
+    except ValueError:
+        pass
+    del(config)
 
 
 def test_mandatory_multi_empty_allow_empty_list():
     descr = make_description()
-    config = Config(descr)
+    config = Config(descr, session_id='man009')
     config.str4 = []
     assert config.getowner(config.unwrap_from_path('str4')) == 'user'
     config.read_only()
@@ -271,19 +311,29 @@ def test_mandatory_multi_empty_allow_empty_list():
     except PropertiesOptionError as err:
         prop = err.proptype
     assert 'mandatory' in prop
+    try:
+        delete_session('config', config.impl_getsessionid())
+    except ValueError:
+        pass
+    del(config)
 
 
 def test_mandatory_multi_append():
     descr = make_description()
-    config = Config(descr)
+    config = Config(descr, session_id='man010')
     config.str3 = ['yes']
     config.read_write()
     config.str3.append(None)
+    try:
+        delete_session('config', config.impl_getsessionid())
+    except ValueError:
+        pass
+    del(config)
 
 
 def test_mandatory_disabled():
     descr = make_description()
-    config = Config(descr)
+    config = Config(descr, session_id='man011')
     setting = config.cfgimpl_get_settings()
     config.str1
     config.read_only()
@@ -300,11 +350,16 @@ def test_mandatory_disabled():
     except PropertiesOptionError as err:
         prop = err.proptype
     assert set(prop) == set(['disabled', 'mandatory'])
+    try:
+        delete_session('config', config.impl_getsessionid())
+    except ValueError:
+        pass
+    del(config)
 
 
 def test_mandatory_unicode():
     descr = make_description()
-    config = Config(descr)
+    config = Config(descr, session_id='man012')
     config.unicode2
     config.read_only()
     prop = []
@@ -322,11 +377,16 @@ def test_mandatory_unicode():
     except PropertiesOptionError as err:
         prop = err.proptype
     assert prop == ['mandatory']
+    try:
+        delete_session('config', config.impl_getsessionid())
+    except ValueError:
+        pass
+    del(config)
 
 
 def test_mandatory_warnings_ro():
     descr = make_description()
-    config = Config(descr)
+    config = Config(descr, session_id='man013')
     config.str = ''
     config.read_only()
     proc = []
@@ -341,11 +401,16 @@ def test_mandatory_warnings_ro():
     config.read_only()
     assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str1', 'unicode2', 'str3']
     assert list(config.cfgimpl_get_values().mandatory_warnings(force_permissive=True)) == ['str1', 'unicode2', 'str3']
+    try:
+        delete_session('config', config.impl_getsessionid())
+    except ValueError:
+        pass
+    del(config)
 
 
 def test_mandatory_warnings_rw():
     descr = make_description()
-    config = Config(descr)
+    config = Config(descr, session_id='man100')
     config.str = ''
     config.read_write()
     config.str
@@ -354,7 +419,7 @@ def test_mandatory_warnings_rw():
     assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str1', 'unicode2', 'str3']
     assert list(config.cfgimpl_get_values().mandatory_warnings(force_permissive=True)) == ['str1', 'unicode2', 'str3']
     try:
-        delete_session('config', config.impl_getsessionid())
+        delete_session('config', 'man100')
     except ValueError:
         pass
     del(config)
@@ -362,7 +427,7 @@ def test_mandatory_warnings_rw():
 
 def test_mandatory_warnings_disabled():
     descr = make_description()
-    config = Config(descr)
+    config = Config(descr, session_id='man101')
     config.str = ''
     setting = config.cfgimpl_get_settings()
     config.read_write()
@@ -372,7 +437,7 @@ def test_mandatory_warnings_disabled():
     assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str1', 'unicode2', 'str3']
     assert list(config.cfgimpl_get_values().mandatory_warnings(force_permissive=True)) == ['str1', 'unicode2', 'str3']
     try:
-        delete_session('config', config.impl_getsessionid())
+        delete_session('config', 'man101')
     except ValueError:
         pass
     del(config)
@@ -380,7 +445,7 @@ def test_mandatory_warnings_disabled():
 
 def test_mandatory_warnings_hidden():
     descr = make_description()
-    config = Config(descr)
+    config = Config(descr, session_id='man102')
     config.str = ''
     setting = config.cfgimpl_get_settings()
     config.read_write()
@@ -391,7 +456,7 @@ def test_mandatory_warnings_hidden():
     assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str1', 'unicode2', 'str3']
     assert list(config.cfgimpl_get_values().mandatory_warnings(force_permissive=True)) == ['str', 'str1', 'unicode2', 'str3']
     try:
-        delete_session('config', config.impl_getsessionid())
+        delete_session('config', 'man102')
     except ValueError:
         pass
     del(config)
@@ -399,7 +464,7 @@ def test_mandatory_warnings_hidden():
 
 def test_mandatory_warnings_frozen():
     descr = make_description()
-    config = Config(descr)
+    config = Config(descr, session_id='man103')
     config.str = ''
     setting = config.cfgimpl_get_settings()
     config.read_write()
@@ -409,7 +474,7 @@ def test_mandatory_warnings_frozen():
     config.read_only()
     assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str', 'str1', 'unicode2', 'str3']
     try:
-        delete_session('config', config.impl_getsessionid())
+        delete_session('config', 'man103')
     except ValueError:
         pass
     del(config)
@@ -423,12 +488,12 @@ def test_mandatory_master():
     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
     interface1.impl_set_group_type(groups.master)
     o = OptionDescription('o', '', [interface1])
-    config = Config(o)
+    config = Config(o, session_id='man104')
     config.read_only()
     raises(PropertiesOptionError, 'config.ip_admin_eth0.ip_admin_eth0')
     raises(PropertiesOptionError, 'config.ip_admin_eth0.netmask_admin_eth0')
     try:
-        delete_session('config', config.impl_getsessionid())
+        delete_session('config', 'man104')
     except ValueError:
         pass
     del(config)
@@ -442,10 +507,10 @@ def test_mandatory_warnings_master():
     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
     interface1.impl_set_group_type(groups.master)
     o = OptionDescription('o', '', [interface1])
-    config = Config(o)
+    config = Config(o, session_id='man105')
     assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['ip_admin_eth0.ip_admin_eth0']
     try:
-        delete_session('config', config.impl_getsessionid())
+        delete_session('config', 'man105')
     except ValueError:
         pass
     del(config)
@@ -458,7 +523,7 @@ def test_mandatory_master_empty():
     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
     interface1.impl_set_group_type(groups.master)
     o = OptionDescription('o', '', [interface1])
-    config = Config(o)
+    config = Config(o, session_id='man106')
     config.read_write()
     assert config.ip_admin_eth0.ip_admin_eth0 == []
     assert config.ip_admin_eth0.netmask_admin_eth0 == []
@@ -489,7 +554,7 @@ def test_mandatory_master_empty():
     assert config.ip_admin_eth0.ip_admin_eth0 == ['ip']
     assert config.ip_admin_eth0.netmask_admin_eth0 == [None]
     try:
-        delete_session('config', config.impl_getsessionid())
+        delete_session('config', 'man106')
     except ValueError:
         pass
     del(config)
@@ -502,7 +567,7 @@ def test_mandatory_warnings_master_empty():
     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
     interface1.impl_set_group_type(groups.master)
     o = OptionDescription('o', '', [interface1])
-    config = Config(o)
+    config = Config(o, session_id='man107')
     config.read_write()
     config.ip_admin_eth0.ip_admin_eth0.append()
     assert config.ip_admin_eth0.ip_admin_eth0 == [None]
@@ -520,7 +585,7 @@ def test_mandatory_warnings_master_empty():
     config.ip_admin_eth0.ip_admin_eth0 = ['ip']
     assert list(config.cfgimpl_get_values().mandatory_warnings()) == []
     try:
-        delete_session('config', config.impl_getsessionid())
+        delete_session('config', 'man107')
     except ValueError:
         pass
     del(config)
@@ -533,7 +598,7 @@ def test_mandatory_slave():
     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
     interface1.impl_set_group_type(groups.master)
     o = OptionDescription('o', '', [interface1])
-    config = Config(o)
+    config = Config(o, session_id='man108')
     config.read_only()
     assert config.ip_admin_eth0.ip_admin_eth0 == []
     assert config.ip_admin_eth0.netmask_admin_eth0 == []
@@ -556,7 +621,7 @@ def test_mandatory_slave():
     assert config.ip_admin_eth0.ip_admin_eth0 == ['ip']
     assert config.ip_admin_eth0.netmask_admin_eth0 == ['ip']
     try:
-        delete_session('config', config.impl_getsessionid())
+        delete_session('config', 'man108')
     except ValueError:
         pass
     del(config)
@@ -569,7 +634,7 @@ def test_mandatory_warnings_slave():
     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
     interface1.impl_set_group_type(groups.master)
     o = OptionDescription('o', '', [interface1])
-    config = Config(o)
+    config = Config(o, session_id='man109')
     config.read_only()
     assert config.ip_admin_eth0.ip_admin_eth0 == []
     assert config.ip_admin_eth0.netmask_admin_eth0 == []
@@ -579,7 +644,7 @@ def test_mandatory_warnings_slave():
     config.ip_admin_eth0.ip_admin_eth0.append('ip')
     assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['ip_admin_eth0.netmask_admin_eth0']
     try:
-        delete_session('config', config.impl_getsessionid())
+        delete_session('config', 'man109')
     except ValueError:
         pass
     del(config)
@@ -587,7 +652,7 @@ def test_mandatory_warnings_slave():
 
 def test_mandatory_warnings_symlink():
     descr = make_description_sym()
-    config = Config(descr)
+    config = Config(descr, session_id='man110')
     config.str = ''
     setting = config.cfgimpl_get_settings()
     config.read_write()
@@ -597,7 +662,7 @@ def test_mandatory_warnings_symlink():
     config.read_only()
     assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str', 'str1', 'str3']
     try:
-        delete_session('config', config.impl_getsessionid())
+        delete_session('config', 'man110')
     except ValueError:
         pass
     del(config)
@@ -605,7 +670,7 @@ def test_mandatory_warnings_symlink():
 
 def test_mandatory_warnings_validate():
     descr = make_description3()
-    config = Config(descr)
+    config = Config(descr, session_id='man111')
     config.str = ''
     raises(ValueError, "list(config.cfgimpl_get_values().mandatory_warnings())")
     assert list(config.cfgimpl_get_values().mandatory_warnings(validate=False)) == ['str', 'str1', 'str3', 'unicode1', 'int1']
@@ -613,7 +678,7 @@ def test_mandatory_warnings_validate():
     raises(ValueError, "list(config.cfgimpl_get_values().mandatory_warnings())")
     assert list(config.cfgimpl_get_values().mandatory_warnings(validate=False)) == ['str1', 'str3']
     try:
-        delete_session('config', config.impl_getsessionid())
+        delete_session('config', 'man111')
     except ValueError:
         pass
     del(config)
@@ -621,13 +686,13 @@ def test_mandatory_warnings_validate():
 
 def test_mandatory_warnings_validate_empty():
     descr = make_description2()
-    config = Config(descr)
+    config = Config(descr, session_id='man112')
     config.str = ''
     config.read_only()
     raises(ConfigError, "list(config.cfgimpl_get_values().mandatory_warnings())")
     assert list(config.cfgimpl_get_values().mandatory_warnings(validate=False)) == ['str', 'str1', 'str3', 'unicode1']
     try:
-        delete_session('config', config.impl_getsessionid())
+        delete_session('config', 'man112')
     except ValueError:
         pass
     del(config)
@@ -635,7 +700,7 @@ def test_mandatory_warnings_validate_empty():
 
 def test_mandatory_warnings_requires():
     descr = make_description4()
-    config = Config(descr)
+    config = Config(descr, session_id='man113')
     config.str = ''
     config.read_write()
     config.str
@@ -646,7 +711,7 @@ def test_mandatory_warnings_requires():
     config.str = 'yes'
     assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str1', 'unicode2', 'str3']
     try:
-        delete_session('config', config.impl_getsessionid())
+        delete_session('config', 'man113')
     except ValueError:
         pass
     del(config)
@@ -655,13 +720,13 @@ def test_mandatory_warnings_requires():
 def test_mandatory_od_disabled():
     descr = make_description()
     od = OptionDescription('od', '', [descr])
-    config = Config(od)
+    config = Config(od, session_id='man114')
     config.read_only()
     assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['tiram.str1', 'tiram.unicode2', 'tiram.str3']
     config.cfgimpl_get_settings()[descr].append('disabled')
     assert list(config.cfgimpl_get_values().mandatory_warnings()) == []
     try:
-        delete_session('config', config.impl_getsessionid())
+        delete_session('config', 'man114')
     except ValueError:
         pass
     del(config)
index 6412c81..20beef5 100644 (file)
@@ -11,6 +11,9 @@ from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption,\
     URLOption, FilenameOption
 
 
+print "FIXME slot pour un masterslaves !!"
+
+
 def test_slots_option():
     c = ChoiceOption('a', '', ('a',))
     raises(AttributeError, "c.x = 1")
index f4be865..824e368 100644 (file)
@@ -107,9 +107,9 @@ def _diff_opt(opt1, opt2):
                         else:
                             assert v[1] == val2[idx][1]
         elif attr == '_master_slaves':
-            assert val1.master.impl_getname() == val2.master.impl_getname()
-            sval1 = [opt.impl_getname() for opt in val1.slaves]
-            sval2 = [opt.impl_getname() for opt in val2.slaves]
+            assert val1._p_._sm_getmaster().impl_getname() == val2._p_._sm_getmaster().impl_getname()
+            sval1 = [opt.impl_getname() for opt in val1._p_._sm_getslaves()]
+            sval2 = [opt.impl_getname() for opt in val2._p_._sm_getslaves()]
             assert sval1 == sval2
         elif attr == '_subdyn':
             try:
@@ -214,14 +214,18 @@ def test_diff_information_config():
     except ValueError:
         cfg = Config(o1, session_id='29090938')
         cfg._impl_test = True
-    cfg.impl_set_information('info', 'oh')
-
-    a = dumps(cfg)
-    q = loads(a)
-    _diff_opts(cfg.cfgimpl_get_description(), q.cfgimpl_get_description())
-    _diff_conf(cfg, q)
-    assert cfg.impl_get_information('info') == 'oh'
-    assert q.impl_get_information('info') == 'oh'
+        cfg.impl_set_information('info', 'oh')
+
+        a = dumps(cfg)
+        q = loads(a)
+        _diff_opts(cfg.cfgimpl_get_description(), q.cfgimpl_get_description())
+        _diff_conf(cfg, q)
+        assert cfg.impl_get_information('info') == 'oh'
+        assert q.impl_get_information('info') == 'oh'
+    try:
+        delete_session('config', '29090938')
+    except ValueError:
+        pass
 
 
 def test_diff_opt_multi():
@@ -295,10 +299,10 @@ def test_state_config():
     except ValueError:
         cfg = Config(maconfig, session_id='29090931')
         cfg._impl_test = True
-    a = dumps(cfg)
-    q = loads(a)
-    _diff_opts(cfg.cfgimpl_get_description(), q.cfgimpl_get_description())
-    _diff_conf(cfg, q)
+        a = dumps(cfg)
+        q = loads(a)
+        _diff_opts(cfg.cfgimpl_get_description(), q.cfgimpl_get_description())
+        _diff_conf(cfg, q)
     try:
         delete_session('config', '29090931')
     except ValueError:
@@ -324,10 +328,10 @@ def test_state_config2():
     except ValueError:
         cfg = Config(od2, session_id='29090939')
         cfg._impl_test = True
-    a = dumps(cfg)
-    q = loads(a)
-    _diff_opts(cfg.cfgimpl_get_description(), q.cfgimpl_get_description())
-    _diff_conf(cfg, q)
+        a = dumps(cfg)
+        q = loads(a)
+        _diff_opts(cfg.cfgimpl_get_description(), q.cfgimpl_get_description())
+        _diff_conf(cfg, q)
     try:
         delete_session('config', '29090939')
     except ValueError:
@@ -349,10 +353,14 @@ def test_diff_opt_config():
         cfg = Config(o1, session_id='29090940')
         cfg._impl_test = True
 
-    a = dumps(cfg)
-    q = loads(a)
-    _diff_opts(cfg.cfgimpl_get_description(), q.cfgimpl_get_description())
-    _diff_conf(cfg, q)
+        a = dumps(cfg)
+        q = loads(a)
+        _diff_opts(cfg.cfgimpl_get_description(), q.cfgimpl_get_description())
+        _diff_conf(cfg, q)
+    try:
+        delete_session('config', '29090940')
+    except ValueError:
+        pass
 
 
 def test_state_properties():
@@ -363,11 +371,11 @@ def test_state_properties():
     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)
+        cfg.read_write()
+        cfg.cfgimpl_get_settings()[val1].append('test')
+        a = dumps(cfg)
+        q = loads(a)
+        _diff_conf(cfg, q)
     try:
         delete_session('config', '29090932')
     except ValueError:
@@ -382,13 +390,13 @@ def test_state_values():
     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
+        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('config', '29090933')
     except ValueError:
@@ -403,15 +411,15 @@ def test_state_values_owner():
     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
+        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('config', '29090934')
     except ValueError:
@@ -422,17 +430,18 @@ 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:
+        cfg = Config(od2, persistent=True, session_id='29090935')
+    except ValueError:
+        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('config', '29090935')
-        delete_session('config', '29090936')
-        delete_session('config', '29090937')
     except ValueError:
         pass
 
@@ -441,19 +450,20 @@ 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('config', '29090935')
-        delete_session('config', '29090936')
-        delete_session('config', '29090937')
+        cfg = Config(od2, persistent=True, session_id='29090938')
+    except ValueError:
+        conf1 = Config(od2, session_id='29090938')
+        conf1._impl_test = True
+        conf2 = Config(od2, session_id='29090939')
+        conf2._impl_test = True
+        meta = GroupConfig([conf1, conf2], session_id='29090940')
+        meta._impl_test = True
+        a = dumps(meta)
+        q = loads(a)
+        _diff_conf(meta, q)
+    try:
+        delete_session('config', '29090938')
     except ValueError:
         pass
 
index 8cf061d..4be5440 100644 (file)
@@ -258,7 +258,7 @@ class SubConfig(object):
         return subpath
 
     def getattr(self, name, force_permissive=False, validate=True,
-                _setting_properties=undefined, index=None,
+                _setting_properties=undefined, _self_properties=undefined, index=None,
                 returns_raise=False):
         """
         attribute notation mechanism for accessing the value of an option
@@ -277,6 +277,7 @@ class SubConfig(object):
             return homeconfig.getattr(name, force_permissive=force_permissive,
                                       validate=validate,
                                       _setting_properties=_setting_properties,
+                                      _self_properties=_self_properties,
                                       index=index, returns_raise=returns_raise)
         context = self._cfgimpl_get_context()
         option = self.cfgimpl_get_description().__getattr__(name,
@@ -287,7 +288,9 @@ class SubConfig(object):
                 option, path=subpath,
                 validate=validate,
                 force_permissive=force_permissive,
-                setting_properties=_setting_properties, index=index,
+                setting_properties=_setting_properties,
+                self_properties=_self_properties,
+                index=index,
                 returns_raise=returns_raise)
         elif isinstance(option, SymLinkOption):  # pragma: no dynoptiondescription cover
             path = context.cfgimpl_get_description().impl_get_path_by_opt(
@@ -295,11 +298,13 @@ class SubConfig(object):
             return context.getattr(path, validate=validate,
                                    force_permissive=force_permissive,
                                    _setting_properties=_setting_properties,
+                                   _self_properties=_self_properties,
                                    index=index, returns_raise=returns_raise)
         elif option.impl_is_optiondescription():
             props = self.cfgimpl_get_settings().validate_properties(
                 option, True, False, path=subpath,
                 force_permissive=force_permissive,
+                self_properties=_self_properties,
                 setting_properties=_setting_properties)
             if props:
                 if returns_raise:
@@ -313,6 +318,7 @@ class SubConfig(object):
                 validate=validate,
                 force_permissive=force_permissive,
                 setting_properties=_setting_properties,
+                self_properties=_self_properties,
                 index=index, returns_raise=returns_raise)
 
     def find(self, bytype=None, byname=None, byvalue=undefined, type_='option',
@@ -656,7 +662,8 @@ class _CommonConfig(SubConfig):
 
     def duplicate(self):
         config = Config(self._impl_descr)
-        config.cfgimpl_get_values()._p_._values = self.cfgimpl_get_values()._p_._values
+        session = self.cfgimpl_get_values()._p_.getsession()
+        config.cfgimpl_get_values()._p_.importation(self.cfgimpl_get_values()._p_.exportation(session))
         config.cfgimpl_get_settings()._p_._properties = self.cfgimpl_get_settings()._p_.get_modified_properties()
         config.cfgimpl_get_settings()._p_._permissives = self.cfgimpl_get_settings()._p_.get_modified_permissives()
         return config
index d05358c..55aaf71 100644 (file)
@@ -29,6 +29,7 @@ from ..autolib import carry_out_calculation
 from ..error import (ConfigError, ValueWarning, PropertiesOptionError,
     display_list)
 from ..storage import get_storages_option
+from . import MasterSlaves
 
 
 StorageBase = get_storages_option('base')
@@ -99,7 +100,7 @@ class Base(StorageBase):
                  requires=None, multi=False, callback=None,
                  callback_params=None, validator=None, validator_params=None,
                  properties=None, warnings_only=False, extra=None,
-                 allow_empty_list=undefined):
+                 allow_empty_list=undefined, session=None):
         if not valid_name(name):  # pragma: optional cover
             raise ValueError(_("invalid name: {0} for option").format(name))
         if not multi and default_multi is not None:  # pragma: optional cover
@@ -138,9 +139,11 @@ class Base(StorageBase):
                 raise ValueError('conflict: properties already set in '
                                  'requirement {0}'.format(
                                      list(set_forbidden_properties)))
+        if session is None:
+            session = self.getsession()
         StorageBase.__init__(self, name, _multi, warnings_only, doc, extra,
                              calc_properties, requires, properties,
-                             allow_empty_list)
+                             allow_empty_list, session=session)
         if multi is not False and default is None:
             default = []
         err = self.impl_validate(default, is_multi=is_multi)
@@ -150,7 +153,7 @@ class Base(StorageBase):
         ##callback is False in optiondescription
         if callback is not False:
             self.impl_set_callback(callback, callback_params, _init=True)
-        self.commit()
+        self.commit(session)
 
     def impl_set_callback(self, callback, callback_params=None, _init=False):
         if callback is None and callback_params is not None:  # pragma: optional cover
@@ -342,9 +345,6 @@ class BaseOption(Base):
     def _is_subdyn(self):
         return getattr(self, '_subdyn', None) is not None
 
-    def impl_getproperties(self):
-        return self._properties
-
     def _impl_valid_unicode(self, value):
         if sys.version_info[0] >= 3:
             if not isinstance(value, str):
@@ -590,10 +590,13 @@ class Option(OnlyOption):
                 return self._valid_consistency(current_opt, None, context,
                                                None, None)
 
+    def impl_is_dynsymlinkoption(self):
+        return False
+
     def impl_is_master_slaves(self, type_='both'):
         """FIXME
         """
-        master_slaves = getattr(self, '_master_slaves', None)
+        master_slaves = self.impl_get_master_slaves()
         if master_slaves is not None:
             if type_ in ('both', 'master') and \
                     master_slaves.is_master(self):
@@ -604,7 +607,12 @@ class Option(OnlyOption):
         return False
 
     def impl_get_master_slaves(self):
-        return self._master_slaves
+        masterslaves = self._get_master_slave()
+        if masterslaves is None:
+            return None
+        if not isinstance(masterslaves, MasterSlaves):
+            return MasterSlaves(masterslaves)
+        return masterslaves
 
     def impl_getdoc(self):
         "accesses the Option's doc"
@@ -876,10 +884,11 @@ class SymLinkOption(OnlyOption):
             raise ValueError(_('malformed symlinkoption '
                                'must be an option '
                                'for symlink {0}').format(name))
+        session = self.getsession()
         super(Base, self).__init__(name, undefined, undefined, undefined,
                                    undefined, undefined, undefined, undefined,
-                                   undefined, opt)
-        self.commit()
+                                   undefined, opt, session=session)
+        self.commit(session)
 
     def __getattr__(self, name, context=undefined):
         if name in ('_opt', '_readonly', 'impl_getpath', '_name',
@@ -964,3 +973,6 @@ class DynSymLinkOption(object):
                                                  force_submulti_index,
                                                  current_opt=self,
                                                  is_multi=is_multi)
+
+    def impl_is_dynsymlinkoption(self):
+        return True
index ca12351..4a9ba8b 100644 (file)
 from ..i18n import _
 from ..setting import log, undefined, debug
 from ..error import SlaveError, PropertiesOptionError
-from .baseoption import DynSymLinkOption, SymLinkOption, Option
+from ..storage import get_storages_option
+
+
+StorageMasterSlaves = get_storages_option('masterslaves')
 
 
 class MasterSlaves(object):
-    __slots__ = ('master', 'slaves')
+    __slots__ = ('_p_')
 
-    def __init__(self, name, childs, validate=True):
+    def __init__(self, name, childs=None, validate=True, add=True):
         #if master (same name has group) is set
         #for collect all slaves
-        self.master = None
-        slaves = []
-        for child in childs:
-            if isinstance(child, SymLinkOption):  # pragma: optional cover
-                raise ValueError(_("master group {0} shall not have "
-                                   "a symlinkoption").format(name))
-            if not isinstance(child, Option):  # pragma: optional cover
-                raise ValueError(_("master group {0} shall not have "
-                                   "a subgroup").format(name))
-            if not child.impl_is_multi():  # pragma: optional cover
-                raise ValueError(_("not allowed option {0} "
-                                   "in group {1}"
-                                   ": this option is not a multi"
-                                   "").format(child.impl_getname(), name))
-            if child.impl_getname() == name:
-                self.master = child
+        if isinstance(name, StorageMasterSlaves):
+            self._p_ = name
+        else:
+            slaves = []
+            if childs[0].impl_getname() == name:
+                master = childs[0]
             else:
+                raise ValueError(_('master group with wrong'
+                                   ' master name for {0}'
+                                   ).format(name))
+            for child in childs[1:]:
                 if child.impl_getdefault() != []:
                     raise ValueError(_("not allowed default value for option {0} "
                                        "in group {1}").format(child.impl_getname(),
                                                               name))
                 slaves.append(child)
-        if self.master is None:  # pragma: optional cover
-            raise ValueError(_('master group with wrong'
-                               ' master name for {0}'
-                               ).format(name))
-        if validate:
-            callback, callback_params = self.master.impl_get_callback()
-            if callback is not None and callback_params != {}:  # pragma: optional cover
-                for key, callbacks in callback_params.items():
-                    for callbk in callbacks:
-                        if isinstance(callbk, tuple):
-                            if callbk[0] in slaves:
-                                raise ValueError(_("callback of master's option shall "
-                                                   "not refered a slave's ones"))
-        #everything is ok, store references
-        self.slaves = tuple(slaves)
-        for child in childs:
-            child._master_slaves = self
+            if validate:
+                callback, callback_params = master.impl_get_callback()
+                if callback is not None and callback_params != {}:  # pragma: optional cover
+                    for key, callbacks in callback_params.items():
+                        for callbk in callbacks:
+                            if isinstance(callbk, tuple):
+                                if callbk[0] in slaves:
+                                    raise ValueError(_("callback of master's option shall "
+                                                       "not refered a slave's ones"))
+            #everything is ok, store references
+            self._p_ = StorageMasterSlaves(master, slaves)
+            if add:
+                for child in childs:
+                    child._set_master_slaves(self)
 
     def is_master(self, opt):
-        return opt == self.master or (isinstance(opt, DynSymLinkOption) and
-                                      opt._opt == self.master)
+        master = self._p_._sm_getmaster().impl_getname()
+        return opt.impl_getname() == master or (opt.impl_is_dynsymlinkoption() and
+                                      opt._opt.impl_getname() == master)
 
     def getmaster(self, opt):
-        if isinstance(opt, DynSymLinkOption):
+        master = self._p_._sm_getmaster()
+        if opt.impl_is_dynsymlinkoption():
             suffix = opt.impl_getsuffix()
-            name = self.master.impl_getname() + suffix
+            name = master.impl_getname() + suffix
             base_path = opt._dyn.split('.')[0] + '.'
             path = base_path + name
-            master = self.master._impl_to_dyn(name, path)
-        else:  # pragma: no dynoptiondescription cover
-            master = self.master
+            master = master._impl_to_dyn(name, path)
         return master
 
     def getslaves(self, opt):
-        if isinstance(opt, DynSymLinkOption):
-            for slave in self.slaves:
+        if opt.impl_is_dynsymlinkoption():
+            for slave in self._p_._sm_getslaves():
                 suffix = opt.impl_getsuffix()
                 name = slave.impl_getname() + suffix
                 base_path = opt._dyn.split('.')[0] + '.'
                 path = base_path + name
                 yield slave._impl_to_dyn(name, path)
         else:  # pragma: no dynoptiondescription cover
-            for slave in self.slaves:
+            for slave in self._p_._sm_getslaves():
                 yield slave
 
     def in_same_group(self, opt):
-        if isinstance(opt, DynSymLinkOption):
-            return opt._opt == self.master or opt._opt in self.slaves
+        if opt.impl_is_dynsymlinkoption():
+            return opt._opt == self._p_._sm_getmaster() or opt._opt in self._p_._sm_getslaves()
         else:  # pragma: no dynoptiondescription cover
-            return opt == self.master or opt in self.slaves
+            return opt == self._p_._sm_getmaster() or opt in self._p_._sm_getslaves()
 
     def reset(self, opt, values, setting_properties):
         for slave in self.getslaves(opt):
index d809f26..b92a382 100644 (file)
@@ -55,9 +55,8 @@ class ChoiceOption(Option):
             if not isinstance(values, tuple):  # pragma: optional cover
                 raise TypeError(_('values must be a tuple or a function for {0}'
                                   ).format(name))
-        _setattr = object.__setattr__
-        _setattr(self, '_choice_values', values)
-        _setattr(self, '_choice_values_params', values_params)
+        self.impl_set_choice_values_params(values, values_params)
+
         super(ChoiceOption, self).__init__(name, doc, default=default,
                                            default_multi=default_multi,
                                            callback=callback,
@@ -79,9 +78,7 @@ class ChoiceOption(Option):
             if context is None:
                 values = []
             else:
-                values_params = self._choice_values_params
-                if values_params is None:
-                    values_params = {}
+                values_params = self.impl_get_choice_values_params()
                 values = carry_out_calculation(current_opt, context=context,
                                                callback=values,
                                                callback_params=values_params,
@@ -93,6 +90,7 @@ class ChoiceOption(Option):
                                         '').format(self.impl_getname()))
         return values
 
+
     def _validate(self, value, context=undefined, current_opt=undefined,
                   returns_raise=False):
         values = self.impl_get_values(context, current_opt=current_opt,
index 6edc458..fc7ab04 100644 (file)
@@ -24,7 +24,7 @@ import re
 
 from ..i18n import _
 from ..setting import groups, undefined, owners  # , log
-from .baseoption import BaseOption, SymLinkOption
+from .baseoption import BaseOption, SymLinkOption, Option
 from . import MasterSlaves
 from ..error import ConfigError, ConflictError
 from ..storage import get_storages_option
@@ -229,7 +229,20 @@ class OptionDescription(BaseOption, StorageOptionDescription):
         if isinstance(group_type, groups.GroupType):
             self._group_type = group_type
             if isinstance(group_type, groups.MasterGroupType):
-                MasterSlaves(self.impl_getname(), self.impl_getchildren())
+                children = self.impl_getchildren()
+                for child in children:
+                    if isinstance(child, SymLinkOption):  # pragma: optional cover
+                        raise ValueError(_("master group {0} shall not have "
+                                           "a symlinkoption").format(self.impl_getname()))
+                    if not isinstance(child, Option):  # pragma: optional cover
+                        raise ValueError(_("master group {0} shall not have "
+                                           "a subgroup").format(self.impl_getname()))
+                    if not child.impl_is_multi():  # pragma: optional cover
+                        raise ValueError(_("not allowed option {0} "
+                                           "in group {1}"
+                                           ": this option is not a multi"
+                                           "").format(child.impl_getname(), self.impl_getname()))
+                MasterSlaves(self.impl_getname(), children)
         else:  # pragma: optional cover
             raise ValueError(_('group_type: {0}'
                                ' not allowed').format(group_type))
@@ -365,7 +378,6 @@ class DynOptionDescription(OptionDescription):
                                     'dynoptiondescription'))
             child._impl_setsubdyn(self)
         self.impl_set_callback(callback, callback_params)
-        self.commit()
 
     def _validate_callback(self, callback, callback_params):
         if callback is None:
index a53653b..a95a629 100644 (file)
@@ -135,6 +135,8 @@ def get_storages_option(type_):
     imp = storage_option_type.get()
     if type_ == 'base':
         return imp.StorageBase
+    elif type_ == 'masterslaves':
+        return imp.StorageMasterSlaves
     else:
         return imp.StorageOptionDescription
 
index a52bf26..cf7e03d 100644 (file)
@@ -25,7 +25,7 @@ use it. But if something goes wrong, you will lost your modifications.
 from .value import Values
 from .setting import Settings
 from .storage import setting, Storage, list_sessions, delete_session
-from .option import StorageBase, StorageOptionDescription
+from .option import StorageBase, StorageOptionDescription, StorageMasterSlaves
 
 __all__ = (setting, Values, Settings, Storage, list_sessions, delete_session,
-           StorageBase, StorageOptionDescription)
+           StorageBase, StorageOptionDescription, StorageMasterSlaves)
index 481a1f4..ea49b50 100644 (file)
@@ -65,7 +65,8 @@ class StorageBase(object):
                  )
 
     def __init__(self, name, multi, warnings_only, doc, extra, calc_properties,
-                 requires, properties, allow_empty_list, opt=undefined):
+                 requires, properties, allow_empty_list, opt=undefined,
+                 session=None):
         _setattr = object.__setattr__
         _setattr(self, '_name', name)
         if doc is not undefined:
@@ -164,6 +165,12 @@ class StorageBase(object):
             val_call = tuple([callback, callback_params])
         self._val_call = (val, val_call)
 
+    def impl_set_choice_values_params(self, values, values_params):
+        self._choice_values = values
+        if values_params is not None:
+            self._choice_values_params = values_params
+
+
     def impl_get_callback(self):
         call = getattr(self, '_val_call', (None, None))[1]
         if call is None:
@@ -174,6 +181,9 @@ class StorageBase(object):
             ret_call = call
         return ret_call
 
+    def impl_get_choice_values_params(self):
+        return getattr(self, '_choice_values_params', {})
+
     def impl_get_calc_properties(self):
         return getattr(self, '_calc_properties', static_set)
 
@@ -259,6 +269,9 @@ class StorageBase(object):
                 if extra is not None:
                     _setattr(self, '_extra', tuple([tuple(extra.keys()), tuple(extra.values())]))
 
+    def impl_getproperties(self):
+        return self._properties
+
     def _impl_setsubdyn(self, subdyn):
         self._subdyn = subdyn
 
@@ -357,7 +370,16 @@ class StorageBase(object):
         "accessing the default value for a multi"
         return getattr(self, '_default_multi', None)
 
-    def commit(self):
+    def _get_master_slave(self):
+        return getattr(self, '_master_slaves', None)
+
+    def _set_master_slaves(self, option):
+        self._master_slaves = option
+
+    def getsession(self):
+        pass
+
+    def commit(self, session):
         pass
 
 
@@ -549,3 +571,17 @@ class StorageOptionDescription(StorageBase):
             raise AttributeError(_('unknown Option {0} '
                                    'in OptionDescription {1}'
                                    '').format(name, self.impl_getname()))
+
+
+class StorageMasterSlaves(object):
+    __slots__ = ('master', 'slaves')
+
+    def __init__(self, master, slaves):
+        self.master = master
+        self.slaves = slaves
+
+    def _sm_getmaster(self):
+        return self.master
+
+    def _sm_getslaves(self):
+        return tuple(self.slaves)
index cd9a039..75f6984 100644 (file)
@@ -25,7 +25,7 @@ use it. But if something goes wrong, you will lost your modifications.
 from .value import Values
 from .setting import Settings
 from .storage import Storage, list_sessions, delete_session, storage_setting
-from .option import StorageBase, StorageOptionDescription
+from .option import StorageBase, StorageOptionDescription, StorageMasterSlaves
 from .util import load
 
 
@@ -33,5 +33,5 @@ load()
 
 
 __all__ = (storage_setting, Values, Settings, Storage, list_sessions, delete_session,
-           StorageBase, StorageOptionDescription)
+           StorageBase, StorageOptionDescription, StorageMasterSlaves)
 #           Base, OptionDescription)
index ee638ab..3945109 100644 (file)
@@ -40,8 +40,9 @@ def load_requires(collection_type, proxy):
             return None
         ret = []
         requires = getattr(obj, proxy.value_attr)
+        session = util.Session()
         for require in requires:
-            option = util.session.query(_Base).filter_by(id=require.option).first()
+            option = session.query(_Base).filter_by(id=require.option).first()
             ret.append(tuple([option, require.expected, require.action, require.inverse, require.transitive, require.same_action]))
         return tuple(ret)
 
@@ -128,11 +129,12 @@ class _PropertyOption(SqlAlchemyBase):
 class _Information(SqlAlchemyBase):
     __tablename__ = 'information'
     id = Column(Integer, primary_key=True)
-    option = Column(Integer, ForeignKey('baseoption.id'), nullable=False)
+    option = Column(String, index=True, nullable=False)
     key = Column(String)
     value = Column(PickleType)
 
-    def __init__(self, key, value):
+    def __init__(self, option, key, value):
+        self.option = option
         self.key = key
         self.value = value
 
@@ -146,11 +148,12 @@ def load_callback_parm(collection_type, proxy):
             return None
         ret = []
         requires = getattr(obj, proxy.value_attr)
+        session = util.Session()
         for require in requires:
             if require.value is not None:
                 ret.append(require.value)
             else:
-                option = util.session.query(_Base).filter_by(id=require.option).first()
+                option = session.query(_Base).filter_by(id=require.option).first()
                 ret.append((option, require.force_permissive))
         return tuple(ret)
 
@@ -239,20 +242,20 @@ class _Base(SqlAlchemyBase):
     id = Column(Integer, primary_key=True)
     _name = Column(String)
     #FIXME not autoload
-    _infos = relationship("_Information",
-                          collection_class=attribute_mapped_collection('key'),
-                          cascade="all, delete-orphan")
-    _informations = association_proxy("_infos", "value")
+#    _infos = relationship("_Information",
+#                          collection_class=attribute_mapped_collection('key'),
+#                          cascade="all, delete-orphan")
+#    _informations = association_proxy("_infos", "value")
     _default = Column(PickleType)
     _default_multi = Column(PickleType)
     _subdyn = Column(Integer)
     _dyn = Column(String)
     _opt = Column(Integer)
+    _master_slaves = Column(Integer)
     _choice_values = Column(PickleType)
     _cho_params = relationship('_CallbackParam',
-                               collection_class=
-                               attribute_mapped_collection('key'))
-    _choice_params = association_proxy("_cho_params", "params",
+                               collection_class=attribute_mapped_collection('key'))
+    _choice_values_params = association_proxy("_cho_params", "params",
                                        getset_factory=load_callback_parm)
     _reqs = relationship("_Require", collection_class=list)
     _requires = association_proxy("_reqs", "requires", getset_factory=load_requires)
@@ -260,14 +263,12 @@ class _Base(SqlAlchemyBase):
     ######
     _callback = Column(PickleType)
     _call_params = relationship('_CallbackParam',
-                                collection_class=
-                                attribute_mapped_collection('key'))
+                                collection_class=attribute_mapped_collection('key'))
     _callback_params = association_proxy("_call_params", "params",
                                          getset_factory=load_callback_parm)
     _validator = Column(PickleType)
     _val_params = relationship('_CallbackParam',
-                               collection_class=
-                               attribute_mapped_collection('key'))
+                               collection_class=attribute_mapped_collection('key'))
     _validator_params = association_proxy("_val_params", "params",
                                           getset_factory=load_callback_parm)
     ######
@@ -282,10 +283,10 @@ class _Base(SqlAlchemyBase):
     _consistencies = relationship('_Consistency', secondary=consistency_table,
                                   backref=backref('options',
                                                   enable_typechecks=False))
-    _type = Column(String(50))
     _stated = Column(Boolean)
+    _type = Column(String(50))
     __mapper_args__ = {
-        'polymorphic_identity': 'option',
+        'polymorphic_identity': 'optionsql',
         'polymorphic_on': _type
     }
     _extra = Column(PickleType)
@@ -293,10 +294,8 @@ class _Base(SqlAlchemyBase):
     _group_type = Column(String)
     _is_build_cache = Column(Boolean, default=False)
 
-    #def __init__(self):
     def __init__(self, name, multi, warnings_only, doc, extra, calc_properties,
-                 requires, properties, allow_empty_list, opt=undefined):
-        util.session.add(self)
+                 requires, properties, allow_empty_list, opt=undefined, session=None):
         self._name = name
         if multi is not undefined:
             self._multi = multi
@@ -316,14 +315,19 @@ class _Base(SqlAlchemyBase):
             self._requires = requires
         if properties is not undefined:
             self._properties = properties
+        session.add(self)
 
-    def commit(self):
-        util.session.commit()
+    def getsession(self):
+        return util.Session()
+
+    def commit(self, session):
+        session.commit()
+        del(session)
 
     def _add_consistency(self, func, all_cons_opts, params):
         _Consistency(func, all_cons_opts, params)
 
-    def _set_default_values(self, default, default_multi):
+    def _set_default_values(self, default, default_multi, is_multi):
         self._default = default
         if self.impl_is_multi() and default_multi is not None:
             err = self._validate(default_multi)
@@ -344,6 +348,9 @@ class _Base(SqlAlchemyBase):
             return (None, {})
         return ret, self._callback_params
 
+    def impl_get_choice_values_params(self):
+        return self._choice_values_params
+
     def impl_get_validator(self):
         ret = self._validator
         if ret is None:
@@ -351,16 +358,30 @@ class _Base(SqlAlchemyBase):
         return ret, self._validator_params
 
     def _impl_getsubdyn(self):
-        return util.session.query(_Base).filter_by(id=self._subdyn).first()
+        session = self.getsession()
+        return session.query(_Base).filter_by(id=self._subdyn).first()
 
     def _impl_getopt(self):
-        return util.session.query(_Base).filter_by(id=self._opt).first()
+        session = self.getsession()
+        return session.query(_Base).filter_by(id=self._opt).first()
 
     def impl_getname(self):
         return self._name
 
     def impl_getrequires(self):
-        return self._requires
+        session = self.getsession()
+        requires = session.query(_Require).filter_by(requires_id=self.id).all()
+        for require in requires:
+            _ret = []
+            for req in require.requires:
+                _ret.append((session.query(_Base).filter_by(id=req.option).first(),
+                       req.expected,
+                       req.action,
+                       req.inverse,
+                       req.transitive,
+                       req.same_action))
+            yield(_ret)
+            
 
     def impl_getdefault(self):
         ret = self._default
@@ -381,10 +402,11 @@ class _Base(SqlAlchemyBase):
         self._opt = opt.id
 
     def _impl_setsubdyn(self, subdyn):
+        session = self.getsession()
         self._subdyn = subdyn.id
-        self.commit()
+        self.commit(session)
 
-    def _set_readonly(self):
+    def _set_readonly(self, has_extra):
         self._readonly = True
 
     def _set_callback(self, callback, callback_params):
@@ -392,6 +414,11 @@ class _Base(SqlAlchemyBase):
         if callback_params is not None:
             self._callback_params = callback_params
 
+    def impl_set_choice_values_params(self, values, values_params):
+        self._choice_values = values
+        if values_params is not None:
+            self._choice_values_params = values_params
+
     def _set_validator(self, validator, validator_params):
         self._validator = validator
         if validator_params is not None:
@@ -419,27 +446,39 @@ class _Base(SqlAlchemyBase):
         return self._warnings_only
 
     def impl_get_calc_properties(self):
-        try:
-            return self._calc_properties
-        except AttributeError:
-            return frozenset()
+        session = self.getsession()
+        return session.query(_CalcProperties).filter_by(require=self.id).all()
+        #try:
+        #    return self._calc_properties
+        #except AttributeError:
+        #    return frozenset()
 
     # information
     def impl_set_information(self, key, value):
-        self._informations[key] = value
+        session = self.getsession()
+#        self._informations[key] = value
+        val = session.query(_Information).filter_by(
+            option=self.id, key=key).first()
+        if val is None:
+            session.add(_Information(self.id, key, value))
+        else:
+            val.value = value
+        session.commit()
 
     def impl_get_information(self, key, default=undefined):
         """retrieves one information's item
 
         :param key: the item string (ex: "help")
         """
-        if default is not undefined:
-            return self._informations.get(key, default)
-        try:
-            return self._informations[key]
-        except KeyError:  # pragma: optional cover
+        session = self.getsession()
+        val = session.query(_Information).filter_by(
+            option=self.id, key=key).first()
+        if not val:
+            if default is not undefined:
+                return default
             raise ValueError(_("information's item not found: {0}").format(
-                key))
+                               key))
+        return val.value
 
     def _impl_getattributes(self):
         slots = set()
@@ -448,6 +487,20 @@ class _Base(SqlAlchemyBase):
                 slots.add(column.key)
         return slots
 
+    def impl_getproperties(self):
+        session = self.getsession()
+        return session.query(_PropertyOption).filter_by(option=self.id).all()
+
+    def _set_master_slaves(self, option):
+        session = self.getsession()
+        opt = session.query(_Base).filter_by(id=self.id).first()
+        opt._master_slaves = option.id
+        self.commit(session)
+
+    def _get_master_slave(self):
+        session = self.getsession()
+        return session.query(StorageMasterSlaves).filter_by(id=self._master_slaves).first()
+
 
 class Cache(SqlAlchemyBase):
     __tablename__ = 'cache'
@@ -477,19 +530,24 @@ class Cache(SqlAlchemyBase):
 
 class StorageOptionDescription(object):
     def impl_already_build_caches(self):
-        return self._is_build_cache
+        cache = self._is_build_cache
+        if cache is None:
+            cache = False
+        return cache
 
     def impl_get_opt_by_path(self, path):
-        ret = util.session.query(Cache).filter_by(descr=self.id, path=path).first()
+        session = self.getsession()
+        ret = session.query(Cache).filter_by(descr=self.id, path=path).first()
         if ret is None:
             raise AttributeError(_('no option for path {0}').format(path))
-        return util.session.query(_Base).filter_by(id=ret.option).first()
+        return session.query(_Base).filter_by(id=ret.option).first()
 
     def impl_get_path_by_opt(self, opt):
-        ret = util.session.query(Cache).filter_by(descr=self.id,
+        session = self.getsession()
+        ret = session.query(Cache).filter_by(descr=self.id,
                                                   option=opt.id).first()
         if ret is None:
-            ret = util.session.query(Cache).filter_by(descr=self.id).first()
+            ret = session.query(Cache).filter_by(descr=self.id).first()
             if ret is None:
                 raise ConfigError(_('use impl_get_path_by_opt only with root OptionDescription'))
             raise AttributeError(_('no option {0} found').format(opt))
@@ -499,11 +557,12 @@ class StorageOptionDescription(object):
         return getattr(groups, self._group_type)
 
     def impl_build_cache_option(self, descr=None, _currpath=None,
-                                subdyn_path=None):
+                                subdyn_path=None, session=None):
         if descr is None:
             save = True
             descr = self
             _currpath = []
+            session = self.getsession()
         else:
             save = False
         for option in self._impl_getchildren(dyn=False):
@@ -512,23 +571,23 @@ class StorageOptionDescription(object):
                 sub = subdyn_path
                 if option.impl_is_dynoptiondescription():
                     sub = '.'.join(_currpath)
-                util.session.add(Cache(descr, self, option,
+                session.add(Cache(descr, self, option,
                                        str('.'.join(_currpath + [attr])),
                                        sub))
                 _currpath.append(attr)
                 option.impl_build_cache_option(descr,
                                                _currpath,
-                                               sub)
+                                               sub, session)
                 _currpath.pop()
             else:
                 if subdyn_path:
                     subdyn_path = '.'.join(_currpath)
-                util.session.add(Cache(descr, self, option,
+                session.add(Cache(descr, self, option,
                                        str('.'.join(_currpath + [attr])),
                                        subdyn_path))
         if save:
             self._is_build_cache = True
-            util.session.commit()
+            self.commit(session)
 
     def impl_get_options_paths(self, bytype, byname, _subpath, only_first,
                                context):
@@ -546,7 +605,8 @@ class StorageOptionDescription(object):
             _opt = option._impl_to_dyn(name + suffix, path)
             return (path, _opt)
 
-        sqlquery = util.session.query(Cache).filter_by(descr=self.id)
+        session = self.getsession()
+        sqlquery = session.query(Cache).filter_by(descr=self.id)
         if bytype is None:
             sqlquery = sqlquery.filter(and_(not_(
                 Cache.opt_type == 'OptionDescription'),
@@ -575,7 +635,7 @@ class StorageOptionDescription(object):
         #else:
         ret = []
         for opt in sqlquery.all():
-            option = util.session.query(_Base).filter_by(id=opt.option).first()
+            option = session.query(_Base).filter_by(id=opt.option).first()
             if opt.is_subdyn:
                 name = option.impl_getname()
                 if byname is not None:
@@ -616,21 +676,24 @@ class StorageOptionDescription(object):
         return ret
 
     def _add_children(self, child_names, children):
+        session = self.getsession()
         for child in children:
-            util.session.add(_Parent(self, child))
+            session.add(_Parent(self, child))
+        self.commit(session)
 
     def _impl_st_getchildren(self, context, only_dyn=False):
+        session = self.getsession()
         if only_dyn is False or context is undefined:
-            for child in util.session.query(_Parent).filter_by(
+            for child in session.query(_Parent).filter_by(
                     parent_id=self.id).all():
-                yield(util.session.query(_Base).filter_by(id=child.child_id
+                yield(session.query(_Base).filter_by(id=child.child_id
                                                           ).first())
         else:
             descr = context.cfgimpl_get_description().id
-            for child in util.session.query(Cache).filter_by(descr=descr,
+            for child in session.query(Cache).filter_by(descr=descr,
                                                              parent=self.id
                                                              ).all():
-                yield(util.session.query(_Base).filter_by(id=child.option).first())
+                yield(session.query(_Base).filter_by(id=child.option).first())
 
     def _getattr(self, name, suffix=undefined, context=undefined, dyn=True):
         error = False
@@ -640,14 +703,15 @@ class StorageOptionDescription(object):
                     raise ConfigError(_("suffix and context needed if "
                                         "it's a dyn option"))
                 if name.endswith(suffix):
+                    session = self.getsession()
                     oname = name[:-len(suffix)]
                     #child = self._children[1][self._children[0].index(oname)]
-                    child = util.session.query(_Parent).filter_by(
+                    child = session.query(_Parent).filter_by(
                         parent_id=self.id, child_name=oname).first()
                     if child is None:
                         error = True
                     else:
-                        opt = util.session.query(_Base).filter_by(
+                        opt = session.query(_Base).filter_by(
                             id=child.child_id).first()
                         return self._impl_get_dynchild(opt, suffix)
                 else:
@@ -655,7 +719,8 @@ class StorageOptionDescription(object):
             except ValueError:  # pragma: optional cover
                 error = True
         else:
-            child = util.session.query(_Parent).filter_by(parent_id=self.id,
+            session = self.getsession()
+            child = session.query(_Parent).filter_by(parent_id=self.id,
                                                           child_name=name
                                                           ).first()
             if child is None:
@@ -664,7 +729,7 @@ class StorageOptionDescription(object):
                     return child
                 error = True
             if error is False:
-                return util.session.query(_Base).filter_by(id=child.child_id
+                return session.query(_Base).filter_by(id=child.child_id
                                                            ).first()
         if error:
             raise AttributeError(_('unknown Option {0} in OptionDescription {1}'
@@ -672,12 +737,13 @@ class StorageOptionDescription(object):
 
     def _get_force_store_value(self):
         #only option in current tree
-        current_ids = tuple(chain(*util.session.query(Cache.option).filter_by(
+        session = self.getsession()
+        current_ids = tuple(chain(*session.query(Cache.option).filter_by(
             descr=self.id).all()))
-        for prop in util.session.query(_PropertyOption).filter(
+        for prop in session.query(_PropertyOption).filter(
                 _PropertyOption.option.in_(current_ids),
                 _PropertyOption.name == 'force_store_value').all():
-            opt = util.session.query(_Base).filter_by(id=prop.option).first()
+            opt = session.query(_Base).filter_by(id=prop.option).first()
             path = self.impl_get_path_by_opt(opt)
             yield (opt, path)
 
@@ -686,3 +752,39 @@ class StorageBase(_Base):
     @declared_attr
     def __mapper_args__(self):
         return {'polymorphic_identity': self.__name__.lower()}
+
+
+class _Slave(SqlAlchemyBase):
+    __tablename__ = 'slaves'
+    id = Column(Integer, primary_key=True)
+    master_id = Column(Integer, index=True, nullable=False)
+    slave_id = Column(Integer)
+
+    def __init__(self, master, slave):
+        self.master_id = master.id
+        self.slave_id = slave.id
+
+
+class StorageMasterSlaves(SqlAlchemyBase):
+    __tablename__ = 'masterslaves2'
+    id = Column(Integer, primary_key=True)
+    master = Column(Integer)
+
+    def __init__(self, master, slaves):
+        session = util.Session()
+        self.master = master.id
+        session.add(self)
+        session.commit()
+        for slave in slaves:
+            sl = _Slave(self, slave)
+            session.add(sl)
+        session.commit()
+
+    def _sm_getslaves(self):
+        session = util.Session()
+        for slave in session.query(_Slave).filter_by(master_id=self.master).all():
+            yield(session.query(_Base).filter_by(id=slave.slave_id).first())
+
+    def _sm_getmaster(self):
+        session = util.Session()
+        return session.query(_Base).filter_by(id=self.master).first()