From 972dff0a1ca356b5622ee92ce43d3ff2ff46ef3a Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Fri, 20 Sep 2013 23:47:40 +0200 Subject: [PATCH] serialize new callback --- test/test_state.py | 33 ++++++++++++++++++++++++ tiramisu/option.py | 63 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 92 insertions(+), 4 deletions(-) diff --git a/test/test_state.py b/test/test_state.py index 03ab670..ea1956c 100644 --- a/test/test_state.py +++ b/test/test_state.py @@ -3,6 +3,10 @@ from tiramisu.option import BoolOption, UnicodeOption, SymLinkOption, \ from pickle import dumps, loads +def return_value(value=None): + return value + + def _get_slots(opt): slots = set() for subclass in opt.__class__.__mro__: @@ -65,6 +69,18 @@ def _diff_opt(opt1, opt2): for index, consistency in enumerate(val1): assert consistency[0] == val2[index][0] assert consistency[1]._name == val2[index][1]._name + elif attr == '_callback': + assert val1[0] == val2[0] + if val1[1] is not None: + for key, values in val1[1].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] + else: + assert val1[1][key][idx] == val2[1][key][idx] + else: + assert val1[1] == val2[1] else: assert val1 == val2 @@ -104,6 +120,23 @@ def test_diff_opt_cache(): _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', '') diff --git a/tiramisu/option.py b/tiramisu/option.py index 0c7e732..89d960a 100644 --- a/tiramisu/option.py +++ b/tiramisu/option.py @@ -188,9 +188,11 @@ class BaseOption(object): _list_cons = [] for _con in _cons: if load: - _list_cons.append(descr.impl_get_opt_by_path(_con)) + _list_cons.append( + descr.impl_get_opt_by_path(_con)) else: - _list_cons.append(descr.impl_get_path_by_opt(_con)) + _list_cons.append( + descr.impl_get_path_by_opt(_con)) new_value[key].append((key_cons, tuple(_list_cons))) if load: del(self._state_consistencies) @@ -322,7 +324,8 @@ class Option(BaseOption): Reminder: an Option object is **not** a container for the value. """ __slots__ = ('_multi', '_validator', '_default_multi', '_default', - '_callback', '_multitype', '_master_slaves', '__weakref__') + '_state_callback', '_callback', '_multitype', + '_master_slaves', '__weakref__') _empty = '' def __init__(self, name, doc, default=None, default_multi=None, @@ -558,6 +561,57 @@ class Option(BaseOption): "must be different as {2} option" "").format(value, self._name, optname)) + def _impl_convert_callbacks(self, descr, load=False): + if not load and self._callback is None: + self._state_callback = None + elif load and self._state_callback is None: + self._callback = None + del(self._state_callback) + else: + if load: + callback, callback_params = self._state_callback + else: + callback, callback_params = self._callback + if callback_params is not None: + cllbck_prms = {} + for key, values in callback_params.items(): + vls = [] + for value in values: + if isinstance(value, tuple): + if load: + value = (descr.impl_get_opt_by_path(value[0]), + value[1]) + else: + value = (descr.impl_get_path_by_opt(value[0]), + value[1]) + vls.append(value) + cllbck_prms[key] = tuple(vls) + else: + cllbck_prms = None + + if load: + del(self._state_callback) + self._callback = (callback, cllbck_prms) + else: + self._state_callback = (callback, cllbck_prms) + + # serialize + def _impl_getstate(self, descr): + """the under the hood stuff that need to be done + before the serialization. + """ + self._stated = True + self._impl_convert_callbacks(descr) + super(Option, self)._impl_getstate(descr) + + # unserialize + def _impl_setstate(self, descr): + """the under the hood stuff that need to be done + before the serialization. + """ + self._impl_convert_callbacks(descr, load=True) + super(Option, self)._impl_setstate(descr) + class ChoiceOption(Option): """represents a choice out of several objects. @@ -1287,4 +1341,5 @@ def validate_callback(callback, callback_params, type_): if force_permissive not in [True, False]: raise ValueError(_('{0}_params should have a boolean' 'not a {0} for second argument' - ).format(type_, type(force_permissive))) + ).format(type_, type( + force_permissive)))