mirror of
https://github.com/bringout/oca-technical.git
synced 2026-04-18 06:52:01 +02:00
96 lines
3.6 KiB
Python
96 lines
3.6 KiB
Python
# Copyright 2017 Camptocamp SA
|
|
# Copyright 2019 ACSONE SA/NV
|
|
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html)
|
|
|
|
"""
|
|
|
|
Datamodels Builder
|
|
==================
|
|
|
|
Build the datamodels at the build of a registry.
|
|
|
|
"""
|
|
from odoo import models, modules
|
|
|
|
from .core import DEFAULT_CACHE_SIZE, DatamodelRegistry, _datamodel_databases
|
|
|
|
|
|
class DatamodelBuilder(models.AbstractModel):
|
|
"""Build the datamodel classes
|
|
|
|
And register them in a global registry.
|
|
|
|
Every time an Odoo registry is built, the know datamodels are cleared and
|
|
rebuilt as well. The Datamodel classes are built using the same mechanism
|
|
than Odoo's Models: a final class is created, taking every Datamodels with
|
|
a ``_name`` and applying Datamodels with an ``_inherits`` upon them.
|
|
|
|
The final Datamodel classes are registered in global registry.
|
|
|
|
This class is an Odoo model, allowing us to hook the build of the
|
|
datamodels at the end of the Odoo's registry loading, using
|
|
``_register_hook``. This method is called after all modules are loaded, so
|
|
we are sure that we have all the datamodels Classes and in the correct
|
|
order.
|
|
|
|
"""
|
|
|
|
_name = "datamodel.builder"
|
|
_description = "Datamodel Builder"
|
|
|
|
_datamodels_registry_cache_size = DEFAULT_CACHE_SIZE
|
|
|
|
def _register_hook(self):
|
|
# This method is called by Odoo when the registry is built,
|
|
# so in case the registry is rebuilt (cache invalidation, ...),
|
|
# we have to rebuild the datamodels. We use a new
|
|
# registry so we have an empty cache and we'll add datamodels in it.
|
|
datamodels_registry = self._init_global_registry()
|
|
self.build_registry(datamodels_registry)
|
|
datamodels_registry.ready = True
|
|
|
|
def _init_global_registry(self):
|
|
datamodels_registry = DatamodelRegistry(
|
|
cachesize=self._datamodels_registry_cache_size
|
|
)
|
|
_datamodel_databases[self.env.cr.dbname] = datamodels_registry
|
|
return datamodels_registry
|
|
|
|
def build_registry(self, datamodels_registry, states=None, exclude_addons=None):
|
|
if not states:
|
|
states = ("installed", "to upgrade")
|
|
# lookup all the installed (or about to be) addons and generate
|
|
# the graph, so we can load the datamodels following the order
|
|
# of the addons' dependencies
|
|
graph = modules.graph.Graph()
|
|
graph.add_module(self.env.cr, "base")
|
|
|
|
query = "SELECT name " "FROM ir_module_module " "WHERE state IN %s "
|
|
params = [tuple(states)]
|
|
if exclude_addons:
|
|
query += " AND name NOT IN %s "
|
|
params.append(tuple(exclude_addons))
|
|
self.env.cr.execute(query, params)
|
|
|
|
module_list = [name for (name,) in self.env.cr.fetchall() if name not in graph]
|
|
graph.add_modules(self.env.cr, module_list)
|
|
|
|
for module in graph:
|
|
self.load_datamodels(module.name, datamodels_registry=datamodels_registry)
|
|
|
|
def load_datamodels(self, module, datamodels_registry=None):
|
|
"""Build every datamodel known by MetaDatamodel for an odoo module
|
|
|
|
The final datamodel (composed by all the Datamodel classes in this
|
|
module) will be pushed into the registry.
|
|
|
|
:param module: the name of the addon for which we want to load
|
|
the datamodels
|
|
:type module: str | unicode
|
|
:param registry: the registry in which we want to put the Datamodel
|
|
:type registry: :py:class:`~.core.DatamodelRegistry`
|
|
"""
|
|
datamodels_registry = (
|
|
datamodels_registry or _datamodel_databases[self.env.cr.dbname]
|
|
)
|
|
datamodels_registry.load_datamodels(module)
|