From 69de44bbb4f589cf85a5e9090c6d9ecf4f0f9db8 Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Fri, 30 Sep 2016 22:45:33 +0200 Subject: [PATCH] better sqlalchemy integration --- test/test_dyn_optiondescription.py | 8 +- test/test_mandatory.py | 151 +++++++++++----- test/test_slots.py | 3 + test/test_state.py | 138 +++++++------- tiramisu/config.py | 13 +- tiramisu/option/baseoption.py | 32 ++-- tiramisu/option/masterslave.py | 92 +++++----- tiramisu/option/option.py | 10 +- tiramisu/option/optiondescription.py | 18 +- tiramisu/storage/__init__.py | 2 + tiramisu/storage/dictionary/__init__.py | 4 +- tiramisu/storage/dictionary/option.py | 40 ++++- tiramisu/storage/sqlalchemy/__init__.py | 4 +- tiramisu/storage/sqlalchemy/option.py | 228 +++++++++++++++++------- 14 files changed, 492 insertions(+), 251 deletions(-) diff --git a/test/test_dyn_optiondescription.py b/test/test_dyn_optiondescription.py index d5796a6..12d45b3 100644 --- a/test/test_dyn_optiondescription.py +++ b/test/test_dyn_optiondescription.py @@ -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') diff --git a/test/test_mandatory.py b/test/test_mandatory.py index ee04be2..6ed8084 100644 --- a/test/test_mandatory.py +++ b/test/test_mandatory.py @@ -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) diff --git a/test/test_slots.py b/test/test_slots.py index 6412c81..20beef5 100644 --- a/test/test_slots.py +++ b/test/test_slots.py @@ -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") diff --git a/test/test_state.py b/test/test_state.py index f4be865..824e368 100644 --- a/test/test_state.py +++ b/test/test_state.py @@ -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') + 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' + 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 diff --git a/tiramisu/config.py b/tiramisu/config.py index 8cf061d..4be5440 100644 --- a/tiramisu/config.py +++ b/tiramisu/config.py @@ -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 diff --git a/tiramisu/option/baseoption.py b/tiramisu/option/baseoption.py index d05358c..55aaf71 100644 --- a/tiramisu/option/baseoption.py +++ b/tiramisu/option/baseoption.py @@ -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 diff --git a/tiramisu/option/masterslave.py b/tiramisu/option/masterslave.py index ca12351..4a9ba8b 100644 --- a/tiramisu/option/masterslave.py +++ b/tiramisu/option/masterslave.py @@ -22,87 +22,81 @@ 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): diff --git a/tiramisu/option/option.py b/tiramisu/option/option.py index d809f26..b92a382 100644 --- a/tiramisu/option/option.py +++ b/tiramisu/option/option.py @@ -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, diff --git a/tiramisu/option/optiondescription.py b/tiramisu/option/optiondescription.py index 6edc458..fc7ab04 100644 --- a/tiramisu/option/optiondescription.py +++ b/tiramisu/option/optiondescription.py @@ -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: diff --git a/tiramisu/storage/__init__.py b/tiramisu/storage/__init__.py index a53653b..a95a629 100644 --- a/tiramisu/storage/__init__.py +++ b/tiramisu/storage/__init__.py @@ -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 diff --git a/tiramisu/storage/dictionary/__init__.py b/tiramisu/storage/dictionary/__init__.py index a52bf26..cf7e03d 100644 --- a/tiramisu/storage/dictionary/__init__.py +++ b/tiramisu/storage/dictionary/__init__.py @@ -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) diff --git a/tiramisu/storage/dictionary/option.py b/tiramisu/storage/dictionary/option.py index 481a1f4..ea49b50 100644 --- a/tiramisu/storage/dictionary/option.py +++ b/tiramisu/storage/dictionary/option.py @@ -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) diff --git a/tiramisu/storage/sqlalchemy/__init__.py b/tiramisu/storage/sqlalchemy/__init__.py index cd9a039..75f6984 100644 --- a/tiramisu/storage/sqlalchemy/__init__.py +++ b/tiramisu/storage/sqlalchemy/__init__.py @@ -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) diff --git a/tiramisu/storage/sqlalchemy/option.py b/tiramisu/storage/sqlalchemy/option.py index ee638ab..3945109 100644 --- a/tiramisu/storage/sqlalchemy/option.py +++ b/tiramisu/storage/sqlalchemy/option.py @@ -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()