tiramisu/tiramisu/autolib.py

250 lines
9.4 KiB
Python
Raw Normal View History

2013-04-03 12:20:26 +02:00
# Copyright (C) 2012-2013 Team tiramisu (see AUTHORS for all contributors)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
2012-09-18 09:48:41 +02:00
# The original `Config` design model is unproudly borrowed from
# the rough gus of pypy: pypy: http://codespeak.net/svn/pypy/dist/pypy/config/
# the whole pypy projet is under MIT licence
# ____________________________________________________________
"enables us to carry out a calculation and return an option's value"
2013-04-14 12:01:32 +02:00
from tiramisu.error import PropertiesOptionError, ConfigError
from tiramisu.setting import multitypes
2013-04-22 16:48:56 +02:00
from tiramisu.i18n import _
# ____________________________________________________________
2013-04-03 12:20:26 +02:00
def carry_out_calculation(option, config, callback, callback_params,
index=None, max_len=None):
2013-08-21 14:52:48 +02:00
"""a function that carries out a calculation for an option's value
2013-04-03 12:20:26 +02:00
2014-01-30 22:55:15 +01:00
:param option: the option
2013-08-21 14:52:48 +02:00
:param config: the context config in order to have
the whole options available
:param callback: the name of the callback function
:type callback: str
:param callback_params: the callback's parameters
(only keyword parameters are allowed)
:type callback_params: dict
:param index: if an option is multi, only calculates the nth value
:type index: int
:param max_len: max length for a multi
:type max_len: int
The callback_params is a dict. Key is used to build args (if key is '')
and kwargs (otherwise). Values are tuple of:
- values
- tuple with option and boolean's force_permissive (True when don't raise
if PropertiesOptionError)
Values could have multiple values only when key is ''.
* if no callback_params:
=> calculate(<function func at 0x2092320>, [], {})
* if callback_params={'': ('yes',)}
=> calculate(<function func at 0x2092320>, ['yes'], {})
* if callback_params={'value': ('yes',)}
=> calculate(<function func at 0x165b320>, [], {'value': 'yes'})
* if callback_params={'': ('yes', 'no')}
=> calculate('yes', 'no')
* if callback_params={'value': ('yes', 'no')}
=> ValueError()
* if callback_params={'': (['yes', 'no'],)}
=> calculate(<function func at 0x176b320>, ['yes', 'no'], {})
* if callback_params={'value': ('yes', 'no')}
=> raises ValueError()
* if callback_params={'': ((opt1, False),)}
- a simple option:
opt1 == 11
=> calculate(<function func at 0x1cea320>, [11], {})
- a multi option and not master/slave:
opt1 == [1, 2, 3]
=> calculate(<function func at 0x223c320>, [[1, 2, 3]], {})
- option is master or slave of opt1:
opt1 == [1, 2, 3]
=> calculate(<function func at 0x223c320>, [1], {})
=> calculate(<function func at 0x223c320>, [2], {})
=> calculate(<function func at 0x223c320>, [3], {})
- opt is a master or slave but not related to option:
opt1 == [1, 2, 3]
=> calculate(<function func at 0x11b0320>, [[1, 2, 3]], {})
* if callback_params={'value': ((opt1, False),)}
- a simple option:
opt1 == 11
=> calculate(<function func at 0x17ff320>, [], {'value': 11})
- a multi option:
opt1 == [1, 2, 3]
=> calculate(<function func at 0x1262320>, [], {'value': [1, 2, 3]})
* if callback_params={'': ((opt1, False), (opt2, False))}
- two single options
opt1 = 11
opt2 = 12
=> calculate(<function func at 0x217a320>, [11, 12], {})
- a multi option with a simple option
opt1 == [1, 2, 3]
opt2 == 12
=> calculate(<function func at 0x2153320>, [[1, 2, 3], 12], {})
- a multi option with an other multi option but with same length
opt1 == [1, 2, 3]
opt2 == [11, 12, 13]
=> calculate(<function func at 0x1981320>, [[1, 2, 3], [11, 12, 13]], {})
- a multi option with an other multi option but with different length
opt1 == [1, 2, 3]
opt2 == [11, 12]
=> calculate(<function func at 0x2384320>, [[1, 2, 3], [11, 12]], {})
- a multi option without value with a simple option
opt1 == []
opt2 == 11
=> calculate(<function func at 0xb65320>, [[], 12], {})
* if callback_params={'value': ((opt1, False), (opt2, False))}
=> raises ValueError()
If index is not None, return a value, otherwise return:
* a list if one parameters have multi option
* a value otherwise
If calculate return list, this list is extend to return value.
2013-08-21 14:52:48 +02:00
"""
tcparams = {}
# if callback_params has a callback, launch several time calculate()
one_is_multi = False
# multi's option should have same value for all option
len_multi = None
2014-01-27 23:28:22 +01:00
for key, callbacks in callback_params.items():
for callbk in callbacks:
if isinstance(callbk, tuple):
# callbk is something link (opt, True|False)
2014-01-27 23:28:22 +01:00
opt, force_permissive = callbk
path = config.cfgimpl_get_description().impl_get_path_by_opt(
opt)
# get value
2012-10-17 11:14:17 +02:00
try:
value = config._getattr(path, force_permissive=True, validate=False)
# convert to list, not modifie this multi
if value.__class__.__name__ == 'Multi':
value = list(value)
except PropertiesOptionError as err:
if force_permissive:
2012-10-17 11:14:17 +02:00
continue
raise ConfigError(_('unable to carry out a calculation, '
'option {0} has properties: {1} for: '
2014-01-09 21:42:32 +01:00
'{2}').format(option.impl_getname(),
err.proptype,
option._name))
is_multi = False
if opt.impl_is_multi():
#opt is master, search if option is a slave
if opt.impl_get_multitype() == multitypes.master:
if option in opt.impl_get_master_slaves():
is_multi = True
#opt is slave, search if option is an other slaves
elif opt.impl_get_multitype() == multitypes.slave:
if option in opt.impl_get_master_slaves().impl_get_master_slaves():
is_multi = True
2012-10-17 11:14:17 +02:00
if is_multi:
len_multi = len(value)
2012-10-17 11:14:17 +02:00
one_is_multi = True
tcparams.setdefault(key, []).append((value, is_multi))
2012-10-17 11:14:17 +02:00
else:
# callbk is a value and not a multi
2014-01-27 23:28:22 +01:00
tcparams.setdefault(key, []).append((callbk, False))
# if one value is a multi, launch several time calculate
# if index is set, return a value
# if no index, return a list
if one_is_multi:
ret = []
if index:
range_ = [index]
else:
range_ = range(len_multi)
for incr in range_:
args = []
kwargs = {}
2012-10-17 11:14:17 +02:00
for key, couples in tcparams.items():
for couple in couples:
value, ismulti = couple
if ismulti:
val = value[incr]
else:
val = value
if key == '':
args.append(val)
2012-09-18 09:48:41 +02:00
else:
kwargs[key] = val
calc = calculate(callback, args, kwargs)
if index:
ret = calc
else:
ret.append(calc)
return ret
else:
# no value is multi
# return a single value
args = []
kwargs = {}
2012-10-17 11:14:17 +02:00
for key, couples in tcparams.items():
for couple in couples:
# couple[1] (ismulti) is always False
2012-10-17 11:14:17 +02:00
if key == '':
args.append(couple[0])
2012-10-17 11:14:17 +02:00
else:
kwargs[key] = couple[0]
ret = calculate(callback, args, kwargs)
if callback_params != {}:
if isinstance(ret, list) and max_len:
ret = ret[:max_len]
if len(ret) < max_len:
ret = ret + [None] * (max_len - len(ret))
if isinstance(ret, list) and index:
if len(ret) < index + 1:
ret = None
else:
ret = ret[index]
return ret
2012-09-18 09:48:41 +02:00
2013-04-03 12:20:26 +02:00
def calculate(callback, args, kwargs):
2013-05-23 14:55:52 +02:00
"""wrapper that launches the 'callback'
2013-05-10 16:02:27 +02:00
:param callback: callback function
:param args: in the callback's arity, the unnamed parameters
:param kwargs: in the callback's arity, the named parameters
2013-05-23 14:55:52 +02:00
2013-05-10 16:02:27 +02:00
"""
return callback(*args, **kwargs)