Source code for odoo.addons.component_event.core
# -*- 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
[docs]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
[docs] 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)
[docs] 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)
[docs] 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)
[docs] 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))