Skip to content

Commit

Permalink
Merge pull request #6 from Garulf/improve-event-handler
Browse files Browse the repository at this point in the history
Improve event handler
  • Loading branch information
Garulf authored Feb 17, 2024
2 parents ef25cd6 + 1ef9e6e commit 7be3b35
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 35 deletions.
56 changes: 38 additions & 18 deletions pyflowlauncher/event.py
Original file line number Diff line number Diff line change
@@ -1,36 +1,56 @@
import asyncio
from typing import Any, Callable, Iterable, Type
from typing import Any, Callable, Iterable, Type, Union


class EventNotFound(Exception):

def __init__(self, event: str):
self.event = event
super().__init__(f"Event '{event}' not found.")


class EventHandler:

def __init__(self):
self._methods = {}
self._events = {}
self._handlers = {}

def _get_callable_name(self, method: Callable[..., Any]):
def _get_callable_name(self, method: Union[Callable[..., Any], Exception]):
return getattr(method, '__name__', method.__class__.__name__).lower()

def add_method(self, method: Callable[..., Any], *, name=None) -> str:
key = name or self._get_callable_name(method)
self._methods[key] = method
def add_event(self, event: Callable[..., Any], *, name=None) -> str:
key = name or self._get_callable_name(event)
self._events[key] = event
return key

def add_methods(self, methods: Iterable[Callable[..., Any]]):
for method in methods:
self.add_method(method)
def add_events(self, events: Iterable[Callable[..., Any]]):
for event in events:
self.add_event(event)

def add_exception_handler(self, exception: Type[Exception], handler: Callable[..., Any]):
self._handlers[exception] = handler

async def __call__(self, method: str, *args, **kwargs):
def get_event(self, event: str) -> Callable[..., Any]:
try:
return self._events[event]
except KeyError:
raise EventNotFound(event)

async def _await_maybe(self, result: Any) -> Any:
if asyncio.iscoroutine(result):
return await result
return result

async def trigger_exception_handler(self, exception: Exception) -> Any:
try:
handler = self._handlers[exception.__class__]
return await self._await_maybe(handler(exception))
except KeyError:
raise exception

async def trigger_event(self, event: str, *args, **kwargs) -> Any:
try:
result = self._methods[method](*args, **kwargs)
if asyncio.iscoroutine(result):
return await result
return result
result = self.get_event(event)(*args, **kwargs)
return await self._await_maybe(result)
except Exception as e:
handler = self._handlers.get(type(e), None)
if handler:
return handler(e)
raise e
return await self.trigger_exception_handler(e)
10 changes: 5 additions & 5 deletions pyflowlauncher/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,16 @@ def __init__(self, methods: list[Method] | None = None) -> None:

def add_method(self, method: Method) -> str:
"""Add a method to the event handler."""
return self._event_handler.add_method(method)
return self._event_handler.add_event(method)

def add_methods(self, methods: Iterable[Method]) -> None:
self._event_handler.add_methods(methods)
self._event_handler.add_events(methods)

def on_method(self, method: Method) -> Method:
@wraps(method)
def wrapper(*args, **kwargs):
return method(*args, **kwargs)
self._event_handler.add_method(wrapper)
self._event_handler.add_event(wrapper)
return wrapper

def method(self, method: Method) -> Method:
Expand Down Expand Up @@ -73,10 +73,10 @@ def run(self) -> None:
method = request["method"]
parameters = request.get('parameters', [])
if sys.version_info >= (3, 10, 0):
feedback = asyncio.run(self._event_handler(method, *parameters))
feedback = asyncio.run(self._event_handler.trigger_event(method, *parameters))
else:
loop = asyncio.get_event_loop()
feedback = loop.run_until_complete(self._event_handler(method, *parameters))
feedback = loop.run_until_complete(self._event_handler.trigger_event(method, *parameters))
if not feedback:
return
self._client.send(feedback)
Expand Down
20 changes: 10 additions & 10 deletions tests/test_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,28 @@ def except_method():

def test_add_method():
handler = EventHandler()
handler.add_method(temp_method1)
assert handler._methods == {"temp_method1": temp_method1}
handler.add_event(temp_method1)
assert handler._events == {"temp_method1": temp_method1}


def test_add_methods():
handler = EventHandler()
handler.add_methods([temp_method1, temp_method2])
assert handler._methods == {"temp_method1": temp_method1, "temp_method2": temp_method2}
handler.add_events([temp_method1, temp_method2])
assert handler._events == {"temp_method1": temp_method1, "temp_method2": temp_method2}


@pytest.mark.asyncio
async def test_call():
handler = EventHandler()
handler.add_method(temp_method1)
assert await handler("temp_method1") is None
handler.add_event(temp_method1)
assert await handler.trigger_event("temp_method1") is None


@pytest.mark.asyncio
async def test_call_async():
handler = EventHandler()
handler.add_method(async_temp_method3)
assert await handler("async_temp_method3") is None
handler.add_event(async_temp_method3)
assert await handler.trigger_event("async_temp_method3") is None


def test_add_exception_handler():
Expand All @@ -53,6 +53,6 @@ def test_add_exception_handler():
@pytest.mark.asyncio
async def test_call_exception():
handler = EventHandler()
handler.add_method(except_method)
handler.add_event(except_method)
with pytest.raises(Exception):
await handler("except_method")
await handler.trigger_event("except_method")
4 changes: 2 additions & 2 deletions tests/test_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ def query(query: str):
def test_add_method():
plugin = Plugin()
plugin.add_method(temp_method1)
assert plugin._event_handler._methods == {'temp_method1': temp_method1}
assert plugin._event_handler._events == {'temp_method1': temp_method1}


def test_add_methods():
plugin = Plugin()
plugin.add_methods([temp_method1, temp_method2])
assert plugin._event_handler._methods == {'temp_method1': temp_method1, 'temp_method2': temp_method2}
assert plugin._event_handler._events == {'temp_method1': temp_method1, 'temp_method2': temp_method2}


def test_settings():
Expand Down

0 comments on commit 7be3b35

Please sign in to comment.