diff options
| author | Christophe Simonis <chs@odoo.com> | 2019-03-06 10:59:32 +0100 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2019-03-06 10:59:32 +0100 |
| commit | afe013330295b5f069a0df8529d1f1f0d12f2b3f (patch) | |
| tree | e9e39304f0e797c0cd8b4314c173948e90181a90 /odoo | |
| parent | b5885f0cb02ba6853e17eb93009b1ebad2ff8d35 (diff) | |
| parent | 3e54704e669441e655b1fe19ee0fa0646cdbf8d5 (diff) | |
[MERGE] forward port branch saas-11.3 up to 3e54704e669
Diffstat (limited to 'odoo')
| -rw-r--r-- | odoo/addons/base/models/ir_model.py | 3 | ||||
| -rw-r--r-- | odoo/addons/base/models/ir_rule.py | 2 | ||||
| -rw-r--r-- | odoo/addons/base/models/qweb.py | 57 | ||||
| -rw-r--r-- | odoo/addons/base/tests/test_expression.py | 30 | ||||
| -rw-r--r-- | odoo/addons/base/tests/test_qweb.py | 41 | ||||
| -rw-r--r-- | odoo/addons/base/tests/test_views.py | 36 | ||||
| -rw-r--r-- | odoo/fields.py | 1 | ||||
| -rw-r--r-- | odoo/models.py | 1 | ||||
| -rw-r--r-- | odoo/osv/expression.py | 2 |
9 files changed, 151 insertions, 22 deletions
diff --git a/odoo/addons/base/models/ir_model.py b/odoo/addons/base/models/ir_model.py index 1bbf53794a6..4a59c5d4249 100644 --- a/odoo/addons/base/models/ir_model.py +++ b/odoo/addons/base/models/ir_model.py @@ -199,6 +199,9 @@ class IrModel(models.Model): # prevent screwing up fields that depend on these models' fields model.field_id._prepare_update() + # delete fields whose comodel is being removed + self.env['ir.model.fields'].search([('relation', 'in', self.mapped('model'))]).unlink() + self._drop_table() res = super(IrModel, self).unlink() diff --git a/odoo/addons/base/models/ir_rule.py b/odoo/addons/base/models/ir_rule.py index 90869ef45ac..9f63a415892 100644 --- a/odoo/addons/base/models/ir_rule.py +++ b/odoo/addons/base/models/ir_rule.py @@ -106,6 +106,8 @@ class IrRule(models.Model): group_domains.append(dom) # combine global domains and group domains + if not group_domains: + return expression.AND(global_domains) return expression.AND(global_domains + [expression.OR(group_domains)]) @api.model diff --git a/odoo/addons/base/models/qweb.py b/odoo/addons/base/models/qweb.py index 51693c55cb1..de5d3cf9e2b 100644 --- a/odoo/addons/base/models/qweb.py +++ b/odoo/addons/base/models/qweb.py @@ -31,6 +31,8 @@ try: except ImportError: astor = None +from odoo.tools.parse_version import parse_version + unsafe_eval = eval _logger = logging.getLogger(__name__) @@ -176,7 +178,7 @@ class QWebException(Exception): return str(self) # Avoid DeprecationWarning while still remaining compatible with werkzeug pre-0.9 -escape = (lambda text: _escape(text, quote=True)) if getattr(werkzeug, '__version__', '0.0') < '0.9.0' else _escape +escape = (lambda text: _escape(text, quote=True)) if parse_version(getattr(werkzeug, '__version__', '0.0')) < parse_version('0.9.0') else _escape def foreach_iterator(base_ctx, enum, name): ctx = base_ctx.copy() @@ -1486,7 +1488,7 @@ class QWeb(object): ) if call_options: - # update this dict with the content of `t-call-options` + # update this dict with the content of `t-call-options` content.extend([ # options_.update(template options) ast.Expr(ast.Call( @@ -1497,7 +1499,56 @@ class QWeb(object): ), args=[self._compile_expr(call_options)], keywords=[], starargs=None, kwargs=None - )) + )), + + # if options.get('lang') != options_.get('lang'): + # self = self.with_context(lang=options.get('lang')) + ast.If( + test=ast.Compare( + left=ast.Call( + func=ast.Attribute( + value=ast.Name(id='options', ctx=ast.Load()), + attr='get', + ctx=ast.Load() + ), + args=[ast.Str("lang")], keywords=[], + starargs=None, kwargs=None + ), + ops=[ast.NotEq()], + comparators=[ast.Call( + func=ast.Attribute( + value=ast.Name(id=name_options, ctx=ast.Load()), + attr='get', + ctx=ast.Load() + ), + args=[ast.Str("lang")], keywords=[], + starargs=None, kwargs=None + )] + ), + body=[ + ast.Assign( + targets=[ast.Name(id='self', ctx=ast.Store())], + value=ast.Call( + func=ast.Attribute( + value=ast.Name(id='self', ctx=ast.Load()), + attr='with_context', + ctx=ast.Load() + ), + args=[], + keywords=[ast.keyword('lang', ast.Call( + func=ast.Attribute( + value=ast.Name(id=name_options, ctx=ast.Load()), + attr='get', + ctx=ast.Load() + ), + args=[ast.Str("lang")], keywords=[], + starargs=None, kwargs=None + ))], + starargs=None, kwargs=None + ) + )], + orelse=[], + ) ]) if nsmap: diff --git a/odoo/addons/base/tests/test_expression.py b/odoo/addons/base/tests/test_expression.py index 9f628054f02..b40035dadd6 100644 --- a/odoo/addons/base/tests/test_expression.py +++ b/odoo/addons/base/tests/test_expression.py @@ -640,6 +640,36 @@ class TestExpression(TransactionCase): '&', ('foo', '=', 2), ('bar', '=', 2)] self.assertEqual(expression.OR([d1, d2]), expected) + def test_proper_combine_unit_leaves(self): + # test that unit leaves (TRUE_LEAF, FALSE_LEAF) are properly handled in specific cases + false = expression.FALSE_DOMAIN + true = expression.TRUE_DOMAIN + normal = [('foo', '=', 'bar')] + # OR with single FALSE_LEAF + expr = expression.OR([false]) + self.assertEqual(expr, false) + # OR with multiple FALSE_LEAF + expr = expression.OR([false, false]) + self.assertEqual(expr, false) + # OR with FALSE_LEAF and a normal leaf + expr = expression.OR([false, normal]) + self.assertEqual(expr, normal) + # OR with AND of single TRUE_LEAF and normal leaf + expr = expression.OR([expression.AND([true]), normal]) + self.assertEqual(expr, true) + # AND with single TRUE_LEAF + expr = expression.AND([true]) + self.assertEqual(expr, true) + # AND with multiple TRUE_LEAF + expr = expression.AND([true, true]) + self.assertEqual(expr, true) + # AND with TRUE_LEAF and normal leaves + expr = expression.AND([true, normal]) + self.assertEqual(expr, normal) + # AND with OR with single FALSE_LEAF and normal leaf + expr = expression.AND([expression.OR([false]), normal]) + self.assertEqual(expr, false) + class TestAutoJoin(TransactionCase): diff --git a/odoo/addons/base/tests/test_qweb.py b/odoo/addons/base/tests/test_qweb.py index 2a01fa1ca44..d8ce5e48f68 100644 --- a/odoo/addons/base/tests/test_qweb.py +++ b/odoo/addons/base/tests/test_qweb.py @@ -501,6 +501,47 @@ class TestQWebNS(TransactionCase): with self.assertRaises(QWebException, msg=error_msg): view1.render() + def test_render_t_call_propagates_t_lang(self): + current_lang = 'en_US' + other_lang = 'fr_FR' + + self.env['res.lang'].load_lang(lang=other_lang) + + self.env['res.lang'].search([('code', '=', other_lang)], limit=1).write({ + 'active': True, + 'decimal_point': '*', + 'thousands_sep': '/' + }) + + view1 = self.env['ir.ui.view'].create({ + 'name': "callee", + 'type': 'qweb', + 'arch': u""" + <t t-name="base.callee"> + <t t-esc="9000000.00" t-options="{'widget': 'float', 'precision': 2}" /> + </t> + """ + }) + self.env['ir.model.data'].create({ + 'name': 'callee', + 'model': 'ir.ui.view', + 'module': 'base', + 'res_id': view1.id, + }) + + view2 = self.env['ir.ui.view'].create({ + 'name': "calling", + 'type': 'qweb', + 'arch': u""" + <t t-name="base.calling"> + <t t-call="base.callee" t-lang="'%s'" /> + </t> + """ % other_lang + }) + + rendered = view2.with_context(lang=current_lang).render().strip() + self.assertEqual(rendered, b'9/000/000*00') + from copy import deepcopy class FileSystemLoader(object): diff --git a/odoo/addons/base/tests/test_views.py b/odoo/addons/base/tests/test_views.py index 7b8deb8ea33..33ac7035488 100644 --- a/odoo/addons/base/tests/test_views.py +++ b/odoo/addons/base/tests/test_views.py @@ -1107,7 +1107,7 @@ class TestViews(ViewCase): # implemeted elsewhere... modifiers_tests() - @mute_logger('odoo.addons.base.models.ir_ui_view') + @mute_logger('odoo.addons.base.models.ir_ui_view', 'odoo.models') def test_invalid_field(self): with self.assertRaises(ValidationError): self.View.create({ @@ -1121,7 +1121,7 @@ class TestViews(ViewCase): """, }) - @mute_logger('odoo.addons.base.models.ir_ui_view') + @mute_logger('odoo.addons.base.models.ir_ui_view', 'odoo.models') def test_invalid_subfield(self): with self.assertRaises(ValidationError): self.View.create({ @@ -1140,7 +1140,7 @@ class TestViews(ViewCase): """, }) - @mute_logger('odoo.addons.base.models.ir_ui_view') + @mute_logger('odoo.addons.base.models.ir_ui_view', 'odoo.models') def test_context_in_view(self): arch = """ <form string="View"> @@ -1160,7 +1160,7 @@ class TestViews(ViewCase): 'arch': arch % '', }) - @mute_logger('odoo.addons.base.models.ir_ui_view') + @mute_logger('odoo.addons.base.models.ir_ui_view', 'odoo.models') def test_context_in_subview(self): arch = """ <form string="View"> @@ -1192,7 +1192,7 @@ class TestViews(ViewCase): 'arch': arch % ('<field name="model"/>', ''), }) - @mute_logger('odoo.addons.base.models.ir_ui_view') + @mute_logger('odoo.addons.base.models.ir_ui_view', 'odoo.models') def test_context_in_subview_with_parent(self): arch = """ <form string="View"> @@ -1223,7 +1223,7 @@ class TestViews(ViewCase): 'arch': arch % ('', '<field name="model"/>'), }) - @mute_logger('odoo.addons.base.models.ir_ui_view') + @mute_logger('odoo.addons.base.models.ir_ui_view', 'odoo.models') def test_context_in_subsubview_with_parent(self): arch = """ <form string="View"> @@ -1265,7 +1265,7 @@ class TestViews(ViewCase): 'arch': arch % ('', '', '<field name="model"/>'), }) - @mute_logger('odoo.addons.base.models.ir_ui_view') + @mute_logger('odoo.addons.base.models.ir_ui_view', 'odoo.models') def test_domain_in_view(self): arch = """ <form string="View"> @@ -1285,7 +1285,7 @@ class TestViews(ViewCase): 'arch': arch % '', }) - @mute_logger('odoo.addons.base.models.ir_ui_view') + @mute_logger('odoo.addons.base.models.ir_ui_view', 'odoo.models') def test_domain_in_subview(self): arch = """ <form string="View"> @@ -1316,7 +1316,7 @@ class TestViews(ViewCase): 'arch': arch % ('<field name="model"/>', ''), }) - @mute_logger('odoo.addons.base.models.ir_ui_view') + @mute_logger('odoo.addons.base.models.ir_ui_view', 'odoo.models') def test_domain_in_subview_with_parent(self): arch = """ <form string="View"> @@ -1347,7 +1347,7 @@ class TestViews(ViewCase): 'arch': arch % ('', '<field name="model"/>'), }) - @mute_logger('odoo.addons.base.models.ir_ui_view') + @mute_logger('odoo.addons.base.models.ir_ui_view', 'odoo.models') def test_domain_on_field_in_view(self): field = self.env['ir.ui.view']._fields['inherit_id'] self.patch(field, 'domain', "[('model', '=', model)]") @@ -1370,7 +1370,7 @@ class TestViews(ViewCase): 'arch': arch % '', }) - @mute_logger('odoo.addons.base.ir.ir_ui_view') + @mute_logger('odoo.addons.base.ir.ir_ui_view', 'odoo.models') def test_domain_on_field_in_subview(self): field = self.env['ir.ui.view']._fields['inherit_id'] self.patch(field, 'domain', "[('model', '=', model)]") @@ -1404,7 +1404,7 @@ class TestViews(ViewCase): 'arch': arch % ('<field name="model"/>', ''), }) - @mute_logger('odoo.addons.base.ir.ir_ui_view') + @mute_logger('odoo.addons.base.ir.ir_ui_view', 'odoo.models') def test_domain_on_field_in_subview_with_parent(self): field = self.env['ir.ui.view']._fields['inherit_id'] self.patch(field, 'domain', "[('model', '=', parent.model)]") @@ -1438,7 +1438,7 @@ class TestViews(ViewCase): 'arch': arch % ('', '<field name="model"/>'), }) - @mute_logger('odoo.addons.base.ir.ir_ui_view') + @mute_logger('odoo.addons.base.ir.ir_ui_view', 'odoo.models') def test_domain_on_field_in_noneditable_subview(self): field = self.env['ir.ui.view']._fields['inherit_id'] self.patch(field, 'domain', "[('model', '=', model)]") @@ -1466,7 +1466,7 @@ class TestViews(ViewCase): 'arch': arch % ' editable="bottom"', }) - @mute_logger('odoo.addons.base.ir.ir_ui_view') + @mute_logger('odoo.addons.base.ir.ir_ui_view', 'odoo.models') def test_domain_on_readonly_field_in_view(self): field = self.env['ir.ui.view']._fields['inherit_id'] self.patch(field, 'domain', "[('model', '=', model)]") @@ -1496,7 +1496,7 @@ class TestViews(ViewCase): 'arch': arch, }) - @mute_logger('odoo.addons.base.ir.ir_ui_view') + @mute_logger('odoo.addons.base.ir.ir_ui_view', 'odoo.models') def test_domain_on_readonly_field_in_subview(self): field = self.env['ir.ui.view']._fields['inherit_id'] self.patch(field, 'domain', "[('model', '=', model)]") @@ -1524,7 +1524,7 @@ class TestViews(ViewCase): 'arch': arch % '', }) - @mute_logger('odoo.addons.base.ir.ir_ui_view') + @mute_logger('odoo.addons.base.ir.ir_ui_view', 'odoo.models') def test_attrs_field(self): arch = """ <form string="View"> @@ -1545,7 +1545,7 @@ class TestViews(ViewCase): 'arch': arch % '', }) - @mute_logger('odoo.addons.base.models.ir_ui_view') + @mute_logger('odoo.addons.base.models.ir_ui_view', 'odoo.models') def test_attrs_subfield(self): arch = """ <form string="View"> @@ -1577,7 +1577,7 @@ class TestViews(ViewCase): 'arch': arch % ('<field name="model"/>', ''), }) - @mute_logger('odoo.addons.base.models.ir_ui_view') + @mute_logger('odoo.addons.base.models.ir_ui_view', 'odoo.models') def test_attrs_subfield_with_parent(self): arch = """ <form string="View"> diff --git a/odoo/fields.py b/odoo/fields.py index 1efc86de888..b02564dd908 100644 --- a/odoo/fields.py +++ b/odoo/fields.py @@ -161,6 +161,7 @@ class Field(MetaField('DummyField', (object,), {})): :param compute_sudo: whether the field should be recomputed as superuser to bypass access rights (boolean, by default ``False``) + Note that this has no effects on non-stored computed fields The methods given for ``compute``, ``inverse`` and ``search`` are model methods. Their signature is shown in the following example:: diff --git a/odoo/models.py b/odoo/models.py index e49f98ee0d8..439b8423f09 100644 --- a/odoo/models.py +++ b/odoo/models.py @@ -1109,6 +1109,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})): except ValidationError as e: raise except Exception as e: + _logger.exception('Exception while validating constraint') raise ValidationError("%s\n\n%s" % (_("Error while validating constraint"), tools.ustr(e))) @api.model diff --git a/odoo/osv/expression.py b/odoo/osv/expression.py index f5518fead94..170c2b971e8 100644 --- a/odoo/osv/expression.py +++ b/odoo/osv/expression.py @@ -262,7 +262,7 @@ def combine(operator, unit, zero, domains): result += normalize_domain(domain) count += 1 result = [operator] * (count - 1) + result - return result + return result or unit def AND(domains): |
