impl_get_information and impl_set_information are, now, persistent in storage
authorEmmanuel Garette <egarette@cadoles.com>
Tue, 3 Sep 2013 08:38:28 +0000 (10:38 +0200)
committerEmmanuel Garette <egarette@cadoles.com>
Tue, 3 Sep 2013 08:38:38 +0000 (10:38 +0200)
test/test_config.py
test/test_storage.py
tiramisu/config.py
tiramisu/option.py
tiramisu/storage/dictionary/value.py
tiramisu/storage/sqlite3/value.py
tiramisu/value.py

index 4e38f19..17e863a 100644 (file)
@@ -141,6 +141,7 @@ def test_information_config():
     string = 'some informations'
     config.impl_set_information('info', string)
     assert config.impl_get_information('info') == string
+    raises(ValueError, "config.impl_get_information('noinfo')")
 
 
 def test_config_impl_get_path_by_opt():
index 6dbb721..56c44e5 100644 (file)
@@ -18,7 +18,6 @@ def test_list():
     b = BoolOption('b', '')
     o = OptionDescription('od', '', [b])
     c = Config(o, session_id='test_non_persistent')
-    from tiramisu.setting import list_sessions
     assert 'test_non_persistent' in list_sessions()
     del(c)
     assert 'test_non_persistent' not in list_sessions()
@@ -43,7 +42,6 @@ def test_list_sessions_persistent():
         # storage is not persistent
         pass
     else:
-        from tiramisu.setting import list_sessions
         assert 'test_persistent' in list_sessions()
 
 
@@ -124,3 +122,19 @@ def test_two_persistent_owner():
         assert c.getowner(b) == owners.persistent
         assert c2.getowner(b) == owners.persistent
         delete_session('test_persistent')
+
+
+def test_two_persistent_information():
+    b = BoolOption('b', '')
+    o = OptionDescription('od', '', [b])
+    try:
+        c = Config(o, session_id='test_persistent', persistent=True)
+    except ValueError:
+        # storage is not persistent
+        pass
+    else:
+        c.impl_set_information('info', 'string')
+        assert c.impl_get_information('info') == 'string'
+        c2 = Config(o, session_id='test_persistent', persistent=True)
+        assert c2.impl_get_information('info') == 'string'
+        delete_session('test_persistent')
index ae68e98..8537c0d 100644 (file)
 # ____________________________________________________________
 import weakref
 from tiramisu.error import PropertiesOptionError, ConfigError
-from tiramisu.option import OptionDescription, Option, SymLinkOption, \
-    BaseInformation
+from tiramisu.option import OptionDescription, Option, SymLinkOption
 from tiramisu.setting import groups, Settings, default_encoding, get_storage
 from tiramisu.value import Values
 from tiramisu.i18n import _
 
 
-class SubConfig(BaseInformation):
+class SubConfig(object):
     "sub configuration management entry"
     __slots__ = ('_impl_context', '_impl_descr', '_impl_path')
 
@@ -252,10 +251,10 @@ class SubConfig(BaseInformation):
             :returns: list of matching Option objects
         """
         return self._cfgimpl_get_context()._find(bytype, byname, byvalue,
-                                                first=False,
-                                                type_=type_,
-                                                _subpath=self.cfgimpl_get_path()
-                                                )
+                                                 first=False,
+                                                 type_=type_,
+                                                 _subpath=self.cfgimpl_get_path()
+                                                 )
 
     def find_first(self, bytype=None, byname=None, byvalue=None,
                    type_='option', display_error=True):
@@ -501,6 +500,22 @@ class CommonConfig(SubConfig):
     def cfgimpl_get_meta(self):
         return self._impl_meta
 
+    # information
+    def impl_set_information(self, key, value):
+        """updates the information's attribute
+
+        :param key: information's key (ex: "help", "doc"
+        :param value: information's value (ex: "the help string")
+        """
+        self._impl_values.set_information(key, value)
+
+    def impl_get_information(self, key, default=None):
+        """retrieves one information's item
+
+        :param key: the item string (ex: "help")
+        """
+        return self._impl_values.get_information(key, default)
+
 
 # ____________________________________________________________
 class Config(CommonConfig):
@@ -526,7 +541,6 @@ class Config(CommonConfig):
         super(Config, self).__init__(descr, weakref.ref(self))
         self._impl_build_all_paths()
         self._impl_meta = None
-        self._impl_informations = {}
 
     def cfgimpl_reset_cache(self,
                             only_expired=False,
@@ -565,7 +579,6 @@ class Config(CommonConfig):
 #        self._impl_settings = Settings(self, storage)
 #        self._impl_values = Values(self, storage)
 #        self._impl_meta = None
-#        self._impl_informations = {}
 
 #    def cfgimpl_get_children(self):
 #        return self._impl_children
index eca61e2..b8bcc0a 100644 (file)
@@ -54,51 +54,15 @@ def valid_name(name):
 #
 
 
-class BaseInformation(object):
-    "interface for an option's information attribute"
-    __slots__ = ('_impl_informations',)
-
-    def impl_set_information(self, key, value):
-        """updates the information's attribute
-        (which is a dictionary)
-
-        :param key: information's key (ex: "help", "doc"
-        :param value: information's value (ex: "the help string")
-        """
-        try:
-            self._impl_informations[key] = value
-        except AttributeError:
-            raise AttributeError(_('{0} has no attribute '
-                                   'impl_set_information').format(
-                                       self.__class__.__name__))
-
-    def impl_get_information(self, key, default=None):
-        """retrieves one information's item
-
-        :param key: the item string (ex: "help")
-        """
-        try:
-            if key in self._impl_informations:
-                return self._impl_informations[key]
-            elif default is not None:
-                return default
-            else:
-                raise ValueError(_("information's item"
-                                   " not found: {0}").format(key))
-        except AttributeError:
-            raise AttributeError(_('{0} has no attribute '
-                                   'impl_get_information').format(
-                                       self.__class__.__name__))
-
-
-class BaseOption(BaseInformation):
+class BaseOption(object):
     """This abstract base class stands for attribute access
     in options that have to be set only once, it is of course done in the
     __setattr__ method
     """
     __slots__ = ('_name', '_requires', '_properties', '_readonly',
-                 '_consistencies', '_calc_properties', '_state_consistencies',
-                 '_state_readonly', '_state_requires', '_stated')
+                 '_consistencies', '_calc_properties', '_impl_informations',
+                 '_state_consistencies', '_state_readonly', '_state_requires',
+                 '_stated')
 
     def __init__(self, name, doc, requires, properties):
         if not valid_name(name):
@@ -160,6 +124,30 @@ class BaseOption(BaseInformation):
                                            name))
         object.__setattr__(self, name, value)
 
+    # information
+    def impl_set_information(self, key, value):
+        """updates the information's attribute
+        (which is a dictionary)
+
+        :param key: information's key (ex: "help", "doc"
+        :param value: information's value (ex: "the help string")
+        """
+        self._impl_informations[key] = value
+
+    def impl_get_information(self, key, default=None):
+        """retrieves one information's item
+
+        :param key: the item string (ex: "help")
+        """
+        if key in self._impl_informations:
+            return self._impl_informations[key]
+        elif default is not None:
+            return default
+        else:
+            raise ValueError(_("information's item not found: {0}").format(
+                key))
+
+    # serialize/unserialize
     def _impl_convert_consistencies(self, descr, load=False):
         if not load and self._consistencies is None:
             self._state_consistencies = None
@@ -215,6 +203,7 @@ class BaseOption(BaseInformation):
             else:
                 self._state_requires = new_value
 
+    # serialize
     def _impl_getstate(self, descr):
         self._stated = True
         self._impl_convert_consistencies(descr)
@@ -252,6 +241,7 @@ class BaseOption(BaseInformation):
             del(states['_stated'])
         return states
 
+    # unserialize
     def _impl_setstate(self, descr):
         self._impl_convert_consistencies(descr, load=True)
         self._impl_convert_requires(descr, load=True)
@@ -860,7 +850,7 @@ class OptionDescription(BaseOption):
                  '_state_group_type', '_properties', '_children',
                  '_consistencies', '_calc_properties', '__weakref__',
                  '_readonly', '_impl_informations', '_state_requires',
-                 '_state_consistencies', '_stated')
+                 '_state_consistencies', '_stated', '_state_readonly')
     _opt_type = 'optiondescription'
 
     def __init__(self, name, doc, children, requires=None, properties=None):
index 9c3e1f9..c1bf2eb 100644 (file)
@@ -22,12 +22,13 @@ from tiramisu.storage.dictionary.storage import Cache
 
 
 class Values(Cache):
-    __slots__ = ('_values', '__weakref__')
+    __slots__ = ('_values', '_informations', '__weakref__')
 
     def __init__(self, storage):
         """init plugin means create values storage
         """
         self._values = {}
+        self._informations = {}
         # should init cache too
         super(Values, self).__init__(storage)
 
@@ -72,3 +73,22 @@ class Values(Cache):
         return: owner object
         """
         return self._values.get(path, (default, None))[0]
+
+    def set_information(self, key, value):
+        """updates the information's attribute
+        (which is a dictionary)
+
+        :param key: information's key (ex: "help", "doc"
+        :param value: information's value (ex: "the help string")
+        """
+        self._informations[key] = value
+
+    def get_information(self, key):
+        """retrieves one information's item
+
+        :param key: the item string (ex: "help")
+        """
+        if key in self._informations:
+            return self._informations[key]
+        else:
+            raise ValueError("not found")
index 4207c43..2b9ddc7 100644 (file)
@@ -32,7 +32,10 @@ class Values(Cache):
         super(Values, self).__init__('value', storage)
         values_table = 'CREATE TABLE IF NOT EXISTS value(path text primary '
         values_table += 'key, value text, owner text)'
-        self.storage.execute(values_table)
+        self.storage.execute(values_table, commit=False)
+        informations_table = 'CREATE TABLE IF NOT EXISTS information(key text primary '
+        informations_table += 'key, value text)'
+        self.storage.execute(informations_table)
         for owner in self.storage.select("SELECT DISTINCT owner FROM value", tuple(), False):
             try:
                 getattr(owners, owner[0])
@@ -114,3 +117,27 @@ class Values(Cache):
             except AttributeError:
                 owners.addowner(owner)
                 return getattr(owners, owner)
+
+    def set_information(self, key, value):
+        """updates the information's attribute
+        (which is a dictionary)
+
+        :param key: information's key (ex: "help", "doc"
+        :param value: information's value (ex: "the help string")
+        """
+        self.storage.execute("DELETE FROM information WHERE key = ?", (key,),
+                             False)
+        self.storage.execute("INSERT INTO information(key, value) VALUES "
+                             "(?, ?)", (key, self._sqlite_encode(value)))
+
+    def get_information(self, key):
+        """retrieves one information's item
+
+        :param key: the item string (ex: "help")
+        """
+        value = self.storage.select("SELECT value FROM information WHERE key = ?",
+                                    (key,))
+        if value is None:
+            raise ValueError("not found")
+        else:
+            return self._sqlite_decode(value[0])
index d846bc4..b401634 100644 (file)
@@ -315,6 +315,30 @@ class Values(object):
         """
         return self.context().cfgimpl_get_description().impl_get_path_by_opt(opt)
 
+    # information
+    def set_information(self, key, value):
+        """updates the information's attribute
+
+        :param key: information's key (ex: "help", "doc"
+        :param value: information's value (ex: "the help string")
+        """
+        self._p_.set_information(key, value)
+
+    def get_information(self, key, default=None):
+        """retrieves one information's item
+
+        :param key: the item string (ex: "help")
+        """
+        try:
+            return self._p_.get_information(key)
+        except ValueError:
+            if default is not None:
+                return default
+            else:
+                raise ValueError(_("information's item"
+                                   " not found: {0}").format(key))
+
+
 # ____________________________________________________________
 # multi types