diff options
Diffstat (limited to 'poezio/events.py')
-rw-r--r-- | poezio/events.py | 113 |
1 files changed, 74 insertions, 39 deletions
diff --git a/poezio/events.py b/poezio/events.py index 3bfe5156..0ba97d56 100644 --- a/poezio/events.py +++ b/poezio/events.py @@ -2,15 +2,20 @@ # This file is part of Poezio. # # Poezio is free software: you can redistribute it and/or modify -# it under the terms of the zlib license. See the COPYING file. +# it under the terms of the GPL-3.0+ license. See the COPYING file. """ Defines the EventHandler class. The list of available events is here: http://poezio.eu/doc/en/plugins.html#_poezio_events """ +import logging +from collections import OrderedDict +from inspect import iscoroutinefunction from typing import Callable, Dict, List +log = logging.getLogger(__name__) + class EventHandler: """ @@ -21,52 +26,73 @@ class EventHandler: """ def __init__(self): - self.events = { - 'highlight': [], - 'muc_say': [], - 'muc_say_after': [], - 'conversation_say': [], - 'conversation_say_after': [], - 'private_say': [], - 'private_say_after': [], - 'conversation_msg': [], - 'private_msg': [], - 'muc_msg': [], - 'conversation_chatstate': [], - 'muc_chatstate': [], - 'private_chatstate': [], - 'normal_presence': [], - 'muc_presence': [], - 'muc_join': [], - 'joining_muc': [], - 'changing_nick': [], - 'muc_kick': [], - 'muc_nickchange': [], - 'muc_ban': [], - 'send_normal_presence': [], - 'ignored_private': [], - 'tab_change': [], - } # type: Dict[str, List[Callable]] + events = [ + 'highlight', + 'muc_say', + 'muc_say_after', + 'conversation_say', + 'conversation_say_after', + 'private_say', + 'private_say_after', + 'conversation_msg', + 'private_msg', + 'muc_msg', + 'conversation_chatstate', + 'muc_chatstate', + 'private_chatstate', + 'normal_presence', + 'muc_presence', + 'muc_join', + 'joining_muc', + 'changing_nick', + 'muc_kick', + 'muc_nickchange', + 'muc_ban', + 'send_normal_presence', + 'ignored_private', + 'tab_change', + ] + self.events: Dict[str, OrderedDict[int, List[Callable]]] = {} + for event in events: + self.events[event] = OrderedDict() def add_event_handler(self, name: str, callback: Callable, - position=0) -> bool: + priority: int = 50) -> bool: """ Add a callback to a given event. Note that if that event name doesn’t exist, it just returns False. If it was successfully added, it returns True - position: 0 means insert at the beginning, -1 means end + priority is a integer between 0 and 100. 0 is the highest priority and + will be called first. 100 is the lowest. """ + if name not in self.events: return False callbacks = self.events[name] - if position >= 0: - callbacks.insert(position, callback) - else: - callbacks.append(callback) + + # Clamp priority + priority = max(0, min(priority, 100)) + + entry = callbacks.setdefault(priority, []) + entry.append(callback) return True + async def trigger_async(self, name: str, *args, **kwargs): + """ + Call all the callbacks associated to the given event name. + """ + callbacks = self.events.get(name, None) + if callbacks is None: + return + for priority in callbacks.values(): + for callback in priority: + if iscoroutinefunction(callback): + await callback(*args, **kwargs) + else: + callback(*args, **kwargs) + def trigger(self, name: str, *args, **kwargs): """ Call all the callbacks associated to the given event name. @@ -74,8 +100,13 @@ class EventHandler: callbacks = self.events.get(name, None) if callbacks is None: return - for callback in callbacks: - callback(*args, **kwargs) + for priority in callbacks.values(): + for callback in priority: + if not iscoroutinefunction(callback): + callback(*args, **kwargs) + else: + log.error(f'async event handler {callback} ' + 'called in sync trigger!') def del_event_handler(self, name: str, callback: Callable): """ @@ -83,9 +114,13 @@ class EventHandler: """ if not name: for callbacks in self.events.values(): - while callback in callbacks: - callbacks.remove(callback) + for priority in callbacks.values(): + for entry in priority[:]: + if entry == callback: + priority.remove(callback) else: callbacks = self.events[name] - if callback in callbacks: - callbacks.remove(callback) + for priority in callbacks.values(): + for entry in priority[:]: + if entry == callback: + priority.remove(callback) |