From 04ca3ccbb9edf10eb935c8a88d2404e154b1f08b Mon Sep 17 00:00:00 2001 From: Richard To Date: Thu, 6 Feb 2025 19:05:43 -0800 Subject: [PATCH] Filter empty web component event handlers (#1193) --- mesop/component_helpers/helper.py | 19 +++++++++++++++---- .../web_component/gemini_live/audio_player.py | 11 ++++------- .../gemini_live/audio_recorder.py | 11 ++++------- .../web_component/gemini_live/gemini_live.py | 13 +++++-------- .../web_component/gemini_live/utils.py | 8 -------- .../gemini_live/video_recorder.py | 11 ++++------- 6 files changed, 32 insertions(+), 41 deletions(-) delete mode 100644 mesop/examples/web_component/gemini_live/utils.py diff --git a/mesop/component_helpers/helper.py b/mesop/component_helpers/helper.py index aa8dc8fb..19b65012 100644 --- a/mesop/component_helpers/helper.py +++ b/mesop/component_helpers/helper.py @@ -440,7 +440,7 @@ def insert_composite_component( def insert_web_component( *, name: str, - events: dict[str, Callable[[WebEvent], Any]] | None = None, + events: dict[str, Callable[[WebEvent], Any] | None] | None = None, properties: dict[str, Any] | None = None, key: str | None = None, ): @@ -459,13 +459,17 @@ def insert_web_component( """ if events is None: events = dict() + + filtered_events = filter_web_events(events) + if properties is None: properties = dict() - check_property_keys_is_safe(events.keys()) + + check_property_keys_is_safe(filtered_events.keys()) check_property_keys_is_safe(properties.keys()) event_to_ids: dict[str, str] = {} - for event in events: - event_handler = events[event] + for event in filtered_events: + event_handler = filtered_events[event] event_to_ids[event] = register_event_handler(event_handler, WebEvent) type_proto = pb.WebComponentType( properties_json=json.dumps(properties), @@ -479,6 +483,13 @@ def insert_web_component( ) +def filter_web_events( + events: dict[str, Callable[[WebEvent], Any] | None], +) -> dict[str, Callable[[WebEvent], Any]]: + """Helper function for filtering out web component events that do not have a callback.""" + return {event: callback for event, callback in events.items() if callback} + + # Note: the logic here should be kept in sync with # component_renderer.ts's checkAttributeNameIsSafe # diff --git a/mesop/examples/web_component/gemini_live/audio_player.py b/mesop/examples/web_component/gemini_live/audio_player.py index 74df20d8..56f3cac5 100644 --- a/mesop/examples/web_component/gemini_live/audio_player.py +++ b/mesop/examples/web_component/gemini_live/audio_player.py @@ -2,7 +2,6 @@ from typing import Any, Callable import mesop.labs as mel -from mesop.examples.web_component.gemini_live.utils import filter_events @mel.web_component(path="./audio_player.js") @@ -41,12 +40,10 @@ def audio_player( """ return mel.insert_web_component( name="audio-player", - events=filter_events( - { - "playEvent": on_play, - "stopEvent": on_stop, - } - ), + events={ + "playEvent": on_play, + "stopEvent": on_stop, + }, properties={ "enabled": enabled, "data": base64.b64encode(data).decode("utf-8"), diff --git a/mesop/examples/web_component/gemini_live/audio_recorder.py b/mesop/examples/web_component/gemini_live/audio_recorder.py index f3b33657..3df846e7 100644 --- a/mesop/examples/web_component/gemini_live/audio_recorder.py +++ b/mesop/examples/web_component/gemini_live/audio_recorder.py @@ -1,7 +1,6 @@ from typing import Any, Callable, Literal import mesop.labs as mel -from mesop.examples.web_component.gemini_live.utils import filter_events @mel.web_component(path="./audio_recorder.js") @@ -44,12 +43,10 @@ def audio_recorder( """ return mel.insert_web_component( name="audio-recorder", - events=filter_events( - { - "dataEvent": on_data, - "stateChangeEvent": on_state_change, - } - ), + events={ + "dataEvent": on_data, + "stateChangeEvent": on_state_change, + }, properties={ "state": state, }, diff --git a/mesop/examples/web_component/gemini_live/gemini_live.py b/mesop/examples/web_component/gemini_live/gemini_live.py index 36feb4ba..70517a88 100644 --- a/mesop/examples/web_component/gemini_live/gemini_live.py +++ b/mesop/examples/web_component/gemini_live/gemini_live.py @@ -1,7 +1,6 @@ from typing import Any, Callable import mesop.labs as mel -from mesop.examples.web_component.gemini_live.utils import filter_events _HOST = "generativelanguage.googleapis.com" @@ -44,13 +43,11 @@ def gemini_live( """ return mel.insert_web_component( name="gemini-live", - events=filter_events( - { - "startEvent": on_start, - "stopEvent": on_stop, - "toolCallEvent": on_tool_call, - } - ), + events={ + "startEvent": on_start, + "stopEvent": on_stop, + "toolCallEvent": on_tool_call, + }, properties={ "api_config": api_config, "enabled": enabled, diff --git a/mesop/examples/web_component/gemini_live/utils.py b/mesop/examples/web_component/gemini_live/utils.py deleted file mode 100644 index ab60d3ae..00000000 --- a/mesop/examples/web_component/gemini_live/utils.py +++ /dev/null @@ -1,8 +0,0 @@ -from typing import Any, Callable - -import mesop.labs as mel - - -def filter_events(events: dict[str, Callable[[mel.WebEvent], Any] | None]): - """Helper function for filtering out web component events that do not have a callback.""" - return {event: callback for event, callback in events.items() if callback} diff --git a/mesop/examples/web_component/gemini_live/video_recorder.py b/mesop/examples/web_component/gemini_live/video_recorder.py index d62079ed..3dc06e23 100644 --- a/mesop/examples/web_component/gemini_live/video_recorder.py +++ b/mesop/examples/web_component/gemini_live/video_recorder.py @@ -1,7 +1,6 @@ from typing import Any, Callable, Literal import mesop.labs as mel -from mesop.examples.web_component.gemini_live.utils import filter_events @mel.web_component(path="./video_recorder.js") @@ -39,12 +38,10 @@ def video_recorder( """ return mel.insert_web_component( name="video-recorder", - events=filter_events( - { - "dataEvent": on_data, - "stateChangeEvent": on_state_change, - } - ), + events={ + "dataEvent": on_data, + "stateChangeEvent": on_state_change, + }, properties={ "enabled": enabled, "state": state,