154 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Python
		
	
	
			
		
		
	
	
			154 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Python
		
	
	
# -*- coding: utf-8 -*-
 | 
						|
# Copyright 2017 Camptocamp SA
 | 
						|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
 | 
						|
 | 
						|
"""
 | 
						|
Events Internals
 | 
						|
================
 | 
						|
 | 
						|
Core classes for the events system.
 | 
						|
 | 
						|
 | 
						|
"""
 | 
						|
 | 
						|
 | 
						|
from odoo.addons.component.core import WorkContext
 | 
						|
 | 
						|
 | 
						|
class EventWorkContext(WorkContext):
 | 
						|
    """ Work context used by the Events internals
 | 
						|
 | 
						|
    Should not be used outside of the events internals.
 | 
						|
    The work context to use generally is
 | 
						|
    :class:`odoo.addons.component.core.WorkContext` or your own
 | 
						|
    subclass.
 | 
						|
 | 
						|
    The events are a special kind of components because they are
 | 
						|
    not attached to any collection (they can but not the main use case).
 | 
						|
 | 
						|
    So the work context must not need to have a collection, but when
 | 
						|
    it has no collection, it must at least have an 'env'.
 | 
						|
 | 
						|
    When no collection is provided, the methods to get the Components
 | 
						|
    cannot be used, but :meth:`work_on` can be used to switch back to
 | 
						|
    a :class:`odoo.addons.component.core.WorkContext` with collection.
 | 
						|
    This is needed when one want to get a component for a collection
 | 
						|
    from inside an event listener.
 | 
						|
 | 
						|
    """
 | 
						|
 | 
						|
    def __init__(self, model_name=None, collection=None, env=None,
 | 
						|
                 components_registry=None, **kwargs):
 | 
						|
        if not (collection is not None or env):
 | 
						|
            raise ValueError('collection or env is required')
 | 
						|
        if collection and env:
 | 
						|
            # when a collection is used, the env will be the one of
 | 
						|
            # the collection
 | 
						|
            raise ValueError('collection and env cannot both be provided')
 | 
						|
 | 
						|
        self.env = env
 | 
						|
        super(EventWorkContext, self).__init__(
 | 
						|
            model_name=model_name, collection=collection,
 | 
						|
            components_registry=components_registry,
 | 
						|
            **kwargs
 | 
						|
        )
 | 
						|
        if self._env:
 | 
						|
            self._propagate_kwargs.remove('collection')
 | 
						|
            self._propagate_kwargs.append('env')
 | 
						|
 | 
						|
    @property
 | 
						|
    def env(self):
 | 
						|
        """ Return the current Odoo env """
 | 
						|
        if self._env:
 | 
						|
            return self._env
 | 
						|
        return super(EventWorkContext, self).env
 | 
						|
 | 
						|
    @env.setter
 | 
						|
    def env(self, value):
 | 
						|
        self._env = value
 | 
						|
 | 
						|
    @property
 | 
						|
    def collection(self):
 | 
						|
        """ Return the current Odoo env """
 | 
						|
        if self._collection is not None:
 | 
						|
            return self._collection
 | 
						|
        raise ValueError('No collection, it is optional for EventWorkContext')
 | 
						|
 | 
						|
    @collection.setter
 | 
						|
    def collection(self, value):
 | 
						|
        self._collection = value
 | 
						|
 | 
						|
    def work_on(self, model_name=None, collection=None):
 | 
						|
        """ Create a new work context for another model keeping attributes
 | 
						|
 | 
						|
        Used when one need to lookup components for another model.
 | 
						|
 | 
						|
        Used on an EventWorkContext, it switch back to a normal
 | 
						|
        WorkContext. It means we are inside an event listener, and
 | 
						|
        we want to get a component. We need to set a collection
 | 
						|
        to be able to get components.
 | 
						|
        """
 | 
						|
        if self._collection is None and collection is None:
 | 
						|
            raise ValueError('you must provide a collection to work with')
 | 
						|
        if collection is not None:
 | 
						|
            if self.env is not collection.env:
 | 
						|
                raise ValueError('the Odoo env of the collection must be '
 | 
						|
                                 'the same than the current one')
 | 
						|
        kwargs = {attr_name: getattr(self, attr_name)
 | 
						|
                  for attr_name in self._propagate_kwargs}
 | 
						|
        kwargs.pop('env', None)
 | 
						|
        if collection is not None:
 | 
						|
            kwargs['collection'] = collection
 | 
						|
        if model_name is not None:
 | 
						|
            kwargs['model_name'] = model_name
 | 
						|
        return WorkContext(**kwargs)
 | 
						|
 | 
						|
    def component_by_name(self, name, model_name=None):
 | 
						|
        if self._collection is not None:
 | 
						|
            # switch to a normal WorkContext
 | 
						|
            work = self.work_on(collection=self._collection,
 | 
						|
                                model_name=model_name)
 | 
						|
        else:
 | 
						|
            raise TypeError(
 | 
						|
                "Can't be used on an EventWorkContext without collection. "
 | 
						|
                "The collection must be known to find components.\n"
 | 
						|
                "Hint: you can set the collection and get a component with:\n"
 | 
						|
                ">>> work.work_on(collection=self.env[...].browse(...))\n"
 | 
						|
                ">>> work.component_by_name(name, model_name=model_name)"
 | 
						|
            )
 | 
						|
        return work.component_by_name(name, model_name=model_name)
 | 
						|
 | 
						|
    def component(self, usage=None, model_name=None):
 | 
						|
        if self._collection is not None:
 | 
						|
            # switch to a normal WorkContext
 | 
						|
            work = self.work_on(collection=self._collection,
 | 
						|
                                model_name=model_name)
 | 
						|
        else:
 | 
						|
            raise TypeError(
 | 
						|
                "Can't be used on an EventWorkContext without collection. "
 | 
						|
                "The collection must be known to find components.\n"
 | 
						|
                "Hint: you can set the collection and get a component with:\n"
 | 
						|
                ">>> work.work_on(collection=self.env[...].browse(...))\n"
 | 
						|
                ">>> work.component(usage=usage, model_name=model_name)"
 | 
						|
            )
 | 
						|
        return work.component(usage=usage, model_name=model_name)
 | 
						|
 | 
						|
    def many_components(self, usage=None, model_name=None):
 | 
						|
        if self._collection is not None:
 | 
						|
            # switch to a normal WorkContext
 | 
						|
            work = self.work_on(collection=self._collection,
 | 
						|
                                model_name=model_name)
 | 
						|
        else:
 | 
						|
            raise TypeError(
 | 
						|
                "Can't be used on an EventWorkContext without collection. "
 | 
						|
                "The collection must be known to find components.\n"
 | 
						|
                "Hint: you can set the collection and get a component with:\n"
 | 
						|
                ">>> work.work_on(collection=self.env[...].browse(...))\n"
 | 
						|
                ">>> work.many_components(usage=usage, model_name=model_name)"
 | 
						|
            )
 | 
						|
        return work.component(usage=usage, model_name=model_name)
 | 
						|
 | 
						|
    def __str__(self):
 | 
						|
        return ("EventWorkContext(%s,%s)" %
 | 
						|
                (repr(self._env or self._collection), self.model_name))
 |