[IMP] base_view_inheritance_extension: black, isort
parent
848ad96c1e
commit
45542a0071
|
@ -8,10 +8,6 @@
|
||||||
"license": "LGPL-3",
|
"license": "LGPL-3",
|
||||||
"category": "Hidden/Dependency",
|
"category": "Hidden/Dependency",
|
||||||
"summary": "Adds more operators for view inheritance",
|
"summary": "Adds more operators for view inheritance",
|
||||||
"depends": [
|
"depends": ["base"],
|
||||||
'base',
|
"demo": ["demo/ir_ui_view.xml"],
|
||||||
],
|
|
||||||
"demo": [
|
|
||||||
"demo/ir_ui_view.xml",
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,34 +2,30 @@
|
||||||
# Copyright 2018 Tecnativa - Sergio Teruel
|
# Copyright 2018 Tecnativa - Sergio Teruel
|
||||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
|
||||||
from odoo import api, models, tools
|
from odoo import api, models, tools
|
||||||
from odoo.tools.safe_eval import safe_eval
|
from odoo.tools.safe_eval import safe_eval
|
||||||
|
|
||||||
|
|
||||||
class UnquoteObject(str):
|
class UnquoteObject(str):
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
return UnquoteObject('%s.%s' % (self, name))
|
return UnquoteObject("{}.{}".format(self, name))
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __call__(self, *args, **kwargs):
|
def __call__(self, *args, **kwargs):
|
||||||
return UnquoteObject(
|
return UnquoteObject(
|
||||||
'%s(%s)' % (
|
"%s(%s)"
|
||||||
|
% (
|
||||||
self,
|
self,
|
||||||
','.join(
|
",".join(
|
||||||
[
|
[
|
||||||
UnquoteObject(
|
UnquoteObject(a if not isinstance(a, str) else "'%s'" % a)
|
||||||
a if not isinstance(a, str)
|
|
||||||
else "'%s'" % a
|
|
||||||
)
|
|
||||||
for a in args
|
for a in args
|
||||||
] +
|
|
||||||
[
|
|
||||||
'%s=%s' % (UnquoteObject(k), v)
|
|
||||||
for (k, v) in kwargs.items()
|
|
||||||
]
|
]
|
||||||
)
|
+ ["{}={}".format(UnquoteObject(k), v) for (k, v) in kwargs.items()]
|
||||||
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -40,7 +36,7 @@ class UnquoteEvalObjectContext(tools.misc.UnquoteEvalContext):
|
||||||
|
|
||||||
|
|
||||||
class IrUiView(models.Model):
|
class IrUiView(models.Model):
|
||||||
_inherit = 'ir.ui.view'
|
_inherit = "ir.ui.view"
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def apply_inheritance_specs(self, source, specs_tree, inherit_id):
|
def apply_inheritance_specs(self, source, specs_tree, inherit_id):
|
||||||
|
@ -50,52 +46,40 @@ class IrUiView(models.Model):
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _iter_inheritance_specs(self, spec):
|
def _iter_inheritance_specs(self, spec):
|
||||||
if spec.tag == 'data':
|
if spec.tag == "data":
|
||||||
for child in spec:
|
for child in spec:
|
||||||
for node, handler in self._iter_inheritance_specs(child):
|
for node, handler in self._iter_inheritance_specs(child):
|
||||||
yield node, handler
|
yield node, handler
|
||||||
return
|
return
|
||||||
if spec.get('position') == 'attributes':
|
if spec.get("position") == "attributes":
|
||||||
if all(not c.get('operation') for c in spec):
|
if all(not c.get("operation") for c in spec):
|
||||||
yield spec, self._get_inheritance_handler(spec)
|
yield spec, self._get_inheritance_handler(spec)
|
||||||
return
|
return
|
||||||
for child in spec:
|
for child in spec:
|
||||||
node = etree.Element(spec.tag, **spec.attrib)
|
node = etree.Element(spec.tag, **spec.attrib)
|
||||||
node.insert(0, child)
|
node.insert(0, child)
|
||||||
yield node, self._get_inheritance_handler_attributes(
|
yield node, self._get_inheritance_handler_attributes(child)
|
||||||
child
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
yield spec, self._get_inheritance_handler(spec)
|
yield spec, self._get_inheritance_handler(spec)
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _get_inheritance_handler(self, node):
|
def _get_inheritance_handler(self, node):
|
||||||
handler = super(IrUiView, self).apply_inheritance_specs
|
handler = super(IrUiView, self).apply_inheritance_specs
|
||||||
if hasattr(
|
if hasattr(self, "inheritance_handler_%s" % node.tag):
|
||||||
self, 'inheritance_handler_%s' % node.tag
|
handler = getattr(self, "inheritance_handler_%s" % node.tag)
|
||||||
):
|
|
||||||
handler = getattr(
|
|
||||||
self,
|
|
||||||
'inheritance_handler_%s' % node.tag
|
|
||||||
)
|
|
||||||
return handler
|
return handler
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _get_inheritance_handler_attributes(self, node):
|
def _get_inheritance_handler_attributes(self, node):
|
||||||
handler = super(IrUiView, self).apply_inheritance_specs
|
handler = super(IrUiView, self).apply_inheritance_specs
|
||||||
if hasattr(
|
if hasattr(self, "inheritance_handler_attributes_%s" % node.get("operation")):
|
||||||
self, 'inheritance_handler_attributes_%s' % node.get('operation')
|
|
||||||
):
|
|
||||||
handler = getattr(
|
handler = getattr(
|
||||||
self,
|
self, "inheritance_handler_attributes_%s" % node.get("operation")
|
||||||
'inheritance_handler_attributes_%s' % node.get('operation')
|
|
||||||
)
|
)
|
||||||
return handler
|
return handler
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def inheritance_handler_attributes_python_dict(
|
def inheritance_handler_attributes_python_dict(self, source, specs, inherit_id):
|
||||||
self, source, specs, inherit_id
|
|
||||||
):
|
|
||||||
"""Implement
|
"""Implement
|
||||||
<$node position="attributes">
|
<$node position="attributes">
|
||||||
<attribute name="$attribute" operation="python_dict" key="$key">
|
<attribute name="$attribute" operation="python_dict" key="$key">
|
||||||
|
@ -105,20 +89,16 @@ class IrUiView(models.Model):
|
||||||
node = self.locate_node(source, specs)
|
node = self.locate_node(source, specs)
|
||||||
for attribute_node in specs:
|
for attribute_node in specs:
|
||||||
python_dict = safe_eval(
|
python_dict = safe_eval(
|
||||||
node.get(attribute_node.get('name')) or '{}',
|
node.get(attribute_node.get("name")) or "{}",
|
||||||
UnquoteEvalObjectContext(),
|
UnquoteEvalObjectContext(),
|
||||||
nocopy=True
|
nocopy=True,
|
||||||
)
|
)
|
||||||
python_dict[attribute_node.get('key')] = UnquoteObject(
|
python_dict[attribute_node.get("key")] = UnquoteObject(attribute_node.text)
|
||||||
attribute_node.text
|
node.attrib[attribute_node.get("name")] = str(python_dict)
|
||||||
)
|
|
||||||
node.attrib[attribute_node.get('name')] = str(python_dict)
|
|
||||||
return source
|
return source
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def inheritance_handler_attributes_list_add(
|
def inheritance_handler_attributes_list_add(self, source, specs, inherit_id):
|
||||||
self, source, specs, inherit_id
|
|
||||||
):
|
|
||||||
"""Implement
|
"""Implement
|
||||||
<$node position="attributes">
|
<$node position="attributes">
|
||||||
<attribute name="$attribute" operation="list_add">
|
<attribute name="$attribute" operation="list_add">
|
||||||
|
@ -127,16 +107,14 @@ class IrUiView(models.Model):
|
||||||
</$node>"""
|
</$node>"""
|
||||||
node = self.locate_node(source, specs)
|
node = self.locate_node(source, specs)
|
||||||
for attribute_node in specs:
|
for attribute_node in specs:
|
||||||
attribute_name = attribute_node.get('name')
|
attribute_name = attribute_node.get("name")
|
||||||
old_value = node.get(attribute_name) or ''
|
old_value = node.get(attribute_name) or ""
|
||||||
new_value = old_value + ',' + attribute_node.text
|
new_value = old_value + "," + attribute_node.text
|
||||||
node.attrib[attribute_name] = new_value
|
node.attrib[attribute_name] = new_value
|
||||||
return source
|
return source
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def inheritance_handler_attributes_list_remove(
|
def inheritance_handler_attributes_list_remove(self, source, specs, inherit_id):
|
||||||
self, source, specs, inherit_id
|
|
||||||
):
|
|
||||||
"""Implement
|
"""Implement
|
||||||
<$node position="attributes">
|
<$node position="attributes">
|
||||||
<attribute name="$attribute" operation="list_remove">
|
<attribute name="$attribute" operation="list_remove">
|
||||||
|
@ -145,10 +123,9 @@ class IrUiView(models.Model):
|
||||||
</$node>"""
|
</$node>"""
|
||||||
node = self.locate_node(source, specs)
|
node = self.locate_node(source, specs)
|
||||||
for attribute_node in specs:
|
for attribute_node in specs:
|
||||||
attribute_name = attribute_node.get('name')
|
attribute_name = attribute_node.get("name")
|
||||||
old_values = (node.get(attribute_name) or '').split(',')
|
old_values = (node.get(attribute_name) or "").split(",")
|
||||||
remove_values = attribute_node.text.split(',')
|
remove_values = attribute_node.text.split(",")
|
||||||
new_values = [x for x in old_values if x not in remove_values]
|
new_values = [x for x in old_values if x not in remove_values]
|
||||||
node.attrib[attribute_name] = ','.join(
|
node.attrib[attribute_name] = ",".join([_f for _f in new_values if _f])
|
||||||
[_f for _f in new_values if _f])
|
|
||||||
return source
|
return source
|
||||||
|
|
|
@ -29,5 +29,3 @@ to refer to some xmlid, say ``%(xmlid)s``.
|
||||||
**Move an element in the view**
|
**Move an element in the view**
|
||||||
|
|
||||||
This feature is now native, cf the `official Odoo documentation <https://www.odoo.com/documentation/12.0/reference/views.html#inheritance-specs>`_.
|
This feature is now native, cf the `official Odoo documentation <https://www.odoo.com/documentation/12.0/reference/views.html#inheritance-specs>`_.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,32 +1,29 @@
|
||||||
# Copyright 2016 Therp BV <http://therp.nl>
|
# Copyright 2016 Therp BV <http://therp.nl>
|
||||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
|
||||||
from odoo.tests.common import TransactionCase
|
from odoo.tests.common import TransactionCase
|
||||||
|
|
||||||
|
|
||||||
class TestBaseViewInheritanceExtension(TransactionCase):
|
class TestBaseViewInheritanceExtension(TransactionCase):
|
||||||
|
|
||||||
def test_base_view_inheritance_extension(self):
|
def test_base_view_inheritance_extension(self):
|
||||||
view_id = self.env.ref('base.view_partner_simple_form').id
|
view_id = self.env.ref("base.view_partner_simple_form").id
|
||||||
fields_view_get = self.env['res.partner'].fields_view_get(
|
fields_view_get = self.env["res.partner"].fields_view_get(view_id=view_id)
|
||||||
view_id=view_id
|
view = etree.fromstring(fields_view_get["arch"])
|
||||||
)
|
|
||||||
view = etree.fromstring(fields_view_get['arch'])
|
|
||||||
# verify normal attributes work
|
# verify normal attributes work
|
||||||
self.assertEqual(view.xpath('//form')[0].get('string'), 'Partner form')
|
self.assertEqual(view.xpath("//form")[0].get("string"), "Partner form")
|
||||||
# verify our extra context key worked
|
# verify our extra context key worked
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
'default_name' in
|
"default_name" in view.xpath('//field[@name="parent_id"]')[0].get("context")
|
||||||
view.xpath('//field[@name="parent_id"]')[0].get('context')
|
|
||||||
)
|
)
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
"context.get('company_id', context.get('company'))" in
|
"context.get('company_id', context.get('company'))"
|
||||||
view.xpath('//field[@name="parent_id"]')[0].get('context')
|
in view.xpath('//field[@name="parent_id"]')[0].get("context")
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_list_add(self):
|
def test_list_add(self):
|
||||||
view_model = self.env['ir.ui.view']
|
view_model = self.env["ir.ui.view"]
|
||||||
inherit_id = self.env.ref('base.view_partner_form').id
|
inherit_id = self.env.ref("base.view_partner_form").id
|
||||||
source = etree.fromstring(
|
source = etree.fromstring(
|
||||||
"""\
|
"""\
|
||||||
<form>
|
<form>
|
||||||
|
@ -45,15 +42,11 @@ class TestBaseViewInheritanceExtension(TransactionCase):
|
||||||
</button>
|
</button>
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
modified_source = \
|
modified_source = view_model.inheritance_handler_attributes_list_add(
|
||||||
view_model.inheritance_handler_attributes_list_add(
|
source, specs, inherit_id
|
||||||
source, specs, inherit_id
|
|
||||||
)
|
|
||||||
button_node = modified_source.xpath('//button[@name="test"]')[0]
|
|
||||||
self.assertEqual(
|
|
||||||
button_node.attrib['states'],
|
|
||||||
'draft,open,valid'
|
|
||||||
)
|
)
|
||||||
|
button_node = modified_source.xpath('//button[@name="test"]')[0]
|
||||||
|
self.assertEqual(button_node.attrib["states"], "draft,open,valid")
|
||||||
# extend with list of values
|
# extend with list of values
|
||||||
specs = etree.fromstring(
|
specs = etree.fromstring(
|
||||||
"""\
|
"""\
|
||||||
|
@ -65,19 +58,15 @@ class TestBaseViewInheritanceExtension(TransactionCase):
|
||||||
</button>
|
</button>
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
modified_source = \
|
modified_source = view_model.inheritance_handler_attributes_list_add(
|
||||||
view_model.inheritance_handler_attributes_list_add(
|
source, specs, inherit_id
|
||||||
source, specs, inherit_id
|
|
||||||
)
|
|
||||||
button_node = modified_source.xpath('//button[@name="test"]')[0]
|
|
||||||
self.assertEqual(
|
|
||||||
button_node.attrib['states'],
|
|
||||||
'draft,open,valid,payable,paid'
|
|
||||||
)
|
)
|
||||||
|
button_node = modified_source.xpath('//button[@name="test"]')[0]
|
||||||
|
self.assertEqual(button_node.attrib["states"], "draft,open,valid,payable,paid")
|
||||||
|
|
||||||
def test_list_remove(self):
|
def test_list_remove(self):
|
||||||
view_model = self.env['ir.ui.view']
|
view_model = self.env["ir.ui.view"]
|
||||||
inherit_id = self.env.ref('base.view_partner_form').id
|
inherit_id = self.env.ref("base.view_partner_form").id
|
||||||
source = etree.fromstring(
|
source = etree.fromstring(
|
||||||
"""\
|
"""\
|
||||||
<form>
|
<form>
|
||||||
|
@ -96,12 +85,8 @@ class TestBaseViewInheritanceExtension(TransactionCase):
|
||||||
</button>
|
</button>
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
modified_source = \
|
modified_source = view_model.inheritance_handler_attributes_list_remove(
|
||||||
view_model.inheritance_handler_attributes_list_remove(
|
source, specs, inherit_id
|
||||||
source, specs, inherit_id
|
|
||||||
)
|
|
||||||
button_node = modified_source.xpath('//button[@name="test"]')[0]
|
|
||||||
self.assertEqual(
|
|
||||||
button_node.attrib['states'],
|
|
||||||
'draft,valid,paid'
|
|
||||||
)
|
)
|
||||||
|
button_node = modified_source.xpath('//button[@name="test"]')[0]
|
||||||
|
self.assertEqual(button_node.attrib["states"], "draft,valid,paid")
|
||||||
|
|
Loading…
Reference in New Issue