From 9bec52273af2d1fd36f4f97c603922fbc2a43e16 Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Mon, 14 Apr 2014 22:53:40 +0200 Subject: [PATCH] we can pickle object --- test/test_state.py | 495 +++++++++++++------------- tiramisu/option/baseoption.py | 41 ++- tiramisu/option/optiondescription.py | 5 +- tiramisu/storage/dictionary/option.py | 12 +- 4 files changed, 288 insertions(+), 265 deletions(-) diff --git a/test/test_state.py b/test/test_state.py index 8739789..9b40219 100644 --- a/test/test_state.py +++ b/test/test_state.py @@ -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__ diff --git a/tiramisu/option/baseoption.py b/tiramisu/option/baseoption.py index 25c5e11..b3720eb 100644 --- a/tiramisu/option/baseoption.py +++ b/tiramisu/option/baseoption.py @@ -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 diff --git a/tiramisu/option/optiondescription.py b/tiramisu/option/optiondescription.py index e692458..7a1a7c1 100644 --- a/tiramisu/option/optiondescription.py +++ b/tiramisu/option/optiondescription.py @@ -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) diff --git a/tiramisu/storage/dictionary/option.py b/tiramisu/storage/dictionary/option.py index 0634e5e..f86d970 100644 --- a/tiramisu/storage/dictionary/option.py +++ b/tiramisu/storage/dictionary/option.py @@ -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} '