From 5913b7265ef5bd8a01a882fa0977bbd64321054d Mon Sep 17 00:00:00 2001 From: Gorash Date: Fri, 26 Feb 2021 08:53:37 +0000 Subject: [PATCH] [REF] base,*: refactor Qweb engine * Remove AST in favor of pure Pyhon. This should make it easier for developers to understand and create new directives because they do not need to know AST. * Remove `t-call-options` as it has been merged into `t-options` for more consistency. Support for t-call-options is retained. * Use generators for lists. This increases performances as the rendering can be sent directly without having to wait for the creation of the entire list. * Optimize expressions runtime computation by pre-computing the static parts. Example: '<' + 'div' + '>' + '<' + dynamic_value + '>' Now compiles as: '
<' + dynamic_value + '>' --- addons/test_website/tests/test_reset_views.py | 10 +- addons/web/models/ir_qweb.py | 3 +- .../static/lib/qweb/qweb-test-attributes.xml | 4 +- addons/web/static/lib/qweb/qweb-test-call.xml | 21 + .../web/static/lib/qweb/qweb-test-output.xml | 5 + addons/web/static/lib/qweb/qweb-test-set.xml | 9 + addons/web_editor/models/ir_qweb.py | 41 +- addons/website/models/ir_http.py | 2 +- addons/website/tests/test_qweb.py | 16 + odoo/addons/base/models/assetsbundle.py | 13 +- odoo/addons/base/models/ir_qweb.py | 305 +-- odoo/addons/base/models/ir_qweb_fields.py | 43 +- odoo/addons/base/models/qweb.py | 2314 +++++++---------- odoo/addons/base/tests/test_qweb.py | 411 ++- odoo/addons/base/tests/test_views.py | 2 +- 15 files changed, 1568 insertions(+), 1631 deletions(-) diff --git a/addons/test_website/tests/test_reset_views.py b/addons/test_website/tests/test_reset_views.py index a11e82824c3..5d0eeaa64de 100644 --- a/addons/test_website/tests/test_reset_views.py +++ b/addons/test_website/tests/test_reset_views.py @@ -5,7 +5,7 @@ import odoo.tests from odoo.tools import mute_logger -def break_view(view, fr='

placeholder

', to='

'): +def break_view(view, fr='

placeholder

', to='

'): view.arch = view.arch.replace(fr, to) @@ -44,8 +44,8 @@ class TestWebsiteResetViews(odoo.tests.HttpCase): def test_02_reset_specific_view_controller(self): total_views = self.View.search_count([('type', '=', 'qweb')]) # Trigger COW then break the QWEB XML on it - # `t-att-data="not.exist"` will test the case where exception.html contains branding - break_view(self.test_view.with_context(website_id=1), to='

') + # `t-att-data="no_record.exist"` will test the case where exception.html contains branding + break_view(self.test_view.with_context(website_id=1), to='

') self.assertEqual(total_views + 1, self.View.search_count([('type', '=', 'qweb')]), "Missing COW view") self.fix_it('/test_view') @@ -79,12 +79,12 @@ class TestWebsiteResetViews(odoo.tests.HttpCase): # self.assertEqual(total_views + 1, self.View.search_count([('type', '=', 'qweb')]), "Missing COW view (1)") # self.fix_it('/test_view') - # also mute ir.ui.view as `get_view_id()` will raise "Could not find view object with xml_id 'not.exist'"" + # also mute ir.ui.view as `get_view_id()` will raise "Could not find view object with xml_id 'no_record.exist'"" @mute_logger('odoo.addons.http_routing.models.ir_http', 'odoo.addons.website.models.ir_ui_view') def test_06_reset_specific_view_controller_inexisting_template(self): total_views = self.View.search_count([('type', '=', 'qweb')]) # Trigger COW then break the QWEB XML on it - break_view(self.test_view.with_context(website_id=1), to='') + break_view(self.test_view.with_context(website_id=1), to='') self.assertEqual(total_views + 1, self.View.search_count([('type', '=', 'qweb')]), "Missing COW view (2)") self.fix_it('/test_view') diff --git a/addons/web/models/ir_qweb.py b/addons/web/models/ir_qweb.py index 51694a3bc42..d68ff6ff971 100644 --- a/addons/web/models/ir_qweb.py +++ b/addons/web/models/ir_qweb.py @@ -4,6 +4,7 @@ import hashlib from collections import OrderedDict from werkzeug.urls import url_quote +from markupsafe import Markup as M from odoo import api, models from odoo.tools import pycompat @@ -105,7 +106,7 @@ class Image(models.AbstractModel): img.append('"') img.append('/>') - return u''.join(img) + return M(''.join(img)) class ImageUrlConverter(models.AbstractModel): _description = 'Qweb Field Image' diff --git a/addons/web/static/lib/qweb/qweb-test-attributes.xml b/addons/web/static/lib/qweb/qweb-test-attributes.xml index b599b76b629..e9f92a34ae7 100644 --- a/addons/web/static/lib/qweb/qweb-test-attributes.xml +++ b/addons/web/static/lib/qweb/qweb-test-attributes.xml @@ -5,9 +5,9 @@

]]> - Test + Test - ]]> + ]]>
diff --git a/addons/web/static/lib/qweb/qweb-test-call.xml b/addons/web/static/lib/qweb/qweb-test-call.xml index 8cf1d1d657f..888026291d5 100644 --- a/addons/web/static/lib/qweb/qweb-test-call.xml +++ b/addons/web/static/lib/qweb/qweb-test-call.xml @@ -32,6 +32,27 @@ ok + +
+ + + + + +
]]> + + + +
+
+
+ + {"value": "ok"} + + +
ok
+ ]]>
+