validation of the len of the multi in a group

This commit is contained in:
gwen 2012-12-04 12:06:26 +01:00
parent d633574cc5
commit 4393da13ab
4 changed files with 95 additions and 24 deletions

View File

@ -85,7 +85,12 @@ def carry_out_calculation(name, option, config):
params.append(value) params.append(value)
else: else:
tcp[key] = value tcp[key] = value
ret.append(calculate(name, callback, params, tcp)) calc = calculate(name, callback, params, tcp)
if isinstance(calc, list):
ret.extend(calc)
else:
ret.append(calc)
return ret return ret
else: else:
tcp = {} tcp = {}

View File

@ -25,8 +25,8 @@ from tiramisu.error import (PropertiesOptionError, ConfigError, NotFoundError,
AmbigousOptionError, ConflictConfigError, NoMatchingOptionFound, AmbigousOptionError, ConflictConfigError, NoMatchingOptionFound,
MandatoryError, MethodCallError, NoValueReturned) MandatoryError, MethodCallError, NoValueReturned)
from tiramisu.option import (OptionDescription, Option, SymLinkOption, from tiramisu.option import (OptionDescription, Option, SymLinkOption,
group_types, Multi, apply_requires) Multi, apply_requires)
from tiramisu.setting import settings from tiramisu.setting import settings, group_types
# ____________________________________________________________ # ____________________________________________________________
class Config(object): class Config(object):
@ -159,6 +159,52 @@ class Config(object):
def __getattr__(self, name): def __getattr__(self, name):
return self._getattr(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): def _getattr(self, name, permissive=False):
""" """
attribute notation mechanism for accessing the value of an option attribute notation mechanism for accessing the value of an option
@ -195,6 +241,7 @@ class Config(object):
if (not opt_or_descr.is_frozen() or \ if (not opt_or_descr.is_frozen() or \
not opt_or_descr.is_forced_on_freeze()) and \ not opt_or_descr.is_forced_on_freeze()) and \
not opt_or_descr.is_default_owner(self): not opt_or_descr.is_default_owner(self):
self._valid_len(name, value)
return value return value
try: try:
result = opt_or_descr.getcallback_value( result = opt_or_descr.getcallback_value(
@ -203,9 +250,7 @@ class Config(object):
pass pass
else: else:
if opt_or_descr.is_multi(): if opt_or_descr.is_multi():
if not isinstance(result, list): _result = self.fill_multi(name, result)
result = [result]
_result = Multi(result, value.config, value.child)
else: else:
# this result **shall not** be a list # this result **shall not** be a list
if isinstance(result, list): if isinstance(result, list):
@ -218,11 +263,17 @@ class Config(object):
' for option {0}'.format(name)) ' for option {0}'.format(name))
self._cfgimpl_values[name] = _result self._cfgimpl_values[name] = _result
opt_or_descr.setowner(self, 'default') opt_or_descr.setowner(self, 'default')
if not opt_or_descr.has_callback() and opt_or_descr.is_forced_on_freeze():
return opt_or_descr.getdefault()
self._test_mandatory(name, opt_or_descr)
# frozen and force default # frozen and force default
return self._cfgimpl_values[name] if not opt_or_descr.has_callback() and opt_or_descr.is_forced_on_freeze():
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)
value = self._cfgimpl_values[name]
self._valid_len(name, value)
return value
def unwrap_from_name(self, name): def unwrap_from_name(self, name):
"""convenience method to extract and Option() object from the Config() """convenience method to extract and Option() object from the Config()
@ -375,10 +426,8 @@ class Config(object):
def __eq__(self, other): def __eq__(self, other):
"Config comparison" "Config comparison"
if not isinstance(other, Config): if not isinstance(other, OptionDescription):
return False return False
print self.getkey()
print other.getkey()
return self.getkey() == other.getkey() return self.getkey() == other.getkey()
def __ne__(self, other): def __ne__(self, other):

View File

@ -26,7 +26,7 @@ from tiramisu.error import (ConfigError, ConflictConfigError, NotFoundError,
RequiresError, RequirementRecursionError, MandatoryError, RequiresError, RequirementRecursionError, MandatoryError,
PropertiesOptionError) PropertiesOptionError)
from tiramisu.autolib import carry_out_calculation 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')] requires_actions = [('hide', 'show'), ('enable', 'disable'), ('freeze', 'unfreeze')]
@ -37,15 +37,6 @@ for act1, act2 in requires_actions:
reverse_actions[act1] = act2 reverse_actions[act1] = act2
reverse_actions[act2] = act1 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 # multi types
class Multi(list): class Multi(list):
@ -416,6 +407,9 @@ class OptionDescription(HiddenBaseType, DisabledBaseType):
self._requires = requires self._requires = requires
self._build() self._build()
self.properties = [] # 'hidden', 'disabled'... 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): def getdoc(self):
return self.doc return self.doc
@ -466,16 +460,33 @@ class OptionDescription(HiddenBaseType, DisabledBaseType):
paths.append('.'.join(currpath + [attr])) paths.append('.'.join(currpath + [attr]))
return paths 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" ":param group_type: string in group_types"
if group_type in group_types: if group_type in group_types:
self.group_type = group_type 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: else:
raise ConfigError('not allowed value for group_type : {0}'.format( raise ConfigError('not allowed value for group_type : {0}'.format(
group_type)) group_type))
def get_group_type(self): def get_group_type(self):
return self.group_type 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" "actions API"
def hide(self): def hide(self):

View File

@ -21,6 +21,12 @@
# the whole pypy projet is under MIT licence # the whole pypy projet is under MIT licence
# ____________________________________________________________ # ____________________________________________________________
# available group_type values
_group_name = ('default', 'family', 'group')
groups_has_master = ('group', )
class Group(str): pass
group_types = tuple(Group(i) for i in _group_name)
class Setting(): class Setting():
"``Config()``'s configuration options" "``Config()``'s configuration options"
# properties attribute: the name of a property enables this property # properties attribute: the name of a property enables this property