From 2d2274aeede65a7da8cad8a4392293d87391836a Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Mon, 4 Aug 2014 11:45:11 +0200 Subject: [PATCH] [FIX] module loading: manual x2x fields can now refer to manual models The fix consists in this: when setting up models, ignore manual fields that refer to unknown models if all models have not been loaded yet. --- openerp/fields.py | 1 + openerp/models.py | 6 +++++- openerp/modules/loading.py | 5 +++-- openerp/modules/registry.py | 6 ++++-- openerp/osv/fields.py | 1 + 5 files changed, 14 insertions(+), 5 deletions(-) diff --git a/openerp/fields.py b/openerp/fields.py index 08270ae52f0..0aaddad4f6c 100644 --- a/openerp/fields.py +++ b/openerp/fields.py @@ -263,6 +263,7 @@ class Field(object): store = True # whether the field is stored in database index = False # whether the field is indexed in database + manual = False # whether the field is a custom field copyable = True # whether the field is copied over by BaseModel.copy() depends = () # collection of field dependencies recursive = False # whether self depends on itself diff --git a/openerp/models.py b/openerp/models.py index 29288abfe97..c199a7dab73 100644 --- a/openerp/models.py +++ b/openerp/models.py @@ -2956,9 +2956,13 @@ class BaseModel(object): field.reset() @api.model - def _setup_fields(self): + def _setup_fields(self, partial=False): """ Setup the fields (dependency triggers, etc). """ for field in self._fields.itervalues(): + if partial and field.manual and \ + field.relational and field.comodel_name not in self.pool: + # do not set up manual fields that refer to unknown models + continue field.setup(self.env) # group fields by compute to determine field.computed_fields diff --git a/openerp/modules/loading.py b/openerp/modules/loading.py index 656511e4a04..0568b0d1a38 100644 --- a/openerp/modules/loading.py +++ b/openerp/modules/loading.py @@ -159,7 +159,7 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, skip_modules= loaded_modules.append(package.name) if hasattr(package, 'init') or hasattr(package, 'update') or package.state in ('to install', 'to upgrade'): - registry.setup_models(cr) + registry.setup_models(cr, partial=True) init_module_models(cr, package.name, models) # Can't put this line out of the loop: ir.module.module will be @@ -225,7 +225,7 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, skip_modules= registry._init_modules.add(package.name) cr.commit() - registry.setup_models(cr) + registry.setup_models(cr, partial=True) _logger.log(25, "%s modules loaded in %.2fs, %s queries", len(graph), time.time() - t0, openerp.sql_db.sql_counter - t0_sql) @@ -360,6 +360,7 @@ def load_modules(db, force_demo=False, status=None, update_module=False): cr.execute('select model from ir_model where state=%s', ('manual',)) for model in cr.dictfetchall(): registry['ir.model'].instanciate(cr, SUPERUSER_ID, model['model'], {}) + registry.setup_models(cr) # STEP 4: Finish and cleanup installations if processed_modules: diff --git a/openerp/modules/registry.py b/openerp/modules/registry.py index 1d68e228b8f..c87d944bd7c 100644 --- a/openerp/modules/registry.py +++ b/openerp/modules/registry.py @@ -151,9 +151,11 @@ class Registry(Mapping): return [self.models[m] for m in models_to_load] - def setup_models(self, cr): + def setup_models(self, cr, partial=False): """ Complete the setup of models. This must be called after loading modules and before using the ORM. + + :param partial: ``True`` if all models have not been loaded yet. """ # prepare the setup on all models for model in self.models.itervalues(): @@ -162,7 +164,7 @@ class Registry(Mapping): # do the actual setup from a clean state self._m2m = {} for model in self.models.itervalues(): - model._setup_fields(cr, SUPERUSER_ID) + model._setup_fields(cr, SUPERUSER_ID, partial=partial) def clear_caches(self): """ Clear the caches diff --git a/openerp/osv/fields.py b/openerp/osv/fields.py index 07e8b02313c..e00204caf9e 100644 --- a/openerp/osv/fields.py +++ b/openerp/osv/fields.py @@ -134,6 +134,7 @@ class _column(object): ('_origin', self), # field interfaces self ('copy', self.copy), ('index', self.select), + ('manual', self.manual), ('string', self.string), ('help', self.help), ('readonly', self.readonly),