[FIX] tools: allow using datetime in function call

Traceback generated when trying to pass a datetime object into a function tag
in xml.

<function name="action_name" model="model_name" eval="datetime.date.today"/>

Used to fail.

With this commit now one can pass time, datetime, timedelta, relativedelta,
version, ref, pytz in function tag in xml

Task-id: 1772614
Closes odoo/odoo#29212

Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>


Co-authored-by: Dhaval Limbuwala <dli@odoo.com>
This commit is contained in:
Mohammed Shekha
2019-05-16 14:42:41 +00:00
committed by Martin Trigaux
co-authored by Dhaval Limbuwala
parent 272359b86c
commit 90d86e07dd
6 changed files with 45 additions and 3 deletions
+1
View File
@@ -0,0 +1 @@
from . import models
+1
View File
@@ -5,4 +5,5 @@
'name': 'test_convert',
'description': "Data for xml conversion tests",
'version': '0.0.1',
'data': ['ir.model.access.csv'],
}
@@ -0,0 +1,2 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_test_convert_test_model,access_test_convert_test_model,model_test_convert_test_model,,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_test_convert_test_model access_test_convert_test_model model_test_convert_test_model 1 1 1 1
+16
View File
@@ -0,0 +1,16 @@
from odoo import api, models
class TestModel(models.Model):
_name = 'test_convert.test_model'
@api.model
def action_test_date(self, today_date):
return True
@api.model
def action_test_time(self, cur_time):
return True
@api.model
def action_test_timezone(self, timezone):
return True
@@ -4,8 +4,10 @@
import collections
import unittest
from lxml import etree as ET
from lxml.builder import E
import odoo
from odoo.tests import common
from odoo.tools.convert import _eval_xml
@@ -16,6 +18,25 @@ class TestEvalXML(common.TransactionCase):
def eval_xml(self, node, obj=None):
return _eval_xml(obj, node, self.env)
def test_function_eval(self):
def id_get(): pass
Obj = collections.namedtuple('Obj', ['module', 'idref', 'id_get'])
obj = Obj('test_convert', {}, id_get)
try:
test_datetime = ET.XML("<function name='action_test_date' model='test_convert.test_model' eval='[datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")]'/>")
self.eval_xml(node=test_datetime, obj=obj)
test_time = ET.XML("<function name='action_test_time' model='test_convert.test_model' eval='[time.strftime(\"%Y-%m-%d %H:%M:%S\")]'/>")
self.eval_xml(node=test_time, obj=obj)
test_timedelta = ET.XML("<function name='action_test_date' model='test_convert.test_model' eval='[(datetime.today()-timedelta(days=365)).strftime(\"%Y-%m-%d %H:%M:%S\")]'/>")
self.eval_xml(node=test_timedelta, obj=obj)
test_relativedelta = ET.XML("<function name='action_test_date' model='test_convert.test_model' eval='[(datetime.today()+relativedelta(months=3)).strftime(\"%Y-%m-%d %H:%M:%S\")]'/>")
self.eval_xml(node=test_relativedelta, obj=obj)
test_timezone = ET.XML("<function name='action_test_timezone' model='test_convert.test_model' eval='[pytz.timezone(\"Asia/Calcutta\")]'/>")
self.eval_xml(node=test_timezone, obj=obj)
except ValueError as e:
self.fail(e.message)
def test_char(self):
self.assertEqual(
self.eval_xml(Field("foo")),
+4 -3
View File
@@ -177,15 +177,16 @@ def _eval_xml(self, node, env):
elif node.tag == "function":
args = []
a_eval = node.get('eval','')
model_str = node.get('model', '')
# FIXME: should probably be exclusive
if a_eval:
self.idref['ref'] = self.id_get
args = safe_eval(a_eval, self.idref)
idref2 = _get_idref(self, env, model_str, self.idref)
args = safe_eval(a_eval, idref2)
for n in node:
return_val = _eval_xml(self, n, env)
if return_val is not None:
args.append(return_val)
model = env[node.get('model', '')]
model = env[model_str]
method = node.get('name')
# this one still depends on the old API
return odoo.api.call_kw(model, method, args, {})