[FIX] convert: enable kwargs in tag <function>
closes odoo/odoo#31417 Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
This commit is contained in:
@@ -368,8 +368,8 @@ Andrew</p>]]></field>
|
||||
|
||||
<!-- Call Function to Cancel the leads (set as Dead) -->
|
||||
<function model="crm.lead" name="action_set_lost"
|
||||
eval="[ref('crm_case_7'), ref('crm_case_9'), ref('crm_case_11'), ref('crm_case_12')],
|
||||
{'install_mode': True}"/>
|
||||
eval="[[ref('crm_case_7'), ref('crm_case_9'), ref('crm_case_11'), ref('crm_case_12')]]"
|
||||
context="{'install_mode': True}"/>
|
||||
|
||||
<!-- Demo Opportunities -->
|
||||
<record id="crm_case_13" model="crm.lead">
|
||||
@@ -1161,13 +1161,13 @@ Andrew</p>]]></field>
|
||||
|
||||
<!-- Call Function to set dome opportunities as Lost -->
|
||||
<function model="crm.lead" name="action_set_lost"
|
||||
eval="[ref('crm_case_28')],
|
||||
{'install_mode': True}"/>
|
||||
eval="[[ref('crm_case_28')]]"
|
||||
context="{'install_mode': True}"/>
|
||||
|
||||
<!-- Call Function to set some opportunities as Won -->
|
||||
<function model="crm.lead" name="action_set_won"
|
||||
eval="[ref('crm_case_20'), ref('crm_case_23'), ref('crm_case_27')],
|
||||
{'install_mode': True}"/>
|
||||
eval="[[ref('crm_case_20'), ref('crm_case_23'), ref('crm_case_27')]]"
|
||||
context="{'install_mode': True}"/>
|
||||
|
||||
<!-- Activities -->
|
||||
<record id="activity_1" model="mail.activity">
|
||||
|
||||
@@ -264,34 +264,41 @@
|
||||
<value model="link.tracker.code"
|
||||
search="[('link_id.url', '=', 'http://www.example.com')]"
|
||||
use="code"/>
|
||||
<value eval="{'ip': '100.01.02.03', 'country_code': 'BE', 'mail_stat_id': ref('mass_mail_1_stat_0')}"/>
|
||||
<value name="ip">100.01.02.03</value>
|
||||
<value name="country_code">BE</value>
|
||||
<value name="mail_stat_id" eval="ref('mass_mail_1_stat_0')"/>
|
||||
</function>
|
||||
<function model="link.tracker.click" name="add_click">
|
||||
<value model="link.tracker.code"
|
||||
search="[('link_id.url', '=', 'http://www.example.net/page/contactus')]"
|
||||
use="code"/>
|
||||
<value eval="{'ip': '100.01.02.03', 'country_code': 'BE', 'mail_stat_id': ref('mass_mail_1_stat_0')}"/>
|
||||
<value name="ip">100.01.02.03</value>
|
||||
<value name="country_code">BE</value>
|
||||
<value name="mail_stat_id" eval="ref('mass_mail_1_stat_0')"/>
|
||||
</function>
|
||||
<function model="link.tracker.click" name="add_click">
|
||||
<value model="link.tracker.code"
|
||||
search="[('link_id.url', '=', 'http://www.example.com')]"
|
||||
use="code"/>
|
||||
<value eval="{'ip': '100.01.02.04', 'country_code': 'BE', 'mail_stat_id': ref('mass_mail_1_stat_1')}"/>
|
||||
<value name="ip">100.01.02.04</value>
|
||||
<value name="country_code">BE</value>
|
||||
<value name="mail_stat_id" eval="ref('mass_mail_1_stat_1')"/>
|
||||
</function>
|
||||
<function model="link.tracker.click" name="add_click">
|
||||
<value model="link.tracker.code"
|
||||
search="[('link_id.url', '=', 'http://www.example.net/page/contactus')]"
|
||||
use="code"/>
|
||||
<value eval="{'ip': '100.01.02.04', 'country_code': 'BE', 'mail_stat_id': ref('mass_mail_1_stat_0')}"/>
|
||||
<value eval="'100.01.02.04'"/>
|
||||
<value eval="'BE'"/>
|
||||
<value eval="ref('mass_mail_1_stat_0')"/>
|
||||
<value name="ip">100.01.02.04</value>
|
||||
<value name="country_code">BE</value>
|
||||
<value name="mail_stat_id" eval="ref('mass_mail_1_stat_0')"/>
|
||||
</function>
|
||||
<function model="link.tracker.click" name="add_click">
|
||||
<value model="link.tracker.code"
|
||||
search="[('link_id.url', '=', 'http://www.example.com')]"
|
||||
use="code"/>
|
||||
<value eval="{'ip': '100.01.02.05', 'country_code': 'BE', 'mail_stat_id': ref('mass_mail_1_stat_2')}"/>
|
||||
<value name="ip">100.01.02.05</value>
|
||||
<value name="country_code">BE</value>
|
||||
<value name="mail_stat_id" eval="ref('mass_mail_1_stat_2')"/>
|
||||
</function>
|
||||
|
||||
</data>
|
||||
|
||||
@@ -143,20 +143,10 @@
|
||||
</function>
|
||||
|
||||
<!-- create the transit location for each company existing -->
|
||||
<function model="res.company" name="create_missing_transit_location">
|
||||
<value model="res.company" eval="obj()"/>
|
||||
</function>
|
||||
<function model="res.company" name="create_missing_warehouse">
|
||||
<value model="res.company" eval="obj()"/>
|
||||
</function>
|
||||
<function model="res.company" name="create_missing_inventory_loss_location">
|
||||
<value model="res.company" eval="obj()"/>
|
||||
</function>
|
||||
<function model="res.company" name="create_missing_production_location">
|
||||
<value model="res.company" eval="obj()"/>
|
||||
</function>
|
||||
<function model="res.company" name="create_missing_scrap_location">
|
||||
<value model="res.company" eval="obj()"/>
|
||||
</function>
|
||||
<function model="res.company" name="create_missing_transit_location"/>
|
||||
<function model="res.company" name="create_missing_warehouse"/>
|
||||
<function model="res.company" name="create_missing_inventory_loss_location"/>
|
||||
<function model="res.company" name="create_missing_production_location"/>
|
||||
<function model="res.company" name="create_missing_scrap_location"/>
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
<rng:define name="value">
|
||||
<rng:element name="value">
|
||||
<rng:optional><rng:attribute name="name" /></rng:optional>
|
||||
<rng:optional><rng:attribute name="model" /></rng:optional>
|
||||
<rng:choice>
|
||||
<rng:attribute name="search" />
|
||||
|
||||
+14
-22
@@ -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 <function> 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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user