From 1f5c2b67b6d519e19e6fe772f8831f215e8b70fb Mon Sep 17 00:00:00 2001 From: Khaleel Al-Adhami Date: Fri, 31 Jan 2025 19:19:21 -0800 Subject: [PATCH 1/5] adjust setter to include type annotation --- reflex/vars/base.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/reflex/vars/base.py b/reflex/vars/base.py index ec65c37111d..f9ee2792b93 100644 --- a/reflex/vars/base.py +++ b/reflex/vars/base.py @@ -933,7 +933,7 @@ def _get_setter(self) -> Callable[[BaseState, Any], None]: """ actual_name = self._var_field_name - def setter(state: BaseState, value: Any): + def setter(state: Any, value: Any): """Get the setter for the var. Args: @@ -951,6 +951,8 @@ def setter(state: BaseState, value: Any): else: setattr(state, actual_name, value) + setter.__annotations__["value"] = self._var_type + setter.__qualname__ = self._get_setter_name() return setter From 98dcd3dc7eabd6e0b5d03f53ba03b0a4bcdcba03 Mon Sep 17 00:00:00 2001 From: Khaleel Al-Adhami Date: Fri, 31 Jan 2025 19:30:14 -0800 Subject: [PATCH 2/5] apparently this discovered some bugs --- tests/integration/test_background_task.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/integration/test_background_task.py b/tests/integration/test_background_task.py index f312f81221f..976cb67008f 100644 --- a/tests/integration/test_background_task.py +++ b/tests/integration/test_background_task.py @@ -22,6 +22,10 @@ class State(rx.State): _task_id: int = 0 iterations: int = 10 + @rx.event + def set_iterations(self, value: str): + self.iterations = int(value) + @rx.event(background=True) async def handle_event(self): async with self: From 1196b5727bb4aca61981721fa0adfc6d918576d4 Mon Sep 17 00:00:00 2001 From: Khaleel Al-Adhami Date: Fri, 31 Jan 2025 19:44:39 -0800 Subject: [PATCH 3/5] remove some pyright ignores --- benchmarks/test_benchmark_compile_pages.py | 32 ++++++++++++++++------ tests/integration/test_background_task.py | 6 ++-- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/benchmarks/test_benchmark_compile_pages.py b/benchmarks/test_benchmark_compile_pages.py index 149fc613007..6cf39f60ca8 100644 --- a/benchmarks/test_benchmark_compile_pages.py +++ b/benchmarks/test_benchmark_compile_pages.py @@ -46,10 +46,26 @@ def render_multiple_pages(app, num: int): class State(rx.State): """The app state.""" - position: str - college: str - age: Tuple[int, int] = (18, 50) - salary: Tuple[int, int] = (0, 25000000) + position: rx.Field[str] + college: rx.Field[str] + age: rx.Field[Tuple[int, int]] = rx.field((18, 50)) + salary: rx.Field[Tuple[int, int]] = rx.field((0, 25000000)) + + @rx.event + def set_position(self, value: str): + self.position = value + + @rx.event + def set_college(self, value: str): + self.college = value + + @rx.event + def set_age(self, value: list[int]): + self.age = (value[0], value[1]) + + @rx.event + def set_salary(self, value: list[int]): + self.salary = (value[0], value[1]) comp1 = rx.center( rx.theme_panel(), @@ -74,13 +90,13 @@ class State(rx.State): rx.select( ["C", "PF", "SF", "PG", "SG"], placeholder="Select a position. (All)", - on_change=State.set_position, # pyright: ignore [reportAttributeAccessIssue] + on_change=State.set_position, size="3", ), rx.select( college, placeholder="Select a college. (All)", - on_change=State.set_college, # pyright: ignore [reportAttributeAccessIssue] + on_change=State.set_college, size="3", ), ), @@ -95,7 +111,7 @@ class State(rx.State): default_value=[18, 50], min=18, max=50, - on_value_commit=State.set_age, # pyright: ignore [reportAttributeAccessIssue] + on_value_commit=State.set_age, ), align_items="left", width="100%", @@ -110,7 +126,7 @@ class State(rx.State): default_value=[0, 25000000], min=0, max=25000000, - on_value_commit=State.set_salary, # pyright: ignore [reportAttributeAccessIssue] + on_value_commit=State.set_salary, ), align_items="left", width="100%", diff --git a/tests/integration/test_background_task.py b/tests/integration/test_background_task.py index 976cb67008f..91a1b5ae15e 100644 --- a/tests/integration/test_background_task.py +++ b/tests/integration/test_background_task.py @@ -20,7 +20,7 @@ def BackgroundTask(): class State(rx.State): counter: int = 0 _task_id: int = 0 - iterations: int = 10 + iterations: rx.Field[int] = rx.field(10) @rx.event def set_iterations(self, value: str): @@ -129,8 +129,8 @@ def index() -> rx.Component: rx.input( id="iterations", placeholder="Iterations", - value=State.iterations.to_string(), # pyright: ignore [reportAttributeAccessIssue] - on_change=State.set_iterations, # pyright: ignore [reportAttributeAccessIssue] + value=State.iterations.to_string(), + on_change=State.set_iterations, ), rx.button( "Delayed Increment", From 0cfdfd764babdadd140ab4a89c6105861b4f4464 Mon Sep 17 00:00:00 2001 From: Khaleel Al-Adhami Date: Fri, 31 Jan 2025 19:53:50 -0800 Subject: [PATCH 4/5] add str to int/float conversion --- reflex/state.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/reflex/state.py b/reflex/state.py index 92aaa471041..4ae623a3652 100644 --- a/reflex/state.py +++ b/reflex/state.py @@ -1779,12 +1779,25 @@ async def _process_event( hinted_args, (Base, BaseModelV1, BaseModelV2) ): payload[arg] = hinted_args(**value) - if isinstance(value, list) and (hinted_args is set or hinted_args is Set): + elif isinstance(value, list) and (hinted_args is set or hinted_args is Set): payload[arg] = set(value) - if isinstance(value, list) and ( + elif isinstance(value, list) and ( hinted_args is tuple or hinted_args is Tuple ): payload[arg] = tuple(value) + elif isinstance(value, str) and ( + hinted_args is int or hinted_args is float + ): + try: + payload[arg] = hinted_args(value) + except ValueError: + raise ValueError( + f"Received a string value ({value}) for {arg} but expected a {hinted_args}" + ) from None + else: + console.warn( + f"Received a string value ({value}) for {arg} but expected a {hinted_args}. A simple conversion was successful." + ) # Wrap the function in a try/except block. try: From dae30108c13dbe0947d56d06d57b81717b891358 Mon Sep 17 00:00:00 2001 From: Khaleel Al-Adhami Date: Fri, 31 Jan 2025 20:02:35 -0800 Subject: [PATCH 5/5] dang it darglint --- reflex/state.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/reflex/state.py b/reflex/state.py index 4ae623a3652..dceba7e3bc6 100644 --- a/reflex/state.py +++ b/reflex/state.py @@ -1742,6 +1742,9 @@ async def _process_event( Yields: StateUpdate object + + Raises: + ValueError: If a string value is received for an int or float type and cannot be converted. """ from reflex.utils import telemetry