use polymorphism
authorEmmanuel Garette <egarette@cadoles.com>
Thu, 9 Jan 2014 20:42:32 +0000 (21:42 +0100)
committerEmmanuel Garette <egarette@cadoles.com>
Thu, 9 Jan 2014 20:42:32 +0000 (21:42 +0100)
tiramisu/autolib.py
tiramisu/option.py

index 2c6c7d8..503bcdd 100644 (file)
@@ -143,12 +143,13 @@ def carry_out_calculation(option, config, callback, callback_params,
     one_is_multi = False
     # multi's option should have same value for all option
     len_multi = None
-
-    for key, callbacks in callback_params.items():
-        for callbk in callbacks:
-            if isinstance(callbk, tuple):
+    for callbacks in callback_params:
+        key = callbacks.name
+        for callbk in callbacks.params:
+            if callbk.option is not None:
                 # callbk is something link (opt, True|False)
-                opt, force_permissive = callbk
+                opt = callbk.get_option(config)
+                force_permissive = callbk.force_permissive
                 path = config.cfgimpl_get_description().impl_get_path_by_opt(
                     opt)
                 # get value
@@ -159,7 +160,7 @@ def carry_out_calculation(option, config, callback, callback_params,
                         continue
                     raise ConfigError(_('unable to carry out a calculation, '
                                         'option {0} has properties: {1} for: '
-                                        '{2}').format(opt._name,
+                                        '{2}').format(option.impl_getname(),
                                                       err.proptype,
                                                       option._name))
 
@@ -179,7 +180,7 @@ def carry_out_calculation(option, config, callback, callback_params,
                 tcparams.setdefault(key, []).append((value, is_multi))
             else:
                 # callbk is a value and not a multi
-                tcparams.setdefault(key, []).append((callbk, False))
+                tcparams.setdefault(key, []).append((callbk.value, False))
 
     # if one value is a multi, launch several time calculate
     # if index is set, return a value
index b4db8a8..48e02d4 100644 (file)
@@ -191,7 +191,6 @@ class BaseOption(Base):
     __tablename__ = 'baseoption'
     id = Column(Integer, primary_key=True)
     _name = Column(String)
-    _type = Column(PickleType)
     _informations = relationship('_Information')
     _default = Column(PickleType)
     _default_multi = Column(PickleType)
@@ -212,6 +211,11 @@ class BaseOption(Base):
                                   backref=backref('options', enable_typechecks=False))
     _choice_values = Column(PickleType)
     _choice_open_values = Column(Boolean)
+    _type = Column(String(50))
+    __mapper_args__ = {
+        'polymorphic_identity': 'person',
+        'polymorphic_on': _type
+    }
     #FIXME devrait etre une table
     _optiondescription_group_type = Column(String)
     #__slots__ = ('_name', '_requires', '_properties', '_readonly',
@@ -226,7 +230,6 @@ class BaseOption(Base):
         if not valid_name(name):
             raise ValueError(_("invalid name: {0} for option").format(name))
         self._name = name
-        self._type = self.__class__
         self.impl_set_information('doc', doc)
         requires = validate_requires_arg(requires, self._name)
         if requires is not None:
@@ -853,7 +856,9 @@ class ChoiceOption(Option):
     """
 
     #__slots__ = ('_values', '_open_values')
-    _opt_type = 'string'
+    __mapper_args__ = {
+        'polymorphic_identity': 'choice',
+    }
 
     def __init__(self, name, doc, values, default=None, default_multi=None,
                  requires=None, multi=False, callback=None,
@@ -895,8 +900,10 @@ class ChoiceOption(Option):
 
 class BoolOption(Option):
     "represents a choice between ``True`` and ``False``"
-    __slots__ = tuple()
-    _opt_type = 'bool'
+#    __slots__ = tuple()
+    __mapper_args__ = {
+        'polymorphic_identity': 'bool',
+    }
 
     def _validate(self, value):
         if not isinstance(value, bool):
@@ -905,8 +912,10 @@ class BoolOption(Option):
 
 class IntOption(Option):
     "represents a choice of an integer"
-    __slots__ = tuple()
-    _opt_type = 'int'
+#    __slots__ = tuple()
+    __mapper_args__ = {
+        'polymorphic_identity': 'int',
+    }
 
     def _validate(self, value):
         if not isinstance(value, int):
@@ -915,8 +924,10 @@ class IntOption(Option):
 
 class FloatOption(Option):
     "represents a choice of a floating point number"
-    __slots__ = tuple()
-    _opt_type = 'float'
+    #__slots__ = tuple()
+    __mapper_args__ = {
+        'polymorphic_identity': 'float',
+    }
 
     def _validate(self, value):
         if not isinstance(value, float):
@@ -925,8 +936,10 @@ class FloatOption(Option):
 
 class StrOption(Option):
     "represents the choice of a string"
-    __slots__ = tuple()
-    _opt_type = 'string'
+    #__slots__ = tuple()
+    __mapper_args__ = {
+        'polymorphic_identity': 'string',
+    }
 
     def _validate(self, value):
         if not isinstance(value, str):
@@ -936,13 +949,15 @@ class StrOption(Option):
 if sys.version_info[0] >= 3:
     #UnicodeOption is same as StrOption in python 3+
     class UnicodeOption(StrOption):
-        __slots__ = tuple()
+        #__slots__ = tuple()
         pass
 else:
     class UnicodeOption(Option):
         "represents the choice of a unicode string"
-        __slots__ = tuple()
-        _opt_type = 'unicode'
+        #__slots__ = tuple()
+        __mapper_args__ = {
+            'polymorphic_identity': 'unicode',
+        }
         _empty = u''
 
         def _validate(self, value):
@@ -952,7 +967,9 @@ else:
 
 class SymLinkOption(BaseOption):
     #__slots__ = ('_name', '_opt', '_state_opt', '_readonly', '_parent')
-    _opt_type = 'symlink'
+    __mapper_args__ = {
+        'polymorphic_identity': 'symlink',
+    }
     #not return _opt consistencies
     #_consistencies = None
 
@@ -965,7 +982,6 @@ class SymLinkOption(BaseOption):
         self._opt = opt
         self._readonly = True
         self._parent = None
-        self._type = self.__class__
         session.add(self)
         session.commit()
 
@@ -984,9 +1000,6 @@ class SymLinkOption(BaseOption):
         del(self._state_opt)
         super(SymLinkOption, self)._impl_setstate(descr)
 
-    def impl_getname(self):
-        return self._name
-
     def impl_get_information(self, key, default=None):
         #FIXME ne devrait pas etre util si ?
         return self._opt.impl_get_information(key, default)
@@ -994,8 +1007,10 @@ class SymLinkOption(BaseOption):
 
 class IPOption(Option):
     "represents the choice of an ip"
-    __slots__ = ('_private_only', '_allow_reserved')
-    _opt_type = 'ip'
+    #__slots__ = ('_private_only', '_allow_reserved')
+    __mapper_args__ = {
+        'polymorphic_identity': 'ip',
+    }
 
     def __init__(self, name, doc, default=None, default_multi=None,
                  requires=None, multi=False, callback=None,
@@ -1045,8 +1060,10 @@ class PortOption(Option):
     Port number 0 is reserved and can't be used.
     see: http://en.wikipedia.org/wiki/Port_numbers
     """
-    __slots__ = ('_allow_range', '_allow_zero', '_min_value', '_max_value')
-    _opt_type = 'port'
+    #__slots__ = ('_allow_range', '_allow_zero', '_min_value', '_max_value')
+    __mapper_args__ = {
+        'polymorphic_identity': 'port',
+    }
 
     def __init__(self, name, doc, default=None, default_multi=None,
                  requires=None, multi=False, callback=None,
@@ -1108,8 +1125,10 @@ class PortOption(Option):
 
 class NetworkOption(Option):
     "represents the choice of a network"
-    __slots__ = tuple()
-    _opt_type = 'network'
+    #__slots__ = tuple()
+    __mapper_args__ = {
+        'polymorphic_identity': 'network',
+    }
 
     def _validate(self, value):
         try:
@@ -1125,8 +1144,10 @@ class NetworkOption(Option):
 
 class NetmaskOption(Option):
     "represents the choice of a netmask"
-    __slots__ = tuple()
-    _opt_type = 'netmask'
+    #__slots__ = tuple()
+    __mapper_args__ = {
+        'polymorphic_identity': 'netmask',
+    }
 
     def _validate(self, value):
         try:
@@ -1179,8 +1200,10 @@ class NetmaskOption(Option):
 
 
 class BroadcastOption(Option):
-    __slots__ = tuple()
-    _opt_type = 'broadcast'
+    #__slots__ = tuple()
+    __mapper_args__ = {
+        'polymorphic_identity': 'broadcast',
+    }
 
     def _validate(self, value):
         try:
@@ -1208,8 +1231,10 @@ class DomainnameOption(Option):
     domainname:
     fqdn: with tld, not supported yet
     """
-    __slots__ = ('_dom_type', '_allow_ip', '_allow_without_dot', '_domain_re')
-    _opt_type = 'domainname'
+    #__slots__ = ('_dom_type', '_allow_ip', '_allow_without_dot', '_domain_re')
+    __mapper_args__ = {
+        'polymorphic_identity': 'domainname',
+    }
 
     def __init__(self, name, doc, default=None, default_multi=None,
                  requires=None, multi=False, callback=None,
@@ -1271,8 +1296,10 @@ class DomainnameOption(Option):
 
 
 class EmailOption(DomainnameOption):
-    __slots__ = tuple()
-    _opt_type = 'email'
+    #__slots__ = tuple()
+    __mapper_args__ = {
+        'polymorphic_identity': 'email',
+    }
     username_re = re.compile(r"^[\w!#$%&'*+\-/=?^`{|}~.]+$")
 
     def _validate(self, value):
@@ -1288,8 +1315,10 @@ class EmailOption(DomainnameOption):
 
 
 class URLOption(DomainnameOption):
-    __slots__ = tuple()
-    _opt_type = 'url'
+    #__slots__ = tuple()
+    __mapper_args__ = {
+        'polymorphic_identity': 'url',
+    }
     proto_re = re.compile(r'(http|https)://')
     path_re = re.compile(r"^[a-z0-9\-\._~:/\?#\[\]@!%\$&\'\(\)\*\+,;=]+$")
 
@@ -1325,8 +1354,10 @@ class URLOption(DomainnameOption):
 
 
 class FilenameOption(Option):
-    __slots__ = tuple()
-    _opt_type = 'file'
+    #__slots__ = tuple()
+    __mapper_args__ = {
+        'polymorphic_identity': 'file',
+    }
     path_re = re.compile(r"^[a-zA-Z0-9\-\._~/+]+$")
 
     def _validate(self, value):
@@ -1344,7 +1375,9 @@ class OptionDescription(BaseOption):
     #          '_cache_consistencies', '_calc_properties', '__weakref__',
     #          '_readonly', '_impl_informations', '_state_requires',
     #          '_stated', '_state_readonly')
-    _opt_type = 'optiondescription'
+    __mapper_args__ = {
+        'polymorphic_identity': 'optiondescription',
+    }
 
     def __init__(self, name, doc, children, requires=None, properties=None):
         """
@@ -1395,11 +1428,12 @@ class OptionDescription(BaseOption):
             if name.startswith('_') or name.startswith('impl_'):
                 return object.__getattribute__(self, name)
             else:
-                #FIXME regression ...
+                #FIXME regression ... devrait etre un query !
                 for child in self._children:
                     if child.impl_getname() == name:
+                        return child
                         #convert to object
-                        return session.query(child._type).filter_by(id=child.id).first()
+                        #return session.query(child._type).filter_by(id=child.id).first()
                 #return pouet#self._children[1][self._children[0].index(name)]
         except ValueError:
             pass
@@ -1430,12 +1464,13 @@ class OptionDescription(BaseOption):
         return paths
 
     def impl_getchildren(self):
-        for child in self._children:
-            yield(session.query(child._type).filter_by(id=child.id).first())
+        #FIXME dans la base ??
+        return self._children
+        #for child in self._children:
+        #    yield(session.query(child._type).filter_by(id=child.id).first())
 
     def impl_build_cache(self,
                          cache_path=None,
-                         cache_type=None,
                          cache_option=None,
                          _currpath=None,
                          _consistencies=None,
@@ -1452,7 +1487,6 @@ class OptionDescription(BaseOption):
             save = False
         if cache_path is None:
             cache_path = []
-            cache_type = []
             cache_option = []
         for option in self.impl_getchildren():
             attr = option.impl_getname()
@@ -1465,7 +1499,6 @@ class OptionDescription(BaseOption):
             if not force_no_consistencies:
                 option._readonly = True
             cache_path.append(str('.'.join(_currpath + [attr])))
-            cache_type.append(option._type)
             if not isinstance(option, OptionDescription):
                 if not force_no_consistencies and \
                         option._consistencies is not []:
@@ -1478,14 +1511,14 @@ class OptionDescription(BaseOption):
                                                                   all_cons_opts))
             else:
                 _currpath.append(attr)
-                option.impl_build_cache(cache_path, cache_type,
+                option.impl_build_cache(cache_path,
                                         cache_option,
                                         _currpath,
                                         _consistencies,
                                         force_no_consistencies)
                 _currpath.pop()
         if save:
-            self._cache_paths = (tuple(cache_option), tuple(cache_path), tuple(cache_type))
+            self._cache_paths = (tuple(cache_option), tuple(cache_path))
             if not force_no_consistencies:
                 if _consistencies != {}:
                     self._cache_consistencies = {}
@@ -1497,18 +1530,18 @@ class OptionDescription(BaseOption):
 
     def impl_get_opt_by_path(self, path):
         try:
+            #FIXME
             idx = self._cache_paths[1].index(path)
             opt_id = self._cache_paths[0][idx]
-            opt_type = self._cache_paths[2][idx]
-            return session.query(opt_type).filter_by(id=opt_id).first()
+            return session.query(BaseOption).filter_by(id=opt_id).first()
         except ValueError:
             raise AttributeError(_('no option for path {0}').format(path))
 
     def impl_get_opt_by_id(self, opt_id):
         try:
+            #FIXME
             idx = self._cache_paths[0].index(opt_id)
-            opt_type = self._cache_paths[2][idx]
-            return session.query(opt_type).filter_by(id=opt_id).first()
+            return session.query(BaseOption).filter_by(id=opt_id).first()
         except ValueError:
             raise AttributeError(_('no id {0} found').format(opt_id))
 
@@ -1557,13 +1590,15 @@ class OptionDescription(BaseOption):
                     raise ValueError(_('master group with wrong'
                                        ' master name for {0}'
                                        ).format(self.impl_getname()))
-                if master._callback is not None and master._callback[1] is not None:
-                    for key, callbacks in master._callback[1].items():
-                        for callbk in callbacks:
-                            if isinstance(callbk, tuple):
-                                if callbk[0] in slaves:
-                                    raise ValueError(_("callback of master's option shall "
-                                                       "not refered a slave's ones"))
+                #FIXME debut reecriture
+                ##master_callback, master_callback_params = master.impl_get_callback()
+                #if master._callback is not None and master._callback[1] is not None:
+                #    for key, callbacks in master._callback[1].items():
+                #        for callbk in callbacks:
+                #            if isinstance(callbk, tuple):
+                #                if callbk[0] in slaves:
+                #                    raise ValueError(_("callback of master's option shall "
+                #                                       "not refered a slave's ones"))
                 master._master_slaves = tuple(slaves)
                 for child in self.impl_getchildren():
                     if child != master: