summaryrefslogtreecommitdiff
path: root/poezio/events.py
diff options
context:
space:
mode:
Diffstat (limited to 'poezio/events.py')
-rw-r--r--poezio/events.py113
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)