Merge branch 'master' of ssh://git.labs.libre-entreprise.org/gitroot/tiramisu
authorgwen <gremond@cadoles.com>
Wed, 28 Aug 2013 07:22:50 +0000 (09:22 +0200)
committergwen <gremond@cadoles.com>
Wed, 28 Aug 2013 07:22:50 +0000 (09:22 +0200)
doc/config.txt
test/test_dereference.py [new file with mode: 0644]
test/test_storage.py
tiramisu/option.py
tiramisu/setting.py
tiramisu/storage/dictionary/value.py
tiramisu/storage/sqlite3/value.py
tiramisu/value.py

index 9bce1cb..3b24cb6 100644 (file)
@@ -6,7 +6,7 @@ Options handling basics
 
 Tiramisu is made of almost three main objects :
 
-- :class:`tiramisu.config.Config` witch is the whole configuration entry point
+- :class:`tiramisu.config.Config` which is the whole configuration entry point
 - :class:`tiramisu.option.Option` stands for the option types
 - :class:`tiramisu.option.OptionDescription` is the shema, the option's structure
 
diff --git a/test/test_dereference.py b/test/test_dereference.py
new file mode 100644 (file)
index 0000000..be8dfde
--- /dev/null
@@ -0,0 +1,111 @@
+# coding: utf-8
+import autopath
+#from py.test import raises
+
+from tiramisu.config import Config
+from tiramisu.option import BoolOption, OptionDescription
+import weakref
+
+
+def test_deref_storage():
+    b = BoolOption('b', '')
+    o = OptionDescription('od', '', [b])
+    c = Config(o)
+    w = weakref.ref(c.cfgimpl_get_values()._p_)
+    del(c)
+    assert w() is None
+
+
+def test_deref_value():
+    b = BoolOption('b', '')
+    o = OptionDescription('od', '', [b])
+    c = Config(o)
+    w = weakref.ref(c.cfgimpl_get_values())
+    del(c)
+    assert w() is None
+
+
+def test_deref_setting():
+    b = BoolOption('b', '')
+    o = OptionDescription('od', '', [b])
+    c = Config(o)
+    w = weakref.ref(c.cfgimpl_get_settings())
+    del(c)
+    assert w() is None
+
+
+def test_deref_config():
+    b = BoolOption('b', '')
+    o = OptionDescription('od', '', [b])
+    c = Config(o)
+    w = weakref.ref(c)
+    del(c)
+    assert w() is None
+
+
+def test_deref_option():
+    b = BoolOption('b', '')
+    o = OptionDescription('od', '', [b])
+    w = weakref.ref(b)
+    del(b)
+    assert w() is not None
+    del(o)
+    assert w() is None
+
+
+def test_deref_optiondescription():
+    b = BoolOption('b', '')
+    o = OptionDescription('od', '', [b])
+    w = weakref.ref(o)
+    del(b)
+    assert w() is not None
+    del(o)
+    assert w() is None
+
+
+def test_deref_option_cache():
+    b = BoolOption('b', '')
+    o = OptionDescription('od', '', [b])
+    o.impl_build_cache()
+    w = weakref.ref(b)
+    del(b)
+    assert w() is not None
+    del(o)
+    assert w() is None
+
+
+def test_deref_optiondescription_cache():
+    b = BoolOption('b', '')
+    o = OptionDescription('od', '', [b])
+    o.impl_build_cache()
+    w = weakref.ref(o)
+    del(b)
+    assert w() is not None
+    del(o)
+    assert w() is None
+
+
+def test_deref_option_config():
+    b = BoolOption('b', '')
+    o = OptionDescription('od', '', [b])
+    c = Config(o)
+    w = weakref.ref(b)
+    del(b)
+    assert w() is not None
+    del(o)
+    assert w() is not None
+    del(c)
+    assert w() is None
+
+
+def test_deref_optiondescription_config():
+    b = BoolOption('b', '')
+    o = OptionDescription('od', '', [b])
+    c = Config(o)
+    w = weakref.ref(o)
+    del(b)
+    assert w() is not None
+    del(o)
+    assert w() is not None
+    del(c)
+    assert w() is None
index 3857fb5..6dbb721 100644 (file)
@@ -1,8 +1,11 @@
+# coding: utf-8
 import autopath
 #from py.test import raises
 
 from tiramisu.config import Config
 from tiramisu.option import BoolOption, OptionDescription
+from tiramisu.setting import owners
+from tiramisu.setting import list_sessions, delete_session
 
 
 def test_non_persistent():
@@ -53,7 +56,6 @@ def test_delete_session_persistent():
         # storage is not persistent
         pass
     else:
-        from tiramisu.setting import list_sessions, delete_session
         assert 'test_persistent' in list_sessions()
         delete_session('test_persistent')
         assert 'test_persistent' not in list_sessions()
@@ -74,8 +76,51 @@ def test_create_persistent_retrieve():
         del(c)
         c = Config(o, session_id='test_persistent', persistent=True)
         assert c.b is True
-        from tiramisu.setting import list_sessions, delete_session
         assert 'test_persistent' in list_sessions()
         delete_session('test_persistent')
         c = Config(o, session_id='test_persistent', persistent=True)
         assert c.b is None
+        delete_session('test_persistent')
+
+
+def test_two_persistent():
+    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:
+        c2 = Config(o, session_id='test_persistent', persistent=True)
+        assert c.b is None
+        assert c2.b is None
+        c.b = False
+        assert c.b is False
+        assert c2.b is False
+        c.b = True
+        assert c.b is True
+        assert c2.b is True
+        delete_session('test_persistent')
+
+
+def test_two_persistent_owner():
+    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:
+        c2 = Config(o, session_id='test_persistent', persistent=True)
+        owners.addowner('persistent')
+        assert c.getowner(b) == owners.default
+        assert c2.getowner(b) == owners.default
+        c.b = False
+        assert c.getowner(b) == owners.user
+        assert c2.getowner(b) == owners.user
+        c.cfgimpl_get_values().setowner(b, owners.persistent)
+        assert c.getowner(b) == owners.persistent
+        assert c2.getowner(b) == owners.persistent
+        delete_session('test_persistent')
index 498ddf3..724c691 100644 (file)
@@ -69,7 +69,7 @@ class BaseInformation(object):
         except AttributeError:
             raise AttributeError(_('{0} has no attribute '
                                    'impl_set_information').format(
-                                   self.__class__.__name__))
+                                       self.__class__.__name__))
 
     def impl_get_information(self, key, default=None):
         """retrieves one information's item
@@ -87,7 +87,7 @@ class BaseInformation(object):
         except AttributeError:
             raise AttributeError(_('{0} has no attribute '
                                    'impl_get_information').format(
-                                   self.__class__.__name__))
+                                       self.__class__.__name__))
 
 
 class Option(BaseInformation):
@@ -99,7 +99,7 @@ class Option(BaseInformation):
     __slots__ = ('_name', '_requires', '_multi', '_validator',
                  '_default_multi', '_default', '_properties', '_callback',
                  '_multitype', '_master_slaves', '_consistencies', '_empty',
-                 '_calc_properties')
+                 '_calc_properties', '__weakref__')
     _empty = ''
 
     def __init__(self, name, doc, default=None, default_multi=None,
@@ -150,7 +150,7 @@ class Option(BaseInformation):
             except ValueError, err:
                 raise ValueError(_("invalid default_multi value {0} "
                                    "for option {1}: {2}").format(
-                                   str(default_multi), name, err))
+                                       str(default_multi), name, err))
         if callback is not None and (default is not None or
                                      default_multi is not None):
             raise ValueError(_("default value not allowed if option: {0} "
@@ -180,8 +180,8 @@ class Option(BaseInformation):
         if not isinstance(properties, tuple):
             raise TypeError(_('invalid properties type {0} for {1},'
                             ' must be a tuple').format(
-                                                type(properties),
-                                                self._name))
+                                type(properties),
+                                self._name))
         self._properties = properties  # 'hidden', 'disabled'...
 
     def __eq__(self, other):
@@ -329,7 +329,7 @@ class Option(BaseInformation):
         "no default value has been set yet"
         if ((not self.impl_is_multi() and self._default is None) or
                 (self.impl_is_multi() and (self._default == []
-                                      or None in self._default))):
+                                           or None in self._default))):
             return True
         return False
 
@@ -714,7 +714,7 @@ class OptionDescription(BaseInformation):
     """
     __slots__ = ('_name', '_requires', '_cache_paths', '_group_type',
                  '_properties', '_children', '_consistencies',
-                 '_calc_properties')
+                 '_calc_properties', '__weakref__')
 
     def __init__(self, name, doc, children, requires=None, properties=None):
         """
@@ -801,8 +801,8 @@ class OptionDescription(BaseInformation):
         else:
             save = False
         if cache_path is None:
-            cache_path = [self._name]
-            cache_option = [self]
+            cache_path = []
+            cache_option = []
         for option in self.impl_getchildren():
             attr = option._name
             if attr.startswith('_cfgimpl'):
@@ -929,7 +929,7 @@ def validate_requires_arg(requires, name):
     :param requires: have a look at the
                      :meth:`tiramisu.setting.Settings.apply_requires` method to
                      know more about
-                     the description of the requires dictionnary
+                     the description of the requires dictionary
     """
     if requires is None:
         return None, None
@@ -1002,11 +1002,8 @@ def validate_requires_arg(requires, name):
     for opt_requires in ret_requires.values():
         ret_action = []
         for require in opt_requires.values():
-            req = (require[0], tuple(require[1]),
-                                     require[2],
-                                     require[3],
-                                     require[4],
-                                     require[5])
+            req = (require[0], tuple(require[1]), require[2], require[3],
+                   require[4], require[5])
             ret_action.append(req)
         ret.append(tuple(ret_action))
     return frozenset(config_action.keys()), tuple(ret)
index e6bc645..86f900e 100644 (file)
@@ -222,9 +222,8 @@ def get_storage(context, session_id, persistent):
 
     if session_id is None:
         session_id = gen_id(context)
-    a=__import__(storage_type.get_storage(), globals(), locals(),
+    return __import__(storage_type.get_storage(), globals(), locals(),
                       ['Storage'], -1).Storage(session_id, persistent)
-    return a
 
 
 def list_sessions():
@@ -240,7 +239,7 @@ def delete_session(session_id):
 #____________________________________________________________
 class Settings(object):
     "``Config()``'s configuration options"
-    __slots__ = ('context', '_owner', '_p_')
+    __slots__ = ('context', '_owner', '_p_', '__weakref__')
 
     def __init__(self, context, storage):
         """
@@ -496,7 +495,7 @@ class Settings(object):
                                              "'{1}'").format(path, reqpath))
                 try:
                     value = self.context()._getattr(reqpath,
-                                                  force_permissive=True)
+                                                    force_permissive=True)
                 except PropertiesOptionError, err:
                     if not transitive:
                         continue
index e3d41ac..9c3e1f9 100644 (file)
@@ -22,7 +22,7 @@ from tiramisu.storage.dictionary.storage import Cache
 
 
 class Values(Cache):
-    __slots__ = ('_values',)
+    __slots__ = ('_values', '__weakref__')
 
     def __init__(self, storage):
         """init plugin means create values storage
index a70b675..4207c43 100644 (file)
@@ -23,7 +23,7 @@ from tiramisu.setting import owners
 
 
 class Values(Cache):
-    __slots__ = tuple()
+    __slots__ = ('__weakref__',)
 
     def __init__(self, storage):
         """init plugin means create values storage
index c654206..1d1babc 100644 (file)
@@ -32,7 +32,7 @@ class Values(object):
     but the values are physicaly located here, in `Values`, wich is also
     responsible of a caching utility.
     """
-    __slots__ = ('context', '_p_')
+    __slots__ = ('context', '_p_', '__weakref__')
 
     def __init__(self, context, storage):
         """