From 0be141fd30008e0eb4a0e31c2380377748a26514 Mon Sep 17 00:00:00 2001 From: Lendemor Date: Thu, 3 Oct 2024 16:37:10 +0200 Subject: [PATCH] type check for event handler if spec arg are typed --- .../radix/themes/components/slider.py | 6 +++- reflex/event.py | 30 +++++++++++++++---- reflex/utils/exceptions.py | 6 +++- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/reflex/components/radix/themes/components/slider.py b/reflex/components/radix/themes/components/slider.py index 3cf2e172d..f9da1fbaa 100644 --- a/reflex/components/radix/themes/components/slider.py +++ b/reflex/components/radix/themes/components/slider.py @@ -13,6 +13,10 @@ from ..base import ( ) +def _on_change_spec(value: List[Union[float, int]]): + return [value] + + class Slider(RadixThemesComponent): """Provides user selection from a range of values.""" @@ -64,7 +68,7 @@ class Slider(RadixThemesComponent): _rename_props = {"onChange": "onValueChange"} # Fired when the value of the slider changes. - on_change: EventHandler[lambda e0: [e0]] + on_change: EventHandler[_on_change_spec] # Fired when a thumb is released after being dragged. on_value_commit: EventHandler[lambda e0: [e0]] diff --git a/reflex/event.py b/reflex/event.py index 95358ace1..23a8812e6 100644 --- a/reflex/event.py +++ b/reflex/event.py @@ -22,7 +22,11 @@ from typing_extensions import get_args, get_origin from reflex import constants from reflex.utils import format -from reflex.utils.exceptions import EventFnArgMismatch, EventHandlerArgMismatch +from reflex.utils.exceptions import ( + EventFnArgMismatch, + EventHandlerArgMismatch, + EventHandlerArgTypeMismatch, +) from reflex.utils.types import ArgsSpec, GenericType from reflex.vars import VarData from reflex.vars.base import LiteralVar, Var @@ -888,6 +892,7 @@ def call_event_handler( Raises: EventHandlerArgMismatch: if number of arguments expected by event_handler doesn't match the spec. + EventHandlerArgTypeMismatch: if the annotations of args accepted by event_handler differs from the spec of the event trigger. Returns: The event spec from calling the event handler. @@ -898,11 +903,12 @@ def call_event_handler( # Handle partial application of EventSpec args return event_handler.add_args(*parsed_args) - args = inspect.getfullargspec(event_handler.fn).args + fullspec = inspect.getfullargspec(event_handler.fn) + + args = fullspec.args n_args = len(args) - 1 # subtract 1 for bound self arg - if n_args == len(parsed_args): - return event_handler(*parsed_args) # type: ignore - else: + + if n_args != len(parsed_args): raise EventHandlerArgMismatch( "The number of arguments accepted by " f"{event_handler.fn.__qualname__} ({n_args}) " @@ -911,6 +917,20 @@ def call_event_handler( "See https://reflex.dev/docs/events/event-arguments/" ) + # check that args of event handler are matching the spec if type hints are provided + for arg, arg_type in inspect.getfullargspec(arg_spec).annotations.items(): + if arg not in fullspec.annotations: + continue + if arg_type == fullspec.annotations[arg]: + print(f"continue for {arg}: {arg_type} == {fullspec.annotations[arg]}") + continue + else: + raise EventHandlerArgTypeMismatch( + f"Type mismatch for argument {arg} in {event_handler.fn.__qualname__}. Expected {arg_type} but got {fullspec.annotations[arg]}" + ) + + return event_handler(*parsed_args) # type: ignore + def unwrap_var_annotation(annotation: GenericType): """Unwrap a Var annotation or return it as is if it's not Var[X]. diff --git a/reflex/utils/exceptions.py b/reflex/utils/exceptions.py index 7c3532861..be49af563 100644 --- a/reflex/utils/exceptions.py +++ b/reflex/utils/exceptions.py @@ -82,7 +82,11 @@ class MatchTypeError(ReflexError, TypeError): class EventHandlerArgMismatch(ReflexError, TypeError): - """Raised when the number of args accepted by an EventHandler is differs from that provided by the event trigger.""" + """Raised when the number of args accepted by an EventHandler differs from that provided by the event trigger.""" + + +class EventHandlerArgTypeMismatch(ReflexError, TypeError): + """Raised when the annotations of args accepted by an EventHandler differs from the spec of the event trigger.""" class EventFnArgMismatch(ReflexError, TypeError):