can export options
authorEmmanuel Garette <egarette@cadoles.com>
Sun, 1 Sep 2013 20:20:11 +0000 (22:20 +0200)
committerEmmanuel Garette <egarette@cadoles.com>
Sun, 1 Sep 2013 20:20:11 +0000 (22:20 +0200)
tiramisu/option.py

index d5c11a1..7f457a3 100644 (file)
@@ -91,7 +91,7 @@ class BaseInformation(object):
                                        self.__class__.__name__))
 
 
-class _ReadOnlyOption(BaseInformation):
+class BaseOption(BaseInformation):
     __slots__ = ('_readonly',)
 
     def __setattr__(self, name, value):
@@ -120,8 +120,57 @@ class _ReadOnlyOption(BaseInformation):
                                        name))
         object.__setattr__(self, name, value)
 
+    def _impl_convert_consistencies(self, value, cache):
+        # cache is a dico in import/not a dico in export
+        new_value = []
+        for consistency in value:
+            if isinstance(cache, dict):
+                new_value = (consistency[0], cache[consistency[1]])
+            else:
+                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):
+                    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))
+        return tuple(new_value)
+
+    def impl_export(self, descr):
+        descr.impl_build_cache()
+        # add _opt_type (not in __slots__)
+        slots = set(['_opt_type'])
+        for subclass in self.__class__.__mro__:
+            if subclass is not object:
+                slots.update(subclass.__slots__)
+        slots -= frozenset(['_children', '_readonly', '_cache_paths',
+                            '__weakref__'])
+        exported_object = {}
+        for attr in slots:
+            try:
+                value = getattr(self, attr)
+                if value is not None:
+                    if attr == '_consistencies':
+                        value = self._impl_convert_consistencies(value, descr)
+                    elif attr == '_requires':
+                        value = self._impl_convert_requires(value, descr)
+                exported_object[attr] = value
+            except AttributeError:
+                pass
+        return exported_object
+
 
-class Option(_ReadOnlyOption):
+class Option(BaseOption):
     """
     Abstract base class for configuration option's.
 
@@ -480,7 +529,7 @@ else:
                 raise ValueError(_('value must be an unicode'))
 
 
-class SymLinkOption(_ReadOnlyOption):
+class SymLinkOption(BaseOption):
     __slots__ = ('_name', '_opt')
     _opt_type = 'symlink'
 
@@ -499,6 +548,12 @@ class SymLinkOption(_ReadOnlyOption):
         else:
             return getattr(self._opt, name)
 
+    def impl_export(self, descr):
+        export = super(SymLinkOption, self).impl_export(descr)
+        export['_opt'] = descr.impl_get_path_by_opt(self._opt)
+        del(export['_impl_informations'])
+        return export
+
 
 class IPOption(Option):
     "represents the choice of an ip"
@@ -714,13 +769,14 @@ class DomainnameOption(Option):
             raise ValueError(_('invalid domainname'))
 
 
-class OptionDescription(_ReadOnlyOption):
+class OptionDescription(BaseOption):
     """Config's schema (organisation, group) and container of Options
     The `OptionsDescription` objects lives in the `tiramisu.config.Config`.
     """
     __slots__ = ('_name', '_requires', '_cache_paths', '_group_type',
                  '_properties', '_children', '_consistencies',
                  '_calc_properties', '__weakref__', '_readonly', '_impl_informations')
+    _opt_type = 'optiondescription'
 
     def __init__(self, name, doc, children, requires=None, properties=None):
         """
@@ -814,8 +870,6 @@ class OptionDescription(_ReadOnlyOption):
             cache_option = []
         for option in self.impl_getchildren():
             attr = option._name
-            if attr.startswith('_cfgimpl'):
-                continue
             if option in cache_option:
                 raise ConflictError(_('duplicate option: {0}').format(option))
 
@@ -926,6 +980,24 @@ class OptionDescription(_ReadOnlyOption):
                     return False
         return True
 
+    def _impl_convert_group_type(self, value, cache):
+        if isinstance(cache, dict):
+            value = str(value)
+        else:
+            value = getattr(groups, value)
+        return value
+
+    def impl_export(self, descr=None):
+        if descr is None:
+            descr = self
+        export = super(OptionDescription, self).impl_export(descr)
+        export['_group_type'] = self._impl_convert_group_type(
+            export['_group_type'], descr)
+        export['options'] = []
+        for option in self.impl_getchildren():
+            export['options'].append(option.impl_export(descr))
+        return export
+
 
 def validate_requires_arg(requires, name):
     """check malformed requirements