we can pickle object
authorEmmanuel Garette <egarette@cadoles.com>
Mon, 14 Apr 2014 20:53:40 +0000 (22:53 +0200)
committerEmmanuel Garette <egarette@cadoles.com>
Mon, 14 Apr 2014 20:53:40 +0000 (22:53 +0200)
test/test_state.py
tiramisu/option/baseoption.py
tiramisu/option/optiondescription.py
tiramisu/storage/dictionary/option.py

index 8739789..9b40219 100644 (file)
@@ -66,8 +66,11 @@ def _diff_opt(opt1, opt2):
             for index, _opt in enumerate(val1[1]):
                 assert _opt._name == val2[1][index]._name
         elif attr == '_requires':
-            assert val1[0][0][0]._name == val2[0][0][0]._name
-            assert val1[0][0][1:] == val2[0][0][1:]
+            if val1 == val2 == []:
+                pass
+            else:
+                assert val1[0][0][0]._name == val2[0][0][0]._name
+                assert val1[0][0][1:] == val2[0][0][1:]
         elif attr == '_opt':
             assert val1._name == val2._name
         elif attr == '_consistencies':
@@ -78,17 +81,18 @@ def _diff_opt(opt1, opt2):
                     for idx, opt in enumerate(consistency[1]):
                         assert opt._name == val2[index][1][idx]._name
         elif attr == '_callback':
-            assert val1[0] == val2[0]
-            if val1[1] is not None:
-                for key, values in val1[1].items():
+            assert val1 == val2
+        elif attr == '_callback_params':
+            if val1 is not None:
+                for key, values in val1.items():
                     for idx, value in enumerate(values):
                         if isinstance(value, tuple):
-                            assert val1[1][key][idx][0]._name == val2[1][key][idx][0]._name
-                            assert val1[1][key][idx][1] == val2[1][key][idx][1]
+                            assert val1[key][idx][0]._name == val2[key][idx][0]._name
+                            assert val1[key][idx][1] == val2[key][idx][1]
                         else:
-                            assert val1[1][key][idx] == val2[1][key][idx]
+                            assert val1[key][idx] == val2[key][idx]
             else:
-                assert val1[1] == val2[1]
+                assert val1 == val2
         else:
             assert val1 == val2
 
@@ -128,241 +132,246 @@ def _diff_conf(cfg1, cfg2):
             assert cfg1.cfgimpl_get_settings().get_modified_permissives() == cfg2.cfgimpl_get_settings().get_modified_permissives()
         elif attr == '_impl_descr':
             _diff_opt(cfg1.cfgimpl_get_description(), cfg2.cfgimpl_get_description())
+        elif attr == '_impl_children':
+            for index, _opt in enumerate(val1):
+                _diff_conf(_opt, val2[index])
         else:
             assert val1 == val2
 
 
-#def test_diff_opt():
-#    b = BoolOption('b', '')
-#    u = UnicodeOption('u', '', requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}])
-#    s = SymLinkOption('s', u)
-#    o = OptionDescription('o', '', [b, u, s])
-#    o1 = OptionDescription('o1', '', [o])
-#
-#    a = dumps(o1)
-#    q = loads(a)
-#    _diff_opt(o1, q)
-#    _diff_opt(o1.o, q.o)
-#    _diff_opt(o1.o.b, q.o.b)
-#    _diff_opt(o1.o.u, q.o.u)
-#    _diff_opt(o1.o.s, q.o.s)
-#
-#
-#def test_only_optiondescription():
-#    b = BoolOption('b', '')
-#    raises(SystemError, "a = dumps(b)")
-#
-#
-#def test_diff_opt_cache():
-#    b = BoolOption('b', '')
-#    u = UnicodeOption('u', '', requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}])
-#    u.impl_add_consistency('not_equal', b)
-#    s = SymLinkOption('s', u)
-#    o = OptionDescription('o', '', [b, u, s])
-#    o1 = OptionDescription('o1', '', [o])
-#    o1.impl_build_cache()
-#
-#    a = dumps(o1)
-#    q = loads(a)
-#    _diff_opt(o1, q)
-#    _diff_opt(o1.o, q.o)
-#    _diff_opt(o1.o.b, q.o.b)
-#    _diff_opt(o1.o.u, q.o.u)
-#    _diff_opt(o1.o.s, q.o.s)
-#
-#
-#def test_diff_opt_callback():
-#    b = BoolOption('b', '', callback=return_value)
-#    b2 = BoolOption('b2', '', callback=return_value, callback_params={'': ('yes',)})
-#    b3 = BoolOption('b3', '', callback=return_value, callback_params={'': ('yes', (b, False)), 'value': ('no',)})
-#    o = OptionDescription('o', '', [b, b2, b3])
-#    o1 = OptionDescription('o1', '', [o])
-#    o1.impl_build_cache()
-#
-#    a = dumps(o1)
-#    q = loads(a)
-#    _diff_opt(o1, q)
-#    _diff_opt(o1.o, q.o)
-#    _diff_opt(o1.o.b, q.o.b)
-#    _diff_opt(o1.o.b2, q.o.b2)
-#    _diff_opt(o1.o.b3, q.o.b3)
-#
-#
-#def test_no_state_attr():
-#    # all _state_xxx attributes should be deleted
-#    b = BoolOption('b', '')
-#    u = UnicodeOption('u', '', requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}])
-#    s = SymLinkOption('s', u)
-#    o = OptionDescription('o', '', [b, u, s])
-#    o1 = OptionDescription('o1', '', [o])
-#
-#    a = dumps(o1)
-#    q = loads(a)
-#    _no_state(q)
-#    _no_state(q.o)
-#    _no_state(q.o.b)
-#    _no_state(q.o.u)
-#    _no_state(q.o.s)
-#
-#
-#def test_state_config():
-#    val1 = BoolOption('val1', "")
-#    maconfig = OptionDescription('rootconfig', '', [val1])
-#    try:
-#        cfg = Config(maconfig, persistent=True, session_id='29090931')
-#    except ValueError:
-#        cfg = Config(maconfig, session_id='29090931')
-#        cfg._impl_test = True
-#    a = dumps(cfg)
-#    q = loads(a)
-#    _diff_conf(cfg, q)
-#    try:
-#        delete_session('29090931')
-#    except ConfigError:
-#        pass
-#
-#
-#def test_state_properties():
-#    val1 = BoolOption('val1', "")
-#    maconfig = OptionDescription('rootconfig', '', [val1])
-#    try:
-#        cfg = Config(maconfig, persistent=True, session_id='29090932')
-#    except ValueError:
-#        cfg = Config(maconfig, session_id='29090932')
-#        cfg._impl_test = True
-#    cfg.read_write()
-#    cfg.cfgimpl_get_settings()[val1].append('test')
-#    a = dumps(cfg)
-#    q = loads(a)
-#    _diff_conf(cfg, q)
-#    try:
-#        delete_session('29090932')
-#    except ConfigError:
-#        pass
-#
-#
-#def test_state_values():
-#    val1 = BoolOption('val1', "")
-#    maconfig = OptionDescription('rootconfig', '', [val1])
-#    try:
-#        cfg = Config(maconfig, persistent=True, session_id='29090933')
-#    except ValueError:
-#        cfg = Config(maconfig, session_id='29090933')
-#        cfg._impl_test = True
-#    cfg.val1 = True
-#    a = dumps(cfg)
-#    q = loads(a)
-#    _diff_conf(cfg, q)
-#    q.val1 = False
-#    #assert cfg.val1 is True
-#    assert q.val1 is False
-#    try:
-#        delete_session('29090933')
-#    except ConfigError:
-#        pass
-#
-#
-#def test_state_values_owner():
-#    val1 = BoolOption('val1', "")
-#    maconfig = OptionDescription('rootconfig', '', [val1])
-#    try:
-#        cfg = Config(maconfig, persistent=True, session_id='29090934')
-#    except ValueError:
-#        cfg = Config(maconfig, session_id='29090934')
-#        cfg._impl_test = True
-#    owners.addowner('newowner')
-#    cfg.cfgimpl_get_settings().setowner(owners.newowner)
-#    cfg.val1 = True
-#    a = dumps(cfg)
-#    q = loads(a)
-#    _diff_conf(cfg, q)
-#    q.val1 = False
-#    nval1 = q.cfgimpl_get_description().val1
-#    assert q.getowner(nval1) == owners.newowner
-#    try:
-#        delete_session('29090934')
-#    except ConfigError:
-#        pass
-#
-#
-#def test_state_metaconfig():
-#    i1 = IntOption('i1', '')
-#    od1 = OptionDescription('od1', '', [i1])
-#    od2 = OptionDescription('od2', '', [od1])
-#    conf1 = Config(od2, session_id='29090935')
-#    conf1._impl_test = True
-#    conf2 = Config(od2, session_id='29090936')
-#    conf2._impl_test = True
-#    meta = MetaConfig([conf1, conf2], session_id='29090937')
-#    meta._impl_test = True
-#    raises(ConfigError, "dumps(meta)")
-#    try:
-#        delete_session('29090935')
-#        delete_session('29090936')
-#        delete_session('29090937')
-#    except ConfigError:
-#        pass
-#
-#
-#def test_state_groupconfig():
-#    i1 = IntOption('i1', '')
-#    od1 = OptionDescription('od1', '', [i1])
-#    od2 = OptionDescription('od2', '', [od1])
-#    conf1 = Config(od2, session_id='29090935')
-#    conf1._impl_test = True
-#    conf2 = Config(od2, session_id='29090936')
-#    conf2._impl_test = True
-#    meta = GroupConfig([conf1, conf2], session_id='29090937')
-#    meta._impl_test = True
-#    a = dumps(meta)
-#    q = loads(a)
-#    _diff_conf(meta, q)
-#    try:
-#        delete_session('29090935')
-#        delete_session('29090936')
-#        delete_session('29090937')
-#    except ConfigError:
-#        pass
-#
-#
-#def test_state_unkown_setting_owner():
-#    """load an unknow _owner, should create it"""
-#    assert not 'supernewuser' in owners.__dict__
-#    loads("""ccopy_reg
-#_reconstructor
-#p0
-#(ctiramisu.setting
-#Settings
-#p1
-#c__builtin__
-#object
-#p2
-#Ntp3
-#Rp4
-#(dp5
-#S'_owner'
-#p6
-#S'supernewuser'
-#p7
-#sS'_p_'
-#p8
-#g0
-#(ctiramisu.storage.dictionary.setting
-#Settings
-#p9
-#g2
-#Ntp10
-#Rp11
-#(dp12
-#S'_cache'
-#p13
-#(dp14
-#sS'_permissives'
-#p15
-#(dp16
-#sS'_properties'
-#p17
-#(dp18
-#sbsb.
-#.""")
-#    assert 'supernewuser' in owners.__dict__
+def test_diff_opt():
+    b = BoolOption('b', '')
+    u = UnicodeOption('u', '', requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}])
+    s = SymLinkOption('s', u)
+    o = OptionDescription('o', '', [b, u, s])
+    o1 = OptionDescription('o1', '', [o])
+
+    a = dumps(o1)
+    q = loads(a)
+    _diff_opt(o1, q)
+    _diff_opt(o1.o, q.o)
+    _diff_opt(o1.o.b, q.o.b)
+    _diff_opt(o1.o.u, q.o.u)
+    _diff_opt(o1.o.s, q.o.s)
+
+
+def test_only_optiondescription():
+    b = BoolOption('b', '')
+    raises(SystemError, "a = dumps(b)")
+
+
+def test_diff_opt_cache():
+    b = BoolOption('b', '')
+    u = UnicodeOption('u', '', requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}])
+    u.impl_add_consistency('not_equal', b)
+    s = SymLinkOption('s', u)
+    o = OptionDescription('o', '', [b, u, s])
+    o1 = OptionDescription('o1', '', [o])
+    o1.impl_build_cache_consistency()
+    o1.impl_build_cache_option()
+
+    a = dumps(o1)
+    q = loads(a)
+    _diff_opt(o1, q)
+    _diff_opt(o1.o, q.o)
+    _diff_opt(o1.o.b, q.o.b)
+    _diff_opt(o1.o.u, q.o.u)
+    _diff_opt(o1.o.s, q.o.s)
+
+
+def test_diff_opt_callback():
+    b = BoolOption('b', '', callback=return_value)
+    b2 = BoolOption('b2', '', callback=return_value, callback_params={'': ('yes',)})
+    b3 = BoolOption('b3', '', callback=return_value, callback_params={'': ('yes', (b, False)), 'value': ('no',)})
+    o = OptionDescription('o', '', [b, b2, b3])
+    o1 = OptionDescription('o1', '', [o])
+    o1.impl_build_cache_consistency()
+    o1.impl_build_cache_option()
+
+    a = dumps(o1)
+    q = loads(a)
+    _diff_opt(o1, q)
+    _diff_opt(o1.o, q.o)
+    _diff_opt(o1.o.b, q.o.b)
+    _diff_opt(o1.o.b2, q.o.b2)
+    _diff_opt(o1.o.b3, q.o.b3)
+
+
+def test_no_state_attr():
+    # all _state_xxx attributes should be deleted
+    b = BoolOption('b', '')
+    u = UnicodeOption('u', '', requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}])
+    s = SymLinkOption('s', u)
+    o = OptionDescription('o', '', [b, u, s])
+    o1 = OptionDescription('o1', '', [o])
+
+    a = dumps(o1)
+    q = loads(a)
+    _no_state(q)
+    _no_state(q.o)
+    _no_state(q.o.b)
+    _no_state(q.o.u)
+    _no_state(q.o.s)
+
+
+def test_state_config():
+    val1 = BoolOption('val1', "")
+    maconfig = OptionDescription('rootconfig', '', [val1])
+    try:
+        cfg = Config(maconfig, persistent=True, session_id='29090931')
+    except ValueError:
+        cfg = Config(maconfig, session_id='29090931')
+        cfg._impl_test = True
+    a = dumps(cfg)
+    q = loads(a)
+    _diff_conf(cfg, q)
+    try:
+        delete_session('config', '29090931')
+    except ConfigError:
+        pass
+
+
+def test_state_properties():
+    val1 = BoolOption('val1', "")
+    maconfig = OptionDescription('rootconfig', '', [val1])
+    try:
+        cfg = Config(maconfig, persistent=True, session_id='29090932')
+    except ValueError:
+        cfg = Config(maconfig, session_id='29090932')
+        cfg._impl_test = True
+    cfg.read_write()
+    cfg.cfgimpl_get_settings()[val1].append('test')
+    a = dumps(cfg)
+    q = loads(a)
+    _diff_conf(cfg, q)
+    try:
+        delete_session('config', '29090932')
+    except ConfigError:
+        pass
+
+
+def test_state_values():
+    val1 = BoolOption('val1', "")
+    maconfig = OptionDescription('rootconfig', '', [val1])
+    try:
+        cfg = Config(maconfig, persistent=True, session_id='29090933')
+    except ValueError:
+        cfg = Config(maconfig, session_id='29090933')
+        cfg._impl_test = True
+    cfg.val1 = True
+    a = dumps(cfg)
+    q = loads(a)
+    _diff_conf(cfg, q)
+    q.val1 = False
+    assert cfg.val1 is True
+    assert q.val1 is False
+    try:
+        delete_session('config', '29090933')
+    except ConfigError:
+        pass
+
+
+def test_state_values_owner():
+    val1 = BoolOption('val1', "")
+    maconfig = OptionDescription('rootconfig', '', [val1])
+    try:
+        cfg = Config(maconfig, persistent=True, session_id='29090934')
+    except ValueError:
+        cfg = Config(maconfig, session_id='29090934')
+        cfg._impl_test = True
+    owners.addowner('newowner')
+    cfg.cfgimpl_get_settings().setowner(owners.newowner)
+    cfg.val1 = True
+    a = dumps(cfg)
+    q = loads(a)
+    _diff_conf(cfg, q)
+    q.val1 = False
+    nval1 = q.cfgimpl_get_description().val1
+    assert q.getowner(nval1) == owners.newowner
+    try:
+        delete_session('config', '29090934')
+    except ConfigError:
+        pass
+
+
+def test_state_metaconfig():
+    i1 = IntOption('i1', '')
+    od1 = OptionDescription('od1', '', [i1])
+    od2 = OptionDescription('od2', '', [od1])
+    conf1 = Config(od2, session_id='29090935')
+    conf1._impl_test = True
+    conf2 = Config(od2, session_id='29090936')
+    conf2._impl_test = True
+    meta = MetaConfig([conf1, conf2], session_id='29090937')
+    meta._impl_test = True
+    raises(ConfigError, "dumps(meta)")
+    try:
+        delete_session('config', '29090935')
+        delete_session('config', '29090936')
+        delete_session('config', '29090937')
+    except ConfigError:
+        pass
+
+
+def test_state_groupconfig():
+    i1 = IntOption('i1', '')
+    od1 = OptionDescription('od1', '', [i1])
+    od2 = OptionDescription('od2', '', [od1])
+    conf1 = Config(od2, session_id='29090935')
+    conf1._impl_test = True
+    conf2 = Config(od2, session_id='29090936')
+    conf2._impl_test = True
+    meta = GroupConfig([conf1, conf2], session_id='29090937')
+    meta._impl_test = True
+    a = dumps(meta)
+    q = loads(a)
+    _diff_conf(meta, q)
+    try:
+        delete_session('config', '29090935')
+        delete_session('config', '29090936')
+        delete_session('config', '29090937')
+    except ConfigError:
+        pass
+
+
+def test_state_unkown_setting_owner():
+    """load an unknow _owner, should create it"""
+    assert not 'supernewuser' in owners.__dict__
+    loads("""ccopy_reg
+_reconstructor
+p0
+(ctiramisu.setting
+Settings
+p1
+c__builtin__
+object
+p2
+Ntp3
+Rp4
+(dp5
+S'_owner'
+p6
+S'supernewuser'
+p7
+sS'_p_'
+p8
+g0
+(ctiramisu.storage.dictionary.setting
+Settings
+p9
+g2
+Ntp10
+Rp11
+(dp12
+S'_cache'
+p13
+(dp14
+sS'_permissives'
+p15
+(dp16
+sS'_properties'
+p17
+(dp18
+sbsb.
+.""")
+    assert 'supernewuser' in owners.__dict__
index 25c5e11..b3720eb 100644 (file)
@@ -19,7 +19,7 @@
 # the whole pypy projet is under MIT licence
 # ____________________________________________________________
 import re
-from copy import copy, deepcopy
+from copy import copy
 from types import FunctionType
 import warnings
 
@@ -276,16 +276,15 @@ class BaseOption(Base):
             # remove variable if save variable converted
             # in _state_xxxx variable
             if '_state' + slot not in slots:
-                if slot.startswith('_state'):
-                    # should exists
-                    states[slot] = getattr(self, slot)
-                    # remove _state_xxx variable
-                    self.__delattr__(slot)
-                else:
-                    try:
+                try:
+                    if slot.startswith('_state'):
                         states[slot] = getattr(self, slot)
-                    except AttributeError:
-                        pass
+                        # remove _state_xxx variable
+                        self.__delattr__(slot)
+                    else:
+                        states[slot] = getattr(self, slot)
+                except AttributeError:
+                    pass
         if not stated:
             del(states['_stated'])
         return states
@@ -330,7 +329,8 @@ class BaseOption(Base):
         propertie or "read_only" property)
         """
         if name not in ('_option', '_is_build_cache') \
-                and not isinstance(value, tuple):
+                and not isinstance(value, tuple) and \
+                not name.startswith('_state'):
             is_readonly = False
             # never change _name
             if name == '_name':
@@ -669,14 +669,20 @@ class Option(OnlyOption):
     def _impl_convert_callbacks(self, descr, load=False):
         if not load and self._callback is None:
             self._state_callback = None
+            self._state_callback_params = None
         elif load and self._state_callback is None:
             self._callback = None
+            self._callback_params = None
             del(self._state_callback)
+            del(self._state_callback_params)
         else:
             if load:
-                callback, callback_params = self._state_callback
+                callback = self._state_callback
+                callback_params = self._state_callback_params
             else:
-                callback, callback_params = self._callback
+                callback = self._callback
+                callback_params = self._callback_params
+                self._state_callback_params = None
             if callback_params is not None:
                 cllbck_prms = {}
                 for key, values in callback_params.items():
@@ -696,9 +702,12 @@ class Option(OnlyOption):
 
             if load:
                 del(self._state_callback)
-                self._callback = (callback, cllbck_prms)
+                del(self._state_callback_params)
+                self._callback = callback
+                self._callback_params = cllbck_prms
             else:
-                self._state_callback = (callback, cllbck_prms)
+                self._state_callback = callback
+                self._state_callback_params = cllbck_prms
 
     # serialize/unserialize
     def _impl_convert_consistencies(self, descr, load=False):
@@ -834,7 +843,7 @@ def validate_requires_arg(requires, name):
 
 class SymLinkOption(OnlyOption):
     #FIXME : et avec sqlalchemy ca marche vraiment ?
-    __slots__ = ('_opt',)
+    __slots__ = ('_opt', '_state_opt')
     #not return _opt consistencies
     #_consistencies = None
 
index e692458..7a1a7c1 100644 (file)
@@ -188,7 +188,8 @@ class OptionDescription(BaseOption, StorageOptionDescription):
         :param descr: parent :class:`tiramisu.option.OptionDescription`
         """
         if descr is None:
-            self.impl_build_cache()
+            self.impl_build_cache_consistency()
+            self.impl_build_cache_option()
             descr = self
         super(OptionDescription, self)._impl_getstate(descr)
         self._state_group_type = str(self._group_type)
@@ -219,7 +220,7 @@ class OptionDescription(BaseOption, StorageOptionDescription):
         if descr is None:
             self._cache_paths = None
             self._cache_consistencies = None
-            self.impl_build_cache(force_no_consistencies=True)
+            self.impl_build_cache_option()
             descr = self
         self._group_type = getattr(groups, self._state_group_type)
         del(self._state_group_type)
index 0634e5e..f86d970 100644 (file)
@@ -30,9 +30,9 @@ class Base(object):
                  '_state_readonly', '_state_requires', '_stated',
                  '_multi', '_validator', '_validator_params', '_default',
                  '_default_multi', '_state_callback', '_callback',
-                 '_callback_params', '_multitype', '_consistencies',
-                 '_warnings_only', '_master_slaves', '_state_consistencies',
-                 '_extra', '__weakref__')
+                 '_state_callback_params', '_callback_params', '_multitype',
+                 '_consistencies', '_warnings_only', '_master_slaves',
+                 '_state_consistencies', '_extra', '__weakref__')
 
     def __init__(self):
         try:
@@ -68,7 +68,7 @@ class Base(object):
 
 class OptionDescription(Base):
     __slots__ = ('_children', '_cache_paths', '_cache_consistencies',
-                 '_group_type', '_is_build_cache')
+                 '_group_type', '_is_build_cache', '_state_group_type')
 
     def __init__(self):
         pass
@@ -158,6 +158,10 @@ class OptionDescription(Base):
         if name == '_name':
             return object.__getattribute__(self, name)
         try:
+            if name == '_readonly':
+                raise AttributeError("{0} instance has no attribute "
+                                     "'_readonly'".format(
+                                         self.__class__.__name__))
             return self._children[1][self._children[0].index(name)]
         except ValueError:
             raise AttributeError(_('unknown Option {0} '