multi options

This commit is contained in:
gwen 2012-10-17 11:14:17 +02:00
parent a36ae7df85
commit ec2a65bd37
3 changed files with 103 additions and 64 deletions

View file

@ -38,58 +38,65 @@ def carry_out_calculation(name, option, config):
tcparams = {} tcparams = {}
one_is_multi = False one_is_multi = False
len_multi = 0 len_multi = 0
for key, value in callback_params.items():
if type(value) == tuple: for key, values in callback_params.items():
path, check_disabled = value for value in values:
try: if type(value) == tuple:
#opt_value = getattr(config, path) path, check_disabled = value
opt_value = config._getattr(path, permissive=True) try:
opt = config.unwrap_from_path(path) opt_value = config._getattr(path, permissive=True)
except PropertiesOptionError, err: opt = config.unwrap_from_path(path)
if check_disabled: except PropertiesOptionError, err:
continue if check_disabled:
raise PropertiesOptionError(err, err.proptype) continue
is_multi = opt.is_multi() raise PropertiesOptionError(err, err.proptype)
if is_multi: is_multi = opt.is_multi()
if opt_value != None: if is_multi:
len_value = len(opt_value) if opt_value != None:
if len_multi != 0 and len_multi != len_value: len_value = len(opt_value)
raise ConflictConfigError('unable to carry out a calculation, ' if len_multi != 0 and len_multi != len_value:
'option values with multi types must have same length for: ' raise ConflictConfigError('unable to carry out a calculation, '
+ name) 'option values with multi types must have same length for: '
len_multi = len_value + name)
one_is_multi = True len_multi = len_value
tcparams[key] = (opt_value, is_multi) one_is_multi = True
else: tcparams.setdefault(key, []).append((opt_value, is_multi))
tcparams[key] = (value, False) else:
tcparams.setdefault(key, []).append((value, False))
if one_is_multi: if one_is_multi:
ret = [] ret = []
for incr in range(len_multi): for incr in range(len_multi):
tcp = {} tcp = {}
for key, couple in tcparams.items(): params = []
value, ismulti = couple for key, couples in tcparams.items():
if ismulti and value != None: for couple in couples:
if key == '': value, ismulti = couple
params.append(value[incr]) if ismulti and value != None:
if key == '':
params.append(value[incr])
else:
if len(value) > incr:
tcp[key] = value[incr]
else:
tcp[key] = ''
else: else:
tcp[key] = value[incr] if key == '':
else: params.append(value)
if key == '': else:
params.append(value) tcp[key] = value
else: ret.append(calculate(name, callback, params, tcp))
tcp[key] = value
ret.append(calculate(name, callback, tcp))
return ret return ret
else: else:
tcp = {} tcp = {}
params = [] params = []
for key, couple in tcparams.items(): for key, couples in tcparams.items():
if key == '': for couple in couples:
params.append(couple[0]) if key == '':
else: value = couple[0]
tcp[key] = couple[0] params.append(value)
a=calculate(name, callback, params, tcp) else:
tcp[key] = couple[0]
return calculate(name, callback, params, tcp) return calculate(name, callback, params, tcp)
def calculate(name, callback, params, tcparams): def calculate(name, callback, params, tcparams):

View file

@ -239,7 +239,8 @@ class Config(object):
value = self._cfgimpl_values[name] value = self._cfgimpl_values[name]
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.getowner(self) == 'default': not opt_or_descr.is_default_owner(self, all_default=False):
#not opt_or_descr.getowner(self) == 'default':
if opt_or_descr.is_multi(): if opt_or_descr.is_multi():
if None not in value: if None not in value:
return value return value
@ -251,28 +252,52 @@ class Config(object):
except NoValueReturned, err: except NoValueReturned, err:
pass pass
else: else:
# this result **shall not** be a list
# for example, [1, 2, 3, None] -> [1, 2, 3, result]
if isinstance(result, list):
raise ConfigError('invalid calculated value returned'
' for option {0} : shall not be a list'.format(name))
if result != None and not opt_or_descr._validate(result):
raise ConfigError('invalid calculated value returned'
' for option {0}'.format(name))
if opt_or_descr.is_multi(): if opt_or_descr.is_multi():
if value == []: owners = copy(self._cfgimpl_value_owners[name])
self._cfgimpl_value_owners[name] = []
if not isinstance(result, list):
# for example, [1, 2, 3, None] -> [1, 2, 3, result]
_result = Multi([result], value.config, value.child) _result = Multi([result], value.config, value.child)
else:
_result = Multi([], value.config, value.child)
#for val in value:
owners = opt_or_descr.getowner(self)
for cpt in range(len(value)): for cpt in range(len(value)):
val = value[cpt] val = value[cpt]
if owners[cpt] == 'default': if len(owners) > cpt:
val = result if owners[cpt] == 'default':
_result.append(val) _result.append(result)
self._cfgimpl_value_owners[name][cpt] = 'default'
else:
_result.append(val)
else:
_result.append(val)
self._cfgimpl_value_owners[name][cpt] = 'default'
else:
# for example, [1, None, 2, None] + [a, b, c, d]
# = [1, b, 2, d]
_result = Multi([], value.config, value.child)
for cpt in range(max(len(value), len(result))):
if len(value) > cpt:
val = value[cpt]
else:
val = ''
if len(result) > cpt:
rval = result[cpt]
if len(owners) > cpt:
if owners[cpt] == 'default':
_result.append(rval)
self._cfgimpl_value_owners[name][cpt] = 'default'
else:
_result.append(val)
else:
_result.append(rval)
self._cfgimpl_value_owners[name][cpt] = 'default'
else: else:
# this result **shall not** be a list
if isinstance(result, list):
raise ConfigError('invalid calculated value returned'
' for option {0} : shall not be a list'.format(name))
_result = result _result = result
if _result != None and not opt_or_descr.validate(_result):
raise ConfigError('invalid calculated value returned'
' for option {0}'.format(name))
self._cfgimpl_values[name] = _result self._cfgimpl_values[name] = _result
# mandatory options # mandatory options
@ -286,6 +311,7 @@ class Config(object):
# frozen and force default # frozen and force default
if not opt_or_descr.has_callback() and opt_or_descr.is_forced_on_freeze(): if not opt_or_descr.has_callback() and opt_or_descr.is_forced_on_freeze():
return opt_or_descr.getdefault() return opt_or_descr.getdefault()
return self._cfgimpl_values[name] return self._cfgimpl_values[name]
def unwrap_from_name(self, name): def unwrap_from_name(self, name):

View file

@ -59,7 +59,7 @@ class Multi(list):
self.setoption(value) self.setoption(value)
def setoption(self, value, key=None): def setoption(self, value, key=None):
owners = self.child.getowner(self.config) #owners = self.child.getowner(self.config)
# None is replaced by default_multi # None is replaced by default_multi
if value == None: if value == None:
defval = self.child.getdefault() defval = self.child.getdefault()
@ -220,12 +220,18 @@ class Option(HiddenBaseType, DisabledBaseType):
"config *must* be only the **parent** config (not the toplevel config)" "config *must* be only the **parent** config (not the toplevel config)"
return config._cfgimpl_value_owners[self._name] return config._cfgimpl_value_owners[self._name]
def is_default_owner(self, config): def is_default_owner(self, config, all_default=True):
if self.is_multi(): if self.is_multi():
for owner in self.getowner(config): owners = self.getowner(config)
if owner != 'default': for owner in owners:
if all_default and owner != 'default':
return False return False
return True if not all_default and owner == 'default':
return True
if all_default or owners == []:
return True
else:
return False
else: else:
if self.getowner(config) == 'default': if self.getowner(config) == 'default':
return True return True