core (tools/trigger): new add_with_check method:

this method add a wrapper which will skip the trigger is the plugin is not available in
the session (e.g. a component which doesn't use the plugin).
This commit is contained in:
Goffi 2023-12-09 19:19:26 +01:00
commit ba1475962e
2 changed files with 54 additions and 2 deletions

View file

@ -139,7 +139,8 @@ class SatXMPPEntity(core_types.SatXMPPEntity):
- profile_connected* triggers (to call after connection)
"""
plugin_conn_cb = []
for plugin in self._get_plugins_list():
self.plugins = plugins = self._get_plugins_list()
for plugin in plugins:
# we check if plugin handle client mode
if plugin.is_handler:
plugin.get_handler(self).setHandlerParent(self)

View file

@ -19,8 +19,11 @@
"""Misc usefull classes"""
import inspect
from typing import Callable
from libervia.backend.core.i18n import _
from libervia.backend.core.log import getLogger
from libervia.backend.core.core_types import SatXMPPEntity
log = getLogger(__name__)
@ -49,7 +52,18 @@ class TriggerManager(object):
def __init__(self):
self.__triggers = {}
def add(self, point_name, callback, priority=0):
def is_available(self, args: list):
"""Check if plugin used in a client context, and if it's available"""
if not args or not isinstance(args[0], SatXMPPEntity):
# we are not in the context of a client
return True
client = args[0]
if not client.is_component:
# plugins are always avaialble for normal clients
return True
def add(self, point_name, callback: Callable, priority=0):
"""Add a trigger to a point
@param point_name: name of the point when the trigger should be run
@ -74,6 +88,43 @@ class TriggerManager(object):
key=lambda trigger_tuple: trigger_tuple[0], reverse=True
)
def add_with_check(
self,
point_name: str,
plugin,
callback: Callable,
priority: int=0
) -> None:
"""Like [Add], but check session before running the trigger
This method is to be used for triggers which can run in components and are
expecting a ``client``: as all plugins are not run for component, a check will be
added before running the trigger, if the plugin is not valid for this component,
the trigger is ignored. ``client`` must be the first positional argument.
@param point_name: name of the trigger point
@param plugin: instance of the plugin using this trigger. This is necessary to
check if the plugin is available in the session.
@param callback: method to call at the trigger point
@param priority: callback will be called in priority order, biggest first
"""
if inspect.iscoroutinefunction(callback):
async def async_wrapper(client: SatXMPPEntity, *args, **kwargs):
if client.is_component and plugin not in client.plugins:
log.debug(f"Ignoring {callback} as parent plugin is not available")
return True
else:
return await callback(client, *args, **kwargs)
self.add(point_name, async_wrapper, priority)
else:
def sync_wrapper(client: SatXMPPEntity, *args, **kwargs):
if client.is_component and plugin not in client.plugins:
log.debug(f"Ignoring {callback} as parent plugin is not available")
return True
else:
return callback(client, *args, **kwargs)
self.add(point_name, sync_wrapper, priority)
def remove(self, point_name, callback):
"""Remove a trigger from a point