AmbigousOptionError, ConflictConfigError, NoMatchingOptionFound,
MandatoryError, MethodCallError, NoValueReturned)
from tiramisu.option import (OptionDescription, Option, SymLinkOption,
- group_types, Multi, apply_requires)
-from tiramisu.setting import settings
+ Multi, apply_requires)
+from tiramisu.setting import settings, group_types
# ____________________________________________________________
class Config(object):
def __getattr__(self, name):
return self._getattr(name)
+ def _get_master_len(self, slave_name):
+ try:
+ parent_cfg = self._cfgimpl_parent
+ if parent_cfg is None:
+ return None
+ master_name = parent_cfg._cfgimpl_descr.get_master_name()
+ master_value = getattr(parent_cfg, master_name)
+ return len(master_value)
+ except TypeError:
+ # in this case we just don't care about the len
+ return None
+
+ def _valid_len(self, slave_name, slave_value):
+ master_len = self._get_master_len(slave_name)
+ if master_len == None:
+ return True
+ if master_len != len(slave_value):
+ raise ValueError("invalid len for the group {0}"
+ "in the option {1} ".format(master_name, slave_name))
+
+ def fill_multi(self, name, result, default_multi=None):
+ """fills a multi option with default and calculated values
+ """
+ value = self._cfgimpl_values[name]
+ master_len = self._get_master_len(name)
+ if not isinstance(result, list):
+ if master_len is None:
+ master_len = 1
+ # a list is built with the same len as the master
+ _result = []
+ for i in range(master_len):
+ _result.append(result)
+ elif default_multi != None:
+ if master_len != None:
+ slave_len = len(result)
+ if slave_len > master_len:
+ raise ValueError("invalid value's len for"
+ "the option: {1}".format(name))
+ if slave_len != master_len:
+ delta_len = master_len - len(result)
+ for i in range(delta_len):
+ _result.append(default_multi)
+ else:
+ _result = result
+ return Multi(_result, value.config, value.child)
+
def _getattr(self, name, permissive=False):
"""
attribute notation mechanism for accessing the value of an option
if (not opt_or_descr.is_frozen() or \
not opt_or_descr.is_forced_on_freeze()) and \
not opt_or_descr.is_default_owner(self):
+ self._valid_len(name, value)
return value
try:
result = opt_or_descr.getcallback_value(
pass
else:
if opt_or_descr.is_multi():
- if not isinstance(result, list):
- result = [result]
- _result = Multi(result, value.config, value.child)
+ _result = self.fill_multi(name, result)
else:
# this result **shall not** be a list
if isinstance(result, list):
' for option {0}'.format(name))
self._cfgimpl_values[name] = _result
opt_or_descr.setowner(self, 'default')
+ # frozen and force default
if not opt_or_descr.has_callback() and opt_or_descr.is_forced_on_freeze():
- return opt_or_descr.getdefault()
+ value = opt_or_descr.getdefault()
+ if opt_or_descr.is_multi():
+ value = self.fill_multi(name, result, opt_or_descr.getdefault_multi())
+ self._cfgimpl_values[name] = value
+ opt_or_descr.setowner(self, 'default')
self._test_mandatory(name, opt_or_descr)
- # frozen and force default
- return self._cfgimpl_values[name]
+ value = self._cfgimpl_values[name]
+ self._valid_len(name, value)
+ return value
def unwrap_from_name(self, name):
"""convenience method to extract and Option() object from the Config()
def __eq__(self, other):
"Config comparison"
- if not isinstance(other, Config):
+ if not isinstance(other, OptionDescription):
return False
- print self.getkey()
- print other.getkey()
return self.getkey() == other.getkey()
def __ne__(self, other):
RequiresError, RequirementRecursionError, MandatoryError,
PropertiesOptionError)
from tiramisu.autolib import carry_out_calculation
-from tiramisu.setting import settings
+from tiramisu.setting import settings, group_types, groups_has_master
requires_actions = [('hide', 'show'), ('enable', 'disable'), ('freeze', 'unfreeze')]
reverse_actions[act1] = act2
reverse_actions[act2] = act1
# ____________________________________________________________
-# OptionDescription authorized group_type values
-"""
-Three available group_types : `default`, `family`, `group` and
-`master` (for master~slave group type). Notice that for a
-master~slave group, the name of the group and the name of the
-master option are identical.
-"""
-group_types = ['default', 'family', 'group', 'master']
-# ____________________________________________________________
# multi types
class Multi(list):
self._requires = requires
self._build()
self.properties = [] # 'hidden', 'disabled'...
+ # if this group is a master group, master is set
+ # to the master option name
+ self.master = None
def getdoc(self):
return self.doc
paths.append('.'.join(currpath + [attr]))
return paths
# ____________________________________________________________
- def set_group_type(self, group_type):
+ def set_group_type(self, group_type, master=None):
":param group_type: string in group_types"
if group_type in group_types:
self.group_type = group_type
+ if group_type in groups_has_master:
+ if master is None:
+ raise ConfigError('this group type ({0}) needs a master '
+ 'for OptionDescription {1}'.format(group_type,
+ self._name))
+ else:
+ if master is not None:
+ raise ConfigError("this group type ({0}) doesn't need a "
+ "master for OptionDescription {1}".format(
+ group_type, self._name))
+ self.master = master
else:
raise ConfigError('not allowed value for group_type : {0}'.format(
group_type))
def get_group_type(self):
return self.group_type
+
+ def get_master_name(self):
+ if self.master is None:
+ raise TypeError('get_master_name() shall not be called in case of'
+ 'non-master OptionDescription')
+ return self.master
# ____________________________________________________________
"actions API"
def hide(self):