diff --git a/odoo/addons/base/models/ir_qweb.py b/odoo/addons/base/models/ir_qweb.py index 4528ed0a0ea..2b8b896fd29 100644 --- a/odoo/addons/base/models/ir_qweb.py +++ b/odoo/addons/base/models/ir_qweb.py @@ -275,33 +275,6 @@ class IrQWeb(models.AbstractModel, QWeb): ) ] - # for backward compatibility to remove after v10 - def _compile_widget_options(self, el, directive_type): - field_options = super(IrQWeb, self)._compile_widget_options(el, directive_type) - - if ('t-%s-options' % directive_type) in el.attrib: - if tools.config['dev_mode']: - _logger.warning("Use new syntax t-options instead of t-%s-options for '%s'" % (directive_type, etree.tostring(el))) - if not field_options: - field_options = el.attrib.pop('t-%s-options' % directive_type) - - if field_options and 'monetary' in field_options: - try: - options = "{'widget': 'monetary'" - for k, v in json.loads(field_options).items(): - if k in ('display_currency', 'from_currency'): - options = "%s, '%s': %s" % (options, k, v) - else: - options = "%s, '%s': '%s'" % (options, k, v) - options = "%s}" % options - field_options = options - _logger.warning("Use new syntax for '%s' monetary widget t-options (python dict instead of deprecated JSON syntax)." % etree.tostring(el)) - except ValueError: - pass - - return field_options - # end backward - # method called by computing code def get_asset_bundle(self, xmlid, files, remains=None, env=None): diff --git a/odoo/addons/base/models/qweb.py b/odoo/addons/base/models/qweb.py index 937134a6625..05692bc394b 100644 --- a/odoo/addons/base/models/qweb.py +++ b/odoo/addons/base/models/qweb.py @@ -649,7 +649,7 @@ class QWeb(object): el.set("t-groups", el.attrib.pop("groups")) # if tag don't have qweb attributes don't use directives - if self._is_static_node(el): + if self._is_static_node(el, options): return self._compile_static_node(el, options) # create an iterator on directives to compile in order @@ -794,7 +794,7 @@ class QWeb(object): 'content', ] - def _is_static_node(self, el): + def _is_static_node(self, el, options): """ Test whether the given element is purely static, i.e., does not require dynamic rendering for its attributes. """ @@ -1164,7 +1164,7 @@ class QWeb(object): return el.tail is not None and [self._append(ast.Str(pycompat.to_text(el.tail)))] or [] def _compile_directive_esc(self, el, options): - field_options = self._compile_widget_options(el, 'esc') + field_options = self._compile_widget_options(el) content = self._compile_widget(el, el.attrib.pop('t-esc'), field_options) if not field_options: # if content is not False and if content is not None: @@ -1188,7 +1188,7 @@ class QWeb(object): return content + self._compile_widget_value(el, options) def _compile_directive_raw(self, el, options): - field_options = self._compile_widget_options(el, 'raw') + field_options = self._compile_widget_options(el) content = self._compile_widget(el, el.attrib.pop('t-raw'), field_options) return content + self._compile_widget_value(el, options) @@ -1217,7 +1217,7 @@ class QWeb(object): ast.Name(id='content', ctx=ast.Load()), ast.Str(expression), ast.Str(el.tag), - field_options and self._compile_expr(field_options) or ast.Dict(keys=[], values=[]), + field_options, ast.Name(id='options', ctx=ast.Load()), ast.Name(id='values', ctx=ast.Load()), ], @@ -1246,10 +1246,38 @@ class QWeb(object): ) ] - # for backward compatibility to remove after v10 - def _compile_widget_options(self, el, directive_type): - return el.attrib.pop('t-options', None) - # end backward + def _compile_widget_options(self, el): + """ + compile t-options and add to the dict the t-options-xxx values + """ + options = el.attrib.pop('t-options', None) + # the options can be None, a dict {}, or the method dict() + ast_options = options and self._compile_expr(options) or ast.Dict(keys=[], values=[]) + + # convert ast.Call from dict() into ast.Dict + if isinstance(ast_options, ast.Call): + ast_options = ast.Dict( + keys=[ast.Str(k.arg) for k in ast_options.keywords], + values=[k.value for k in ast_options.keywords] + ) + + for complete_key in OrderedDict(el.attrib): + if complete_key.startswith('t-options-'): + key = complete_key[10:] + value = self._compile_expr(el.attrib.pop(complete_key)) + + replacement = False + for astStr in ast_options.keys: + if astStr.s == key: + ast_options.values[ast_options.keys.index(astStr)] = value + replacement = True + break + + if not replacement: + ast_options.keys.append(ast.Str(key)) + ast_options.values.append(value) + + return ast_options.keys and ast_options or None def _compile_directive_field(self, el, options): """ Compile something like ``+1 555 555 8069`` """ @@ -1263,7 +1291,7 @@ class QWeb(object): "t-field must have at least a dot like 'record.field_name'" expression = el.attrib.pop('t-field') - field_options = self._compile_widget_options(el, 'field') + field_options = self._compile_widget_options(el) or ast.Dict(keys=[], values=[]) record, field_name = expression.rsplit('.', 1) return [ @@ -1285,7 +1313,7 @@ class QWeb(object): ast.Str(field_name), ast.Str(expression), ast.Str(node_name), - field_options and self._compile_expr(field_options) or ast.Dict(keys=[], values=[]), + field_options, ast.Name(id='options', ctx=ast.Load()), ast.Name(id='values', ctx=ast.Load()), ], diff --git a/odoo/addons/base/tests/test_qweb.py b/odoo/addons/base/tests/test_qweb.py index 1f276f25e0c..5324b1fef28 100644 --- a/odoo/addons/base/tests/test_qweb.py +++ b/odoo/addons/base/tests/test_qweb.py @@ -64,6 +64,17 @@ class TestQWebTField(TransactionCase): with self.assertRaisesRegexp(QWebException, r'^t-field can not be used on a t element'): self.engine.render(field, {'company': None}) + def test_render_t_options(self): + view1 = self.env['ir.ui.view'].create({ + 'name': "dummy", + 'type': 'qweb', + 'arch': u""" + + """ + }) + text = etree.fromstring(view1.render()).find('span').text + self.assertEqual(text, u'5.0000') + class TestQWebNS(TransactionCase): def test_render_static_xml_with_namespace(self):