diff --git a/bin/tools/yaml_import.py b/bin/tools/yaml_import.py index cd1a1a34fd6..e77999a49f1 100644 --- a/bin/tools/yaml_import.py +++ b/bin/tools/yaml_import.py @@ -286,26 +286,39 @@ class YamlInterpreter(object): record_dict[field_name] = field_value return record_dict + def process_ref(self, node, column=None): + if node.search: + if node.model: + model_name = node.model + elif column: + model_name = column._obj + else: + raise YamlImportException('You need to give a model for the search, or a column to infer it.') + model = self.get_model(model_name) + q = eval(node.search, self.eval_context) + ids = model.search(self.cr, self.uid, q) + if node.use: + instances = model.browse(self.cr, self.uid, ids) + value = [inst[node.use] for inst in instances] + else: + value = ids + elif node.id: + value = self.get_id(node.id) + else: + value = None + return value + + def process_eval(self, node): + return eval(node.expression, self.eval_context) + def _eval_field(self, model, field_name, expression): column = model._columns[field_name] if is_ref(expression): - if expression.model: - other_model_name = expression.model - else: - other_model_name = column._obj - other_model = self.get_model(other_model_name) - if expression.search: - q = eval(expression.search, self.eval_context) - ids = other_model.search(self.cr, self.uid, q) - if expression.use: - instances = other_model.browse(self.cr, self.uid, ids) - elements = [inst[expression.use] for inst in instances] - else: - elements = ids - if column._type in ("many2many", "one2many"): - value = [(6, 0, elements)] - else: # many2one - value = self._get_first_result(elements) + elements = self.process_ref(expression) + if column._type in ("many2many", "one2many"): + value = [(6, 0, elements)] + else: # many2one + value = self._get_first_result(elements) elif column._type == "many2one": value = self.get_id(expression) elif column._type == "one2many": @@ -316,7 +329,7 @@ class YamlInterpreter(object): value = [(6, 0, ids)] else: # scalar field if is_eval(expression): - value = eval(expression.expression, self.eval_context) + value = self.process_eval(expression) else: value = expression # raise YamlImportException('Unsupported column "%s" or value %s:%s' % (field_name, type(expression), expression)) @@ -372,6 +385,32 @@ class YamlInterpreter(object): uid = self.uid wf_service = netsvc.LocalService("workflow") wf_service.trg_validate(uid, workflow.model, id, workflow.action, self.cr) + + def _eval_params(self, model, params): + args = [] + for i, param in enumerate(params): + if isinstance(param, types.ListType): + value = self._eval_params(model, param) + elif is_ref(param): + value = self.process_ref(param) + elif is_eval(param): + value = self.process_eval(param) + elif isinstance(param, types.DictionaryType): # supports XML syntax + param_model = self.get_model(param.get('model', model)) + if 'search' in param: + q = eval(param['search'], self.eval_context) + ids = param_model.search(cr, uid, q) + value = self._get_first_result(ids) + elif 'eval' in param: + local_context = {'obj': lambda x: param_model.browse(self.cr, self.uid, x, context)} + local_context.update(self.id_map) + value = eval(param['eval'], self.eval_context, local_context) + else: + raise YamlImportException('You must provide either a !ref or at least a "eval" or a "search" to function parameter #%d.' % i) + else: + value = param # scalar value + args.append(value) + return args def process_function(self, node): function, params = node.items()[0] @@ -379,25 +418,10 @@ class YamlInterpreter(object): return model = self.get_model(function.model) context = self.get_context(function, self.eval_context) - args = [] if function.eval: - args = eval(function.eval, self.eval_context) - for i, param in enumerate(params): - if 'model' in param: - param_model = self.get_model(param['model']) - else: - param_model = model - if 'search' in param: - q = eval(param['search'], self.eval_context) - ids = param_model.search(cr, uid, q) - value = self._get_first_result(ids) - elif 'eval' in param: - local_context = {'obj': lambda x: value_model.browse(self.cr, self.uid, x, context)} - local_context.update(self.id_map) - value = eval(param['eval'], self.eval_context, local_context) - else: - raise YamlImportException('You must provide at least a "eval" or a "search" to function parameter #%d.' % i) - args.append(value) + args = self.process_eval(function.eval) + else: + args = self._eval_params(function.model, params) method = function.name getattr(model, method)(self.cr, self.uid, *args) diff --git a/bin/tools/yaml_tag.py b/bin/tools/yaml_tag.py index 83f6dde9c8d..1d36dc17a5b 100644 --- a/bin/tools/yaml_tag.py +++ b/bin/tools/yaml_tag.py @@ -87,10 +87,9 @@ class Eval(YamlTag): super(Eval, self).__init__() class Ref(YamlTag): - # 'model' parameter is optional since it defaults to the column type - def __init__(self, search): - self.search = search - super(Ref, self).__init__() + def __init__(self, *args, **kwargs): + print "kwargs %s" % kwargs + super(Ref, self).__init__(*args, **kwargs) class IrSet(YamlTag): def __init__(self): @@ -144,8 +143,11 @@ def eval_constructor(loader, node): expression = loader.construct_scalar(node) return Eval(expression) -def ref_constructor(loader, node): - kwargs = loader.construct_mapping(node) +def ref_constructor(loader, tag_suffix, node): + if tag_suffix == "id": + kwargs = {"id": loader.construct_scalar(node)} + else: + kwargs = loader.construct_mapping(node) return Ref(**kwargs) def ir_set_constructor(loader, node): @@ -167,5 +169,5 @@ yaml.add_constructor(u"!context", context_constructor) yaml.add_constructor(u"!delete", delete_constructor) yaml.add_constructor(u"!url", url_constructor) yaml.add_constructor(u"!eval", eval_constructor) -yaml.add_constructor(u"!ref", ref_constructor) +yaml.add_multi_constructor(u"!ref", ref_constructor) yaml.add_constructor(u"!ir_set", ir_set_constructor)