merge from val_prop_plugin branch

This commit is contained in:
Emmanuel Garette 2013-08-20 16:44:52 +02:00
commit 82b0e26568
15 changed files with 727 additions and 249 deletions

View File

@ -20,13 +20,13 @@ def test_cache():
values = c.cfgimpl_get_values() values = c.cfgimpl_get_values()
settings = c.cfgimpl_get_settings() settings = c.cfgimpl_get_settings()
c.u1 c.u1
assert od1.u1 in values._cache assert od1.u1 in values._p_.get_cached('value', c)
assert od1.u1 in settings._cache assert od1.u1 in settings._p_.get_cached('property', c)
c.u2 c.u2
assert od1.u1 in values._cache assert od1.u1 in values._p_.get_cached('value', c)
assert od1.u1 in settings._cache assert od1.u1 in settings._p_.get_cached('property', c)
assert od1.u2 in values._cache assert od1.u2 in values._p_.get_cached('value', c)
assert od1.u2 in settings._cache assert od1.u2 in settings._p_.get_cached('property', c)
def test_cache_reset(): def test_cache_reset():
@ -36,44 +36,44 @@ def test_cache_reset():
settings = c.cfgimpl_get_settings() settings = c.cfgimpl_get_settings()
#when change a value #when change a value
c.u1 c.u1
assert od1.u1 in values._cache assert od1.u1 in values._p_.get_cached('value', c)
assert od1.u1 in settings._cache assert od1.u1 in settings._p_.get_cached('property', c)
c.u2 = 1 c.u2 = 1
assert od1.u1 not in values._cache assert od1.u1 not in values._p_.get_cached('value', c)
assert od1.u1 not in settings._cache assert od1.u1 not in settings._p_.get_cached('property', c)
#when remove a value #when remove a value
c.u1 c.u1
assert od1.u1 in values._cache assert od1.u1 in values._p_.get_cached('value', c)
assert od1.u1 in settings._cache assert od1.u1 in settings._p_.get_cached('property', c)
del(c.u2) del(c.u2)
assert od1.u1 not in values._cache assert od1.u1 not in values._p_.get_cached('value', c)
assert od1.u1 not in settings._cache assert od1.u1 not in settings._p_.get_cached('property', c)
#when add/del property #when add/del property
c.u1 c.u1
assert od1.u1 in values._cache assert od1.u1 in values._p_.get_cached('value', c)
assert od1.u1 in settings._cache assert od1.u1 in settings._p_.get_cached('property', c)
c.cfgimpl_get_settings()[od1.u2].append('test') c.cfgimpl_get_settings()[od1.u2].append('test')
assert od1.u1 not in values._cache assert od1.u1 not in values._p_.get_cached('value', c)
assert od1.u1 not in settings._cache assert od1.u1 not in settings._p_.get_cached('property', c)
c.u1 c.u1
assert od1.u1 in values._cache assert od1.u1 in values._p_.get_cached('value', c)
assert od1.u1 in settings._cache assert od1.u1 in settings._p_.get_cached('property', c)
c.cfgimpl_get_settings()[od1.u2].remove('test') c.cfgimpl_get_settings()[od1.u2].remove('test')
assert od1.u1 not in values._cache assert od1.u1 not in values._p_.get_cached('value', c)
assert od1.u1 not in settings._cache assert od1.u1 not in settings._p_.get_cached('property', c)
#when enable/disabled property #when enable/disabled property
c.u1 c.u1
assert od1.u1 in values._cache assert od1.u1 in values._p_.get_cached('value', c)
assert od1.u1 in settings._cache assert od1.u1 in settings._p_.get_cached('property', c)
c.cfgimpl_get_settings().append('test') c.cfgimpl_get_settings().append('test')
assert od1.u1 not in values._cache assert od1.u1 not in values._p_.get_cached('value', c)
assert od1.u1 not in settings._cache assert od1.u1 not in settings._p_.get_cached('property', c)
c.u1 c.u1
assert od1.u1 in values._cache assert od1.u1 in values._p_.get_cached('value', c)
assert od1.u1 in settings._cache assert od1.u1 in settings._p_.get_cached('property', c)
c.cfgimpl_get_settings().remove('test') c.cfgimpl_get_settings().remove('test')
assert od1.u1 not in values._cache assert od1.u1 not in values._p_.get_cached('value', c)
assert od1.u1 not in settings._cache assert od1.u1 not in settings._p_.get_cached('property', c)
def test_cache_reset_multi(): def test_cache_reset_multi():
@ -83,32 +83,32 @@ def test_cache_reset_multi():
settings = c.cfgimpl_get_settings() settings = c.cfgimpl_get_settings()
#when change a value #when change a value
c.u1 c.u1
assert od1.u1 in values._cache assert od1.u1 in values._p_.get_cached('value', c)
assert od1.u1 in settings._cache assert od1.u1 in settings._p_.get_cached('property', c)
c.u3 = [1] c.u3 = [1]
assert od1.u1 not in values._cache assert od1.u1 not in values._p_.get_cached('value', c)
assert od1.u1 not in settings._cache assert od1.u1 not in settings._p_.get_cached('property', c)
#when append value #when append value
c.u1 c.u1
assert od1.u1 in values._cache assert od1.u1 in values._p_.get_cached('value', c)
assert od1.u1 in settings._cache assert od1.u1 in settings._p_.get_cached('property', c)
c.u3.append(1) c.u3.append(1)
assert od1.u1 not in values._cache assert od1.u1 not in values._p_.get_cached('value', c)
assert od1.u1 not in settings._cache assert od1.u1 not in settings._p_.get_cached('property', c)
#when pop value #when pop value
c.u1 c.u1
assert od1.u1 in values._cache assert od1.u1 in values._p_.get_cached('value', c)
assert od1.u1 in settings._cache assert od1.u1 in settings._p_.get_cached('property', c)
c.u3.pop(1) c.u3.pop(1)
assert od1.u1 not in values._cache assert od1.u1 not in values._p_.get_cached('value', c)
assert od1.u1 not in settings._cache assert od1.u1 not in settings._p_.get_cached('property', c)
#when remove a value #when remove a value
c.u1 c.u1
assert od1.u1 in values._cache assert od1.u1 in values._p_.get_cached('value', c)
assert od1.u1 in settings._cache assert od1.u1 in settings._p_.get_cached('property', c)
del(c.u3) del(c.u3)
assert od1.u1 not in values._cache assert od1.u1 not in values._p_.get_cached('value', c)
assert od1.u1 not in settings._cache assert od1.u1 not in settings._p_.get_cached('property', c)
def test_reset_cache(): def test_reset_cache():
@ -117,23 +117,23 @@ def test_reset_cache():
values = c.cfgimpl_get_values() values = c.cfgimpl_get_values()
settings = c.cfgimpl_get_settings() settings = c.cfgimpl_get_settings()
c.u1 c.u1
assert od1.u1 in values._cache assert od1.u1 in values._p_.get_cached('value', c)
assert od1.u1 in settings._cache assert od1.u1 in settings._p_.get_cached('property', c)
c.cfgimpl_reset_cache() c.cfgimpl_reset_cache()
assert od1.u1 not in values._cache assert od1.u1 not in values._p_.get_cached('value', c)
assert od1.u1 not in settings._cache assert od1.u1 not in settings._p_.get_cached('property', c)
c.u1 c.u1
sleep(1) sleep(1)
c.u2 c.u2
assert od1.u1 in values._cache assert od1.u1 in values._p_.get_cached('value', c)
assert od1.u1 in settings._cache assert od1.u1 in settings._p_.get_cached('property', c)
assert od1.u2 in values._cache assert od1.u2 in values._p_.get_cached('value', c)
assert od1.u2 in settings._cache assert od1.u2 in settings._p_.get_cached('property', c)
c.cfgimpl_reset_cache() c.cfgimpl_reset_cache()
assert od1.u1 not in values._cache assert od1.u1 not in values._p_.get_cached('value', c)
assert od1.u1 not in settings._cache assert od1.u1 not in settings._p_.get_cached('property', c)
assert od1.u2 not in values._cache assert od1.u2 not in values._p_.get_cached('value', c)
assert od1.u2 not in settings._cache assert od1.u2 not in settings._p_.get_cached('property', c)
def test_reset_cache_only_expired(): def test_reset_cache_only_expired():
@ -142,22 +142,22 @@ def test_reset_cache_only_expired():
values = c.cfgimpl_get_values() values = c.cfgimpl_get_values()
settings = c.cfgimpl_get_settings() settings = c.cfgimpl_get_settings()
c.u1 c.u1
assert od1.u1 in values._cache assert od1.u1 in values._p_.get_cached('value', c)
assert od1.u1 in settings._cache assert od1.u1 in settings._p_.get_cached('property', c)
c.cfgimpl_reset_cache(True) c.cfgimpl_reset_cache(True)
assert od1.u1 in values._cache assert od1.u1 in values._p_.get_cached('value', c)
assert od1.u1 in settings._cache assert od1.u1 in settings._p_.get_cached('property', c)
sleep(1) sleep(1)
c.u2 c.u2
assert od1.u1 in values._cache assert od1.u1 in values._p_.get_cached('value', c)
assert od1.u1 in settings._cache assert od1.u1 in settings._p_.get_cached('property', c)
assert od1.u2 in values._cache assert od1.u2 in values._p_.get_cached('value', c)
assert od1.u2 in settings._cache assert od1.u2 in settings._p_.get_cached('property', c)
c.cfgimpl_reset_cache(True) c.cfgimpl_reset_cache(True)
assert od1.u1 not in values._cache assert od1.u1 not in values._p_.get_cached('value', c)
assert od1.u1 not in settings._cache assert od1.u1 not in settings._p_.get_cached('property', c)
assert od1.u2 in values._cache assert od1.u2 in values._p_.get_cached('value', c)
assert od1.u2 in settings._cache assert od1.u2 in settings._p_.get_cached('property', c)
def test_reset_cache_only(): def test_reset_cache_only():
@ -166,14 +166,14 @@ def test_reset_cache_only():
values = c.cfgimpl_get_values() values = c.cfgimpl_get_values()
settings = c.cfgimpl_get_settings() settings = c.cfgimpl_get_settings()
c.u1 c.u1
assert od1.u1 in values._cache assert od1.u1 in values._p_.get_cached('value', c)
assert od1.u1 in settings._cache assert od1.u1 in settings._p_.get_cached('property', c)
c.cfgimpl_reset_cache(only=('values',)) c.cfgimpl_reset_cache(only=('values',))
assert od1.u1 not in values._cache assert od1.u1 not in values._p_.get_cached('value', c)
assert od1.u1 in settings._cache assert od1.u1 in settings._p_.get_cached('property', c)
c.u1 c.u1
assert od1.u1 in values._cache assert od1.u1 in values._p_.get_cached('value', c)
assert od1.u1 in settings._cache assert od1.u1 in settings._p_.get_cached('property', c)
c.cfgimpl_reset_cache(only=('settings',)) c.cfgimpl_reset_cache(only=('settings',))
assert od1.u1 in values._cache assert od1.u1 in values._p_.get_cached('value', c)
assert od1.u1 not in settings._cache assert od1.u1 not in settings._p_.get_cached('property', c)

View File

@ -327,23 +327,23 @@ def test_reset_properties():
cfg = Config(descr) cfg = Config(descr)
setting = cfg.cfgimpl_get_settings() setting = cfg.cfgimpl_get_settings()
option = cfg.cfgimpl_get_description().gc.dummy option = cfg.cfgimpl_get_description().gc.dummy
assert setting._properties == {} assert setting._p_.get_properties(cfg) == {}
setting.append('frozen') setting.append('frozen')
assert setting._properties == {None: set(('frozen', 'expire', 'validator'))} assert setting._p_.get_properties(cfg) == {None: set(('frozen', 'expire', 'validator'))}
setting.reset() setting.reset()
assert setting._properties == {} assert setting._p_.get_properties(cfg) == {}
setting[option].append('test') setting[option].append('test')
assert setting._properties == {option: set(('test',))} assert setting._p_.get_properties(cfg) == {option: set(('test',))}
setting.reset() setting.reset()
assert setting._properties == {option: set(('test',))} assert setting._p_.get_properties(cfg) == {option: set(('test',))}
setting.append('frozen') setting.append('frozen')
assert setting._properties == {None: set(('frozen', 'expire', 'validator')), option: set(('test',))} assert setting._p_.get_properties(cfg) == {None: set(('frozen', 'expire', 'validator')), option: set(('test',))}
setting.reset(option) setting.reset(option)
assert setting._properties == {None: set(('frozen', 'expire', 'validator'))} assert setting._p_.get_properties(cfg) == {None: set(('frozen', 'expire', 'validator'))}
setting[option].append('test') setting[option].append('test')
assert setting._properties == {None: set(('frozen', 'expire', 'validator')), option: set(('test',))} assert setting._p_.get_properties(cfg) == {None: set(('frozen', 'expire', 'validator')), option: set(('test',))}
setting.reset(all_properties=True) setting.reset(all_properties=True)
assert setting._properties == {} assert setting._p_.get_properties(cfg) == {}
raises(ValueError, 'setting.reset(all_properties=True, opt=option)') raises(ValueError, 'setting.reset(all_properties=True, opt=option)')

View File

@ -20,10 +20,11 @@
# the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/ # the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/
# the whole pypy projet is under MIT licence # the whole pypy projet is under MIT licence
# ____________________________________________________________ # ____________________________________________________________
from time import time
from tiramisu.error import PropertiesOptionError, ConfigError from tiramisu.error import PropertiesOptionError, ConfigError
from tiramisu.option import OptionDescription, Option, SymLinkOption, \ from tiramisu.option import OptionDescription, Option, SymLinkOption, \
BaseInformation BaseInformation
from tiramisu.setting import groups, Setting, default_encoding from tiramisu.setting import groups, Settings, default_encoding, default_storage
from tiramisu.value import Values from tiramisu.value import Values
from tiramisu.i18n import _ from tiramisu.i18n import _
@ -524,8 +525,9 @@ class Config(CommonConfig):
:param context: the current root config :param context: the current root config
:type context: `Config` :type context: `Config`
""" """
self._impl_settings = Setting(self) config_id = str(id(self)) + str(time())
self._impl_values = Values(self) self._impl_settings = Settings(self, config_id, default_storage)
self._impl_values = Values(self, config_id, default_storage)
super(Config, self).__init__(descr, self) super(Config, self).__init__(descr, self)
self._impl_build_all_paths() self._impl_build_all_paths()
self._impl_meta = None self._impl_meta = None
@ -562,9 +564,10 @@ class MetaConfig(CommonConfig):
raise ValueError(_("child has already a metaconfig's")) raise ValueError(_("child has already a metaconfig's"))
child._impl_meta = self child._impl_meta = self
config_id = str(id(self))
self._impl_children = children self._impl_children = children
self._impl_settings = Setting(self) self._impl_settings = Settings(self, config_id, default_storage)
self._impl_values = Values(self) self._impl_values = Values(self, config_id, default_storage)
self._impl_meta = None self._impl_meta = None
self._impl_informations = {} self._impl_informations = {}

View File

@ -59,7 +59,7 @@ class BaseInformation(object):
def impl_set_information(self, key, value): def impl_set_information(self, key, value):
"""updates the information's attribute """updates the information's attribute
(wich is a dictionnary) (which is a dictionary)
:param key: information's key (ex: "help", "doc" :param key: information's key (ex: "help", "doc"
:param value: information's value (ex: "the help string") :param value: information's value (ex: "the help string")
@ -459,7 +459,8 @@ class StrOption(Option):
def _validate(self, value): def _validate(self, value):
if not isinstance(value, str): if not isinstance(value, str):
raise ValueError(_('value must be a string')) raise ValueError(_('value must be a string, not '
'{0}').format(type(value)))
class UnicodeOption(Option): class UnicodeOption(Option):

View File

View File

View File

@ -0,0 +1,55 @@
# -*- coding: utf-8 -*-
"default plugin for cache: set it in a simple dictionary"
# Copyright (C) 2013 Team tiramisu (see AUTHORS for all contributors)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# ____________________________________________________________
class Cache(object):
__slots__ = ('_cache',)
key_is_path = False
def __init__(self):
self._cache = {}
def setcache(self, cache_type, opt, val, time):
self._cache[opt] = (val, time)
def getcache(self, cache_type, opt, exp):
value, created = self._cache[opt]
if exp < created:
return True, value
return False, None
def hascache(self, cache_type, opt):
return opt in self._cache
def reset_expired_cache(self, cache_type, exp):
keys = self._cache.keys()
for key in keys:
val, created = self._cache[key]
if exp > created:
del(self._cache[key])
def reset_all_cache(self, cache_type):
self._cache.clear()
def get_cached(self, cache_type, context):
"""return all values in a dictionary
example: {option1: ('value1', 'time1'), option2: ('value2', 'time2')}
"""
return self._cache

View File

@ -0,0 +1,61 @@
# -*- coding: utf-8 -*-
"default plugin for setting: set it in a simple dictionary"
# Copyright (C) 2013 Team tiramisu (see AUTHORS for all contributors)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# ____________________________________________________________
from tiramisu.plugins.dictionary.cache import Cache
class Settings(Cache):
__slots__ = ('_properties', '_permissives')
def __init__(self, config_id):
# properties attribute: the name of a property enables this property
# key is None for global properties
self._properties = {}
# permissive properties
self._permissives = {}
super(Settings, self).__init__()
# propertives
def setproperties(self, opt, properties):
self._properties[opt] = properties
def getproperties(self, opt, default_properties):
return self._properties.get(opt, set(default_properties))
def hasproperties(self, opt):
return opt in self._properties
def reset_all_propertives(self):
self._properties.clear()
def reset_properties(self, opt):
try:
del(self._properties[opt])
except KeyError:
pass
def get_properties(self, context):
return self._properties
# permissive
def setpermissive(self, opt, permissive):
self._permissives[opt] = frozenset(permissive)
def getpermissive(self, opt=None):
return self._permissives.get(opt, frozenset())

View File

@ -0,0 +1,75 @@
# -*- coding: utf-8 -*-
"default plugin for value: set it in a simple dictionary"
# Copyright (C) 2013 Team tiramisu (see AUTHORS for all contributors)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# ____________________________________________________________
#FIXME
from tiramisu.plugins.dictionary.cache import Cache
class Values(Cache):
__slots__ = ('_values',)
def __init__(self, config_id):
"""init plugin means create values storage
"""
self._values = {}
# should init cache too
super(Values, self).__init__()
# value
def setvalue(self, opt, value, owner):
"""set value for an option
a specified value must be associated to an owner
"""
self._values[opt] = (owner, value)
def getvalue(self, opt):
"""get value for an option
return: only value, not the owner
"""
return self._values[opt][1]
def hasvalue(self, opt):
"""if opt has a value
return: boolean
"""
return opt in self._values
def resetvalue(self, opt):
"""remove value means delete value in storage
"""
del(self._values[opt])
def get_modified_values(self):
"""return all values in a dictionary
example: {option1: (owner, 'value1'), option2: (owner, 'value2')}
"""
return self._values
# owner
def setowner(self, opt, owner):
"""change owner for an option
"""
self._values[opt] = (owner, self._values[opt][1])
def getowner(self, opt, default):
"""get owner for an option
return: owner object
"""
return self._values.get(opt, (default, None))[0]

View File

View File

@ -0,0 +1,82 @@
# -*- coding: utf-8 -*-
"default plugin for cache: set it in a simple dictionary"
# Copyright (C) 2013 Team tiramisu (see AUTHORS for all contributors)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# ____________________________________________________________
from pickle import dumps, loads
import sqlite3
class Cache(object):
__slots__ = ('_conn', '_cursor')
key_is_path = True
def __init__(self, config_id, cache_type):
cache_table = 'CREATE TABLE IF NOT EXISTS cache_{0}(path text primary key, value text, time real)'.format(cache_type)
self._conn = sqlite3.connect(config_id + '.db')
self._conn.text_factory = str
self._cursor = self._conn.cursor()
self._cursor.execute(cache_table)
# value
def _sqlite_decode(self, value):
return loads(value)
def _sqlite_encode(self, value):
if isinstance(value, list):
value = list(value)
return dumps(value)
def setcache(self, cache_type, path, val, time):
convert_value = self._sqlite_encode(val)
self._cursor.execute("DELETE FROM cache_{0} WHERE path = ?".format(cache_type), (path,))
self._cursor.execute("INSERT INTO cache_{0}(path, value, time) VALUES (?, ?, ?)".format(cache_type),
(path, convert_value, time))
self._conn.commit()
def getcache(self, cache_type, path, exp):
self._cursor.execute("SELECT value FROM cache_{0} WHERE path = ? AND time >= ?".format(cache_type), (path, exp))
cached = self._cursor.fetchone()
if cached is None:
return False, None
else:
return True, self._sqlite_decode(cached[0])
def hascache(self, cache_type, path):
self._cursor.execute("SELECT value FROM cache_{0} WHERE path = ?".format(cache_type), (path,))
return self._cursor.fetchone() is not None
def reset_expired_cache(self, cache_type, exp):
self._cursor.execute("DELETE FROM cache_{0} WHERE time < ?".format(cache_type), (exp,))
self._conn.commit()
def reset_all_cache(self, cache_type):
self._cursor.execute("DELETE FROM cache_{0}".format(cache_type))
self._conn.commit()
def get_cached(self, cache_type, context):
"""return all values in a dictionary
example: {option1: ('value1', 'time1'), option2: ('value2', 'time2')}
"""
self._cursor.execute("SELECT * FROM cache_{0}".format(cache_type))
ret = {}
for path, value, time in self._cursor.fetchall():
opt = context.cfgimpl_get_description().impl_get_opt_by_path(path)
value = self._sqlite_decode(value)
ret[opt] = (value, time)
return ret

View File

@ -0,0 +1,88 @@
# -*- coding: utf-8 -*-
"default plugin for setting: set it in a simple dictionary"
# Copyright (C) 2013 Team tiramisu (see AUTHORS for all contributors)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# ____________________________________________________________
from tiramisu.plugins.sqlite3.cache import Cache
class Settings(Cache):
__slots__ = tuple()
def __init__(self, config_id):
settings_table = 'CREATE TABLE IF NOT EXISTS property(path text primary key, properties text)'
permissives_table = 'CREATE TABLE IF NOT EXISTS permissive(path text primary key, permissives text)'
# should init cache too
super(Settings, self).__init__(config_id, 'property')
self._cursor.execute(settings_table)
self._cursor.execute(permissives_table)
self._conn.commit()
# propertives
def setproperties(self, path, properties):
self._cursor.execute("DELETE FROM property WHERE path = ?", (path,))
self._cursor.execute("INSERT INTO property(path, properties) VALUES (?, ?)",
(path, self._sqlite_encode(properties)))
self._conn.commit()
def getproperties(self, path, default_properties):
self._cursor.execute("SELECT properties FROM property WHERE path = ?", (path,))
value = self._cursor.fetchone()
if value is None:
return set(default_properties)
else:
return set(self._sqlite_decode(value[0]))
def hasproperties(self, path):
return self._cursor.execute("SELECT properties FROM property WHERE path = ?", (path,)) is not None
def reset_all_propertives(self):
self._cursor.execute("DELETE FROM property")
self._conn.commit()
def reset_properties(self, path):
self._cursor.execute("DELETE FROM property WHERE path = ?", (path,))
self._conn.commit()
def get_properties(self, context):
"""return all properties in a dictionary
"""
self._cursor.execute("SELECT * FROM property")
ret = {}
for path, properties in self._cursor.fetchall():
if path == '_none':
opt = None
else:
opt = context.cfgimpl_get_description().impl_get_opt_by_path(path)
properties = self._sqlite_decode(properties)
ret[opt] = properties
return ret
# permissive
def setpermissive(self, path, permissive):
self._cursor.execute("DELETE FROM permissive WHERE path = ?", (path,))
self._cursor.execute("INSERT INTO permissive(path, permissives) VALUES (?, ?)",
(path, self._sqlite_encode(permissive)))
self._conn.commit()
def getpermissive(self, path='_none'):
self._cursor.execute("SELECT permissives FROM permissive WHERE path = ?", (path,))
permissives = self._cursor.fetchone()
if permissives is None:
return frozenset()
else:
return frozenset(self._sqlite_decode(permissives[0]))

View File

@ -0,0 +1,104 @@
# -*- coding: utf-8 -*-
"default plugin for value: set it in a simple dictionary"
# Copyright (C) 2013 Team tiramisu (see AUTHORS for all contributors)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# ____________________________________________________________
from tiramisu.plugins.sqlite3.cache import Cache
from tiramisu.setting import owners
class Values(Cache):
__slots__ = tuple()
def __init__(self, config_id):
"""init plugin means create values storage
"""
values_table = 'CREATE TABLE IF NOT EXISTS value(path text primary key, value text, owner text)'
# should init cache too
super(Values, self).__init__(config_id, 'value')
self._cursor.execute(values_table)
self._conn.commit()
# sqlite
def _sqlite_select(self, path):
self._cursor.execute("SELECT value FROM value WHERE path = ?", (path,))
return self._cursor.fetchone()
# value
def setvalue(self, path, value, owner):
"""set value for an option
a specified value must be associated to an owner
"""
self.resetvalue(path)
self._cursor.execute("INSERT INTO value(path, value, owner) VALUES (?, ?, ?)",
(path, self._sqlite_encode(value), str(owner)))
self._conn.commit()
def getvalue(self, path):
"""get value for an option
return: only value, not the owner
"""
return self._sqlite_decode(self._sqlite_select(path)[0])
def hasvalue(self, path):
"""if opt has a value
return: boolean
"""
return self._sqlite_select(path) is not None
def resetvalue(self, path):
"""remove value means delete value in storage
"""
self._cursor.execute("DELETE FROM value WHERE path = ?", (path,))
self._conn.commit()
def get_modified_values(self, context):
"""return all values in a dictionary
example: {option1: (owner, 'value1'), option2: (owner, 'value2')}
"""
self._cursor.execute("SELECT value")
ret = {}
for path, value, owner in self._cursor.fetchall():
opt = context.cfgimpl_get_description().impl_get_opt_by_path(path)
owner = getattr(owners, owner)
value = self._sqlite_decode(value)
ret[opt] = (owner, value)
return ret
# owner
def setowner(self, path, owner):
"""change owner for an option
"""
self._cursor.execute("UPDATE value SET owner = ? WHERE path = ?", (str(owner), path))
self._conn.commit()
def getowner(self, path, default):
"""get owner for an option
return: owner object
"""
self._cursor.execute("SELECT owner FROM value WHERE path = ?", (path,))
owner = self._cursor.fetchone()
if owner is None:
return default
else:
return getattr(owners, owner[0])
def __del__(self):
self._cursor.close()
self._conn.close()

View File

@ -25,6 +25,7 @@ from copy import copy
from tiramisu.error import RequirementError, PropertiesOptionError from tiramisu.error import RequirementError, PropertiesOptionError
from tiramisu.i18n import _ from tiramisu.i18n import _
default_encoding = 'utf-8' default_encoding = 'utf-8'
expires_time = 5 expires_time = 5
ro_remove = ('permissive', 'hidden') ro_remove = ('permissive', 'hidden')
@ -33,6 +34,7 @@ ro_append = ('frozen', 'disabled', 'validator', 'everything_frozen',
rw_remove = ('permissive', 'everything_frozen', 'mandatory') rw_remove = ('permissive', 'everything_frozen', 'mandatory')
rw_append = ('frozen', 'disabled', 'validator', 'hidden') rw_append = ('frozen', 'disabled', 'validator', 'hidden')
default_properties = ('expire', 'validator') default_properties = ('expire', 'validator')
default_storage = 'dictionary'
class _const: class _const:
@ -159,12 +161,12 @@ class Property(object):
def append(self, propname): def append(self, propname):
self._properties.add(propname) self._properties.add(propname)
self._setting._set_properties(self._properties, self._opt) self._setting._setproperties(self._properties, self._opt)
def remove(self, propname): def remove(self, propname):
if propname in self._properties: if propname in self._properties:
self._properties.remove(propname) self._properties.remove(propname)
self._setting._set_properties(self._properties, self._opt) self._setting._setproperties(self._properties, self._opt)
def reset(self): def reset(self):
self._setting.reset(opt=self._opt) self._setting.reset(opt=self._opt)
@ -177,31 +179,37 @@ class Property(object):
#____________________________________________________________ #____________________________________________________________
class Setting(object): class Settings(object):
"``Config()``'s configuration options" "``Config()``'s configuration options"
__slots__ = ('context', '_properties', '_permissives', '_owner', '_cache') __slots__ = ('context', '_owner', '_p_')
def __init__(self, context): def __init__(self, context, config_id, plugin_name):
# properties attribute: the name of a property enables this property
# key is None for global properties
self._properties = {}
# permissive properties
self._permissives = {}
# generic owner # generic owner
self._owner = owners.user self._owner = owners.user
self.context = context self.context = context
self._cache = {} import_lib = 'tiramisu.plugins.{0}.setting'.format(plugin_name)
self._p_ = __import__(import_lib, globals(), locals(), ['Settings'],
-1).Settings(config_id)
def _getkey(self, opt):
if self._p_.key_is_path:
if opt is None:
return '_none'
else:
return self._get_opt_path(opt)
else:
return opt
#____________________________________________________________ #____________________________________________________________
# properties methods # properties methods
def __contains__(self, propname): def __contains__(self, propname):
return propname in self._get_properties() return propname in self._getproperties()
def __repr__(self): def __repr__(self):
return str(list(self._get_properties())) return str(list(self._getproperties()))
def __getitem__(self, opt): def __getitem__(self, opt):
return Property(self, self._get_properties(opt), opt) return Property(self, self._getproperties(opt), opt)
def __setitem__(self, opt, value): def __setitem__(self, opt, value):
raise ValueError('you must only append/remove properties') raise ValueError('you must only append/remove properties')
@ -211,50 +219,49 @@ class Setting(object):
raise ValueError(_('opt and all_properties must not be set ' raise ValueError(_('opt and all_properties must not be set '
'together in reset')) 'together in reset'))
if all_properties: if all_properties:
self._properties = {} self._p_.reset_all_propertives()
else: else:
try: self._p_.reset_properties(self._getkey(opt))
del(self._properties[opt])
except KeyError:
pass
self.context.cfgimpl_reset_cache() self.context.cfgimpl_reset_cache()
def _get_properties(self, opt=None, is_apply_req=True): def _getproperties(self, opt=None, is_apply_req=True):
if opt is None: if opt is None:
props = self._properties.get(opt, set(default_properties)) props = self._p_.getproperties(self._getkey(opt), default_properties)
else: else:
exp = None ntime = None
if opt in self._cache: if self._p_.hascache('property', self._getkey(opt)):
exp = time() ntime = time()
props, created = self._cache[opt] is_cached, props = self._p_.getcache('property', self._getkey(opt), ntime)
if exp < created: if is_cached:
return props return props
if is_apply_req: if is_apply_req:
self.apply_requires(opt) self.apply_requires(opt)
props = self._properties.get(opt, set(opt._properties)) props = self._p_.getproperties(self._getkey(opt), opt._properties)
self._set_cache(opt, props, exp) if 'expire' in self:
if ntime is None:
ntime = time()
self._p_.setcache('property', self._getkey(opt), props, ntime + expires_time)
return props return props
def append(self, propname): def append(self, propname):
"puts property propname in the Config's properties attribute" "puts property propname in the Config's properties attribute"
Property(self, self._get_properties()).append(propname) Property(self, self._getproperties()).append(propname)
def remove(self, propname): def remove(self, propname):
"deletes property propname in the Config's properties attribute" "deletes property propname in the Config's properties attribute"
Property(self, self._get_properties()).remove(propname) Property(self, self._getproperties()).remove(propname)
def _set_properties(self, properties, opt=None): def _setproperties(self, properties, opt=None):
"""save properties for specified opt """save properties for specified opt
(never save properties if same has option properties) (never save properties if same has option properties)
""" """
if opt is None: if opt is None:
self._properties[opt] = properties self._p_.setproperties(self._getkey(opt), properties)
else: else:
if set(opt._properties) == properties: if set(opt._properties) == properties:
if opt in self._properties: self._p_.reset_properties(self._getkey(opt))
del(self._properties[opt])
else: else:
self._properties[opt] = properties self._p_.setproperties(self._getkey(opt), properties)
self.context.cfgimpl_reset_cache() self.context.cfgimpl_reset_cache()
#____________________________________________________________ #____________________________________________________________
@ -273,14 +280,14 @@ class Setting(object):
the behavior can be different (typically with the `frozen` the behavior can be different (typically with the `frozen`
property) property)
""" """
# opt properties #opt properties
properties = copy(self._get_properties(opt_or_descr)) properties = copy(self._getproperties(opt_or_descr))
# remove opt permissive #remove opt permissive
properties -= self._get_permissive(opt_or_descr) properties -= self._p_.getpermissive(self._getkey(opt_or_descr))
# remove global permissive if need #remove global permissive if need
self_properties = copy(self._get_properties()) self_properties = copy(self._getproperties())
if force_permissive is True or 'permissive' in self_properties: if force_permissive is True or 'permissive' in self_properties:
properties -= self._get_permissive() properties -= self._p_.getpermissive()
# global properties # global properties
if force_properties is not None: if force_properties is not None:
@ -293,8 +300,8 @@ class Setting(object):
properties -= frozenset(('mandatory', 'frozen')) properties -= frozenset(('mandatory', 'frozen'))
else: else:
if 'mandatory' in properties and \ if 'mandatory' in properties and \
not self.context.cfgimpl_get_values()._is_empty(opt_or_descr, not self.context.cfgimpl_get_values()._isempty(
value): opt_or_descr, value):
properties.remove('mandatory') properties.remove('mandatory')
if is_write and 'everything_frozen' in self_properties: if is_write and 'everything_frozen' in self_properties:
properties.add('frozen') properties.add('frozen')
@ -315,13 +322,11 @@ class Setting(object):
"").format(opt_or_descr._name, "").format(opt_or_descr._name,
str(props)), props) str(props)), props)
def _get_permissive(self, opt=None): #FIXME should be setpermissive
return self._permissives.get(opt, frozenset())
def set_permissive(self, permissive, opt=None): def set_permissive(self, permissive, opt=None):
if not isinstance(permissive, tuple): if not isinstance(permissive, tuple):
raise TypeError(_('permissive must be a tuple')) raise TypeError(_('permissive must be a tuple'))
self._permissives[opt] = frozenset(permissive) self._p_.setpermissive(self._getkey(opt), permissive)
#____________________________________________________________ #____________________________________________________________
def setowner(self, owner): def setowner(self, owner):
@ -348,22 +353,11 @@ class Setting(object):
"convenience method to freeze, hidde and disable" "convenience method to freeze, hidde and disable"
self._read(rw_remove, rw_append) self._read(rw_remove, rw_append)
def _set_cache(self, opt, props, exp):
if 'expire' in self:
if exp is None:
exp = time()
self._cache[opt] = (props, time() + expires_time)
def reset_cache(self, only_expired): def reset_cache(self, only_expired):
if only_expired: if only_expired:
exp = time() self._p_.reset_expired_cache('property', time())
keys = self._cache.keys()
for key in keys:
props, created = self._cache[key]
if exp > created:
del(self._cache[key])
else: else:
self._cache.clear() self._p_.reset_all_cache('property')
def apply_requires(self, opt): def apply_requires(self, opt):
"carries out the jit (just in time requirements between options" "carries out the jit (just in time requirements between options"
@ -371,7 +365,7 @@ class Setting(object):
return return
# filters the callbacks # filters the callbacks
setting = Property(self, self._get_properties(opt, False), opt) setting = Property(self, self._getproperties(opt, False), opt)
descr = self.context.cfgimpl_get_description() descr = self.context.cfgimpl_get_description()
optpath = descr.impl_get_path_by_opt(opt) optpath = descr.impl_get_path_by_opt(opt)
for requires in opt._requires: for requires in opt._requires:
@ -413,3 +407,6 @@ class Setting(object):
# no requirement has been triggered, then just reverse the action # no requirement has been triggered, then just reverse the action
if not matches: if not matches:
setting.remove(action) setting.remove(action)
def _get_opt_path(self, opt):
return self.context.cfgimpl_get_description().impl_get_path_by_opt(opt)

View File

@ -31,9 +31,9 @@ class Values(object):
but the values are physicaly located here, in `Values`, wich is also but the values are physicaly located here, in `Values`, wich is also
responsible of a caching utility. responsible of a caching utility.
""" """
__slots__ = ('context', '_values', '_cache') __slots__ = ('context', '_p_')
def __init__(self, context): def __init__(self, context, config_id, plugin_name):
""" """
Initializes the values's dict. Initializes the values's dict.
@ -42,11 +42,17 @@ class Values(object):
""" """
self.context = context self.context = context
self._values = {} import_lib = 'tiramisu.plugins.{0}.value'.format(plugin_name)
self._cache = {} self._p_ = __import__(import_lib, globals(), locals(), ['Values'],
super(Values, self).__init__() -1).Values(config_id)
def _get_default(self, opt): def _getkey(self, opt):
if self._p_.key_is_path:
return self._get_opt_path(opt)
else:
return opt
def _getdefault(self, opt):
meta = self.context.cfgimpl_get_meta() meta = self.context.cfgimpl_get_meta()
if meta is not None: if meta is not None:
value = meta.cfgimpl_get_values()[opt] value = meta.cfgimpl_get_values()[opt]
@ -57,34 +63,45 @@ class Values(object):
else: else:
return value return value
def _get_value(self, opt, validate=True): def _getvalue(self, opt, validate=True):
"return value or default value if not set" "return value or default value if not set"
#if no value key = self._getkey(opt)
if opt not in self._values: if not self._p_.hasvalue(key):
value = self._get_default(opt) #if no value
value = self._getdefault(opt)
if opt.impl_is_multi(): if opt.impl_is_multi():
value = Multi(value, self.context, opt, validate) value = Multi(value, self.context, opt, validate)
else: else:
#if value #if value
value = self._values[opt][1] value = self._p_.getvalue(key)
if opt.impl_is_multi() and not isinstance(value, Multi):
#load value so don't need to validate if is not a Multi
value = Multi(value, self.context, opt, validate=False)
return value return value
def __delitem__(self, opt): def get_modified_values(self):
self._reset(opt) return self._p_.get_modified_values()
def _reset(self, opt): def __contains__(self, opt):
if opt in self._values: return self._p_.hasvalue('value', self._getkey(opt))
def __delitem__(self, opt):
self.reset(opt)
def reset(self, opt):
key = self._getkey(opt)
if self._p_.hasvalue(key):
setting = self.context.cfgimpl_get_settings() setting = self.context.cfgimpl_get_settings()
opt.impl_validate(opt.impl_getdefault(), self.context, opt.impl_validate(opt.impl_getdefault(), self.context,
'validator' in setting) 'validator' in setting)
self.context.cfgimpl_reset_cache() self.context.cfgimpl_reset_cache()
if (opt.impl_is_multi() and if (opt.impl_is_multi() and
opt.impl_get_multitype() == multitypes.master): opt.impl_get_multitype() == multitypes.master):
for slave in opt.impl_get_master_slaves(): for slave in opt.impl_get_master_slaves():
self._reset(slave) self.reset(slave)
del(self._values[opt]) self._p_.resetvalue(key)
def _is_empty(self, opt, value): def _isempty(self, opt, value):
"convenience method to know if an option is empty" "convenience method to know if an option is empty"
empty = opt._empty empty = opt._empty
if (not opt.impl_is_multi() and (value is None or value == empty)) or \ if (not opt.impl_is_multi() and (value is None or value == empty)) or \
@ -105,21 +122,27 @@ class Values(object):
def __getitem__(self, opt): def __getitem__(self, opt):
return self.getitem(opt) return self.getitem(opt)
def get_modified_values(self):
return self._values
def getitem(self, opt, validate=True, force_permissive=False, def getitem(self, opt, validate=True, force_permissive=False,
force_properties=None, validate_properties=True): force_properties=None, validate_properties=True):
if opt in self._cache: ntime = None
exp = time() key = self._getkey(opt)
value, created = self._cache[opt] if self._p_.hascache('value', self._getkey(opt)):
if exp < created: ntime = time()
is_cached, value = self._p_.getcache('value', key, ntime)
if is_cached:
if opt.impl_is_multi() and not isinstance(value, Multi):
#load value so don't need to validate if is not a Multi
value = Multi(value, self.context, opt, validate=False)
return value return value
val = self._getitem(opt, validate, force_permissive, force_properties, val = self._getitem(opt, validate, force_permissive, force_properties,
validate_properties) validate_properties)
if validate and validate_properties and force_permissive is False and \ if 'expire' in self.context.cfgimpl_get_settings() and validate and \
validate_properties and force_permissive is False and \
force_properties is None: force_properties is None:
self._set_cache(opt, val) if ntime is None:
ntime = time()
self._p_.setcache('value', key, val, ntime + expires_time)
return val return val
def _getitem(self, opt, validate, force_permissive, force_properties, def _getitem(self, opt, validate, force_permissive, force_properties,
@ -130,15 +153,12 @@ class Values(object):
# if value is callback and is not set # if value is callback and is not set
# or frozen with force_default_on_freeze # or frozen with force_default_on_freeze
if opt.impl_has_callback() and ( if opt.impl_has_callback() and (
self.is_default_owner(opt) or self.is_default_owner(opt) or
(is_frozen and (is_frozen and 'force_default_on_freeze' in setting[opt])):
'force_default_on_freeze' in setting[opt])):
no_value_slave = False no_value_slave = False
if (opt.impl_is_multi() and if (opt.impl_is_multi() and
opt.impl_get_multitype() == multitypes.slave): opt.impl_get_multitype() == multitypes.slave):
masterp = self.context.cfgimpl_get_description( masterp = self._get_opt_path(opt.impl_get_master_slaves())
).impl_get_path_by_opt(
opt.impl_get_master_slaves())
mastervalue = getattr(self.context, masterp) mastervalue = getattr(self.context, masterp)
lenmaster = len(mastervalue) lenmaster = len(mastervalue)
if lenmaster == 0: if lenmaster == 0:
@ -148,20 +168,20 @@ class Values(object):
if not no_value_slave: if not no_value_slave:
value = self._getcallback_value(opt) value = self._getcallback_value(opt)
if (opt.impl_is_multi() and if (opt.impl_is_multi() and
opt.impl_get_multitype() == multitypes.slave): opt.impl_get_multitype() == multitypes.slave):
if not isinstance(value, list): if not isinstance(value, list):
value = [value for i in range(lenmaster)] value = [value for i in range(lenmaster)]
if opt.impl_is_multi(): if opt.impl_is_multi():
value = Multi(value, self.context, opt, validate) value = Multi(value, self.context, opt, validate)
#suppress value if already set #suppress value if already set
self._reset(opt) self.reset(opt)
# frozen and force default # frozen and force default
elif is_frozen and 'force_default_on_freeze' in setting[opt]: elif is_frozen and 'force_default_on_freeze' in setting[opt]:
value = self._get_default(opt) value = self._getdefault(opt)
if opt.impl_is_multi(): if opt.impl_is_multi():
value = Multi(value, self.context, opt, validate) value = Multi(value, self.context, opt, validate)
else: else:
value = self._get_value(opt, validate) value = self._getvalue(opt, validate)
if validate: if validate:
opt.impl_validate(value, self.context, 'validator' in setting) opt.impl_validate(value, self.context, 'validator' in setting)
if self.is_default_owner(opt) and \ if self.is_default_owner(opt) and \
@ -191,30 +211,31 @@ class Values(object):
force_properties=None, force_properties=None,
is_write=True, validate_properties=True): is_write=True, validate_properties=True):
self.context.cfgimpl_reset_cache() self.context.cfgimpl_reset_cache()
setting = self.context.cfgimpl_get_settings()
if validate_properties: if validate_properties:
setting = self.context.cfgimpl_get_settings()
setting.validate_properties(opt, False, is_write, setting.validate_properties(opt, False, is_write,
value=value, value=value,
force_permissive=force_permissive, force_permissive=force_permissive,
force_properties=force_properties) force_properties=force_properties)
self._values[opt] = (setting.getowner(), value) owner = self.context.cfgimpl_get_settings().getowner()
self._p_.setvalue(self._getkey(opt), value, owner)
def getowner(self, opt): def getowner(self, opt):
if isinstance(opt, SymLinkOption): if isinstance(opt, SymLinkOption):
opt = opt._opt opt = opt._opt
owner = self._values.get(opt, (owners.default, None))[0] owner = self._p_.getowner(self._getkey(opt), owners.default)
meta = self.context.cfgimpl_get_meta() meta = self.context.cfgimpl_get_meta()
if owner is owners.default and meta is not None: if owner is owners.default and meta is not None:
owner = meta.cfgimpl_get_values().getowner(opt) owner = meta.cfgimpl_get_values().getowner(opt)
return owner return owner
def setowner(self, opt, owner): def setowner(self, opt, owner):
if opt not in self._values:
raise ConfigError(_('no value for {0} cannot change owner'
' to {1}').format(opt._name, owner))
if not isinstance(owner, owners.Owner): if not isinstance(owner, owners.Owner):
raise TypeError(_("invalid generic owner {0}").format(str(owner))) raise TypeError(_("invalid generic owner {0}").format(str(owner)))
self._values[opt] = (owner, self._values[opt][1]) if self.getowner(opt) == owners.default:
raise ConfigError(_('no value for {0} cannot change owner to {1}'
'').format(opt._name, owner))
self._p_.setowner(self._getkey(opt), owner)
def is_default_owner(self, opt): def is_default_owner(self, opt):
""" """
@ -224,23 +245,14 @@ class Values(object):
""" """
return self.getowner(opt) == owners.default return self.getowner(opt) == owners.default
def _set_cache(self, opt, val):
if 'expire' in self.context.cfgimpl_get_settings():
self._cache[opt] = (val, time() + expires_time)
def reset_cache(self, only_expired): def reset_cache(self, only_expired):
if only_expired: if only_expired:
exp = time() self._p_.reset_expired_cache('value', time())
keys = self._cache.keys()
for key in keys:
val, created = self._cache[key]
if exp > created:
del(self._cache[key])
else: else:
self._cache.clear() self._p_.reset_all_cache('value')
def __contains__(self, opt): def _get_opt_path(self, opt):
return opt in self._values return self.context.cfgimpl_get_description().impl_get_path_by_opt(opt)
# ____________________________________________________________ # ____________________________________________________________
# multi types # multi types
@ -273,13 +285,15 @@ class Multi(list):
self.opt.impl_get_master_slaves()) self.opt.impl_get_master_slaves())
mastervalue = getattr(self.context, masterp) mastervalue = getattr(self.context, masterp)
masterlen = len(mastervalue) masterlen = len(mastervalue)
if len(value) > masterlen or (len(value) < masterlen and valuelen = len(value)
not self.context.cfgimpl_get_values().is_default_owner(self.opt)): if valuelen > masterlen or (valuelen < masterlen and
not self.context.cfgimpl_get_values(
).is_default_owner(self.opt)):
raise SlaveError(_("invalid len for the slave: {0}" raise SlaveError(_("invalid len for the slave: {0}"
" which has {1} as master").format( " which has {1} as master").format(
self.opt._name, masterp)) self.opt._name, masterp))
elif len(value) < masterlen: elif valuelen < masterlen:
for num in range(0, masterlen - len(value)): for num in range(0, masterlen - valuelen):
value.append(self.opt.impl_getdefault_multi()) value.append(self.opt.impl_getdefault_multi())
#else: same len so do nothing #else: same len so do nothing
return value return value
@ -289,7 +303,7 @@ class Multi(list):
values = self.context.cfgimpl_get_values() values = self.context.cfgimpl_get_values()
for slave in self.opt._master_slaves: for slave in self.opt._master_slaves:
if not values.is_default_owner(slave): if not values.is_default_owner(slave):
value_slave = values._get_value(slave) value_slave = values._getvalue(slave)
if len(value_slave) > masterlen: if len(value_slave) > masterlen:
raise SlaveError(_("invalid len for the master: {0}" raise SlaveError(_("invalid len for the master: {0}"
" which has {1} as slave with" " which has {1} as slave with"
@ -303,8 +317,8 @@ class Multi(list):
def __setitem__(self, key, value): def __setitem__(self, key, value):
self._validate(value) self._validate(value)
#assume not checking mandatory property #assume not checking mandatory property
self.context.cfgimpl_get_values()._setvalue(self.opt, self)
super(Multi, self).__setitem__(key, value) super(Multi, self).__setitem__(key, value)
self.context.cfgimpl_get_values()._setvalue(self.opt, self)
def append(self, value, force=False): def append(self, value, force=False):
"""the list value can be updated (appened) """the list value can be updated (appened)
@ -322,12 +336,8 @@ class Multi(list):
if isinstance(value, list): if isinstance(value, list):
value = None value = None
self._validate(value) self._validate(value)
#set value without valid properties
self.context.cfgimpl_get_values(
)._setvalue(self.opt,
self,
validate_properties=not force)
super(Multi, self).append(value) super(Multi, self).append(value)
self.context.cfgimpl_get_values()._setvalue(self.opt, self, validate_properties=not force)
if not force and self.opt.impl_get_multitype() == multitypes.master: if not force and self.opt.impl_get_multitype() == multitypes.master:
for slave in self.opt.impl_get_master_slaves(): for slave in self.opt.impl_get_master_slaves():
if not values.is_default_owner(slave): if not values.is_default_owner(slave):
@ -336,41 +346,44 @@ class Multi(list):
dvalue = values._getcallback_value(slave, index=index) dvalue = values._getcallback_value(slave, index=index)
else: else:
dvalue = slave.impl_getdefault_multi() dvalue = slave.impl_getdefault_multi()
#get multi without valid properties old_value = values.getitem(slave, validate_properties=False)
values.getitem(slave, validate_properties=False).append( if len(old_value) < self.__len__():
dvalue, force=True) values.getitem(slave, validate_properties=False).append(
dvalue, force=True)
else:
values.getitem(slave, validate_properties=False)[index] = dvalue
def sort(self, cmp=None, key=None, reverse=False): def sort(self, cmp=None, key=None, reverse=False):
if self.opt.impl_get_multitype() in [multitypes.slave, if self.opt.impl_get_multitype() in [multitypes.slave,
multitypes.master]: multitypes.master]:
raise SlaveError(_("cannot sort multi option {0} if master or slave" raise SlaveError(_("cannot sort multi option {0} if master or slave"
"").format(self.opt._name)) "").format(self.opt._name))
self.context.cfgimpl_get_values()._setvalue(self.opt, self)
super(Multi, self).sort(cmp=cmp, key=key, reverse=reverse) super(Multi, self).sort(cmp=cmp, key=key, reverse=reverse)
self.context.cfgimpl_get_values()._setvalue(self.opt, self)
def reverse(self): def reverse(self):
if self.opt.impl_get_multitype() in [multitypes.slave, if self.opt.impl_get_multitype() in [multitypes.slave,
multitypes.master]: multitypes.master]:
raise SlaveError(_("cannot reverse multi option {0} if master or " raise SlaveError(_("cannot reverse multi option {0} if master or "
"slave").format(self.opt._name)) "slave").format(self.opt._name))
self.context.cfgimpl_get_values()._setvalue(self.opt, self)
super(Multi, self).reverse() super(Multi, self).reverse()
self.context.cfgimpl_get_values()._setvalue(self.opt, self)
def insert(self, index, obj): def insert(self, index, obj):
if self.opt.impl_get_multitype() in [multitypes.slave, if self.opt.impl_get_multitype() in [multitypes.slave,
multitypes.master]: multitypes.master]:
raise SlaveError(_("cannot insert multi option {0} if master or " raise SlaveError(_("cannot insert multi option {0} if master or "
"slave").format(self.opt._name)) "slave").format(self.opt._name))
self.context.cfgimpl_get_values()._setvalue(self.opt, self)
super(Multi, self).insert(index, obj) super(Multi, self).insert(index, obj)
self.context.cfgimpl_get_values()._setvalue(self.opt, self)
def extend(self, iterable): def extend(self, iterable):
if self.opt.impl_get_multitype() in [multitypes.slave, if self.opt.impl_get_multitype() in [multitypes.slave,
multitypes.master]: multitypes.master]:
raise SlaveError(_("cannot extend multi option {0} if master or " raise SlaveError(_("cannot extend multi option {0} if master or "
"slave").format(self.opt._name)) "slave").format(self.opt._name))
self.context.cfgimpl_get_values()._setvalue(self.opt, self)
super(Multi, self).extend(iterable) super(Multi, self).extend(iterable)
self.context.cfgimpl_get_values()._setvalue(self.opt, self)
def _validate(self, value): def _validate(self, value):
if value is not None: if value is not None:
@ -378,8 +391,9 @@ class Multi(list):
self.opt._validate(value) self.opt._validate(value)
except ValueError, err: except ValueError, err:
raise ValueError(_("invalid value {0} " raise ValueError(_("invalid value {0} "
"for option {1}: {2}").format(str(value), "for option {1}: {2}"
self.opt._name, err)) "").format(str(value),
self.opt._name, err))
def pop(self, key, force=False): def pop(self, key, force=False):
"""the list value can be updated (poped) """the list value can be updated (poped)
@ -401,8 +415,6 @@ class Multi(list):
validate_properties=False validate_properties=False
).pop(key, force=True) ).pop(key, force=True)
#set value without valid properties #set value without valid properties
self.context.cfgimpl_get_values( ret = super(Multi, self).pop(key)
)._setvalue(self.opt, self.context.cfgimpl_get_values()._setvalue(self.opt, self, validate_properties=not force)
self, return ret
validate_properties=not force)
return super(Multi, self).pop(key)