From 286c0473b6c9ab8a9b2fb649d9b41b7acfbb1189 Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Fri, 16 Feb 2024 16:34:10 -0500 Subject: [PATCH 1/4] Update EventHandler naming and structure --- pyflowlauncher/event.py | 30 ++++++++++++++++++------------ pyflowlauncher/plugin.py | 6 +++--- tests/test_events.py | 20 ++++++++++---------- tests/test_plugin.py | 4 ++-- 4 files changed, 33 insertions(+), 27 deletions(-) diff --git a/pyflowlauncher/event.py b/pyflowlauncher/event.py index c156323..ebdf518 100644 --- a/pyflowlauncher/event.py +++ b/pyflowlauncher/event.py @@ -5,30 +5,36 @@ class EventHandler: def __init__(self): - self._methods = {} + self._events = {} self._handlers = {} def _get_callable_name(self, method: Callable[..., Any]): 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 _call_event(self, event: str, *args, **kwargs) -> Callable[..., Any] | None: + return self._events[event](*args, **kwargs) + + async def _await_maybe(self, result: Any) -> Any: + if asyncio.iscoroutine(result): + return await result + return result + + 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._call_event(event, *args, **kwargs) + return await self._await_maybe(result) except Exception as e: handler = self._handlers.get(type(e), None) if handler: diff --git a/pyflowlauncher/plugin.py b/pyflowlauncher/plugin.py index dca701e..d28f070 100644 --- a/pyflowlauncher/plugin.py +++ b/pyflowlauncher/plugin.py @@ -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: diff --git a/tests/test_events.py b/tests/test_events.py index cf96923..e160df7 100644 --- a/tests/test_events.py +++ b/tests/test_events.py @@ -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(): @@ -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") diff --git a/tests/test_plugin.py b/tests/test_plugin.py index 547da24..6dba757 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -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(): From 89e784ecddc716106965f0874a24314408d4aa01 Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Fri, 16 Feb 2024 16:40:59 -0500 Subject: [PATCH 2/4] Plugin now uses uodated event methods --- pyflowlauncher/plugin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyflowlauncher/plugin.py b/pyflowlauncher/plugin.py index d28f070..9f26ee6 100644 --- a/pyflowlauncher/plugin.py +++ b/pyflowlauncher/plugin.py @@ -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) From a829da2789b38ae0c3ed2e87022a8cdd062e28f0 Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Fri, 16 Feb 2024 16:41:49 -0500 Subject: [PATCH 3/4] Refactor event handling in EventHandler class --- pyflowlauncher/event.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyflowlauncher/event.py b/pyflowlauncher/event.py index ebdf518..3db6360 100644 --- a/pyflowlauncher/event.py +++ b/pyflowlauncher/event.py @@ -23,8 +23,8 @@ def add_events(self, events: Iterable[Callable[..., Any]]): def add_exception_handler(self, exception: Type[Exception], handler: Callable[..., Any]): self._handlers[exception] = handler - def _call_event(self, event: str, *args, **kwargs) -> Callable[..., Any] | None: - return self._events[event](*args, **kwargs) + def get_event(self, event: str) -> Callable[..., Any]: + return self._events[event] async def _await_maybe(self, result: Any) -> Any: if asyncio.iscoroutine(result): @@ -33,7 +33,7 @@ async def _await_maybe(self, result: Any) -> Any: async def trigger_event(self, event: str, *args, **kwargs) -> Any: try: - result = self._call_event(event, *args, **kwargs) + result = self.get_event(event)(*args, **kwargs) return await self._await_maybe(result) except Exception as e: handler = self._handlers.get(type(e), None) From 1ef9e6e48f69b31f60835c0b614ffcb9e77d2dac Mon Sep 17 00:00:00 2001 From: Garulf <535299+Garulf@users.noreply.github.com> Date: Fri, 16 Feb 2024 16:56:51 -0500 Subject: [PATCH 4/4] Improve exception handling --- pyflowlauncher/event.py | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/pyflowlauncher/event.py b/pyflowlauncher/event.py index 3db6360..48453d7 100644 --- a/pyflowlauncher/event.py +++ b/pyflowlauncher/event.py @@ -1,5 +1,12 @@ 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: @@ -8,7 +15,7 @@ def __init__(self): 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_event(self, event: Callable[..., Any], *, name=None) -> str: @@ -24,19 +31,26 @@ def add_exception_handler(self, exception: Type[Exception], handler: Callable[.. self._handlers[exception] = handler def get_event(self, event: str) -> Callable[..., Any]: - return self._events[event] + 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.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)