[IMP] core: group all field_inverses dicts on registry

This makes the union of many dicts into a single dict.

On a registry with 296 modules, this saves 300 kilobytes of memory,
which is about 3% of the registry's memory footprint.
This commit is contained in:
Raphael Collet
2021-05-10 14:29:43 +00:00
parent e2c4167826
commit 4fb958d086
4 changed files with 29 additions and 27 deletions
+1 -1
View File
@@ -756,7 +756,7 @@ class IrModelFields(models.Model):
for dep in model._dependent_fields(field):
if dep.manual:
failed_dependencies.append((field, dep))
for inverse in model._field_inverses.get(field, ()):
for inverse in model.pool.field_inverses[field]:
if inverse.manual and inverse.type == 'one2many':
failed_dependencies.append((field, inverse))
+15 -15
View File
@@ -721,7 +721,7 @@ class Field(MetaField('DummyField', (object,), {})):
yield tuple(field_seq)
if field.type in ('one2many', 'many2many'):
for inv_field in Model._field_inverses[field]:
for inv_field in Model.pool.field_inverses[field]:
yield tuple(field_seq) + (inv_field,)
model_name = field.comodel_name
@@ -2846,7 +2846,7 @@ class Many2one(_Relational):
# align(id) returns a NewId if records are new, a real id otherwise
align = (lambda id_: id_) if all(record_ids) else (lambda id_: id_ and NewId(id_))
for invf in records._field_inverses[self]:
for invf in records.pool.field_inverses[self]:
corecords = records.env[self.comodel_name].browse(
align(id_) for id_ in cache.get_values(records, self)
)
@@ -2862,7 +2862,7 @@ class Many2one(_Relational):
return
cache = records.env.cache
corecord = self.convert_to_record(value, records)
for invf in records._field_inverses[self]:
for invf in records.pool.field_inverses[self]:
valid_records = records.filtered_domain(invf.get_domain_list(corecord))
if not valid_records:
continue
@@ -2905,7 +2905,7 @@ class Many2oneReference(Integer):
record_ids = set(records._ids)
model_ids = self._record_ids_per_res_model(records)
for invf in records._field_inverses[self]:
for invf in records.pool.field_inverses[self]:
records = records.browse(model_ids[invf.model_name])
if not records:
continue
@@ -2925,7 +2925,7 @@ class Many2oneReference(Integer):
cache = records.env.cache
model_ids = self._record_ids_per_res_model(records)
for invf in records._field_inverses[self]:
for invf in records.pool.field_inverses[self]:
records = records.browse(model_ids[invf.model_name])
if not records:
continue
@@ -3198,7 +3198,7 @@ class _RelationalMulti(_Relational):
return val._origin if isinstance(val, BaseModel) else val
# make result with new and existing records
inv_names = {field.name for field in record._field_inverses[self]}
inv_names = {field.name for field in record.pool.field_inverses[self]}
result = [Command.set([])]
for record in value:
origin = record._origin
@@ -3332,8 +3332,8 @@ class One2many(_RelationalMulti):
if isinstance(invf, (Many2one, Many2oneReference)):
# setting one2many fields only invalidates many2one inverses;
# integer inverses (res_model/res_id pairs) are not supported
model._field_inverses.add(self, invf)
comodel._field_inverses.add(invf, self)
model.pool.field_inverses.add(self, invf)
comodel.pool.field_inverses.add(invf, self)
_description_relation_field = property(attrgetter('inverse_name'))
@@ -3679,10 +3679,10 @@ class Many2many(_RelationalMulti):
raise TypeError(msg % (self, field))
fields.append(self)
# retrieve inverse fields, and link them in _field_inverses
# retrieve inverse fields, and link them in field_inverses
for field in m2m[(self.relation, self.column2, self.column1)]:
model._field_inverses.add(self, field)
model.env[field.model_name]._field_inverses.add(field, self)
model.pool.field_inverses.add(self, field)
model.pool.field_inverses.add(field, self)
def update_db(self, model, columns):
cr = model._cr
@@ -3854,7 +3854,7 @@ class Many2many(_RelationalMulti):
y_to_xs = defaultdict(set)
for x, y in pairs:
y_to_xs[y].add(x)
for invf in records._field_inverses[self]:
for invf in records.pool.field_inverses[self]:
domain = invf.get_domain_list(comodel)
valid_ids = set(records.filtered_domain(domain)._ids)
if not valid_ids:
@@ -3892,7 +3892,7 @@ class Many2many(_RelationalMulti):
cr.execute(query, params)
# update the cache of inverse fields
for invf in records._field_inverses[self]:
for invf in records.pool.field_inverses[self]:
for y, xs in y_to_xs.items():
corecord = comodel.browse(y)
try:
@@ -3968,7 +3968,7 @@ class Many2many(_RelationalMulti):
y_to_xs = defaultdict(set)
for x, y in pairs:
y_to_xs[y].add(x)
for invf in records._field_inverses[self]:
for invf in records.pool.field_inverses[self]:
domain = invf.get_domain_list(comodel)
valid_ids = set(records.filtered_domain(domain)._ids)
if not valid_ids:
@@ -3989,7 +3989,7 @@ class Many2many(_RelationalMulti):
y_to_xs = defaultdict(set)
for x, y in pairs:
y_to_xs[y].add(x)
for invf in records._field_inverses[self]:
for invf in records.pool.field_inverses[self]:
for y, xs in y_to_xs.items():
corecord = comodel.browse([y])
try:
+5 -7
View File
@@ -2898,8 +2898,6 @@ class BaseModel(metaclass=MetaModel):
self._add_inherited_fields()
# 4. initialize more field metadata
cls._field_inverses = Collector() # inverse fields for related fields
cls._setup_done = True
for field in cls._fields.values():
@@ -3690,7 +3688,7 @@ Fields:
# DLE P150: `test_cancel_propagation`, `test_manufacturing_3_steps`, `test_manufacturing_flow`
# TODO: check whether still necessary
records_to_inverse[field] = self.filtered('id')
if field.relational or self._field_inverses[field]:
if field.relational or self.pool.field_inverses[field]:
relational_names.append(fname)
if field.inverse or (field.compute and not field.readonly):
if field.store or field.type not in ('one2many', 'many2many'):
@@ -4079,7 +4077,7 @@ Fields:
else:
cache_value = field.convert_to_cache(value, record)
self.env.cache.set(record, field, cache_value)
if field.type in ('many2one', 'many2one_reference') and record._field_inverses[field]:
if field.type in ('many2one', 'many2one_reference') and self.pool.field_inverses[field]:
inverses_update[(field, cache_value)].append(record.id)
for (field, value), record_ids in inverses_update.items():
@@ -5230,7 +5228,7 @@ Fields:
inv_recs = self[field.name].filtered(lambda r: not r.id)
if not inv_recs:
continue
for invf in self._field_inverses[field]:
for invf in self.pool.field_inverses[field]:
# DLE P98: `test_40_new_fields`
# /home/dle/src/odoo/master-nochange-fp/odoo/addons/test_new_api/tests/test_new_fields.py
# Be careful to not break `test_onchange_taxes_1`, `test_onchange_taxes_2`, `test_onchange_taxes_3`
@@ -5813,7 +5811,7 @@ Fields:
# invalidate fields and inverse fields, too
spec = [(f, ids) for f in fields] + \
[(invf, None) for f in fields for invf in self._field_inverses[f]]
[(invf, None) for f in fields for invf in self.pool.field_inverses[f]]
self.env.cache.invalidate(spec)
def modified(self, fnames, create=False, before=False):
@@ -5914,7 +5912,7 @@ Fields:
else:
# val is another tree of dependencies
model = self.env[key.model_name]
for invf in model._field_inverses[key]:
for invf in model.pool.field_inverses[key]:
# use an inverse of field without domain
if not (invf.type in ('one2many', 'many2many') and invf.domain):
if invf.type == 'many2one_reference':
+8 -4
View File
@@ -135,6 +135,7 @@ class Registry(Mapping):
# field dependencies
self.field_depends = Collector()
self.field_depends_context = Collector()
self.field_inverses = Collector()
# Inter-process signaling:
# The `base_registry_signaling` sequence indicates the whole registry
@@ -271,20 +272,23 @@ class Registry(Mapping):
for model in models:
model._prepare_setup()
# do the actual setup from a clean state
self._m2m = defaultdict(list)
self.field_depends.clear()
self.field_depends_context.clear()
self.field_inverses.clear()
# do the actual setup
for model in models:
model._setup_base()
self._m2m = defaultdict(list)
for model in models:
model._setup_fields()
del self._m2m
for model in models:
model._setup_complete()
# determine field_depends and field_depends_context
self.field_depends.clear()
self.field_depends_context.clear()
for model in models:
for field in model._fields.values():
depends, depends_context = field.get_depends(model)