[FIX] web, tools: static inheritance supports replace in debug mode
Have a parent template Have a child, in extension inherit mode of the parent The child has a xpath like `<xpath expr="." position="replace" />` Before this commit, there was a crash. That was because the Comment (which indicates which templates modified the parent) was taken as the replacer node instead of the actual content of the xpath After this commit, there is no crash, and it works as expected closes odoo/odoo#39453 X-original-commit: 02d790e1d21b78395e489f57bf30c82f728cbee6 Signed-off-by: Lucas Perais (lpe) <lpe@odoo.com>
This commit is contained in:
committed by
fw-bot
parent
eccfdd5512
commit
bbbfca2d97
@@ -450,3 +450,270 @@ class TestStaticInheritance(BaseCase):
|
||||
after = datetime.now()
|
||||
|
||||
self.assertLessEqual(after - before, timedelta(milliseconds=1000))
|
||||
|
||||
def test_replace_in_debug_mode(self):
|
||||
"""
|
||||
Replacing a template's meta definition in place doesn't keep the original attrs of the template
|
||||
"""
|
||||
self.modules = [
|
||||
('module_1_file_1', None, 'module_1'),
|
||||
]
|
||||
self.template_files = {
|
||||
'module_1_file_1': b"""
|
||||
<templates id="template" xml:space="preserve">
|
||||
<form t-name="template_1_1" random-attr="gloria">
|
||||
<div>At first I was afraid</div>
|
||||
</form>
|
||||
<t t-name="template_1_2" t-inherit="template_1_1" t-inherit-mode="extension">
|
||||
<xpath expr="." position="replace">
|
||||
<div overriden-attr="overriden">And I grew strong</div>
|
||||
</xpath>
|
||||
</t>
|
||||
</templates>
|
||||
""",
|
||||
}
|
||||
|
||||
contents = HomeStaticTemplateHelpers.get_qweb_templates(addons=self._get_module_names(), debug=True)
|
||||
expected = b"""
|
||||
<templates>
|
||||
<form overriden-attr="overriden">
|
||||
<!-- Modified by template_1_2 from module_1 -->And I grew strong
|
||||
</form>
|
||||
</templates>
|
||||
"""
|
||||
|
||||
self.assertXMLEqual(contents, expected)
|
||||
|
||||
def test_replace_in_debug_mode2(self):
|
||||
self.modules = [
|
||||
('module_1_file_1', None, 'module_1'),
|
||||
]
|
||||
self.template_files = {
|
||||
'module_1_file_1': b"""
|
||||
<templates id="template" xml:space="preserve">
|
||||
<form t-name="template_1_1" random-attr="gloria">
|
||||
<div>At first I was afraid</div>
|
||||
</form>
|
||||
<t t-name="template_1_2" t-inherit="template_1_1" t-inherit-mode="extension">
|
||||
<xpath expr="." position="replace">
|
||||
<div>
|
||||
And I grew strong
|
||||
<p>And I learned how to get along</p>
|
||||
And so you're back
|
||||
</div>
|
||||
</xpath>
|
||||
</t>
|
||||
</templates>
|
||||
""",
|
||||
}
|
||||
|
||||
contents = HomeStaticTemplateHelpers.get_qweb_templates(addons=self._get_module_names(), debug=True)
|
||||
expected = b"""
|
||||
<templates>
|
||||
<form>
|
||||
<!-- Modified by template_1_2 from module_1 -->And I grew strong
|
||||
<p>And I learned how to get along</p>
|
||||
And so you're back
|
||||
</form>
|
||||
</templates>
|
||||
"""
|
||||
|
||||
self.assertXMLEqual(contents, expected)
|
||||
|
||||
def test_replace_in_debug_mode3(self):
|
||||
"""Text outside of a div which will replace a whole template
|
||||
becomes outside of the template
|
||||
This doesn't mean anything in terms of the business of template inheritance
|
||||
But it is in the XPATH specs"""
|
||||
self.modules = [
|
||||
('module_1_file_1', None, 'module_1'),
|
||||
]
|
||||
self.template_files = {
|
||||
'module_1_file_1': b"""
|
||||
<templates id="template" xml:space="preserve">
|
||||
<form t-name="template_1_1" random-attr="gloria">
|
||||
<div>At first I was afraid</div>
|
||||
</form>
|
||||
<t t-name="template_1_2" t-inherit="template_1_1" t-inherit-mode="extension">
|
||||
<xpath expr="." position="replace">
|
||||
<div>
|
||||
And I grew strong
|
||||
<p>And I learned how to get along</p>
|
||||
</div>
|
||||
And so you're back
|
||||
</xpath>
|
||||
</t>
|
||||
</templates>
|
||||
""",
|
||||
}
|
||||
|
||||
contents = HomeStaticTemplateHelpers.get_qweb_templates(addons=self._get_module_names(), debug=True)
|
||||
expected = b"""
|
||||
<templates>
|
||||
<form>
|
||||
<!-- Modified by template_1_2 from module_1 -->
|
||||
And I grew strong
|
||||
<p>And I learned how to get along</p>
|
||||
</form>
|
||||
And so you're back
|
||||
</templates>
|
||||
"""
|
||||
|
||||
self.assertXMLEqual(contents, expected)
|
||||
|
||||
def test_replace_root_node_tag(self):
|
||||
"""
|
||||
Root node is not targeted by //NODE_TAG in xpath
|
||||
"""
|
||||
self.modules = [
|
||||
('module_1_file_1', None, 'module_1'),
|
||||
]
|
||||
self.template_files = {
|
||||
'module_1_file_1': b"""
|
||||
<templates id="template" xml:space="preserve">
|
||||
<form t-name="template_1_1" random-attr="gloria">
|
||||
<div>At first I was afraid</div>
|
||||
<form>Inner Form</form>
|
||||
</form>
|
||||
<t t-name="template_1_2" t-inherit="template_1_1" t-inherit-mode="extension">
|
||||
<xpath expr="//form" position="replace">
|
||||
<div>
|
||||
Form replacer
|
||||
</div>
|
||||
</xpath>
|
||||
</t>
|
||||
</templates>
|
||||
""",
|
||||
}
|
||||
|
||||
contents = HomeStaticTemplateHelpers.get_qweb_templates(addons=self._get_module_names(), debug=True)
|
||||
expected = b"""
|
||||
<templates>
|
||||
<form t-name="template_1_1" random-attr="gloria">
|
||||
<div>At first I was afraid</div>
|
||||
<!-- Modified by template_1_2 from module_1 -->
|
||||
<div>Form replacer</div>
|
||||
</form>
|
||||
</templates>
|
||||
"""
|
||||
|
||||
self.assertXMLEqual(contents, expected)
|
||||
|
||||
def test_replace_root_node_tag_in_primary(self):
|
||||
"""
|
||||
Root node is not targeted by //NODE_TAG in xpath
|
||||
"""
|
||||
self.maxDiff = None
|
||||
self.modules = [
|
||||
('module_1_file_1', None, 'module_1'),
|
||||
]
|
||||
self.template_files = {
|
||||
'module_1_file_1': b"""
|
||||
<templates id="template" xml:space="preserve">
|
||||
<form t-name="template_1_1" random-attr="gloria">
|
||||
<div>At first I was afraid</div>
|
||||
<form>Inner Form</form>
|
||||
</form>
|
||||
<t t-name="template_1_2" t-inherit="template_1_1" t-inherit-mode="primary">
|
||||
<xpath expr="//form" position="replace">
|
||||
<div>Form replacer</div>
|
||||
</xpath>
|
||||
</t>
|
||||
</templates>
|
||||
""",
|
||||
}
|
||||
|
||||
contents = HomeStaticTemplateHelpers.get_qweb_templates(addons=self._get_module_names(), debug=True)
|
||||
expected = b"""
|
||||
<templates>
|
||||
<form t-name="template_1_1" random-attr="gloria">
|
||||
<div>At first I was afraid</div>
|
||||
<form>Inner Form</form>
|
||||
</form>
|
||||
<form t-name="template_1_2" random-attr="gloria" t-inherit="template_1_1">
|
||||
<div>At first I was afraid</div>
|
||||
<div>Form replacer</div>
|
||||
</form>
|
||||
</templates>
|
||||
"""
|
||||
|
||||
self.assertXMLEqual(contents, expected)
|
||||
|
||||
def test_inherit_primary_replace_debug(self):
|
||||
"""
|
||||
The inheriting template has got both its own defining attrs
|
||||
and new ones if one is to replace its defining root node
|
||||
"""
|
||||
self.modules = [
|
||||
('module_1_file_1', None, 'module_1'),
|
||||
]
|
||||
self.template_files = {
|
||||
'module_1_file_1': b"""
|
||||
<templates id="template" xml:space="preserve">
|
||||
<form t-name="template_1_1" random-attr="gloria">
|
||||
<div>At first I was afraid</div>
|
||||
</form>
|
||||
<t t-name="template_1_2" t-inherit="template_1_1" t-inherit-mode="primary">
|
||||
<xpath expr="." position="replace">
|
||||
<div overriden-attr="overriden">
|
||||
And I grew strong
|
||||
<p>And I learned how to get along</p>
|
||||
</div>
|
||||
</xpath>
|
||||
</t>
|
||||
</templates>
|
||||
""",
|
||||
}
|
||||
|
||||
contents = HomeStaticTemplateHelpers.get_qweb_templates(addons=self._get_module_names(), debug=True)
|
||||
expected = b"""
|
||||
<templates>
|
||||
<form t-name="template_1_1" random-attr="gloria">
|
||||
<div>At first I was afraid</div>
|
||||
</form>
|
||||
<form overriden-attr="overriden" t-name="template_1_2" t-inherit="template_1_1">
|
||||
And I grew strong
|
||||
<p>And I learned how to get along</p>
|
||||
</form>
|
||||
</templates>
|
||||
"""
|
||||
|
||||
self.assertXMLEqual(contents, expected)
|
||||
|
||||
def test_replace_in_nodebug_mode1(self):
|
||||
"""Comments already in the arch are ignored"""
|
||||
self.modules = [
|
||||
('module_1_file_1', None, 'module_1'),
|
||||
]
|
||||
self.template_files = {
|
||||
'module_1_file_1': b"""
|
||||
<templates id="template" xml:space="preserve">
|
||||
<form t-name="template_1_1" random-attr="gloria">
|
||||
<div>At first I was afraid</div>
|
||||
</form>
|
||||
<t t-name="template_1_2" t-inherit="template_1_1" t-inherit-mode="extension">
|
||||
<xpath expr="." position="replace">
|
||||
<div>
|
||||
<!-- Random Comment -->
|
||||
And I grew strong
|
||||
<p>And I learned how to get along</p>
|
||||
And so you're back
|
||||
</div>
|
||||
</xpath>
|
||||
</t>
|
||||
</templates>
|
||||
""",
|
||||
}
|
||||
|
||||
contents = HomeStaticTemplateHelpers.get_qweb_templates(addons=self._get_module_names(), debug=False)
|
||||
expected = b"""
|
||||
<templates>
|
||||
<form>
|
||||
And I grew strong
|
||||
<p>And I learned how to get along</p>
|
||||
And so you're back
|
||||
</form>
|
||||
</templates>
|
||||
"""
|
||||
|
||||
self.assertXMLEqual(contents, expected)
|
||||
|
||||
@@ -129,7 +129,20 @@ def apply_inheritance_specs(source, specs_tree, inherit_branding=False, pre_loca
|
||||
loc.text = ''
|
||||
loc.append(copy.deepcopy(node))
|
||||
if node.getparent() is None:
|
||||
source = copy.deepcopy(spec[0])
|
||||
spec_content = None
|
||||
comment = None
|
||||
for content in spec:
|
||||
if content.tag is not etree.Comment:
|
||||
spec_content = content
|
||||
break
|
||||
else:
|
||||
comment = content
|
||||
source = copy.deepcopy(spec_content)
|
||||
if comment is not None:
|
||||
text = source.text
|
||||
source.text = None
|
||||
comment.tail = text
|
||||
source.insert(0, comment)
|
||||
else:
|
||||
replaced_node_tag = None
|
||||
for child in spec:
|
||||
|
||||
Reference in New Issue
Block a user