add index to properties/permissives

This commit is contained in:
Emmanuel Garette 2019-11-19 18:39:44 +01:00
parent 15669372db
commit 7325f6e12f
5 changed files with 183 additions and 134 deletions

View file

@ -17,6 +17,7 @@
from inspect import ismethod, getdoc, signature from inspect import ismethod, getdoc, signature
from time import time from time import time
from typing import List, Set, Any, Optional, Callable, Union, Dict from typing import List, Set, Any, Optional, Callable, Union, Dict
from warnings import catch_warnings, simplefilter
from .error import APIError, ConfigError, LeadershipError, PropertiesOptionError, ValueErrorWarning from .error import APIError, ConfigError, LeadershipError, PropertiesOptionError, ValueErrorWarning
@ -134,7 +135,7 @@ class CommonTiramisuOption(CommonTiramisu):
if not option.impl_is_optiondescription() and \ if not option.impl_is_optiondescription() and \
self._option_bag.index is None and \ self._option_bag.index is None and \
option.impl_is_follower(): option.impl_is_follower():
raise APIError(_('index must be set with the follower option "{}"').format(self._option_bag.path)) raise APIError(_('index must be set with the follower option "{}"').format(self._option_bag.option.impl_get_display_name()))
def __getattr__(self, name): def __getattr__(self, name):
raise APIError(_('unknown method {} in {}').format(name, self.__class__.__name__)) raise APIError(_('unknown method {} in {}').format(name, self.__class__.__name__))
@ -389,6 +390,7 @@ class TiramisuOptionProperty(CommonTiramisuOption):
raise ConfigError(_('cannot add this property: "{0}"').format( raise ConfigError(_('cannot add this property: "{0}"').format(
' '.join(prop))) ' '.join(prop)))
props = self._settings._p_.getproperties(self._option_bag.path, props = self._settings._p_.getproperties(self._option_bag.path,
self._option_bag.index,
option.impl_getproperties()) option.impl_getproperties())
self._settings.setproperties(self._option_bag.path, self._settings.setproperties(self._option_bag.path,
props | {prop}, props | {prop},
@ -399,6 +401,7 @@ class TiramisuOptionProperty(CommonTiramisuOption):
"""Remove new property for an option""" """Remove new property for an option"""
option = self._option_bag.option option = self._option_bag.option
props = self._settings._p_.getproperties(self._option_bag.path, props = self._settings._p_.getproperties(self._option_bag.path,
self._option_bag.index,
option.impl_getproperties()) option.impl_getproperties())
self._settings.setproperties(self._option_bag.path, self._settings.setproperties(self._option_bag.path,
props - {prop}, props - {prop},
@ -430,8 +433,7 @@ class TiramisuOptionPermissive(CommonTiramisuOption):
def get(self): def get(self):
"""Get permissives value""" """Get permissives value"""
return self._settings.getpermissives(self._option_bag.option, return self._settings.getpermissives(self._option_bag)
self._option_bag.path)
def set(self, permissives): def set(self, permissives):
"""Set permissives value""" """Set permissives value"""
@ -528,7 +530,8 @@ class _TiramisuOptionValueOption:
def valid(self): def valid(self):
try: try:
with warnings.catch_warnings(record=True) as warns: with catch_warnings(record=True) as warns:
simplefilter("always", ValueErrorWarning)
self.get() self.get()
for warn in warns: for warn in warns:
if isinstance(warns.message, ValueErrorWarning): if isinstance(warns.message, ValueErrorWarning):
@ -538,6 +541,13 @@ class _TiramisuOptionValueOption:
return True return True
class _TiramisuOptionValueChoiceOption:
def list(self):
"""All values available for a ChoiceOption"""
option = self._option_bag.option
return option.impl_get_values(self._option_bag)
class _TiramisuOptionValueLeader: class _TiramisuOptionValueLeader:
def pop(self, index): def pop(self, index):
"""Pop a value""" """Pop a value"""
@ -556,12 +566,6 @@ class _TiramisuOptionValueLeader:
return self._length return self._length
class _TiramisuOptionValueGroup:
def reset(self):
"""Reset value"""
self._option_bag.config_bag.context.reset(self._option_bag.path)
class _TiramisuOptionValueFollower: class _TiramisuOptionValueFollower:
def len(self): def len(self):
"""Length of follower option""" """Length of follower option"""
@ -572,16 +576,10 @@ class _TiramisuOptionValueFollower:
return self._length return self._length
class _TiramisuOptionValueChoiceOption: class _TiramisuOptionValueGroup:
def list(self): def reset(self):
"""All values available for a ChoiceOption""" """Reset value"""
option = self._option_bag.option self._option_bag.config_bag.context.reset(self._option_bag.path)
return option.impl_get_values(self._option_bag)
def callbacks(self):
"""Get callbacks for a values"""
option = self._option_bag.option
return option.get_callback()
class _TiramisuOptionValueOptionDescription: class _TiramisuOptionValueOptionDescription:
@ -901,6 +899,7 @@ class TiramisuContextValue(TiramisuConfig):
"""Return path of options with mandatory property without any value""" """Return path of options with mandatory property without any value"""
return self._config_bag.context.cfgimpl_get_values().mandatory_warnings(self._config_bag) return self._config_bag.context.cfgimpl_get_values().mandatory_warnings(self._config_bag)
# FIXME should be only for group/meta
def set(self, def set(self,
path: str, path: str,
value, value,
@ -925,6 +924,7 @@ class TiramisuContextValue(TiramisuConfig):
self._config_bag, self._config_bag,
**kwargs) **kwargs)
# FIXME should be only for group/meta
def reset(self, def reset(self,
path: str, path: str,
only_children: bool=False): only_children: bool=False):
@ -1026,20 +1026,20 @@ class TiramisuContextProperty(TiramisuConfig):
"""Add a config property""" """Add a config property"""
props = set(self.get()) props = set(self.get())
props.add(prop) props.add(prop)
self.set(frozenset(props)) self._set(frozenset(props))
def pop(self, prop): def pop(self, prop):
"""Remove a config property""" """Remove a config property"""
props = set(self.get()) props = set(self.get())
if prop in props: if prop in props:
props.remove(prop) props.remove(prop)
self.set(frozenset(props)) self._set(frozenset(props))
def get(self): def get(self):
"""Get all config properties""" """Get all config properties"""
return self._config_bag.properties return self._config_bag.properties
def set(self, props): def _set(self, props):
"""Personalise config properties""" """Personalise config properties"""
if 'force_store_value' in props: if 'force_store_value' in props:
force_store_value = 'force_store_value' not in self._config_bag.properties force_store_value = 'force_store_value' not in self._config_bag.properties
@ -1065,7 +1065,7 @@ class TiramisuContextProperty(TiramisuConfig):
def importation(self, properties): def importation(self, properties):
"""Import config properties""" """Import config properties"""
if 'force_store_value' in properties.get(None, []): if 'force_store_value' in properties.get(None, {}).get(None, []):
force_store_value = 'force_store_value' not in self._config_bag.properties force_store_value = 'force_store_value' not in self._config_bag.properties
else: else:
force_store_value = False force_store_value = False
@ -1134,7 +1134,7 @@ class TiramisuContextPermissive(TiramisuConfig):
"""Get config permissives""" """Get config permissives"""
return self._config_bag.context.cfgimpl_get_settings().get_context_permissives() return self._config_bag.context.cfgimpl_get_settings().get_context_permissives()
def set(self, permissives): def _set(self, permissives):
"""Set config permissives""" """Set config permissives"""
self._config_bag.context.cfgimpl_get_settings().set_context_permissives(permissives) self._config_bag.context.cfgimpl_get_settings().set_context_permissives(permissives)
del self._config_bag.permissives del self._config_bag.permissives
@ -1161,14 +1161,14 @@ class TiramisuContextPermissive(TiramisuConfig):
"""Add a config permissive""" """Add a config permissive"""
props = set(self.get()) props = set(self.get())
props.add(prop) props.add(prop)
self.set(frozenset(props)) self._set(frozenset(props))
def pop(self, prop): def pop(self, prop):
"""Remove a config permissive""" """Remove a config permissive"""
props = set(self.get()) props = set(self.get())
if prop in props: if prop in props:
props.remove(prop) props.remove(prop)
self.set(frozenset(props)) self._set(frozenset(props))
class TiramisuContextOption(TiramisuConfig): class TiramisuContextOption(TiramisuConfig):

View file

@ -15,6 +15,7 @@
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# ____________________________________________________________ # ____________________________________________________________
from itertools import chain
from .error import PropertiesOptionError, ConstError, ConfigError, LeadershipError, display_list from .error import PropertiesOptionError, ConstError, ConfigError, LeadershipError, display_list
from .i18n import _ from .i18n import _
@ -42,11 +43,6 @@ frozen
cannot set value for option with this properties if 'frozen' is set in cannot set value for option with this properties if 'frozen' is set in
config config
mandatory
should set value for option with this properties if 'mandatory' is set in
config
* Special property: * Special property:
permissive permissive
@ -55,6 +51,16 @@ permissive
config with 'permissive', whole option in this config cannot raise config with 'permissive', whole option in this config cannot raise
PropertiesOptionError for properties set in permissive PropertiesOptionError for properties set in permissive
mandatory
should set value for option with this properties if 'mandatory' is set in
config
empty
raise mandatory PropertiesOptionError if multi or leader have empty value
unique
raise ValueError if a value is set twice or more in a multi Option
* Special Config properties: * Special Config properties:
cache cache
@ -67,9 +73,6 @@ everything_frozen
whole option in config are frozen (even if option have not frozen whole option in config are frozen (even if option have not frozen
property) property)
empty
raise mandatory PropertiesOptionError if multi or leader have empty value
validator validator
launch validator set by user in option (this property has no effect launch validator set by user in option (this property has no effect
for internal validator) for internal validator)
@ -109,6 +112,7 @@ FORBIDDEN_SET_PERMISSIVES = frozenset(['force_default_on_freeze',
'force_metaconfig_on_freeze', 'force_metaconfig_on_freeze',
'force_store_value']) 'force_store_value'])
ALLOWED_LEADER_PROPERTIES = frozenset(['empty', ALLOWED_LEADER_PROPERTIES = frozenset(['empty',
'unique',
'force_store_value', 'force_store_value',
'mandatory', 'mandatory',
'force_default_on_freeze', 'force_default_on_freeze',
@ -405,6 +409,7 @@ class Settings(object):
'context_props') 'context_props')
if not is_cached: if not is_cached:
props = self._p_.getproperties(None, props = self._p_.getproperties(None,
None,
self.default_properties) self.default_properties)
cache.setcache(None, cache.setcache(None,
None, None,
@ -416,11 +421,9 @@ class Settings(object):
def getproperties(self, def getproperties(self,
option_bag, option_bag,
apply_requires=True, apply_requires=True):
search_properties=None):
""" """
""" """
# FIXME search_properties
option = option_bag.option option = option_bag.option
config_bag = option_bag.config_bag config_bag = option_bag.config_bag
if option.impl_is_symlinkoption(): if option.impl_is_symlinkoption():
@ -430,25 +433,32 @@ class Settings(object):
if apply_requires: if apply_requires:
cache = config_bag.context._impl_properties_cache cache = config_bag.context._impl_properties_cache
props = config_bag.properties config_bag_props = config_bag.properties
is_cached, props, validated = cache.getcache(path, is_cached, props, validated = cache.getcache(path,
config_bag.expiration_time, config_bag.expiration_time,
index, index,
props, config_bag_props,
{}, {},
'self_props') 'self_props')
else: else:
is_cached = False is_cached = False
if not is_cached: if not is_cached:
props = set() props = set()
for prop in self._p_.getproperties(path, p_props = self._p_.getproperties(path,
option.impl_getproperties()): None,
option.impl_getproperties())
if index is not None:
p_props = chain(p_props,
self._p_.getproperties(path,
index,
option.impl_getproperties()))
for prop in p_props:
if isinstance(prop, str): if isinstance(prop, str):
props.add(prop) props.add(prop)
elif apply_requires: elif apply_requires:
new_prop = prop.execute(option_bag, new_prop = prop.execute(option_bag,
leadership_must_have_index=True) leadership_must_have_index=True)
if not new_prop: if new_prop is None:
continue continue
elif not isinstance(new_prop, str): elif not isinstance(new_prop, str):
raise ValueError(_('invalid property type {} for {} with {} function').format(type(new_prop), raise ValueError(_('invalid property type {} for {} with {} function').format(type(new_prop),
@ -457,8 +467,7 @@ class Settings(object):
if not option.impl_is_optiondescription() and option.impl_is_leader() and new_prop not in ALLOWED_LEADER_PROPERTIES: if not option.impl_is_optiondescription() and option.impl_is_leader() and new_prop not in ALLOWED_LEADER_PROPERTIES:
raise LeadershipError(_('leader cannot have "{}" property').format(new_prop)) raise LeadershipError(_('leader cannot have "{}" property').format(new_prop))
props.add(new_prop) props.add(new_prop)
props -= self.getpermissives(option, props -= self.getpermissives(option_bag)
path)
if apply_requires and not config_bag.is_unrestraint: if apply_requires and not config_bag.is_unrestraint:
cache.setcache(path, cache.setcache(path,
index, index,
@ -470,37 +479,61 @@ class Settings(object):
def get_calculated_properties(self, def get_calculated_properties(self,
option_bag): option_bag):
opt = option_bag.option option = option_bag.option
if opt.impl_is_symlinkoption(): if option.impl_is_symlinkoption():
opt = opt.impl_getopt() option = option.impl_getopt()
path = opt.impl_getpath() path = option.impl_getpath()
for prop in self._p_.getproperties(path, p_props = self._p_.getproperties(path,
opt.impl_getproperties()): None,
option.impl_getproperties())
if option_bag.index is not None:
p_props = chain(p_props,
self._p_.getproperties(path,
option_bag.index,
option.impl_getproperties()))
for prop in p_props:
if not isinstance(prop, str): if not isinstance(prop, str):
yield prop yield prop
def has_properties_index(self, def has_properties_index(self,
option_bag): option_bag):
opt = option_bag.option option = option_bag.option
if opt.impl_is_symlinkoption(): if option.impl_is_symlinkoption():
opt = opt.impl_getopt() option = option.impl_getopt()
path = opt.impl_getpath() path = option.impl_getpath()
for prop in self._p_.getproperties(path, p_props = self._p_.getproperties(path,
opt.impl_getproperties()): None,
if not isinstance(prop, str) and prop.has_index: option.impl_getproperties())
if option_bag.index is not None:
p_props = chain(p_props,
self._p_.getproperties(path,
option_bag.index,
option.impl_getproperties()))
for prop in p_props:
if not isinstance(prop, str) and prop.has_index(option_bag.option):
return True return True
return False return False
def get_context_permissives(self): def get_context_permissives(self):
return self.getpermissives(None, None) return self.getpermissives(None)
def getpermissives(self, def getpermissives(self,
opt, option_bag):
path): if option_bag is None:
if opt and opt.impl_is_symlinkoption(): path = None
index = None
else:
opt = option_bag.option
if opt.impl_is_symlinkoption():
opt = opt.impl_getopt() opt = opt.impl_getopt()
path = opt.impl_getpath() path = opt.impl_getpath()
return self._pp_.getpermissives(path) else:
path = option_bag.path
index = option_bag.index
permissives = self._pp_.getpermissives(path, None)
if index is not None:
permissives = frozenset(self._pp_.getpermissives(path, index) | permissives)
return permissives
#____________________________________________________________ #____________________________________________________________
# set methods # set methods
@ -508,6 +541,7 @@ class Settings(object):
properties, properties,
context): context):
self._p_.setproperties(None, self._p_.setproperties(None,
None,
properties) properties)
context.cfgimpl_reset_cache(None) context.cfgimpl_reset_cache(None)
@ -536,6 +570,7 @@ class Settings(object):
'"force_default_on_freeze" or "force_metaconfig_on_freeze" property without "frozen"' '"force_default_on_freeze" or "force_metaconfig_on_freeze" property without "frozen"'
'').format(opt.impl_get_display_name())) '').format(opt.impl_get_display_name()))
self._p_.setproperties(path, self._p_.setproperties(path,
option_bag.index,
properties) properties)
# values too because of follower values could have a PropertiesOptionError has value # values too because of follower values could have a PropertiesOptionError has value
context.cfgimpl_reset_cache(option_bag) context.cfgimpl_reset_cache(option_bag)
@ -566,13 +601,15 @@ class Settings(object):
raise TypeError(_("can't assign permissive to the symlinkoption \"{}\"" raise TypeError(_("can't assign permissive to the symlinkoption \"{}\""
"").format(opt.impl_get_display_name())) "").format(opt.impl_get_display_name()))
path = option_bag.path path = option_bag.path
index = option_bag.index
else: else:
path = None path = None
index = None
forbidden_permissives = FORBIDDEN_SET_PERMISSIVES & permissives forbidden_permissives = FORBIDDEN_SET_PERMISSIVES & permissives
if forbidden_permissives: if forbidden_permissives:
raise ConfigError(_('cannot add those permissives: {0}').format( raise ConfigError(_('cannot add those permissives: {0}').format(
' '.join(forbidden_permissives))) ' '.join(forbidden_permissives)))
self._pp_.setpermissives(path, permissives) self._pp_.setpermissives(path, index, permissives)
if option_bag is not None: if option_bag is not None:
option_bag.config_bag.context.cfgimpl_reset_cache(option_bag) option_bag.config_bag.context.cfgimpl_reset_cache(option_bag)
@ -585,13 +622,15 @@ class Settings(object):
if option_bag is None: if option_bag is None:
opt = None opt = None
path = None path = None
index = None
else: else:
opt = option_bag.option opt = option_bag.option
assert not opt.impl_is_symlinkoption(), _("can't reset properties to " assert not opt.impl_is_symlinkoption(), _("can't reset properties to "
"the symlinkoption \"{}\"" "the symlinkoption \"{}\""
"").format(opt.impl_get_display_name()) "").format(opt.impl_get_display_name())
path = option_bag.path path = option_bag.path
self._p_.delproperties(path) index = option_bag.index
self._p_.delproperties(path, index)
context.cfgimpl_reset_cache(option_bag) context.cfgimpl_reset_cache(option_bag)
def reset_permissives(self, def reset_permissives(self,
@ -600,13 +639,15 @@ class Settings(object):
if option_bag is None: if option_bag is None:
opt = None opt = None
path = None path = None
index = None
else: else:
opt = option_bag.option opt = option_bag.option
assert not opt.impl_is_symlinkoption(), _("can't reset permissives to " assert not opt.impl_is_symlinkoption(), _("can't reset permissives to "
"the symlinkoption \"{}\"" "the symlinkoption \"{}\""
"").format(opt.impl_get_display_name()) "").format(opt.impl_get_display_name())
index = option_bag.index
path = option_bag.path path = option_bag.path
self._pp_.delpermissive(path) self._pp_.delpermissive(path, index)
context.cfgimpl_reset_cache(option_bag) context.cfgimpl_reset_cache(option_bag)
#____________________________________________________________ #____________________________________________________________
@ -658,28 +699,27 @@ class Settings(object):
option_bag): option_bag):
if 'mandatory' in option_bag.config_bag.properties: if 'mandatory' in option_bag.config_bag.properties:
values = option_bag.config_bag.context.cfgimpl_get_values() values = option_bag.config_bag.context.cfgimpl_get_values()
is_mandatory = False
if not ('permissive' in option_bag.config_bag.properties and if not ('permissive' in option_bag.config_bag.properties and
'mandatory' in option_bag.config_bag.permissives) and \ 'mandatory' in option_bag.config_bag.permissives) and \
'mandatory' in option_bag.properties and values.isempty(option_bag.option, 'mandatory' in option_bag.properties and values.isempty(option_bag.option,
value, value,
index=option_bag.index): index=option_bag.index):
is_mandatory = True raise PropertiesOptionError(option_bag,
['mandatory'],
self)
if 'empty' in option_bag.properties and values.isempty(option_bag.option, if 'empty' in option_bag.properties and values.isempty(option_bag.option,
value, value,
force_allow_empty_list=True, force_allow_empty_list=True,
index=option_bag.index): index=option_bag.index):
is_mandatory = True
if is_mandatory:
raise PropertiesOptionError(option_bag, raise PropertiesOptionError(option_bag,
['mandatory'], ['empty'],
self) self)
def validate_frozen(self, def validate_frozen(self,
option_bag): option_bag):
if option_bag.config_bag.properties and \ if option_bag.config_bag.properties and \
('everything_frozen' in option_bag.config_bag.properties or ('everything_frozen' in option_bag.config_bag.properties or
'frozen' in option_bag.properties) and \ ('frozen' in option_bag.config_bag.properties and 'frozen' in option_bag.properties)) and \
not (('permissive' in option_bag.config_bag.properties) and not (('permissive' in option_bag.config_bag.properties) and
'frozen' in option_bag.config_bag.permissives): 'frozen' in option_bag.config_bag.permissives):
raise PropertiesOptionError(option_bag, raise PropertiesOptionError(option_bag,
@ -694,6 +734,7 @@ class Settings(object):
append, append,
context): context):
props = self._p_.getproperties(None, props = self._p_.getproperties(None,
None,
self.default_properties) self.default_properties)
modified = False modified = False
if remove & props: if remove & props:

View file

@ -15,7 +15,7 @@
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# ____________________________________________________________ # ____________________________________________________________
from copy import copy from copy import deepcopy
from ...log import log from ...log import log
@ -30,25 +30,29 @@ class Properties:
self._storage = storage self._storage = storage
# properties # properties
def setproperties(self, path, properties): def setproperties(self, path, index, properties):
log.debug('setproperties %s %s', path, properties) log.debug('setproperties %s %s %s', path, index, properties)
self._properties[path] = properties self._properties.setdefault(path, {})[index] = properties
def getproperties(self, path, default_properties): def getproperties(self, path, index, default_properties):
ret = self._properties.get(path, frozenset(default_properties)) if path not in self._properties:
log.debug('getproperties %s %s', path, ret) ret = frozenset(default_properties)
else:
ret = self._properties[path].get(index, frozenset(default_properties))
log.debug('getproperties %s %s %s', path, index, ret)
return ret return ret
def delproperties(self, path): def delproperties(self, path, index):
log.debug('delproperties %s', path) log.debug('delproperties %s', path)
if path in self._properties: if path in self._properties and index in self._properties[path]:
del(self._properties[path]) del(self._properties[path][index])
def exportation(self): def exportation(self):
"""return all modified settings in a dictionary """return all modified settings in a dictionary
example: {'path1': set(['prop1', 'prop2'])} example: {'path1': set(['prop1', 'prop2'])}
""" """
return copy(self._properties) return deepcopy(self._properties)
def importation(self, properties): def importation(self, properties):
self._properties = properties self._properties = properties
@ -63,29 +67,28 @@ class Permissives:
self._permissives = {} self._permissives = {}
self._storage = storage self._storage = storage
def setpermissives(self, path, permissives): def setpermissives(self, path, index, permissives):
log.debug('setpermissives %s %s', path, permissives) log.debug('setpermissives %s %s', path, permissives)
if not permissives: self._permissives.setdefault(path, {})[index] = permissives
if path in self._permissives:
del self._permissives[path]
else:
self._permissives[path] = permissives
def getpermissives(self, path=None): def getpermissives(self, path, index):
ret = self._permissives.get(path, frozenset()) if not path in self._permissives:
ret = frozenset()
else:
ret = self._permissives[path].get(index, frozenset())
log.debug('getpermissives %s %s', path, ret) log.debug('getpermissives %s %s', path, ret)
return ret return ret
def delpermissive(self, path, index):
log.debug('delpermissive %s', path)
if path in self._permissives and index in self._permissives[path]:
del(self._permissives[path][index])
def exportation(self): def exportation(self):
"""return all modified permissives in a dictionary """return all modified permissives in a dictionary
example: {'path1': set(['perm1', 'perm2'])} example: {'path1': set(['perm1', 'perm2'])}
""" """
return copy(self._permissives) return deepcopy(self._permissives)
def importation(self, permissives): def importation(self, permissives):
self._permissives = permissives self._permissives = permissives
def delpermissive(self, path):
log.debug('delpermissive %s', path)
if path in self._permissives:
del(self._permissives[path])

View file

@ -26,29 +26,30 @@ class Properties(Sqlite3DB):
super(Properties, self).__init__(storage) super(Properties, self).__init__(storage)
# properties # properties
def setproperties(self, path, properties): def setproperties(self, path, index, properties):
path = self._sqlite_encode_path(path) path = self._sqlite_encode_path(path)
self._storage.execute("DELETE FROM property WHERE path = ? AND session_id = ?", self._storage.execute("DELETE FROM property WHERE path = ? AND tiram_index = ? AND session_id = ?",
(path, self._session_id), (path, index, self._session_id),
False) False)
self._storage.execute("INSERT INTO property(path, properties, session_id) VALUES " self._storage.execute("INSERT INTO property(path, tiram_index, properties, session_id) VALUES "
"(?, ?, ?)", (path, "(?, ?, ?, ?)", (path,
index,
self._sqlite_encode(properties), self._sqlite_encode(properties),
self._session_id)) self._session_id))
def getproperties(self, path, default_properties): def getproperties(self, path, index, default_properties):
path = self._sqlite_encode_path(path) path = self._sqlite_encode_path(path)
value = self._storage.select("SELECT properties FROM property WHERE " value = self._storage.select("SELECT properties FROM property WHERE "
"path = ? AND session_id = ? LIMIT 1", (path, self._session_id)) "path = ? AND tiram_index = ? AND session_id = ? LIMIT 1", (path, index, self._session_id))
if value is None: if value is None:
return set(default_properties) return set(default_properties)
else: else:
return set(self._sqlite_decode(value[0])) return set(self._sqlite_decode(value[0]))
def delproperties(self, path): def delproperties(self, path, index):
path = self._sqlite_encode_path(path) path = self._sqlite_encode_path(path)
self._storage.execute("DELETE FROM property WHERE path = ? AND session_id = ?", self._storage.execute("DELETE FROM property WHERE path = ? AND tiram_index = ? AND session_id = ?",
(path, self._session_id)) (path, index, self._session_id))
def exportation(self): def exportation(self):
"""return all modified settings in a dictionary """return all modified settings in a dictionary
@ -79,22 +80,25 @@ class Permissives(Sqlite3DB):
__slots__ = tuple() __slots__ = tuple()
# permissive # permissive
def setpermissives(self, path, permissive): def setpermissives(self, path, index, permissive):
path = self._sqlite_encode_path(path) path = self._sqlite_encode_path(path)
log.debug('setpermissive %s %s %s', path, permissive, id(self)) log.debug('setpermissive %s %s %s %s', path, index, permissive, id(self))
self._storage.execute("DELETE FROM permissive WHERE path = ? AND session_id = ?", self._storage.execute("DELETE FROM permissive WHERE path = ? AND tiram_index = ? AND session_id = ?",
(path, self._session_id), (path,
index,
self._session_id),
False) False)
self._storage.execute("INSERT INTO permissive(path, permissives, session_id) " self._storage.execute("INSERT INTO permissive(path, tiram_index, permissives, session_id) "
"VALUES (?, ?, ?)", (path, "VALUES (?, ?, ?, ?)", (path,
index,
self._sqlite_encode(permissive), self._sqlite_encode(permissive),
self._session_id)) self._session_id))
def getpermissives(self, path='_none'): def getpermissives(self, path, index):
path = self._sqlite_encode_path(path) path = self._sqlite_encode_path(path)
permissives = self._storage.select("SELECT permissives FROM " permissives = self._storage.select("SELECT permissives FROM "
"permissive WHERE path = ? AND session_id = ? LIMIT 1", "permissive WHERE path = ? AND tiram_index = ? AND session_id = ? LIMIT 1",
(path, self._session_id)) (path, index, self._session_id))
if permissives is None: if permissives is None:
ret = frozenset() ret = frozenset()
else: else:
@ -102,17 +106,17 @@ class Permissives(Sqlite3DB):
log.debug('getpermissive %s %s %s', path, ret, id(self)) log.debug('getpermissive %s %s %s', path, ret, id(self))
return ret return ret
def delpermissive(self, path): def delpermissive(self, path, index):
path = self._sqlite_encode_path(path) path = self._sqlite_encode_path(path)
self._storage.execute("DELETE FROM permissive WHERE path = ? AND session_id = ?", self._storage.execute("DELETE FROM permissive WHERE path = ? AND tiram_index = ? AND session_id = ?",
(path, self._session_id)) (path, index, self._session_id))
def exportation(self): def exportation(self):
"""return all modified permissives in a dictionary """return all modified permissives in a dictionary
example: {'path1': set(['perm1', 'perm2'])} example: {'path1': set(['perm1', 'perm2'])}
""" """
ret = {} ret = {}
for path, permissives in self._storage.select("SELECT path, permissives FROM permissive " for path, index, permissives in self._storage.select("SELECT path, tiram_index, permissives FROM permissive "
"WHERE session_id = ?", "WHERE session_id = ?",
(self._session_id,), (self._session_id,),
only_one=False): only_one=False):
@ -125,8 +129,9 @@ class Permissives(Sqlite3DB):
commit=False) commit=False)
for path, permissive in permissives.items(): for path, permissive in permissives.items():
path = self._sqlite_encode_path(path) path = self._sqlite_encode_path(path)
self._storage.execute("INSERT INTO permissive(path, permissives, session_id) " self._storage.execute("INSERT INTO permissive(path, tiram_index, permissives, session_id) "
"VALUES (?, ?, ?)", (path, "VALUES (?, ?, ?)", (path,
index,
self._sqlite_encode(permissive), self._sqlite_encode(permissive),
self._session_id, self._session_id,
), False) ), False)

View file

@ -106,10 +106,10 @@ class Storage(object):
session_table = 'CREATE TABLE IF NOT EXISTS session(session_id INTEGER, ' session_table = 'CREATE TABLE IF NOT EXISTS session(session_id INTEGER, '
session_table += 'session TEXT UNIQUE, persistent BOOL, PRIMARY KEY(session_id))' session_table += 'session TEXT UNIQUE, persistent BOOL, PRIMARY KEY(session_id))'
settings_table = 'CREATE TABLE IF NOT EXISTS property(path TEXT, ' settings_table = 'CREATE TABLE IF NOT EXISTS property(path TEXT, '
settings_table += 'properties text, session_id INTEGER, PRIMARY KEY(path, session_id), ' settings_table += 'tiram_index INTEGER, properties TEXT, session_id INTEGER, PRIMARY KEY(path, tiram_index, session_id), '
settings_table += 'FOREIGN KEY(session_id) REFERENCES session(session_id))' settings_table += 'FOREIGN KEY(session_id) REFERENCES session(session_id))'
permissives_table = 'CREATE TABLE IF NOT EXISTS permissive(path TEXT,' permissives_table = 'CREATE TABLE IF NOT EXISTS permissive(path TEXT,'
permissives_table += 'permissives TEXT, session_id INTEGER, PRIMARY KEY(path, session_id), ' permissives_table += 'tiram_index INTEGER, permissives TEXT, session_id INTEGER, PRIMARY KEY(path, tiram_index, session_id), '
permissives_table += 'FOREIGN KEY(session_id) REFERENCES session(session_id))' permissives_table += 'FOREIGN KEY(session_id) REFERENCES session(session_id))'
values_table = 'CREATE TABLE IF NOT EXISTS value(path TEXT, ' values_table = 'CREATE TABLE IF NOT EXISTS value(path TEXT, '
values_table += 'value TEXT, owner TEXT, idx INTEGER, session_id INTEGER, '\ values_table += 'value TEXT, owner TEXT, idx INTEGER, session_id INTEGER, '\