diff options
| author | Raphael Collet <rco@openerp.com> | 2014-07-06 16:44:26 +0200 |
|---|---|---|
| committer | Antony Lesuisse <al@openerp.com> | 2014-07-06 17:05:41 +0200 |
| commit | cbe2dbb672a6c55d86f2e515f9d1cdfee426ef80 (patch) | |
| tree | d6ff62b719fce32392397783c961b734b1e4c50e /openerp/modules | |
| parent | d78192c489d3be66cd6487b39f5ce7ba4733a187 (diff) | |
[MERGE] new v8 api by rco
A squashed merge is required as the conversion of the apiculture branch from
bzr to git was not correctly done. The git history contains irrelevant blobs
and commits. This branch brings a lot of changes and fixes, too many to list
exhaustively.
- New orm api, objects are now used instead of ids
- Environements to encapsulates cr uid context while maintaining backward compatibility
- Field compute attribute is a new object oriented way to define function fields
- Shared browse record cache
- New onchange protocol
- Optional copy flag on fields
- Documentation update
- Dead code cleanup
- Lots of fixes
Diffstat (limited to 'openerp/modules')
| -rw-r--r-- | openerp/modules/loading.py | 5 | ||||
| -rw-r--r-- | openerp/modules/module.py | 2 | ||||
| -rw-r--r-- | openerp/modules/registry.py | 105 |
3 files changed, 70 insertions, 42 deletions
diff --git a/openerp/modules/loading.py b/openerp/modules/loading.py index d81461d6a77..eb703e25eb6 100644 --- a/openerp/modules/loading.py +++ b/openerp/modules/loading.py @@ -162,6 +162,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) init_module_models(cr, package.name, models) status['progress'] = float(index) / len(graph) @@ -188,6 +189,7 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, skip_modules= status['progress'] = (index + 0.75) / len(graph) _load_data(cr, module_name, idref, mode, kind='demo') cr.execute('update ir_module_module set demo=%s where id=%s', (True, module_id)) + modobj.invalidate_cache(cr, SUPERUSER_ID, ['demo'], [module_id]) migrations.migrate_module(package, 'post') @@ -228,6 +230,8 @@ 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) + _logger.log(25, "%s modules loaded in %.2fs, %s queries", len(graph), time.time() - t0, openerp.sql_db.sql_counter - t0_sql) # The query won't be valid for models created later (i.e. custom model @@ -332,6 +336,7 @@ def load_modules(db, force_demo=False, status=None, update_module=False): modobj.button_upgrade(cr, SUPERUSER_ID, ids) cr.execute("update ir_module_module set state=%s where name=%s", ('installed', 'base')) + modobj.invalidate_cache(cr, SUPERUSER_ID, ['state']) # STEP 3: Load marked modules (skipping base which was done in STEP 1) diff --git a/openerp/modules/module.py b/openerp/modules/module.py index 0dd93629830..505e51b0394 100644 --- a/openerp/modules/module.py +++ b/openerp/modules/module.py @@ -278,7 +278,7 @@ def init_module_models(cr, module_name, obj_list): for obj in obj_list: obj._auto_end(cr, {'module': module_name}) cr.commit() - todo.sort() + todo.sort(key=lambda x: x[0]) for t in todo: t[1](cr, *t[2]) cr.commit() diff --git a/openerp/modules/registry.py b/openerp/modules/registry.py index eb591c53521..1d68e228b8f 100644 --- a/openerp/modules/registry.py +++ b/openerp/modules/registry.py @@ -27,12 +27,9 @@ from contextlib import contextmanager import logging import threading -import openerp.sql_db -import openerp.osv.orm -import openerp.tools -import openerp.modules.db -import openerp.tools.config -from openerp.tools import assertion_report +import openerp +from .. import SUPERUSER_ID +from openerp.tools import assertion_report, lazy_property _logger = logging.getLogger(__name__) @@ -49,6 +46,7 @@ class Registry(Mapping): self.models = {} # model name/model instance mapping self._sql_error = {} self._store_function = {} + self._pure_function_fields = {} # {model: [field, ...], ...} self._init = True self._init_parent = {} self._assertion_report = assertion_report.assertion_report() @@ -97,10 +95,6 @@ class Registry(Mapping): """ Return an iterator over all model names. """ return iter(self.models) - def __contains__(self, model_name): - """ Test whether the model with the given name exists. """ - return model_name in self.models - def __getitem__(self, model_name): """ Return the model with the given name or raise KeyError if it doesn't exist.""" return self.models[model_name] @@ -109,6 +103,16 @@ class Registry(Mapping): """ Same as ``self[model_name]``. """ return self.models[model_name] + @lazy_property + def pure_function_fields(self): + """ Return the list of pure function fields (field objects) """ + fields = [] + for mname, fnames in self._pure_function_fields.iteritems(): + model_fields = self[mname]._fields + for fname in fnames: + fields.append(model_fields[fname]) + return fields + def do_parent_store(self, cr): for o in self._init_parent: self.get(o)._parent_store_compute(cr) @@ -131,17 +135,35 @@ class Registry(Mapping): and registers them in the registry. """ + from .. import models + models_to_load = [] # need to preserve loading order + lazy_property.reset_all(self) + # Instantiate registered classes (via the MetaModel automatic discovery # or via explicit constructor call), and add them to the pool. - for cls in openerp.osv.orm.MetaModel.module_to_models.get(module.name, []): + for cls in models.MetaModel.module_to_models.get(module.name, []): # models register themselves in self.models - model = cls.create_instance(self, cr) + model = cls._build_model(self, cr) if model._name not in models_to_load: # avoid double-loading models whose declaration is split models_to_load.append(model._name) + return [self.models[m] for m in models_to_load] + def setup_models(self, cr): + """ Complete the setup of models. + This must be called after loading modules and before using the ORM. + """ + # prepare the setup on all models + for model in self.models.itervalues(): + model._prepare_setup_fields(cr, SUPERUSER_ID) + + # do the actual setup from a clean state + self._m2m = {} + for model in self.models.itervalues(): + model._setup_fields(cr, SUPERUSER_ID) + def clear_caches(self): """ Clear the caches This clears the caches associated to methods decorated with @@ -151,7 +173,7 @@ class Registry(Mapping): model.clear_caches() # Special case for ir_ui_menu which does not use openerp.tools.ormcache. ir_ui_menu = self.models.get('ir.ui.menu') - if ir_ui_menu: + if ir_ui_menu is not None: ir_ui_menu.clear_cache() @@ -282,36 +304,37 @@ class RegistryManager(object): """ import openerp.modules with cls.lock(): - registry = Registry(db_name) - - # Initializing a registry will call general code which will in turn - # call registries.get (this object) to obtain the registry being - # initialized. Make it available in the registries dictionary then - # remove it if an exception is raised. - cls.delete(db_name) - cls.registries[db_name] = registry - try: - with registry.cursor() as cr: - seq_registry, seq_cache = Registry.setup_multi_process_signaling(cr) - registry.base_registry_signaling_sequence = seq_registry - registry.base_cache_signaling_sequence = seq_cache - # This should be a method on Registry - openerp.modules.load_modules(registry._db, force_demo, status, update_module) - except Exception: - del cls.registries[db_name] - raise + with openerp.api.Environment.manage(): + registry = Registry(db_name) - # load_modules() above can replace the registry by calling - # indirectly new() again (when modules have to be uninstalled). - # Yeah, crazy. - registry = cls.registries[db_name] + # Initializing a registry will call general code which will in + # turn call registries.get (this object) to obtain the registry + # being initialized. Make it available in the registries + # dictionary then remove it if an exception is raised. + cls.delete(db_name) + cls.registries[db_name] = registry + try: + with registry.cursor() as cr: + seq_registry, seq_cache = Registry.setup_multi_process_signaling(cr) + registry.base_registry_signaling_sequence = seq_registry + registry.base_cache_signaling_sequence = seq_cache + # This should be a method on Registry + openerp.modules.load_modules(registry._db, force_demo, status, update_module) + except Exception: + del cls.registries[db_name] + raise + + # load_modules() above can replace the registry by calling + # indirectly new() again (when modules have to be uninstalled). + # Yeah, crazy. + registry = cls.registries[db_name] - cr = registry.cursor() - try: - registry.do_parent_store(cr) - cr.commit() - finally: - cr.close() + cr = registry.cursor() + try: + registry.do_parent_store(cr) + cr.commit() + finally: + cr.close() registry.ready = True |
