Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ENG-3943]type check for event handler if spec arg are typed #4046

Merged
merged 31 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
0be141f
type check for event handler if spec arg are typed
Lendemor Oct 3, 2024
26eb358
fix the typecheck logic
Lendemor Oct 3, 2024
df289b3
Merge branch 'main' into lendemor/type_check_event_handler
Lendemor Oct 15, 2024
d2a32e4
rearrange logic pieces
adhami3310 Oct 15, 2024
9ce6320
add try except
adhami3310 Oct 15, 2024
437848f
add try except around compare
adhami3310 Oct 15, 2024
eecc94f
change form and improve type checking
adhami3310 Oct 15, 2024
30501a5
print key instead
adhami3310 Oct 15, 2024
26f62a4
dang it darglint
adhami3310 Oct 15, 2024
f41b6e4
change wording
adhami3310 Oct 15, 2024
233033c
add basic test to cover it
adhami3310 Oct 16, 2024
b17ed24
add a slightly more complicated test
adhami3310 Oct 16, 2024
2ef7ae4
challenge it a bit by doing small capital list
adhami3310 Oct 16, 2024
fcf6aa6
merging
adhami3310 Oct 22, 2024
0ec59aa
add multiple argspec
adhami3310 Oct 22, 2024
7a62265
fix slider event order
adhami3310 Oct 22, 2024
1151419
i hate 3.9
adhami3310 Oct 22, 2024
92190c2
add note for UnionType
adhami3310 Oct 22, 2024
95711b8
move function to types
adhami3310 Oct 28, 2024
dd1ddd6
merging
adhami3310 Oct 28, 2024
cec4e3c
add a test for type hint is subclass
adhami3310 Oct 28, 2024
978c059
make on submit dict str any
adhami3310 Oct 28, 2024
024efa3
add testing for dict cases
adhami3310 Oct 28, 2024
b09907c
add check against any
adhami3310 Oct 29, 2024
cbdaca7
accept dict str str
adhami3310 Oct 29, 2024
40e3de9
bruh i used i twice
adhami3310 Oct 29, 2024
e9a2dc3
escape strings and print actual error message
adhami3310 Oct 29, 2024
94c15f4
disable the error and print deprecation warning instead
adhami3310 Oct 29, 2024
312bb42
disable tests
adhami3310 Oct 29, 2024
074b339
fix doc message
adhami3310 Oct 29, 2024
c6a625f
Merge branch 'main' into lendemor/type_check_event_handler
adhami3310 Oct 31, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions reflex/components/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,7 @@ def __init__(self, *args, **kwargs):
kwargs["event_triggers"][key] = self._create_event_chain(
value=value, # type: ignore
args_spec=component_specific_triggers[key],
key=key,
)

# Remove any keys that were added as events.
Expand Down Expand Up @@ -540,12 +541,14 @@ def _create_event_chain(
List[Union[EventHandler, EventSpec, EventVar]],
Callable,
],
key: Optional[str] = None,
) -> Union[EventChain, Var]:
"""Create an event chain from a variety of input types.

Args:
args_spec: The args_spec of the event trigger being bound.
value: The value to create the event chain from.
key: The key of the event trigger being bound.

Returns:
The event chain.
Expand All @@ -560,7 +563,7 @@ def _create_event_chain(
elif isinstance(value, EventVar):
value = [value]
elif issubclass(value._var_type, (EventChain, EventSpec)):
return self._create_event_chain(args_spec, value.guess_type())
return self._create_event_chain(args_spec, value.guess_type(), key=key)
else:
raise ValueError(
f"Invalid event chain: {str(value)} of type {value._var_type}"
Expand All @@ -579,10 +582,10 @@ def _create_event_chain(
for v in value:
if isinstance(v, (EventHandler, EventSpec)):
# Call the event handler to get the event.
events.append(call_event_handler(v, args_spec))
events.append(call_event_handler(v, args_spec, key=key))
elif isinstance(v, Callable):
# Call the lambda to get the event chain.
result = call_event_fn(v, args_spec)
result = call_event_fn(v, args_spec, key=key)
if isinstance(result, Var):
raise ValueError(
f"Invalid event chain: {v}. Cannot use a Var-returning "
Expand All @@ -599,7 +602,7 @@ def _create_event_chain(
result = call_event_fn(value, args_spec)
if isinstance(result, Var):
# Recursively call this function if the lambda returned an EventChain Var.
return self._create_event_chain(args_spec, result)
return self._create_event_chain(args_spec, result, key=key)
events = [*result]

# Otherwise, raise an error.
Expand Down Expand Up @@ -1722,6 +1725,7 @@ def __init__(self, *args, **kwargs):
args_spec=event_triggers_in_component_declaration.get(
key, empty_event
),
key=key,
)
self.props[format.to_camel_case(key)] = value
continue
Expand Down
11 changes: 10 additions & 1 deletion reflex/components/el/elements/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,15 @@ def on_submit_event_spec() -> Tuple[Var[Dict[str, Any]]]:
return (FORM_DATA,)


def on_submit_string_event_spec() -> Tuple[Var[Dict[str, str]]]:
"""Event handler spec for the on_submit event.

Returns:
The event handler spec.
"""
return (FORM_DATA,)


class Form(BaseHTML):
"""Display the form element."""

Expand Down Expand Up @@ -150,7 +159,7 @@ class Form(BaseHTML):
handle_submit_unique_name: Var[str]

# Fired when the form is submitted
on_submit: EventHandler[on_submit_event_spec]
on_submit: EventHandler[on_submit_event_spec, on_submit_string_event_spec]

@classmethod
def create(cls, *children, **props):
Expand Down
5 changes: 4 additions & 1 deletion reflex/components/el/elements/forms.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ class Fieldset(Element):
...

def on_submit_event_spec() -> Tuple[Var[Dict[str, Any]]]: ...
def on_submit_string_event_spec() -> Tuple[Var[Dict[str, str]]]: ...

class Form(BaseHTML):
@overload
Expand Down Expand Up @@ -337,7 +338,9 @@ class Form(BaseHTML):
on_mouse_over: Optional[EventType[[]]] = None,
on_mouse_up: Optional[EventType[[]]] = None,
on_scroll: Optional[EventType[[]]] = None,
on_submit: Optional[EventType[Dict[str, Any]]] = None,
on_submit: Optional[
Union[EventType[Dict[str, Any]], EventType[Dict[str, str]]]
] = None,
on_unmount: Optional[EventType[[]]] = None,
**props,
) -> "Form":
Expand Down
12 changes: 9 additions & 3 deletions reflex/components/radix/primitives/form.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,9 @@ class FormRoot(FormComponent, HTMLForm):
on_mouse_over: Optional[EventType[[]]] = None,
on_mouse_up: Optional[EventType[[]]] = None,
on_scroll: Optional[EventType[[]]] = None,
on_submit: Optional[EventType[Dict[str, Any]]] = None,
on_submit: Optional[
Union[EventType[Dict[str, Any]], EventType[Dict[str, str]]]
] = None,
on_unmount: Optional[EventType[[]]] = None,
**props,
) -> "FormRoot":
Expand Down Expand Up @@ -596,7 +598,9 @@ class Form(FormRoot):
on_mouse_over: Optional[EventType[[]]] = None,
on_mouse_up: Optional[EventType[[]]] = None,
on_scroll: Optional[EventType[[]]] = None,
on_submit: Optional[EventType[Dict[str, Any]]] = None,
on_submit: Optional[
Union[EventType[Dict[str, Any]], EventType[Dict[str, str]]]
] = None,
on_unmount: Optional[EventType[[]]] = None,
**props,
) -> "Form":
Expand Down Expand Up @@ -720,7 +724,9 @@ class FormNamespace(ComponentNamespace):
on_mouse_over: Optional[EventType[[]]] = None,
on_mouse_up: Optional[EventType[[]]] = None,
on_scroll: Optional[EventType[[]]] = None,
on_submit: Optional[EventType[Dict[str, Any]]] = None,
on_submit: Optional[
Union[EventType[Dict[str, Any]], EventType[Dict[str, str]]]
] = None,
on_unmount: Optional[EventType[[]]] = None,
**props,
) -> "Form":
Expand Down
22 changes: 7 additions & 15 deletions reflex/components/radix/themes/components/slider.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,23 @@

from __future__ import annotations

from typing import List, Literal, Optional, Tuple, Union
from typing import List, Literal, Optional, Union

from reflex.components.component import Component
from reflex.components.core.breakpoints import Responsive
from reflex.event import EventHandler
from reflex.event import EventHandler, identity_event
from reflex.vars.base import Var

from ..base import (
LiteralAccentColor,
RadixThemesComponent,
)


def on_value_event_spec(
value: Var[List[Union[int, float]]],
) -> Tuple[Var[List[Union[int, float]]]]:
"""Event handler spec for the value event.

Args:
value: The value of the event.

Returns:
The event handler spec.
"""
return (value,) # type: ignore
on_value_event_spec = (
identity_event(list[Union[int, float]]),
identity_event(list[int]),
identity_event(list[float]),
)


class Slider(RadixThemesComponent):
Expand Down
28 changes: 21 additions & 7 deletions reflex/components/radix/themes/components/slider.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@
# ------------------- DO NOT EDIT ----------------------
# This file was generated by `reflex/utils/pyi_generator.py`!
# ------------------------------------------------------
from typing import Any, Dict, List, Literal, Optional, Tuple, Union, overload
from typing import Any, Dict, List, Literal, Optional, Union, overload

from reflex.components.core.breakpoints import Breakpoints
from reflex.event import EventType
from reflex.event import EventType, identity_event
from reflex.style import Style
from reflex.vars.base import Var

from ..base import RadixThemesComponent

def on_value_event_spec(
value: Var[List[Union[int, float]]],
) -> Tuple[Var[List[Union[int, float]]]]: ...
on_value_event_spec = (
identity_event(list[Union[int, float]]),
identity_event(list[int]),
identity_event(list[float]),
)

class Slider(RadixThemesComponent):
@overload
Expand Down Expand Up @@ -138,7 +140,13 @@ class Slider(RadixThemesComponent):
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
on_blur: Optional[EventType[[]]] = None,
on_change: Optional[EventType[List[Union[int, float]]]] = None,
on_change: Optional[
Union[
EventType[list[Union[int, float]]],
EventType[list[int]],
EventType[list[float]],
]
] = None,
on_click: Optional[EventType[[]]] = None,
on_context_menu: Optional[EventType[[]]] = None,
on_double_click: Optional[EventType[[]]] = None,
Expand All @@ -153,7 +161,13 @@ class Slider(RadixThemesComponent):
on_mouse_up: Optional[EventType[[]]] = None,
on_scroll: Optional[EventType[[]]] = None,
on_unmount: Optional[EventType[[]]] = None,
on_value_commit: Optional[EventType[List[Union[int, float]]]] = None,
on_value_commit: Optional[
Union[
EventType[list[Union[int, float]]],
EventType[list[int]],
EventType[list[float]],
]
] = None,
**props,
) -> "Slider":
"""Create a Slider component.
Expand Down
Loading
Loading