add __setstate__ to loads from a serialised object

This commit is contained in:
Emmanuel Garette 2013-09-02 23:04:37 +02:00
parent cc3a33ef4f
commit 0212a15387
1 changed files with 100 additions and 30 deletions

View File

@ -98,7 +98,7 @@ class BaseOption(BaseInformation):
"""
__slots__ = ('_name', '_requires', '_properties', '_readonly',
'_consistencies', '_calc_properties', '_state_consistencies',
'_state_requires', '_stated')
'_state_readonly', '_state_requires', '_stated')
def __init__(self, name, doc, requires, properties):
if not valid_name(name):
@ -133,7 +133,7 @@ class BaseOption(BaseInformation):
"frozen" (which has noting to do with the high level "freeze"
propertie or "read_only" property)
"""
if not name.startswith('_state'):
if not name.startswith('_state') and name not in ('_cache_paths', '_consistencies'):
is_readonly = False
# never change _name
if name == '_name':
@ -160,42 +160,58 @@ class BaseOption(BaseInformation):
name))
object.__setattr__(self, name, value)
def _impl_convert_consistencies(self, cache):
# cache is a dico in import/not a dico in export
if self._consistencies is None:
def _impl_convert_consistencies(self, descr, load=False):
if not load and self._consistencies is None:
self._state_consistencies = None
elif load and self._state_consistencies is None:
self._consistencies = None
del(self._state_consistencies)
else:
if load:
consistencies = self._state_consistencies
else:
consistencies = self._consistencies
new_value = []
for consistency in self._consistencies:
if isinstance(cache, dict):
new_value.append((consistency[0], cache[consistency[1]]))
for consistency in consistencies:
if load:
new_value.append((consistency[0],
descr.impl_get_opt_by_path(
consistency[1])))
else:
new_value.append((consistency[0],
cache.impl_get_path_by_opt(
descr.impl_get_path_by_opt(
consistency[1])))
if isinstance(cache, dict):
pass
if load:
del(self._state_consistencies)
self._consistencies = tuple(new_value)
else:
self._state_consistencies = tuple(new_value)
def _impl_convert_requires(self, cache):
# cache is a dico in import/not a dico in export
if self._requires is None:
def _impl_convert_requires(self, descr, load=False):
if not load and self._requires is None:
self._state_requires = None
elif load and self._state_requires is None:
self._requires = None
del(self._state_requires)
else:
if load:
_requires = self._state_requires
else:
_requires = self._requires
new_value = []
for requires in self._requires:
for requires in _requires:
new_requires = []
for require in requires:
if isinstance(cache, dict):
new_require = [cache[require[0]]]
if load:
new_require = [descr.impl_get_opt_by_path(require[0])]
else:
new_require = [cache.impl_get_path_by_opt(require[0])]
new_require = [descr.impl_get_path_by_opt(require[0])]
new_require.extend(require[1:])
new_requires.append(tuple(new_require))
new_value.append(tuple(new_requires))
if isinstance(cache, dict):
pass
if load:
del(self._state_requires)
self._requires = new_value
else:
self._state_requires = new_value
@ -203,8 +219,12 @@ class BaseOption(BaseInformation):
self._stated = True
self._impl_convert_consistencies(descr)
self._impl_convert_requires(descr)
try:
self._state_readonly = self._readonly
except AttributeError:
pass
def __getstate__(self, export=False):
def __getstate__(self, stated=True):
try:
self._stated
except AttributeError:
@ -228,8 +248,24 @@ class BaseOption(BaseInformation):
states[slot] = getattr(self, slot)
except AttributeError:
pass
if not stated:
del(states['_stated'])
return states
def _impl_setstate(self, descr):
self._impl_convert_consistencies(descr, load=True)
self._impl_convert_requires(descr, load=True)
try:
self._readonly = self._state_readonly
del(self._state_readonly)
del(self._stated)
except AttributeError:
pass
def __setstate__(self, state):
for key, value in state.items():
setattr(self, key, value)
class Option(BaseOption):
"""
@ -596,6 +632,11 @@ class SymLinkOption(BaseOption):
super(SymLinkOption, self)._impl_getstate(descr)
self._state_opt = descr.impl_get_path_by_opt(self._opt)
def _impl_setstate(self, descr):
self._opt = descr.impl_get_opt_by_path(self._state_opt)
del(self._state_opt)
super(SymLinkOption, self)._impl_setstate(descr)
class IPOption(Option):
"represents the choice of an ip"
@ -885,14 +926,16 @@ class OptionDescription(BaseOption):
cache_path=None,
cache_option=None,
_currpath=None,
_consistencies=None):
_consistencies=None,
force_no_consistencies=False):
if _currpath is None and self._cache_paths is not None:
# cache already set
return
if _currpath is None:
save = True
_currpath = []
_consistencies = {}
if not force_no_consistencies:
_consistencies = {}
else:
save = False
if cache_path is None:
@ -904,10 +947,12 @@ class OptionDescription(BaseOption):
raise ConflictError(_('duplicate option: {0}').format(option))
cache_option.append(option)
option._readonly = True
if not force_no_consistencies:
option._readonly = True
cache_path.append(str('.'.join(_currpath + [attr])))
if not isinstance(option, OptionDescription):
if option._consistencies is not None:
if not force_no_consistencies and \
option._consistencies is not None:
for consistency in option._consistencies:
func, opt = consistency
opts = (option, opt)
@ -920,12 +965,14 @@ class OptionDescription(BaseOption):
option.impl_build_cache(cache_path,
cache_option,
_currpath,
_consistencies)
_consistencies,
force_no_consistencies)
_currpath.pop()
if save:
self._cache_paths = (tuple(cache_option), tuple(cache_path))
self._consistencies = _consistencies
self._readonly = True
if not force_no_consistencies:
self._consistencies = _consistencies
self._readonly = True
def impl_get_opt_by_path(self, path):
try:
@ -1023,15 +1070,38 @@ class OptionDescription(BaseOption):
option._impl_getstate(descr)
def __getstate__(self):
stated = True
try:
del(self._stated)
self._stated
except AttributeError:
# if cannot delete, _impl_getstate never launch
# launch it recursivement
# _stated prevent __getstate__ launch more than one time
# _stated is delete, if re-serialize, re-lauch _impl_getstate
self._impl_getstate()
return super(OptionDescription, self).__getstate__()
stated = False
return super(OptionDescription, self).__getstate__(stated)
def _impl_setstate(self, descr=None):
"""enables us to import from a dict
:param descr: parent :class:`tiramisu.option.OptionDescription`
"""
if descr is None:
self._cache_paths = None
self.impl_build_cache(force_no_consistencies=True)
descr = self
self._group_type = getattr(groups, self._state_group_type)
del(self._state_group_type)
super(OptionDescription, self)._impl_setstate(descr)
for option in self.impl_getchildren():
option._impl_setstate(descr)
def __setstate__(self, state):
super(OptionDescription, self).__setstate__(state)
try:
self._stated
except AttributeError:
self._impl_setstate()
def validate_requires_arg(requires, name):