[FIX] registry: use a unique list of models to load per module
[odoo/odoo.git] / openerp / modules / registry.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU Affero General Public License as
9 #    published by the Free Software Foundation, either version 3 of the
10 #    License, or (at your option) any later version.
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU Affero General Public License for more details.
16 #
17 #    You should have received a copy of the GNU Affero General Public License
18 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 #
20 ##############################################################################
21
22 """ Models registries.
23
24 """
25
26 import openerp.sql_db
27 import openerp.osv.orm
28
29
30 class Registry(object):
31     """ Model registry for a particular database.
32
33     The registry is essentially a mapping between model names and model
34     instances. There is one registry instance per database.
35
36     """
37
38     def __init__(self, db_name):
39         self.models = {} # model name/model instance mapping
40         self._sql_error = {}
41         self._store_function = {}
42         self._init = True
43         self._init_parent = {}
44         self.db_name = db_name
45         self.db = openerp.sql_db.db_connect(db_name)
46
47     def do_parent_store(self, cr):
48         for o in self._init_parent:
49             self.get(o)._parent_store_compute(cr)
50         self._init = False
51
52     def obj_list(self):
53         """ Return the list of model names in this registry."""
54         return self.models.keys()
55
56     def add(self, model_name, model):
57         """ Add or replace a model in the registry."""
58         self.models[model_name] = model
59
60     def get(self, model_name):
61         """ Return a model for a given name or None if it doesn't exist."""
62         return self.models.get(model_name)
63
64     def __getitem__(self, model_name):
65         """ Return a model for a given name or raise KeyError if it doesn't exist."""
66         return self.models[model_name]
67
68     def instanciate(self, module, cr):
69         """ Instanciate all the classes of a given module for a particular db."""
70
71         res = []
72
73         # Instantiate registered classes (via metamodel discovery or via explicit
74         # constructor call), and add them to the pool.
75         for cls in openerp.osv.orm.MetaModel.module_to_models.get(module, []):
76             res.append(cls.createInstance(self, cr))
77
78         return res
79
80
81 class RegistryManager(object):
82     """ Model registries manager.
83
84         The manager is responsible for creation and deletion of model
85         registries (essentially database connection/model registry pairs).
86
87     """
88
89     # Mapping between db name and model registry.
90     # Accessed through the methods below.
91     registries = {}
92
93
94     @classmethod
95     def get(cls, db_name, force_demo=False, status=None, update_module=False,
96             pooljobs=True):
97         """ Return a registry for a given database name."""
98
99         if db_name in cls.registries:
100             registry = cls.registries[db_name]
101         else:
102             registry = cls.new(db_name, force_demo, status,
103                 update_module, pooljobs)
104         return registry
105
106
107     @classmethod
108     def new(cls, db_name, force_demo=False, status=None,
109             update_module=False, pooljobs=True):
110         """ Create and return a new registry for a given database name.
111
112         The (possibly) previous registry for that database name is discarded.
113
114         """
115
116         import openerp.modules
117         registry = Registry(db_name)
118
119         # Initializing a registry will call general code which will in turn
120         # call registries.get (this object) to obtain the registry being
121         # initialized. Make it available in the registries dictionary then
122         # remove it if an exception is raised.
123         cls.delete(db_name)
124         cls.registries[db_name] = registry
125         try:
126             # This should be a method on Registry
127             openerp.modules.load_modules(registry.db, force_demo, status, update_module)
128         except Exception:
129             del cls.registries[db_name]
130             raise
131
132         cr = registry.db.cursor()
133         try:
134             registry.do_parent_store(cr)
135             registry.get('ir.actions.report.xml').register_all(cr)
136             cr.commit()
137         finally:
138             cr.close()
139
140         if pooljobs:
141             registry.get('ir.cron').restart(registry.db.dbname)
142
143         return registry
144
145
146     @classmethod
147     def delete(cls, db_name):
148         """ Delete the registry linked to a given database. """
149         if db_name in cls.registries:
150             del cls.registries[db_name]
151
152
153 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: