an OptionDescription can be serialized

This commit is contained in:
Emmanuel Garette 2013-09-02 15:01:49 +02:00
parent f379a0fc0a
commit 2c1da6d72e

View File

@ -92,82 +92,100 @@ class BaseInformation(object):
class BaseOption(BaseInformation): class BaseOption(BaseInformation):
__slots__ = ('_readonly',) __slots__ = ('_readonly', '_state_consistencies', '_state_requires')
def __setattr__(self, name, value): def __setattr__(self, name, value):
is_readonly = False if not name.startswith('_state'):
# never change _name is_readonly = False
if name == '_name': # never change _name
if name == '_name':
try:
self._name
#so _name is already set
is_readonly = True
except:
pass
try: try:
self._name if self._readonly is True:
#so _name is already set if value is True:
is_readonly = True # already readonly and try to re set readonly
except: # don't raise, just exit
return
is_readonly = True
except AttributeError:
pass pass
try: if is_readonly:
if self._readonly is True: raise AttributeError(_("'{0}' ({1}) object attribute '{2}' is"
if value is True: " read-only").format(
# already readonly and try to re set readonly self.__class__.__name__,
# don't raise, just exit self._name,
return name))
is_readonly = True
except AttributeError:
pass
if is_readonly:
raise AttributeError(_("'{0}' ({1}) object attribute '{2}' is"
" read-only").format(
self.__class__.__name__, self._name,
name))
object.__setattr__(self, name, value) object.__setattr__(self, name, value)
def _impl_convert_consistencies(self, value, cache): def _impl_convert_consistencies(self, cache):
# cache is a dico in import/not a dico in export # cache is a dico in import/not a dico in export
new_value = [] if self._consistencies is None:
for consistency in value: self._state_consistencies = None
if isinstance(cache, dict): else:
new_value = (consistency[0], cache[consistency[1]]) new_value = []
else: for consistency in self._consistencies:
new_value = (consistency[0], cache.impl_get_path_by_opt(
consistency[1]))
return tuple(new_value)
def _impl_convert_requires(self, value, cache):
# cache is a dico in import/not a dico in export
new_value = []
for requires in value:
new_requires = []
for require in requires:
if isinstance(cache, dict): if isinstance(cache, dict):
new_require = [cache[require[0]]] new_value.append((consistency[0], cache[consistency[1]]))
else: else:
new_require = [cache.impl_get_path_by_opt(require[0])] new_value.append((consistency[0],
new_require.extend(require[1:]) cache.impl_get_path_by_opt(
new_requires.append(tuple(new_require)) consistency[1])))
new_value.append(tuple(new_requires)) if isinstance(cache, dict):
return tuple(new_value) pass
else:
self._state_consistencies = tuple(new_value)
def impl_export(self, descr): def _impl_convert_requires(self, cache):
descr.impl_build_cache() # cache is a dico in import/not a dico in export
# add _opt_type (not in __slots__) if self._requires is None:
slots = set(['_opt_type']) self._state_requires = None
else:
new_value = []
for requires in self._requires:
new_requires = []
for require in requires:
if isinstance(cache, dict):
new_require = [cache[require[0]]]
else:
new_require = [cache.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
else:
self._state_requires = new_value
def _impl_getstate(self, descr):
self._impl_convert_consistencies(descr)
self._impl_convert_requires(descr)
def __getstate__(self, export=False):
slots = set()
for subclass in self.__class__.__mro__: for subclass in self.__class__.__mro__:
if subclass is not object: if subclass is not object:
slots.update(subclass.__slots__) slots.update(subclass.__slots__)
slots -= frozenset(['_children', '_readonly', '_cache_paths', slots -= frozenset(['_children', '_cache_paths', '__weakref__'])
'__weakref__']) states = {}
exported_object = {} for slot in slots:
for attr in slots: # remove variable if save variable converted in _state_xxxx variable
try: if '_state' + slot not in slots:
value = getattr(self, attr) if slot.startswith('_state'):
if value is not None: # should exists
if attr == '_consistencies': states[slot] = getattr(self, slot)
value = self._impl_convert_consistencies(value, descr) # remove _state_xxx variable
elif attr == '_requires': self.__delattr__(slot)
value = self._impl_convert_requires(value, descr) else:
exported_object[attr] = value try:
except AttributeError: states[slot] = getattr(self, slot)
pass except AttributeError:
return exported_object pass
return states
class Option(BaseOption): class Option(BaseOption):
@ -530,7 +548,7 @@ else:
class SymLinkOption(BaseOption): class SymLinkOption(BaseOption):
__slots__ = ('_name', '_opt') __slots__ = ('_name', '_opt', '_state_opt')
_opt_type = 'symlink' _opt_type = 'symlink'
def __init__(self, name, opt): def __init__(self, name, opt):
@ -548,11 +566,9 @@ class SymLinkOption(BaseOption):
else: else:
return getattr(self._opt, name) return getattr(self._opt, name)
def impl_export(self, descr): def _impl_getstate(self, descr):
export = super(SymLinkOption, self).impl_export(descr) super(SymLinkOption, self)._impl_getstate(descr)
export['_opt'] = descr.impl_get_path_by_opt(self._opt) self._state_opt = descr.impl_get_path_by_opt(self._opt)
del(export['_impl_informations'])
return export
class IPOption(Option): class IPOption(Option):
@ -774,8 +790,9 @@ class OptionDescription(BaseOption):
The `OptionsDescription` objects lives in the `tiramisu.config.Config`. The `OptionsDescription` objects lives in the `tiramisu.config.Config`.
""" """
__slots__ = ('_name', '_requires', '_cache_paths', '_group_type', __slots__ = ('_name', '_requires', '_cache_paths', '_group_type',
'_properties', '_children', '_consistencies', '_state_group_type', '_properties', '_children',
'_calc_properties', '__weakref__', '_readonly', '_impl_informations') '_consistencies', '_calc_properties', '__weakref__',
'_readonly', '_impl_informations')
_opt_type = 'optiondescription' _opt_type = 'optiondescription'
def __init__(self, name, doc, children, requires=None, properties=None): def __init__(self, name, doc, children, requires=None, properties=None):
@ -980,23 +997,23 @@ class OptionDescription(BaseOption):
return False return False
return True return True
def _impl_convert_group_type(self, value, cache): def _impl_getstate(self, descr=None):
if isinstance(cache, dict):
value = str(value)
else:
value = getattr(groups, value)
return value
def impl_export(self, descr=None):
if descr is None: if descr is None:
self.impl_build_cache()
descr = self descr = self
export = super(OptionDescription, self).impl_export(descr) super(OptionDescription, self)._impl_getstate(descr)
export['_group_type'] = self._impl_convert_group_type( self._state_group_type = str(self._group_type)
export['_group_type'], descr)
export['options'] = []
for option in self.impl_getchildren(): for option in self.impl_getchildren():
export['options'].append(option.impl_export(descr)) option._impl_getstate(descr)
return export
def __getstate__(self, export=False):
if not export:
self._impl_getstate()
states = super(OptionDescription, self).__getstate__(True)
states['_state_children'] = []
for option in self.impl_getchildren():
states['_state_children'].append(option.__getstate__(True))
return states
def validate_requires_arg(requires, name): def validate_requires_arg(requires, name):