# HG changeset patch # User Goffi # Date 1702145966 -3600 # Node ID 4dc00e848961a7b7fc51041265d26d2afa4cf6f8 # Parent bc898879af34916029161264e24baae735e1c9d3 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). diff -r bc898879af34 -r 4dc00e848961 libervia/backend/core/xmpp.py --- a/libervia/backend/core/xmpp.py Sat Dec 09 19:17:34 2023 +0100 +++ b/libervia/backend/core/xmpp.py Sat Dec 09 19:19:26 2023 +0100 @@ -139,7 +139,8 @@ - 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) diff -r bc898879af34 -r 4dc00e848961 libervia/backend/tools/trigger.py --- a/libervia/backend/tools/trigger.py Sat Dec 09 19:17:34 2023 +0100 +++ b/libervia/backend/tools/trigger.py Sat Dec 09 19:19:26 2023 +0100 @@ -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 @@ 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 @@ 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