diff --git a/addons/crm/data/crm_lead_demo.xml b/addons/crm/data/crm_lead_demo.xml index 4f638a42f0e..0e73640175a 100644 --- a/addons/crm/data/crm_lead_demo.xml +++ b/addons/crm/data/crm_lead_demo.xml @@ -368,8 +368,8 @@ Andrew

]]> + eval="[[ref('crm_case_7'), ref('crm_case_9'), ref('crm_case_11'), ref('crm_case_12')]]" + context="{'install_mode': True}"/> @@ -1161,13 +1161,13 @@ Andrew

]]> + eval="[[ref('crm_case_28')]]" + context="{'install_mode': True}"/> + eval="[[ref('crm_case_20'), ref('crm_case_23'), ref('crm_case_27')]]" + context="{'install_mode': True}"/> diff --git a/addons/mass_mailing/data/mass_mailing_demo.xml b/addons/mass_mailing/data/mass_mailing_demo.xml index 19957054c66..e9df5daaa35 100644 --- a/addons/mass_mailing/data/mass_mailing_demo.xml +++ b/addons/mass_mailing/data/mass_mailing_demo.xml @@ -264,34 +264,41 @@ - + 100.01.02.03 + BE + - + 100.01.02.03 + BE + - + 100.01.02.04 + BE + - - - - + 100.01.02.04 + BE + - + 100.01.02.05 + BE + diff --git a/addons/stock/data/stock_data.xml b/addons/stock/data/stock_data.xml index d522f76d9c6..34693a1c29f 100644 --- a/addons/stock/data/stock_data.xml +++ b/addons/stock/data/stock_data.xml @@ -143,20 +143,10 @@ - - - - - - - - - - - - - - - + + + + + diff --git a/odoo/addons/test_convert/__init__.py b/odoo/addons/test_convert/__init__.py index a301ab24b52..dc5e6b693d1 100644 --- a/odoo/addons/test_convert/__init__.py +++ b/odoo/addons/test_convert/__init__.py @@ -1,10 +1,4 @@ -from odoo import fields, models +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. - -class Usered(models.Model): - _name = 'test_convert.usered' - _description = "z test model ignore" - - name = fields.Char() - user_id = fields.Many2one('res.users', default=lambda self: self.env.user) - tz = fields.Char(default=lambda self: self.env.context.get('tz') or self.env.user.tz) +from . import models diff --git a/odoo/addons/test_convert/models.py b/odoo/addons/test_convert/models.py new file mode 100644 index 00000000000..e48ac2d1e7f --- /dev/null +++ b/odoo/addons/test_convert/models.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import models, fields, api + + +class Usered(models.Model): + _name = 'test_convert.usered' + _description = "z test model ignore" + + name = fields.Char() + user_id = fields.Many2one('res.users', default=lambda self: self.env.user) + tz = fields.Char(default=lambda self: self.env.context.get('tz') or self.env.user.tz) + + @api.model + def model_method(self, *args, **kwargs): + return self, args, kwargs + + def method(self, *args, **kwargs): + return self, args, kwargs diff --git a/odoo/addons/test_convert/tests/test_convert.py b/odoo/addons/test_convert/tests/test_convert.py index e81526dd43c..709a5eeab10 100644 --- a/odoo/addons/test_convert/tests/test_convert.py +++ b/odoo/addons/test_convert/tests/test_convert.py @@ -7,7 +7,7 @@ import unittest from lxml.builder import E from odoo.tests import common -from odoo.tools.convert import _eval_xml +from odoo.tools.convert import xml_import, _eval_xml Field = E.field Value = E.value @@ -74,6 +74,118 @@ class TestEvalXML(common.TransactionCase): with self.assertRaises(IOError): self.eval_xml(Field('test_nofile.txt', type='file'), obj) + def test_function(self): + obj = xml_import(self.cr, 'test_convert', None, 'init') + + # pass args in eval + xml = E.function( + model="test_convert.usered", + name="model_method", + eval="[1, 2]", + ) + rec, args, kwargs = self.eval_xml(xml, obj) + self.assertEqual(rec.env.context, self.env.context) + self.assertEqual(rec.ids, []) + self.assertEqual(args, (1, 2)) + self.assertEqual(kwargs, {}) + + xml = E.function( + model="test_convert.usered", + name="method", + eval="[1, 2]", + ) + rec, args, kwargs = self.eval_xml(xml, obj) + self.assertEqual(rec.env.context, self.env.context) + self.assertEqual(rec.ids, [1]) + self.assertEqual(args, (2,)) + self.assertEqual(kwargs, {}) + + # pass args in child elements + xml = E.function( + E.value(eval="1"), E.value(eval="2"), + model="test_convert.usered", + name="model_method", + ) + rec, args, kwargs = self.eval_xml(xml, obj) + self.assertEqual(rec.env.context, self.env.context) + self.assertEqual(rec.ids, []) + self.assertEqual(args, (1, 2)) + self.assertEqual(kwargs, {}) + + xml = E.function( + E.value(eval="1"), E.value(eval="2"), + model="test_convert.usered", + name="method", + ) + rec, args, kwargs = self.eval_xml(xml, obj) + self.assertEqual(rec.env.context, self.env.context) + self.assertEqual(rec.ids, [1]) + self.assertEqual(args, (2,)) + self.assertEqual(kwargs, {}) + + def test_function_kwargs(self): + obj = xml_import(self.cr, 'test_convert', None, 'init') + + # pass args and kwargs in child elements + xml = E.function( + E.value(eval="1"), E.value(name="foo", eval="2"), + model="test_convert.usered", + name="model_method", + ) + rec, args, kwargs = self.eval_xml(xml, obj) + self.assertEqual(rec.env.context, self.env.context) + self.assertEqual(rec.ids, []) + self.assertEqual(args, (1,)) + self.assertEqual(kwargs, {'foo': 2}) + + xml = E.function( + E.value(eval="1"), E.value(name="foo", eval="2"), + model="test_convert.usered", + name="method", + ) + rec, args, kwargs = self.eval_xml(xml, obj) + self.assertEqual(rec.env.context, self.env.context) + self.assertEqual(rec.ids, [1]) + self.assertEqual(args, ()) + self.assertEqual(kwargs, {'foo': 2}) + + # pass args and context in kwargs + xml = E.function( + E.value(eval="1"), E.value(name="context", eval="{'foo': 2}"), + model="test_convert.usered", + name="model_method", + ) + rec, args, kwargs = self.eval_xml(xml, obj) + self.assertEqual(rec.env.context, {'foo': 2}) + self.assertEqual(rec.ids, []) + self.assertEqual(args, (1,)) + self.assertEqual(kwargs, {}) + + xml = E.function( + E.value(eval="1"), E.value(name="context", eval="{'foo': 2}"), + model="test_convert.usered", + name="method", + ) + rec, args, kwargs = self.eval_xml(xml, obj) + self.assertEqual(rec.env.context, {'foo': 2}) + self.assertEqual(rec.ids, [1]) + self.assertEqual(args, ()) + self.assertEqual(kwargs, {}) + + def test_function_function(self): + obj = xml_import(self.cr, 'test_convert', None, 'init') + + xml = E.function( + E.function(model="test_convert.usered", name="search", eval="[[]]"), + model="test_convert.usered", + name="method", + ) + rec, args, kwargs = self.eval_xml(xml, obj) + self.assertEqual(rec.env.context, {}) + self.assertEqual(rec.ids, []) + self.assertEqual(args, ()) + self.assertEqual(kwargs, {}) + @unittest.skip("not tested") def test_xml(self): pass diff --git a/odoo/import_xml.rng b/odoo/import_xml.rng index 953cac69e42..83324f379a9 100644 --- a/odoo/import_xml.rng +++ b/odoo/import_xml.rng @@ -23,6 +23,7 @@ + diff --git a/odoo/tools/convert.py b/odoo/tools/convert.py index e677560979e..7a3ff444cce 100644 --- a/odoo/tools/convert.py +++ b/odoo/tools/convert.py @@ -177,32 +177,24 @@ def _eval_xml(self, node, env): return tuple(res) return res elif node.tag == "function": + model = env[node.get('model')] + method_name = node.get('name') + # determine arguments + args = [] + kwargs = {} a_eval = node.get('eval') if a_eval: self.idref['ref'] = self.id_get - # ensure the args are a list (sometimes folks eval a tuple which - # is inconvenient when trying to concatenate w/ a list) args = list(safe_eval(a_eval, self.idref)) - else: - args = [ - r for r in (_eval_xml(self, n, env) for n in node) - if r is not None - ] - - model = env[node.get('model')] - method_name = node.get('name') - method = getattr(model, method_name) - - # this mess is necessary to merge @context and a possible positional - # context parameter, as works on the old API so ids and - # context are just args - ids, args = [], list(args) - if getattr(method, '_api', None) not in ('model', 'model_create'): - ids, args = args[:1], args[1:] - context, args, kwargs = api.split_context(method, args, {}) - kwargs['context'] = {**env.context, **(context or {})} - - return odoo.api.call_kw(model, method_name, ids + args, kwargs) + for child in node: + if child.tag == 'value' and child.get('name'): + kwargs[child.get('name')] = _eval_xml(self, child, env) + else: + args.append(_eval_xml(self, child, env)) + # merge current context with context in kwargs + kwargs['context'] = {**env.context, **kwargs.get('context', {})} + # invoke method + return odoo.api.call_kw(model, method_name, args, kwargs) elif node.tag == "test": return node.text