108 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Python
		
	
	
			
		
		
	
	
			108 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Python
		
	
	
# -*- coding: utf-8 -*-
 | 
						|
# Copyright 2017 Camptocamp SA
 | 
						|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
 | 
						|
 | 
						|
"""
 | 
						|
 | 
						|
Components Builder
 | 
						|
==================
 | 
						|
 | 
						|
Build the components at the build of a registry.
 | 
						|
 | 
						|
"""
 | 
						|
import odoo
 | 
						|
from odoo import api, models
 | 
						|
from .core import (
 | 
						|
    _component_databases,
 | 
						|
    ComponentRegistry,
 | 
						|
    DEFAULT_CACHE_SIZE,
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
class ComponentBuilder(models.AbstractModel):
 | 
						|
    """ Build the component classes
 | 
						|
 | 
						|
    And register them in a global registry.
 | 
						|
 | 
						|
    Every time an Odoo registry is built, the know components are cleared and
 | 
						|
    rebuilt as well.  The Component classes are built using the same mechanism
 | 
						|
    than Odoo's Models: a final class is created, taking every Components with
 | 
						|
    a ``_name`` and applying Components with an ``_inherits`` upon them.
 | 
						|
 | 
						|
    The final Component classes are registered in global registry.
 | 
						|
 | 
						|
    This class is an Odoo model, allowing us to hook the build of the
 | 
						|
    components 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 components Classes and in the correct
 | 
						|
    order.
 | 
						|
 | 
						|
    """
 | 
						|
    _name = 'component.builder'
 | 
						|
    _description = 'Component Builder'
 | 
						|
 | 
						|
    _components_registry_cache_size = DEFAULT_CACHE_SIZE
 | 
						|
 | 
						|
    @api.model_cr
 | 
						|
    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 to rebuild the components. We use a new
 | 
						|
        # registry so we have an empty cache and we'll add components in it.
 | 
						|
        components_registry = self._init_global_registry()
 | 
						|
        self.build_registry(components_registry)
 | 
						|
        components_registry.ready = True
 | 
						|
 | 
						|
    def _init_global_registry(self):
 | 
						|
        components_registry = ComponentRegistry(
 | 
						|
            cachesize=self._components_registry_cache_size
 | 
						|
        )
 | 
						|
        _component_databases[self.env.cr.dbname] = components_registry
 | 
						|
        return components_registry
 | 
						|
 | 
						|
    def build_registry(self, components_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 components following the order
 | 
						|
        # of the addons' dependencies
 | 
						|
        graph = odoo.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_components(module.name,
 | 
						|
                                 components_registry=components_registry)
 | 
						|
 | 
						|
    def load_components(self, module, components_registry=None):
 | 
						|
        """ Build every component known by MetaComponent for an odoo module
 | 
						|
 | 
						|
        The final component (composed by all the Component classes in this
 | 
						|
        module) will be pushed into the registry.
 | 
						|
 | 
						|
        :param module: the name of the addon for which we want to load
 | 
						|
                       the components
 | 
						|
        :type module: str | unicode
 | 
						|
        :param registry: the registry in which we want to put the Component
 | 
						|
        :type registry: :py:class:`~.core.ComponentRegistry`
 | 
						|
        """
 | 
						|
        components_registry = (
 | 
						|
            components_registry or
 | 
						|
            _component_databases[self.env.cr.dbname])
 | 
						|
        components_registry.load_components(module)
 |