diff --git a/test/test_parsing_group.py b/test/test_parsing_group.py index 03c99b5..1ae909a 100644 --- a/test/test_parsing_group.py +++ b/test/test_parsing_group.py @@ -503,6 +503,76 @@ def test_values_with_master_and_slaves_master(): assert cfg.ip_admin_eth0.netmask_admin_eth0 == [] +def test_values_with_master_and_slaves_master_pop(): + 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]) + maconfig = OptionDescription('toto', '', [interface1]) + cfg = Config(maconfig) + cfg.read_write() + cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145") + cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.146") + cfg.ip_admin_eth0.netmask_admin_eth0[1] = '255.255.0.0' + assert cfg.ip_admin_eth0.ip_admin_eth0 == ["192.168.230.145", "192.168.230.146"] + assert cfg.ip_admin_eth0.netmask_admin_eth0 == [None, '255.255.0.0'] + assert cfg.cfgimpl_get_values().get_modified_values() == {'ip_admin_eth0.ip_admin_eth0': ( + 'user', + ('192.168.230.145', '192.168.230.146')), + 'ip_admin_eth0.netmask_admin_eth0': ( + {'1': 'user'}, + {'1': '255.255.0.0'})} + cfg.ip_admin_eth0.ip_admin_eth0.pop(0) + assert cfg.cfgimpl_get_values().get_modified_values() == {'ip_admin_eth0.ip_admin_eth0': ( + 'user', + ('192.168.230.146',)), + 'ip_admin_eth0.netmask_admin_eth0': ( + {'0': 'user'}, + {'0': '255.255.0.0'})} + assert cfg.ip_admin_eth0.ip_admin_eth0 == ["192.168.230.146"] + assert cfg.ip_admin_eth0.netmask_admin_eth0 == ['255.255.0.0'] + cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145") + cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.146") + cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.147") + cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.148") + cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.149") + cfg.ip_admin_eth0.netmask_admin_eth0[3] = '255.255.0.0' + cfg.ip_admin_eth0.netmask_admin_eth0[4] = '255.255.0.0' + assert cfg.cfgimpl_get_values().get_modified_values() == {'ip_admin_eth0.ip_admin_eth0': ( + 'user', + ('192.168.230.146', "192.168.230.145", "192.168.230.146", "192.168.230.147", "192.168.230.148", "192.168.230.149")), + 'ip_admin_eth0.netmask_admin_eth0': ( + {'0': 'user', '3': 'user', '4': 'user'}, + {'0': '255.255.0.0', '3': '255.255.0.0', '4': '255.255.0.0'})} + cfg.ip_admin_eth0.ip_admin_eth0.pop(5) + assert cfg.cfgimpl_get_values().get_modified_values() == {'ip_admin_eth0.ip_admin_eth0': ( + 'user', + ('192.168.230.146', "192.168.230.145", "192.168.230.146", "192.168.230.147", "192.168.230.148")), + 'ip_admin_eth0.netmask_admin_eth0': ( + {'0': 'user', '3': 'user', '4': 'user'}, + {'0': '255.255.0.0', '3': '255.255.0.0', '4': '255.255.0.0'})} + cfg.ip_admin_eth0.ip_admin_eth0.pop(2) + assert cfg.cfgimpl_get_values().get_modified_values() == {'ip_admin_eth0.ip_admin_eth0': ( + 'user', + ('192.168.230.146', "192.168.230.145", "192.168.230.147", "192.168.230.148")), + 'ip_admin_eth0.netmask_admin_eth0': ( + {'0': 'user', '2': 'user', '3': 'user'}, + {'0': '255.255.0.0', '2': '255.255.0.0', '3': '255.255.0.0'})} + cfg.ip_admin_eth0.ip_admin_eth0.pop(2) + assert cfg.cfgimpl_get_values().get_modified_values() == {'ip_admin_eth0.ip_admin_eth0': ( + 'user', + ('192.168.230.146', "192.168.230.145", "192.168.230.148")), + 'ip_admin_eth0.netmask_admin_eth0': ( + {'0': 'user', '2': 'user'}, + {'0': '255.255.0.0', '2': '255.255.0.0'})} + cfg.ip_admin_eth0.ip_admin_eth0.pop(2) + assert cfg.cfgimpl_get_values().get_modified_values() == {'ip_admin_eth0.ip_admin_eth0': ( + 'user', + ('192.168.230.146', "192.168.230.145")), + 'ip_admin_eth0.netmask_admin_eth0': ( + {'0': 'user'}, + {'0': '255.255.0.0'})} + + def test_values_with_master_and_slaves_master_error(): 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) diff --git a/tiramisu/option/optiondescription.py b/tiramisu/option/optiondescription.py index 80f481e..816d6aa 100644 --- a/tiramisu/option/optiondescription.py +++ b/tiramisu/option/optiondescription.py @@ -651,6 +651,9 @@ class MasterSlaves(OptionDescription): def pop(self, opt, values, index): for slave in self.getslaves(opt): + slave_path = slave.impl_getpath(values._getcontext()) + slavelen = values._p_.get_max_length(slave_path, None) + # just for raise if needed if not values.is_default_owner(slave, validate_properties=False, validate_meta=False, index=index): multi = values._get_cached_value(slave, validate=False, @@ -658,7 +661,12 @@ class MasterSlaves(OptionDescription): ) if isinstance(multi, Exception): raise multi - multi.pop(index, force=True) + if slavelen > index: + values._p_.resetvalue_index(slave_path, index) + if slavelen > index + 1: + for idx in xrange(index + 1, slavelen): + values._p_.reduce_index(slave_path, idx) + def getitem(self, values, opt, path, validate, force_permissive, trusted_cached_properties, validate_properties, diff --git a/tiramisu/storage/dictionary/value.py b/tiramisu/storage/dictionary/value.py index 8f8b979..336a34e 100644 --- a/tiramisu/storage/dictionary/value.py +++ b/tiramisu/storage/dictionary/value.py @@ -92,6 +92,51 @@ class Values(Cache): """ return path in self._values[0] + def reduce_index(self, path, index): + """ + _values == ((path1, path2), ((idx1_1, idx1_2), None), ((value1_1, value1_2), value2), ((owner1_1, owner1_2), owner2)) + """ + 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) + + def resetvalue_index(self, path, index): + def _resetvalue(nb): + values_idx = list(values[nb]) + del(values_idx[path_idx]) + values[nb] = tuple(values_idx) + + def _resetvalue_index(nb): + values_idx = list(values[nb]) + lvalues = list(values_idx[path_idx]) + del(lvalues[subidx]) + values_idx[path_idx] = tuple(lvalues) + values[nb] = tuple(values_idx) + + 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) + if len(values[1][path_idx]) == 1: + _resetvalue(0) + _resetvalue(1) + _resetvalue(2) + _resetvalue(3) + else: + _resetvalue_index(1) + _resetvalue_index(2) + _resetvalue_index(3) + self._values = tuple(values) + def resetvalue(self, path, session, commit): """remove value means delete value in storage """