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 ad7092159a4..bd4fce872d1 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 6b41bbec108..7d129bfa44b 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 7dad4cf0f54..c9b3a414df1 100644 --- a/odoo/fields.py +++ b/odoo/fields.py @@ -724,7 +724,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. """ @@ -735,11 +735,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(): @@ -749,11 +750,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