[FIX] registry: use a unique list of models to load per module
authorOlivier Dony <odo@openerp.com>
Fri, 26 Aug 2011 16:17:36 +0000 (18:17 +0200)
committerOlivier Dony <odo@openerp.com>
Fri, 26 Aug 2011 16:17:36 +0000 (18:17 +0200)
This is necessary to preserve the model loading order
as defined in the module. This was broken when the
metaclass was introduced to make the explicit model
constructor call optional.
One consequence is that the order in which the classes
are declared in the module really defines their
initialization order, even if the constructors are
later called explcitly in a different order.
This latter case should be fairly rare, and easy to
fix too - simply putting the class declaration in the
right order.

bzr revid: odo@openerp.com-20110826161736-lgnpurtbcqtbseey

openerp/modules/registry.py
openerp/osv/orm.py

index 11f484a..1cb31cd 100644 (file)
@@ -70,15 +70,10 @@ class Registry(object):
 
         res = []
 
-        # Instanciate classes registered through their constructor and
-        # add them to the pool.
-        for klass in openerp.osv.orm.module_class_list.get(module, []):
-            res.append(klass.createInstance(self, cr))
-
-        # Instanciate classes automatically discovered.
+        # Instantiate registered classes (via metamodel discovery or via explicit
+        # constructor call), and add them to the pool.
         for cls in openerp.osv.orm.MetaModel.module_to_models.get(module, []):
-            if cls not in openerp.osv.orm.module_class_list.get(module, []):
-                res.append(cls.createInstance(self, cr))
+            res.append(cls.createInstance(self, cr))
 
         return res
 
index d4a5d80..d328d54 100644 (file)
@@ -70,9 +70,6 @@ from openerp.tools import SKIPPED_ELEMENT_TYPES
 regex_order = re.compile('^(([a-z0-9_]+|"[a-z0-9_]+")( *desc| *asc)?( *, *|))+$', re.I)
 regex_object_name = re.compile(r'^[a-z0-9_.]+$')
 
-# Mapping between openerp module names and their osv classes.
-module_class_list = {}
-
 # Super-user identifier (aka Administrator aka root)
 ROOT_USER_ID = 1
 
@@ -806,23 +803,21 @@ class orm_template(object):
         return obj
 
     def __new__(cls):
-        """ Register this model.
+        """Register this model.
 
         This doesn't create an instance but simply register the model
         as being part of the module where it is defined.
-
-        TODO make it possible to not even have to call the constructor
-        to be registered.
-
         """
-
         # Set the module name (e.g. base, sale, accounting, ...) on the class.
         module = cls.__module__.split('.')[0]
         if not hasattr(cls, '_module'):
             cls._module = module
 
-        # Remember which models to instanciate for this module.
-        module_class_list.setdefault(cls._module, []).append(cls)
+        # Record this class in the list of models to instantiate for this module,
+        # managed by the metaclass.
+        module_model_list = MetaModel.module_to_models.setdefault(cls._module, [])
+        if cls not in module_model_list:
+            module_model_list.append(cls)
 
         # Since we don't return an instance here, the __init__
         # method won't be called.