From 59c59cd8a04af18cedd5005222de6744a215d903 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Thu, 4 Jan 2018 14:22:17 +0000 Subject: [PATCH 1/2] [FIX] field: compute transitive dependencies over non-stored fields In other words, when a field F depends on a non-stored field G, it also depends on G's dependencies. This guarantees that whenever a dependency of G is modified, F will be invalidated and marked to recompute (if necessary). The transitive closure of dependencies is not computed over stored fields. Anyway stored fields already trigger the recomputation of their dependent fields during their recomputation. The performance impact on the loading of a registry is negligible (less than 1%), and the increase of recomputation triggers is small (less than 10%). (cherry picked from commit 3fbd86bcbe6dffe923e10d4690ee302c6a779f90) opw-2033493 closes odoo/odoo#35636 Signed-off-by: Raphael Collet (rco) --- odoo/addons/test_new_api/ir.model.access.csv | 1 + odoo/addons/test_new_api/models.py | 18 ++++++++++++++++++ .../test_new_api/tests/test_new_fields.py | 5 +++++ odoo/fields.py | 12 ++++++++---- 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/odoo/addons/test_new_api/ir.model.access.csv b/odoo/addons/test_new_api/ir.model.access.csv index 4e136481512..b250877ada3 100644 --- a/odoo/addons/test_new_api/ir.model.access.csv +++ b/odoo/addons/test_new_api/ir.model.access.csv @@ -18,3 +18,4 @@ access_test_new_api_company_attr,access_test_new_api_company_attr,model_test_new access_test_new_api_sparse,access_test_new_api_sparse,model_test_new_api_sparse,,1,1,1,1 access_test_new_api_compute_inverse,access_test_new_api_compute_inverse,model_test_new_api_compute_inverse,,1,1,1,1 access_test_new_api_recursive,access_test_new_api_recursive,model_test_new_api_recursive,,1,1,1,1 +access_test_new_api_cascade,access_test_new_api_cascade,model_test_new_api_cascade,,1,1,1,1 diff --git a/odoo/addons/test_new_api/models.py b/odoo/addons/test_new_api/models.py index 5dccb48be43..2d79760631f 100644 --- a/odoo/addons/test_new_api/models.py +++ b/odoo/addons/test_new_api/models.py @@ -376,3 +376,21 @@ class ComputeRecursive(models.Model): rec.display_name = rec.parent.display_name + " / " + rec.name else: rec.display_name = rec.name + + +class ComputeCascade(models.Model): + _name = 'test_new_api.cascade' + + foo = fields.Char() + bar = fields.Char(compute='_compute_bar') # depends on foo + baz = fields.Char(compute='_compute_baz', store=True) # depends on bar + + @api.depends('foo') + def _compute_bar(self): + for record in self: + record.bar = "[%s]" % (record.foo or "") + + @api.depends('bar') + def _compute_baz(self): + for record in self: + record.baz = "<%s>" % (record.bar or "") diff --git a/odoo/addons/test_new_api/tests/test_new_fields.py b/odoo/addons/test_new_api/tests/test_new_fields.py index 2755612db53..5e9726a5cd9 100644 --- a/odoo/addons/test_new_api/tests/test_new_fields.py +++ b/odoo/addons/test_new_api/tests/test_new_fields.py @@ -223,6 +223,11 @@ class TestFields(common.TransactionCase): double_size = message.double_size self.assertEqual(double_size, message.size) + record = self.env['test_new_api.cascade'].create({'foo': "Hi"}) + self.assertEqual(record.baz, "<[Hi]>") + record.foo = "Ho" + self.assertEqual(record.baz, "<[Ho]>") + def test_13_inverse(self): """ test inverse computation of fields """ Category = self.env['test_new_api.category'] diff --git a/odoo/fields.py b/odoo/fields.py index 4eea1021e9e..0396ec45446 100644 --- a/odoo/fields.py +++ b/odoo/fields.py @@ -721,7 +721,7 @@ class Field(object): # on ``path``. See method ``modified`` below for details. # - def resolve_deps(self, model): + def resolve_deps(self, model, path0=[], seen=frozenset()): """ Return the dependencies of ``self`` as tuples ``(model, field, path)``, where ``path`` is an optional list of field names. """ @@ -732,11 +732,12 @@ class Field(object): for dotnames in self.depends: if dotnames == self.name: _logger.warning("Field %s depends on itself; please fix its decorator @api.depends().", self) - model, path = model0, dotnames.split('.') - for i, fname in enumerate(path): + model, path = model0, path0 + for fname in dotnames.split('.'): field = model._fields[fname] - result.append((model, field, path[:i])) + result.append((model, field, path)) model = model0.env.get(field.comodel_name) + path = None if path is None else path + [fname] # add self's model dependencies for mname, fnames in model0._depends.iteritems(): @@ -746,11 +747,14 @@ class Field(object): result.append((model, field, None)) # add indirect dependencies from the dependencies found above + seen = seen.union([self]) for model, field, path in list(result): for inv_field in model._field_inverses[field]: inv_model = model0.env[inv_field.model_name] inv_path = None if path is None else path + [field.name] result.append((inv_model, inv_field, inv_path)) + if not field.store and field not in seen: + result += field.resolve_deps(model, path, seen) return result From 2fc46a064d36d9de2c6debf9582976f938e3568b Mon Sep 17 00:00:00 2001 From: Abridbus Date: Tue, 13 Aug 2019 09:00:35 +0000 Subject: [PATCH 2/2] [FIX] mail: removing whitespace on message_id from incoming mail Because of a whitespace character present at the beginning of the message_id of some mails, they were fetched twice. From the SQL side, we see that Outlook is formatting the header following the RFC822 by allowing the header to look like: Header: From RFC822: "Each header field can be viewed as a single, logical line of ASCII characters. For convenience, the field-body portion of this conceptual entity can be split into a multiple-line representation" (abr.) It was also possible to find out by checking the logs. One or two whitespace(s) can be seen before the hash of the msg_id. The following commit is making sure we use and save the message_id without the whitespace by stripping them off on the coming mail. OPW-2006806 Applying CHS solution to avoid crash on empty header. closes odoo/odoo#35682 Signed-off-by: bve-odoo --- addons/mail/models/mail_thread.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py index 9de945ece86..25c01b723d9 100644 --- a/addons/mail/models/mail_thread.py +++ b/addons/mail/models/mail_thread.py @@ -1500,7 +1500,7 @@ class MailThread(models.AbstractModel): # Very unusual situation, be we should be fault-tolerant here message_id = "<%s@localhost>" % time.time() _logger.debug('Parsing Message without message-id, generating a random one: %s', message_id) - msg_dict['message_id'] = message_id + msg_dict['message_id'] = message_id.strip() if message.get('Subject'): msg_dict['subject'] = tools.decode_smtp_header(message.get('Subject'))