diff --git a/test/test_config.py b/test/test_config.py index 92270be..a5e7b75 100644 --- a/test/test_config.py +++ b/test/test_config.py @@ -210,6 +210,19 @@ def test_config_impl_get_path_by_opt(): # assert str(config) == '[od]' +def to_tuple(val): + ret = [] + for v in val: + t = [] + for w in v: + if isinstance(w, list): + t.append(tuple(w)) + else: + t.append(w) + ret.append(tuple(t)) + return tuple(ret) + + def test_get_modified_values(): g1 = IntOption('g1', '', 1) g2 = StrOption('g2', '', 'héhé') @@ -221,21 +234,21 @@ def test_get_modified_values(): root = OptionDescription('root', '', [d1]) config = Config(root) api = getapi(config) - assert api.value.exportation() == ((), (), (), ()) + assert to_tuple(api.value.exportation()) == ((), (), (), ()) api.option('od.g5').value.set('yes') - assert api.value.exportation() == (('od.g5',), (None,), ('yes',), ('user',)) + assert to_tuple(api.value.exportation()) == (('od.g5',), (None,), ('yes',), ('user',)) api.option('od.g4').value.set(True) - assert api.value.exportation() == (('od.g5', 'od.g4'), (None, None), ('yes', True), ('user', 'user')) + assert to_tuple(api.value.exportation()) == (('od.g5', 'od.g4'), (None, None), ('yes', True), ('user', 'user')) api.option('od.g4').value.reset() - assert api.value.exportation() == (('od.g5',), (None,), ('yes',), ('user',)) + assert to_tuple(api.value.exportation()) == (('od.g5',), (None,), ('yes',), ('user',)) api.option('od.g6').value.set([undefined]) - assert api.value.exportation() == (('od.g5', 'od.g6'), (None, None), ('yes', (None,)), ('user', 'user')) + assert to_tuple(api.value.exportation()) == (('od.g5', 'od.g6'), (None, None), ('yes', (None,)), ('user', 'user')) api.option('od.g6').value.set([]) - assert api.value.exportation() == (('od.g5', 'od.g6'), (None, None), ('yes', tuple()), ('user', 'user')) + assert to_tuple(api.value.exportation()) == (('od.g5', 'od.g6'), (None, None), ('yes', tuple()), ('user', 'user')) api.option('od.g6').value.set(['3']) - assert api.value.exportation() == (('od.g5', 'od.g6'), (None, None), ('yes', ('3',)), ('user', 'user')) + assert to_tuple(api.value.exportation()) == (('od.g5', 'od.g6'), (None, None), ('yes', ('3',)), ('user', 'user')) api.option('od.g6').value.set([]) - assert api.value.exportation() == (('od.g5', 'od.g6'), (None, None), ('yes', tuple()), ('user', 'user')) + assert to_tuple(api.value.exportation()) == (('od.g5', 'od.g6'), (None, None), ('yes', tuple()), ('user', 'user')) #def test_has_value(): diff --git a/test/test_duplicate_config.py b/test/test_duplicate_config.py index e651e36..feb036e 100644 --- a/test/test_duplicate_config.py +++ b/test/test_duplicate_config.py @@ -61,6 +61,8 @@ def test_duplicate(): # raises(AssertionError, "_diff_conf(cfg, ncfg)") # ncfg.creole.general.numero_etab = 'oui' # _diff_conf(cfg, ncfg) +def to_tuple(val): + return tuple([tuple(v) for v in val]) def test_duplicate_force_store_value(): @@ -69,8 +71,8 @@ def test_duplicate_force_store_value(): conf2 = Config(descr) api = getapi(conf) api2 = getapi(conf2) - assert api.value.exportation() == (('creole.general.wantref',), (None,), (False,), ('forced',)) - assert api2.value.exportation() == (('creole.general.wantref',), (None,), (False,), ('forced',)) + assert to_tuple(api.value.exportation()) == (('creole.general.wantref',), (None,), (False,), ('forced',)) + assert to_tuple(api2.value.exportation()) == (('creole.general.wantref',), (None,), (False,), ('forced',)) api.option('creole.general.wantref').value.set(True) - assert api.value.exportation() == (('creole.general.wantref',), (None,), (True,), ('user',)) - assert api2.value.exportation() == (('creole.general.wantref',), (None,), (False,), ('forced',)) + assert to_tuple(api.value.exportation()) == (('creole.general.wantref',), (None,), (True,), ('user',)) + assert to_tuple(api2.value.exportation()) == (('creole.general.wantref',), (None,), (False,), ('forced',)) diff --git a/test/test_freeze.py b/test/test_freeze.py index d55c0be..3065e2e 100644 --- a/test/test_freeze.py +++ b/test/test_freeze.py @@ -12,6 +12,18 @@ from tiramisu import ChoiceOption, BoolOption, IntOption, FloatOption, \ from tiramisu.error import PropertiesOptionError, ConfigError +def compare(calculated, expected): + def convert_list(val): + if isinstance(val, list): + val = tuple(val) + return val + # convert to tuple + for idx in range(len(calculated[0])): + right_idx = expected[0].index(calculated[0][idx]) + for typ in range(4): + assert convert_list(calculated[typ][idx]) == expected[typ][right_idx] + + #____________________________________________________________ #freeze def make_description_freeze(): @@ -146,11 +158,11 @@ def test_force_store_value(): descr = make_description_freeze() conf = Config(descr) api = getapi(conf) - assert api.value.exportation() == (('wantref', 'wantref2', 'wantref3'), (None, None, None), (False, False, (False,)), ('forced', 'forced', 'forced')) + compare(api.value.exportation(), (('wantref', 'wantref2', 'wantref3'), (None, None, None), (False, False, (False,)), ('forced', 'forced', 'forced'))) api.option('wantref').value.set(True) - assert api.value.exportation() == (('wantref', 'wantref2', 'wantref3'), (None, None, None), (True, False, (False,)), ('user', 'forced', 'forced')) + compare(api.value.exportation(), (('wantref', 'wantref2', 'wantref3'), (None, None, None), (True, False, (False,)), ('user', 'forced', 'forced'))) api.option('wantref').value.reset() - assert api.value.exportation() == (('wantref', 'wantref2', 'wantref3'), (None, None, None), (False, False, (False,)), ('forced', 'forced', 'forced')) + compare(api.value.exportation(), (('wantref', 'wantref2', 'wantref3'), (None, None, None), (False, False, (False,)), ('forced', 'forced', 'forced'))) def test_force_store_value_no_requirement(): @@ -183,28 +195,28 @@ def test_force_store_value_masterslaves_sub(): descr = MasterSlaves("int", "", [b, c]) odr = OptionDescription('odr', '', [descr]) api = getapi(Config(odr)) - assert api.value.exportation() == (('int.int',), (None,), (tuple(),), ('forced',)) + compare(api.value.exportation(), (('int.int',), (None,), (tuple(),), ('forced',))) def test_force_store_value_callback(): b = IntOption('int', 'Test int option', properties=('force_store_value',), callback=return_val) descr = OptionDescription("int", "", [b]) api = getapi(Config(descr)) - assert api.value.exportation() == (('int',), (None,), (1,), ('forced',)) + compare(api.value.exportation(), (('int',), (None,), (1,), ('forced',))) def test_force_store_value_callback_params(): b = IntOption('int', 'Test int option', properties=('force_store_value',), callback=return_val2, callback_params=Params(kwargs={'value': ParamValue(2)})) descr = OptionDescription("int", "", [b]) api = getapi(Config(descr)) - assert api.value.exportation() == (('int',), (None,), (2,), ('forced',)) + compare(api.value.exportation(), (('int',), (None,), (2,), ('forced',))) def test_force_store_value_callback_params_2(): b = IntOption('int', 'Test int option', properties=('force_store_value',), callback=return_val3, callback_params=Params(ParamContext(), {'value': ParamValue(2)})) descr = OptionDescription("int", "", [b]) api = getapi(Config(descr)) - assert api.value.exportation() == (('int',), (None,), (2,), ('forced',)) + compare(api.value.exportation(), (('int',), (None,), (2,), ('forced',))) def test_force_store_value_callback_params_with_opt(): @@ -212,4 +224,4 @@ def test_force_store_value_callback_params_with_opt(): b = IntOption('int', 'Test int option', properties=('force_store_value',), callback=return_val2, callback_params=Params(kwargs={'value': ParamOption(a)})) descr = OptionDescription("int", "", [a, b]) api = getapi(Config(descr)) - assert api.value.exportation() == (('int',), (None,), (2,), ('forced',)) + compare(api.value.exportation(), (('int',), (None,), (2,), ('forced',))) diff --git a/test/test_masterslaves.py b/test/test_masterslaves.py index f10ad49..386419a 100644 --- a/test/test_masterslaves.py +++ b/test/test_masterslaves.py @@ -11,6 +11,18 @@ from tiramisu.api import TIRAMISU_VERSION from py.test import raises +def compare(calculated, expected): + def convert_list(val): + if isinstance(val, list): + val = tuple(val) + return val + # convert to tuple + for idx in range(len(calculated[0])): + right_idx = expected[0].index(calculated[0][idx]) + for typ in range(4): + assert convert_list(calculated[typ][idx]) == expected[typ][right_idx] + + def make_description(): numero_etab = StrOption('numero_etab', "identifiant de l'établissement") nom_machine = StrOption('nom_machine', "nom de la machine", default="eoleng") @@ -513,23 +525,23 @@ def test_values_with_master_and_slaves_master_pop(): assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == ["192.168.230.145", "192.168.230.146"] assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == None assert api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == '255.255.0.0' - assert api.value.exportation() == (('ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'), (None, (1,)), (('192.168.230.145', '192.168.230.146'), ('255.255.0.0',)), ('user', ('user',))) + compare(api.value.exportation(), (('ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'), (None, (1,)), (('192.168.230.145', '192.168.230.146'), ('255.255.0.0',)), ('user', ('user',)))) api.option('ip_admin_eth0.ip_admin_eth0').value.pop(0) - assert api.value.exportation() == (('ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'), (None, (0,)), (('192.168.230.146',), ('255.255.0.0',)), ('user', ('user',))) + compare(api.value.exportation(), (('ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'), (None, (0,)), (('192.168.230.146',), ('255.255.0.0',)), ('user', ('user',)))) assert api.option('ip_admin_eth0.ip_admin_eth0').value.get() == ["192.168.230.146"] assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == '255.255.0.0' api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.230.146', "192.168.230.145", "192.168.230.146", "192.168.230.147", "192.168.230.148", "192.168.230.149"]) api.option('ip_admin_eth0.netmask_admin_eth0', 3).value.set('255.255.0.0') api.option('ip_admin_eth0.netmask_admin_eth0', 4).value.set('255.255.0.0') - assert api.value.exportation() == (('ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'), (None, (0, 3, 4)), (('192.168.230.146', "192.168.230.145", "192.168.230.146", "192.168.230.147", "192.168.230.148", "192.168.230.149"), ('255.255.0.0', '255.255.0.0', '255.255.0.0')), ('user', ('user', 'user', 'user'))) + compare(api.value.exportation(), (('ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'), (None, (0, 3, 4)), (('192.168.230.146', "192.168.230.145", "192.168.230.146", "192.168.230.147", "192.168.230.148", "192.168.230.149"), ('255.255.0.0', '255.255.0.0', '255.255.0.0')), ('user', ('user', 'user', 'user')))) api.option('ip_admin_eth0.ip_admin_eth0').value.pop(5) - assert api.value.exportation() == (('ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'), (None, (0, 3, 4)), (('192.168.230.146', "192.168.230.145", "192.168.230.146", "192.168.230.147", "192.168.230.148"), ('255.255.0.0', '255.255.0.0', '255.255.0.0')), ('user', ('user', 'user', 'user'))) + compare(api.value.exportation(), (('ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'), (None, (0, 3, 4)), (('192.168.230.146', "192.168.230.145", "192.168.230.146", "192.168.230.147", "192.168.230.148"), ('255.255.0.0', '255.255.0.0', '255.255.0.0')), ('user', ('user', 'user', 'user')))) api.option('ip_admin_eth0.ip_admin_eth0').value.pop(2) - assert api.value.exportation() == (('ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'), (None, (0, 2, 3)), (('192.168.230.146', "192.168.230.145", "192.168.230.147", "192.168.230.148"), ('255.255.0.0', '255.255.0.0', '255.255.0.0')), ('user', ('user', 'user', 'user'))) + compare(api.value.exportation(), (('ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'), (None, (0, 2, 3)), (('192.168.230.146', "192.168.230.145", "192.168.230.147", "192.168.230.148"), ('255.255.0.0', '255.255.0.0', '255.255.0.0')), ('user', ('user', 'user', 'user')))) api.option('ip_admin_eth0.ip_admin_eth0').value.pop(2) - assert api.value.exportation() == (('ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'), (None, (0, 2)), (('192.168.230.146', "192.168.230.145", "192.168.230.148"), ('255.255.0.0', '255.255.0.0')), ('user', ('user', 'user'))) + compare(api.value.exportation(), (('ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'), (None, (0, 2)), (('192.168.230.146', "192.168.230.145", "192.168.230.148"), ('255.255.0.0', '255.255.0.0')), ('user', ('user', 'user')))) api.option('ip_admin_eth0.ip_admin_eth0').value.pop(2) - assert api.value.exportation() == (('ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'), (None, (0,)), (('192.168.230.146', "192.168.230.145"), ('255.255.0.0',)), ('user', ('user',))) + compare(api.value.exportation(), (('ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'), (None, (0,)), (('192.168.230.146', "192.168.230.145"), ('255.255.0.0',)), ('user', ('user',)))) def test_values_with_master_owner(): @@ -610,14 +622,31 @@ def test_groups_with_master_get_modified_value(): maconfig = OptionDescription('toto', '', [interface1]) api = getapi(Config(maconfig)) api.property.read_write() - assert api.value.exportation() == ((), (), (), ()) + compare(api.value.exportation(), ((), (), (), ())) api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.1']) - assert api.value.exportation() == (('ip_admin_eth0.ip_admin_eth0',), (None,), (('192.168.1.1',),), ('user',)) + compare(api.value.exportation(), (('ip_admin_eth0.ip_admin_eth0',), (None,), (('192.168.1.1',),), ('user',))) api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set('255.255.255.255') - assert api.value.exportation() == (('ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0',), (None, (0,)), (('192.168.1.1',), ('255.255.255.255',)), ('user', ('user',))) + compare(api.value.exportation(), (('ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0',), (None, (0,)), (('192.168.1.1',), ('255.255.255.255',)), ('user', ('user',)))) api.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.1', '192.168.1.1']) api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.set('255.255.255.255') - assert api.value.exportation() == (('ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0',), (None, (0, 1)), (('192.168.1.1', '192.168.1.1'), ('255.255.255.255', '255.255.255.255')), ('user', ('user', 'user'))) + compare(api.value.exportation(), (('ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0',), (None, (0, 1)), (('192.168.1.1', '192.168.1.1'), ('255.255.255.255', '255.255.255.255')), ('user', ('user', 'user')))) + + +def test_groups_with_master_importation(): + ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True) + netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True) + interface1 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + #interface1.impl_set_group_type(groups.master) + maconfig = OptionDescription('toto', '', [interface1]) + api = getapi(Config(maconfig)) + api.property.read_write() + api.value.importation((('ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0',), (None, (0, 1)), (('192.168.1.1', '192.168.1.0'), ('255.255.255.255', '255.255.255.0')), ('user', ('user', 'user')))) + api.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['192.168.1.1', '192.168.1.0'] + api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == '255.255.255.255' + api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == '255.255.255.0' + api.option('ip_admin_eth0.ip_admin_eth0').owner.get() == 'user' + api.option('ip_admin_eth0.netmask_admin_eth0', 0).owner.get() == 'user' + api.option('ip_admin_eth0.netmask_admin_eth0', 1).owner.get() == 'user' def test_wrong_index(): diff --git a/tiramisu/config.py b/tiramisu/config.py index 94b5501..f2f1748 100644 --- a/tiramisu/config.py +++ b/tiramisu/config.py @@ -680,18 +680,20 @@ class _CommonConfig(SubConfig): persistent=False, force_values=get_default_values_storages(), force_settings=self.cfgimpl_get_settings()) - fake_config.cfgimpl_get_values()._p_.importation(self.cfgimpl_get_values()._p_.exportation(fake=True)) + fake_config.cfgimpl_get_values()._p_.importation(self.cfgimpl_get_values()._p_.exportation()) return fake_config def duplicate(self, session_id=None, force_values=None, - force_settings=None): + force_settings=None, + storage=None): config = Config(self._impl_descr, _duplicate=True, session_id=session_id, force_values=force_values, - force_settings=force_settings) + force_settings=force_settings, + storage=storage) config.cfgimpl_get_values()._p_.importation(self.cfgimpl_get_values()._p_.exportation()) config.cfgimpl_get_settings()._p_.importation(self.cfgimpl_get_settings( )._p_.exportation()) @@ -711,7 +713,8 @@ class Config(_CommonConfig): persistent=False, force_values=None, force_settings=None, - _duplicate=False): + _duplicate=False, + storage=None): """ Configuration option management master class :param descr: describes the configuration schema @@ -741,7 +744,8 @@ class Config(_CommonConfig): else: properties, permissives, values, session_id = get_storages(self, session_id, - persistent) + persistent, + storage=storage) if not valid_name(session_id): raise ValueError(_("invalid session ID: {0} for config").format(session_id)) self._impl_settings = Settings(self, @@ -774,7 +778,8 @@ class GroupConfig(_CommonConfig): children, session_id=None, persistent=False, - _descr=None): + _descr=None, + storage=None): if not isinstance(children, list): raise ValueError(_("groupconfig's children must be a list")) names = [] @@ -793,7 +798,8 @@ class GroupConfig(_CommonConfig): self._impl_children = children properties, permissives, values, session_id = get_storages(self, session_id, - persistent) + persistent, + storage=storage) self._impl_settings = Settings(self, properties, permissives) diff --git a/tiramisu/option/masterslave.py b/tiramisu/option/masterslave.py index 58cd617..9d3bc71 100644 --- a/tiramisu/option/masterslave.py +++ b/tiramisu/option/masterslave.py @@ -139,8 +139,9 @@ class MasterSlaves(OptionDescription): index) if slavelen > index + 1: for idx in range(index + 1, slavelen): - values._p_.reduce_index(slave_path, - idx) + if values._p_.hasvalue(slave_path, idx): + values._p_.reduce_index(slave_path, + idx) def reset_cache(self, path, diff --git a/tiramisu/storage/__init__.py b/tiramisu/storage/__init__.py index cf6c2e0..f67a4b9 100644 --- a/tiramisu/storage/__init__.py +++ b/tiramisu/storage/__init__.py @@ -36,7 +36,8 @@ from ..i18n import _ MODULE_PATH = os.path.split(os.path.split(os.path.split(__file__)[0])[0])[1] -DEFAULT_STORAGE = 'dictionary' +MEMORY_STORAGE = 'dictionary' +DEFAULT_STORAGE = MEMORY_STORAGE class StorageType(object): @@ -79,8 +80,8 @@ class StorageType(object): storage_type = StorageType() #storage_option_type = StorageType() #storage_option_type.set(DEFAULT_STORAGE) -default_validation = StorageType() -default_validation.set(DEFAULT_STORAGE) +memory_storage = StorageType() +memory_storage.set(MEMORY_STORAGE) def set_storage(type_, name): # pragma: optional cover @@ -95,28 +96,30 @@ def set_storage(type_, name): # pragma: optional cover setting = storage_type.get().setting -def get_storages(context, session_id, persistent): +def get_storages(context, session_id, persistent, storage): def gen_id(config): return 'c' + str(id(config)) + str(int(time())) + str(randint(0, 500)) if session_id is None: session_id = gen_id(context) - imp = storage_type.get() - storage = imp.Storage(session_id, persistent) - properties = imp.Properties(storage) - permissives = imp.Permissives(storage) - values = imp.Values(storage) + if storage is None: + storage = storage_type + imp = storage.get() + imp_storage = imp.Storage(session_id, persistent) + properties = imp.Properties(imp_storage) + permissives = imp.Permissives(imp_storage) + values = imp.Values(imp_storage) return properties, permissives, values, session_id def get_default_values_storages(): - imp = default_validation.get() + imp = memory_storage.get() storage = imp.Storage('__validator_storage', persistent=False, test=True) return imp.Values(storage) def get_default_settings_storages(): - imp = default_validation.get() + imp = memory_storage.get() storage = imp.Storage('__validator_storage', persistent=False, test=True) properties = imp.Properties(storage) permissives = imp.Permissives(storage) diff --git a/tiramisu/storage/dictionary/setting.py b/tiramisu/storage/dictionary/setting.py index 9bd0cf0..317081f 100644 --- a/tiramisu/storage/dictionary/setting.py +++ b/tiramisu/storage/dictionary/setting.py @@ -96,4 +96,3 @@ class Permissives(Cache): def importation(self, permissives): self._permissives = permissives - diff --git a/tiramisu/storage/dictionary/value.py b/tiramisu/storage/dictionary/value.py index 38bc739..f0ef835 100644 --- a/tiramisu/storage/dictionary/value.py +++ b/tiramisu/storage/dictionary/value.py @@ -71,7 +71,12 @@ class Values(Cache): return vidx # value - def setvalue(self, path, value, owner, index, commit): + def setvalue(self, + path, + value, + owner, + index, + commit): """set value for a path a specified value must be associated to an owner """ @@ -114,16 +119,18 @@ class Values(Cache): if DEBUG: # pragma: no cover print('reduce_index', path, index, id(self)) path_idx = self._values[0].index(path) - indexes = self._values[1][path_idx] - if index in indexes: - subidx = indexes.index(index) - values = list(self._values) - values_idx = list(values[1]) - lvalues = list(values_idx[path_idx]) - lvalues[subidx] = lvalues[subidx] - 1 - values_idx[path_idx] = tuple(lvalues) - values[1] = tuple(values_idx) - self._values = tuple(values) + # get the "index" position + subidx = self._values[1][path_idx].index(index) + # transform tuple to list + values = list(self._values) + values_idx = list(values[1]) + lvalues = list(values_idx[path_idx]) + # reduce to one the index + lvalues[subidx] = lvalues[subidx] - 1 + # store modification + values_idx[path_idx] = tuple(lvalues) + values[1] = tuple(values_idx) + self._values = tuple(values) def resetvalue_index(self, path, index): if DEBUG: # pragma: no cover @@ -156,7 +163,9 @@ class Values(Cache): _resetvalue_index(3) self._values = tuple(values) - def resetvalue(self, path, commit): + def resetvalue(self, + path, + commit): """remove value means delete value in storage """ if DEBUG: # pragma: no cover @@ -189,7 +198,8 @@ class Values(Cache): lst[3] = tuple(values[0]) self._values = tuple(lst) - def get_max_length(self, path): + def get_max_length(self, + path): if path in self._values[0]: idx = self._values[0].index(path) else: @@ -276,7 +286,7 @@ class Values(Cache): if raises: raise ValueError(_("information's item not found {0}").format(key)) - def exportation(self, fake=False): + def exportation(self): return self._values def importation(self, export): diff --git a/tiramisu/storage/sqlite3/setting.py b/tiramisu/storage/sqlite3/setting.py index fea200b..ffb9791 100644 --- a/tiramisu/storage/sqlite3/setting.py +++ b/tiramisu/storage/sqlite3/setting.py @@ -18,6 +18,10 @@ from .sqlite3db import Sqlite3DB +DEBUG=False +#DEBUG=True + + class Properties(Sqlite3DB): __slots__ = tuple() @@ -35,11 +39,6 @@ class Properties(Sqlite3DB): self._sqlite_encode(properties), self._session_id)) - def delproperties(self, path): - path = self._sqlite_encode_path(path) - self._storage.execute("DELETE FROM property WHERE path = ? AND session_id = ?", - (path, self._session_id)) - def getproperties(self, path, default_properties): path = self._sqlite_encode_path(path) value = self._storage.select("SELECT properties FROM property WHERE " @@ -52,7 +51,7 @@ class Properties(Sqlite3DB): def reset_all_properties(self): self._storage.execute("DELETE FROM property WHERE session_id = ?", (self._session_id,)) - def reset_properties(self, path): + def delproperties(self, path): path = self._sqlite_encode_path(path) self._storage.execute("DELETE FROM property WHERE path = ? AND session_id = ?", (path, self._session_id)) @@ -87,6 +86,8 @@ class Permissives(Sqlite3DB): # permissive def setpermissive(self, path, permissive): path = self._sqlite_encode_path(path) + if DEBUG: # pragma: no cover + print('setpermissive', path, permissive, id(self)) self._storage.execute("DELETE FROM permissive WHERE path = ? AND session_id = ?", (path, self._session_id), False) @@ -96,13 +97,17 @@ class Permissives(Sqlite3DB): self._session_id)) def getpermissive(self, path='_none'): + path = self._sqlite_encode_path(path) permissives = self._storage.select("SELECT permissives FROM " "permissive WHERE path = ? AND session_id = ? LIMIT 1", (path, self._session_id)) if permissives is None: - return frozenset() + ret = frozenset() else: - return frozenset(self._sqlite_decode(permissives[0])) + ret = frozenset(self._sqlite_decode(permissives[0])) + if DEBUG: # pragma: no cover + print('getpermissive', path, ret, id(self)) + return ret def exportation(self): """return all modified permissives in a dictionary diff --git a/tiramisu/storage/sqlite3/sqlite3db.py b/tiramisu/storage/sqlite3/sqlite3db.py index 9bbf671..2202b13 100644 --- a/tiramisu/storage/sqlite3/sqlite3db.py +++ b/tiramisu/storage/sqlite3/sqlite3db.py @@ -44,6 +44,6 @@ class Sqlite3DB(Cache): return loads(value) def _sqlite_encode(self, value): - if isinstance(value, list): + if isinstance(value, tuple): value = list(value) return dumps(value) diff --git a/tiramisu/storage/sqlite3/storage.py b/tiramisu/storage/sqlite3/storage.py index 1ea2ff5..b22ce9b 100644 --- a/tiramisu/storage/sqlite3/storage.py +++ b/tiramisu/storage/sqlite3/storage.py @@ -60,12 +60,11 @@ global CONN CONN = None class Storage(object): - __slots__ = ('_conn', '_cursor', 'persistent', 'session_id', 'serializable') + __slots__ = ('_conn', '_cursor', 'persistent', 'session_id') storage = 'sqlite3' def __init__(self, session_id, persistent, test=False): self.persistent = persistent - self.serializable = self.persistent self.session_id = session_id global CONN init = False diff --git a/tiramisu/storage/sqlite3/value.py b/tiramisu/storage/sqlite3/value.py index 1852e9a..5e9793c 100644 --- a/tiramisu/storage/sqlite3/value.py +++ b/tiramisu/storage/sqlite3/value.py @@ -22,6 +22,10 @@ from ...setting import undefined, owners from ...i18n import _ +DEBUG = False +#DEBUG = True + + class Values(Sqlite3DB): __slots__ = ('__weakref__',) @@ -47,14 +51,21 @@ class Values(Sqlite3DB): self._storage.commit() # value - def setvalue(self, path, value, owner, index, session, commit): + def setvalue(self, + path, + value, + owner, + index, + commit): """set value for an option a specified value must be associated to an owner """ + if DEBUG: + print('setvalue', path, value, owner, index, commit) path = self._sqlite_encode_path(path) if index is not None: - self._storage.execute("DELETE FROM value WHERE path = ? AND idx = ? AND " - "session_id = ?", (path, index, self._session_id), + self.resetvalue_index(path, + index, commit=False) self._storage.execute("INSERT INTO value(path, value, owner, idx, session_id) VALUES " "(?, ?, ?, ?, ?)", (path, self._sqlite_encode(value), @@ -63,33 +74,71 @@ class Values(Sqlite3DB): self._session_id), commit=commit) else: - self._storage.execute("DELETE FROM value WHERE path = ? AND session_id = ?", - (path, self._session_id), - commit=False) + self.resetvalue(path, + commit=False) self._storage.execute("INSERT INTO value(path, value, owner, session_id) VALUES " "(?, ?, ?, ?)", (path, self._sqlite_encode(value), str(owner), self._session_id), commit=commit) - def hasvalue(self, path, index=None): + def hasvalue(self, + path, + index=None): """if opt has a value return: boolean """ + if DEBUG: + print('hasvalue', path, index) path = self._sqlite_encode_path(path) return self._sqlite_select(path, index) is not None - def resetvalue(self, path, session, _commit): + + def reduce_index(self, path, index): + """ + _values == ((path1, path2), ((idx1_1, idx1_2), None), + ((value1_1, value1_2), value2), ((owner1_1, owner1_2), owner2)) + """ + if DEBUG: # pragma: no cover + print('reduce_index', path, index, id(self)) + self._storage.execute("UPDATE value SET idx = ? WHERE path = ? and idx = ? " + "AND session_id = ?", + (index - 1, path, index, self._session_id)) + + def resetvalue_index(self, + path, + index, + commit=True): """remove value means delete value in storage """ + if DEBUG: + print('resetvalue_index', path, index, commit) path = self._sqlite_encode_path(path) - self._storage.execute("DELETE FROM value WHERE path = ? AND session_id = ?", (path, self._session_id), - commit=_commit) + self._storage.execute("DELETE FROM value WHERE path = ? AND session_id = ? AND idx = ?", + (path, self._session_id, index), + commit=commit) + + def resetvalue(self, + path, + commit): + """remove value means delete value in storage + """ + if DEBUG: + print('resetvalue', path, commit) + path = self._sqlite_encode_path(path) + self._storage.execute("DELETE FROM value WHERE path = ? AND session_id = ?", + (path, self._session_id), + commit=commit) # owner - def setowner(self, path, owner, session, index=None): + def setowner(self, + path, + owner, + index=None): """change owner for an option """ + if DEBUG: + print('setowner', path, owner, index) path = self._sqlite_encode_path(path) if index is None: self._storage.execute("UPDATE value SET owner = ? WHERE path = ? AND session_id = ?", @@ -98,10 +147,16 @@ class Values(Sqlite3DB): self._storage.execute("UPDATE value SET owner = ? WHERE path = ? and idx = ? AND session_id = ?", (str(owner), path, index, self._session_id)) - def getowner(self, path, default, session, index=None, only_default=False, with_value=False): + def getowner(self, + path, + default, + index=None, + with_value=False): """get owner for an option return: owner object """ + if DEBUG: + print('getowner', path, default, index, with_value) path = self._sqlite_encode_path(path) request = "SELECT owner, value FROM value WHERE path = ? AND session_id = ?" if index is not None: @@ -136,6 +191,8 @@ class Values(Sqlite3DB): :param key: information's key (ex: "help", "doc" :param value: information's value (ex: "the help string") """ + if DEBUG: + print('set_information', key, value) self._storage.execute("DELETE FROM information WHERE key = ? AND session_id = ?", (key, self._session_id), False) @@ -147,6 +204,8 @@ class Values(Sqlite3DB): :param key: the item string (ex: "help") """ + if DEBUG: + print('get_information', key, default) value = self._storage.select("SELECT value FROM information WHERE key = ? AND " "session_id = ?", (key, self._session_id)) @@ -159,6 +218,8 @@ class Values(Sqlite3DB): return self._sqlite_decode(value[0]) def del_information(self, key, raises): + if DEBUG: + print('del_information', key, raises) if raises and self._storage.select("SELECT value FROM information WHERE key = ? " "AND session_id = ?", (key, self._session_id)) is None: @@ -166,7 +227,9 @@ class Values(Sqlite3DB): self._storage.execute("DELETE FROM information WHERE key = ? AND session_id = ?", (key, self._session_id)) - def exportation(self, session, fake=False): + def exportation(self): + if DEBUG: + print('exportation') rows = self._storage.select("SELECT path, value, owner, idx FROM value WHERE " "session_id = ?;", (self._session_id,), only_one=False) ret = [[], [], [], []] @@ -185,15 +248,18 @@ class Values(Sqlite3DB): path_idx = ret[0].index(path) ret[1][path_idx].append(index) ret[2][path_idx].append(value) + ret[3][path_idx].append(owner) else: ret[0].append(path) ret[1].append([index]) ret[2].append([value]) - ret[3].append(owner) + ret[3].append([owner]) return ret def importation(self, export): + if DEBUG: + print('importation') self._storage.execute("DELETE FROM value WHERE session_id = ?", (self._session_id,), commit=False) for idx, path in enumerate(export[0]): @@ -215,7 +281,10 @@ class Values(Sqlite3DB): commit=False) self._storage._conn.commit() - def get_max_length(self, path, session): + def get_max_length(self, + path): + if DEBUG: + print('get_max_length', path) val_max = self._storage.select("SELECT max(idx) FROM value WHERE path = ? AND session_id = ?", (path, self._session_id), False) if val_max[0][0] is None: