-
- Downloads
[FIX] core: maximum recursion because of `active` fields.
In specific situation, unlink can lead to raise a `RecursionError`: - The model `A` has a many2one `b_id` field toward a model `B`. This field is set with `ondelete='cascade'`. - The model `A` has one **store** related field **no-sudo** named `a_related` (`related='b_id.b_other_field`). - With `ir.rule` on model `A` with a domain containing `a_related` You have one record B `b_1` with 20 records A linked to it (`a_1, ..., a_20`). When you try to unlink `b_1`: Stack: File "...", line 543, in ... b_1.unlink() File "/home/odoo/Documents/dev/odoo/odoo/models.py", line 3594, in unlink self.env.flush_all() => At this point, `a_1, ..., a_20` have already been deleted from the database because of the 'cascade' deletion. But the ORM doesn't have any information about this, and `a_related` (for `a_1, ..., a_20`) are flagged to be recomputed (because it depends on `b_id.b_other_field`) File "/home/odoo/Documents/dev/odoo/odoo/api.py", line 732, in flush_all self._recompute_all() File "/home/odoo/Documents/dev/odoo/odoo/api.py", line 728, in _recompute_all self[field.model_name]._recompute_field(field) File "/home/odoo/Documents/dev/odoo/odoo/models.py", line 6165, in _recompute_field field.recompute(records) File "/home/odoo/Documents/dev/odoo/odoo/fields.py", line 1348, in recompute self.compute_value(record) => `self.compute_value(recs)` raised a `MissingError` before recalling `compute_value` with only the first `record` (but others are still in the prefetch) File "/home/odoo/Documents/dev/odoo/odoo/fields.py", line 1368, in compute_value records._compute_field_value(self) => `a_related` of `record` is removed from to_compute, but only the first record, not the rest of the records present in the prefetch set. File "/home/odoo/Documents/dev/odoo/odoo/models.py", line 4194, in _compute_field_value fields.determine(field.compute, self) File "/home/odoo/Documents/dev/odoo/odoo/fields.py", line 100, in determine return needle(records, *args) File "/home/odoo/Documents/dev/odoo/odoo/fields.py", line 689, in _compute_related values = [first(value[name]) for value in values] File "/home/odoo/Documents/dev/odoo/odoo/fields.py", line 689, in <listcomp> values = [first(value[name]) for value in values] File "/home/odoo/Documents/dev/odoo/odoo/models.py", line 5860, in __getitem__ return self._fields[key].__get__(self, type(self)) File "/home/odoo/Documents/dev/odoo/odoo/fields.py", line 2772, in __get__ return super().__get__(records, owner) File "/home/odoo/Documents/dev/odoo/odoo/fields.py", line 1186, in __get__ recs._fetch_field(self) File "/home/odoo/Documents/dev/odoo/odoo/models.py", line 3162, in _fetch_field self._read(fnames) => `_read` tries to read the first record + others from the prefetch set File "/home/odoo/Documents/dev/odoo/odoo/models.py", line 3215, in _read self.with_context(active_test=False)._flush_search([], order='id') File "/home/odoo/Documents/dev/odoo/odoo/models.py", line 4607, in _flush_search self.env[model_name].flush_model(field_names) File "/home/odoo/Documents/dev/odoo/odoo/models.py", line 5560, in flush_model self._recompute_model(fnames) File "/home/odoo/Documents/dev/odoo/odoo/models.py", line 6134, in _recompute_model self._recompute_field(field) => This is where the recursion starts, record compute will move forward one by one. But sadly, the stack grows very fast, and with only a few (already deleted) records to recompute, the issue will be generated. File "/home/odoo/Documents/dev/odoo/odoo/models.py", line 6165, in _recompute_field field.recompute(records) File "/home/odoo/Documents/dev/odoo/odoo/fields.py", line 1348, in recompute self.compute_value(record) File "/home/odoo/Documents/dev/odoo/odoo/fields.py", line 1368, in compute_value records._compute_field_value(self) File "/home/odoo/Documents/dev/odoo/odoo/models.py", line 4194, in _compute_field_value fields.determine(field.compute, self) File "/home/odoo/Documents/dev/odoo/odoo/fields.py", line 100, in determine return needle(records, *args) File "/home/odoo/Documents/dev/odoo/odoo/fields.py", line 689, in _compute_related values = [first(value[name]) for value in values] File "/home/odoo/Documents/dev/odoo/odoo/fields.py", line 689, in <listcomp> values = [first(value[name]) for value in values] File "/home/odoo/Documents/dev/odoo/odoo/models.py", line 5860, in __getitem__ return self._fields[key].__get__(self, type(self)) File "/home/odoo/Documents/dev/odoo/odoo/fields.py", line 2772, in __get__ return super().__get__(records, owner) File "/home/odoo/Documents/dev/odoo/odoo/fields.py", line 1186, in __get__ recs._fetch_field(self) File "/home/odoo/Documents/dev/odoo/odoo/models.py", line 3162, in _fetch_field self._read(fnames) File "/home/odoo/Documents/dev/odoo/odoo/models.py", line 3215, in _read self.with_context(active_test=False)._flush_search([], order='id') File "/home/odoo/Documents/dev/odoo/odoo/models.py", line 4607, in _flush_search self.env[model_name].flush_model(field_names) File "/home/odoo/Documents/dev/odoo/odoo/models.py", line 5560, in flush_model self._recompute_model(fnames) File "/home/odoo/Documents/dev/odoo/odoo/models.py", line 6134, in _recompute_model self._recompute_field(field) How to fix it: Move the logic of the MissingError of `_recompute_field` inside the `recompute` directly. Part-of: odoo/odoo#121355
Showing
- addons/product/tests/test_product_pricelist.py 13 additions, 0 deletionsaddons/product/tests/test_product_pricelist.py
- odoo/addons/test_new_api/models/test_new_api.py 2 additions, 0 deletionsodoo/addons/test_new_api/models/test_new_api.py
- odoo/addons/test_new_api/tests/test_new_fields.py 32 additions, 0 deletionsodoo/addons/test_new_api/tests/test_new_fields.py
- odoo/addons/test_new_api/tests/test_properties.py 1 addition, 1 deletionodoo/addons/test_new_api/tests/test_properties.py
- odoo/fields.py 24 additions, 5 deletionsodoo/fields.py
- odoo/models.py 1 addition, 10 deletionsodoo/models.py
Loading
Please register or sign in to comment