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))
 |