From da03c2e22fcd2e2dfb54dfe4add8cd6c81e6e511 Mon Sep 17 00:00:00 2001 From: rmorshea Date: Thu, 17 Jun 2021 15:19:25 -0700 Subject: [PATCH] add try/except around event handling --- src/idom/core/layout.py | 5 ++++- tests/test_core/test_layout.py | 25 ++++++++++++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/idom/core/layout.py b/src/idom/core/layout.py index 6c6d7c039..bbae0a6bf 100644 --- a/src/idom/core/layout.py +++ b/src/idom/core/layout.py @@ -105,7 +105,10 @@ async def dispatch(self, event: LayoutEvent) -> None: handler = self._event_handlers.get(event.target) if handler is not None: - await handler(event.data) + try: + await handler(event.data) + except Exception: + logger.exception(f"Failed to execute event handler {handler}") else: logger.info( f"Ignored event - handler {event.target!r} does not exist or its component unmounted" diff --git a/tests/test_core/test_layout.py b/tests/test_core/test_layout.py index aea8da4cb..4b2db2550 100644 --- a/tests/test_core/test_layout.py +++ b/tests/test_core/test_layout.py @@ -288,7 +288,7 @@ def use_toggle(init=False): return state, lambda: set_state(lambda old: not old) -async def test_model_key_preserves_callback_identity_for_common_elements(): +async def test_model_key_preserves_callback_identity_for_common_elements(caplog): called_good_trigger = idom.Ref(False) good_handler = StaticEventHandler() bad_handler = StaticEventHandler() @@ -330,6 +330,8 @@ def bad_trigger(): await layout.render() + assert not caplog.records + async def test_model_key_preserves_callback_identity_for_components(): called_good_trigger = idom.Ref(False) @@ -495,3 +497,24 @@ def SomeComponent(): next(iter(caplog.records)).message == f"Did not render component - {component_not_in_layout} already unmounted or does not belong to this layout" ) + + +async def test_log_error_on_bad_event_handler(caplog): + bad_handler = StaticEventHandler() + + @idom.component + def ComponentWithBadEventHandler(): + @bad_handler.use + def raise_error(): + raise Exception("bad event handler") + + return idom.html.button({"onClick": raise_error}) + + with idom.Layout(ComponentWithBadEventHandler()) as layout: + await layout.render() + event = LayoutEvent(bad_handler.target, []) + await layout.dispatch(event) + + assert next(iter(caplog.records)).message.startswith( + "Failed to execute event handler" + )