diff --git a/reflex/.templates/web/utils/state.js b/reflex/.templates/web/utils/state.js index efb18c6049..676ace47d6 100644 --- a/reflex/.templates/web/utils/state.js +++ b/reflex/.templates/web/utils/state.js @@ -144,18 +144,8 @@ export const applyEvent = async (event, socket) => { return false; } - if (event.name == "_set_cookie") { - cookies.set(event.payload.key, event.payload.value, { path: "/" }); - return false; - } - if (event.name == "_remove_cookie") { - cookies.remove(event.payload.key, { path: "/", ...event.payload.options }) - return false; - } - - if (event.name == "_set_local_storage") { - localStorage.setItem(event.payload.key, event.payload.value); + cookies.remove(event.payload.key, { ...event.payload.options }) return false; } diff --git a/reflex/__init__.py b/reflex/__init__.py index f4d897cb8b..77811efc80 100644 --- a/reflex/__init__.py +++ b/reflex/__init__.py @@ -12,14 +12,12 @@ from .base import Base as Base from .compiler.utils import get_asset_path from .components import * -from .components.base.script import client_side from .components.component import custom_component as memo from .components.graphing import recharts as recharts from .components.graphing.victory import data as data from .config import Config as Config from .config import DBConfig as DBConfig from .constants import Env as Env -from .event import EVENT_ARG as EVENT_ARG from .event import EventChain as EventChain from .event import FileUpload as upload_files from .event import background as background @@ -31,9 +29,7 @@ from .event import remove_cookie as remove_cookie from .event import remove_local_storage as remove_local_storage from .event import set_clipboard as set_clipboard -from .event import set_cookie as set_cookie from .event import set_focus as set_focus -from .event import set_local_storage as set_local_storage from .event import set_value as set_value from .event import window_alert as window_alert from .middleware import Middleware as Middleware @@ -48,4 +44,3 @@ from .style import toggle_color_mode as toggle_color_mode from .vars import Var as Var from .vars import cached_var as cached_var -from .vars import get_local_storage as get_local_storage diff --git a/reflex/components/base/script.py b/reflex/components/base/script.py index 67470f2738..e379a1824c 100644 --- a/reflex/components/base/script.py +++ b/reflex/components/base/script.py @@ -7,9 +7,7 @@ from typing import Any, Union from reflex.components.component import Component -from reflex.event import EventChain -from reflex.utils import console -from reflex.vars import BaseVar, Var +from reflex.vars import Var class Script(Component): @@ -72,26 +70,3 @@ def get_event_triggers(self) -> dict[str, Union[Var, Any]]: "on_ready": lambda: [], "on_error": lambda: [], } - - -def client_side(javascript_code) -> Var[EventChain]: - """Create an event handler that executes arbitrary javascript code. - - The provided code will have access to `args`, which come from the event itself. - The code may call functions or reference variables defined in a previously - included rx.script function. - - Args: - javascript_code: The code to execute. - - Returns: - An EventChain, passable to any component, that will execute the client side javascript - when triggered. - """ - console.deprecate( - feature_name="rx.client_side", - reason="and has been replaced by rx.call_script, which can be used from backend EventHandler too", - deprecation_version="0.2.9", - removal_version="0.3.0", - ) - return BaseVar(_var_name=f"...args => {{{javascript_code}}}", _var_type=EventChain) diff --git a/reflex/components/component.py b/reflex/components/component.py index 518fc2dc6a..b290d996eb 100644 --- a/reflex/components/component.py +++ b/reflex/components/component.py @@ -307,29 +307,6 @@ def get_event_triggers(self) -> Dict[str, Any]: Returns: The event triggers. """ - deprecated_triggers = self.get_triggers() - if deprecated_triggers: - console.deprecate( - feature_name=f"get_triggers ({self.__class__.__name__})", - reason="replaced by get_event_triggers", - deprecation_version="0.2.8", - removal_version="0.3.1", - ) - deprecated_triggers = { - trigger: lambda: [] for trigger in deprecated_triggers - } - else: - deprecated_triggers = {} - - deprecated_controlled_triggers = self.get_controlled_triggers() - if deprecated_controlled_triggers: - console.deprecate( - feature_name=f"get_controlled_triggers ({self.__class__.__name__})", - reason="replaced by get_event_triggers", - deprecation_version="0.2.8", - removal_version="0.3.0", - ) - return { EventTriggers.ON_FOCUS: lambda: [], EventTriggers.ON_BLUR: lambda: [], @@ -346,26 +323,8 @@ def get_event_triggers(self) -> Dict[str, Any]: EventTriggers.ON_SCROLL: lambda: [], EventTriggers.ON_MOUNT: lambda: [], EventTriggers.ON_UNMOUNT: lambda: [], - **deprecated_triggers, - **deprecated_controlled_triggers, } - def get_triggers(self) -> Set[str]: - """Get the triggers for non controlled events [DEPRECATED]. - - Returns: - A set of non controlled triggers. - """ - return set() - - def get_controlled_triggers(self) -> Dict[str, Var]: - """Get the event triggers that pass the component's value to the handler [DEPRECATED]. - - Returns: - A dict mapping the event trigger to the var that is passed to the handler. - """ - return {} - def __repr__(self) -> str: """Represent the component in React. diff --git a/reflex/event.py b/reflex/event.py index 450c7cd980..c31353db6d 100644 --- a/reflex/event.py +++ b/reflex/event.py @@ -210,10 +210,6 @@ class FrontendEvent(Base): value: Any = None -# The default event argument. -EVENT_ARG = BaseVar(_var_name="_e", _var_type=FrontendEvent, _var_is_local=True) - - class FileUpload(Base): """Class to represent a file upload.""" @@ -320,31 +316,7 @@ def set_value(ref: str, value: Any) -> EventSpec: ) -def set_cookie(key: str, value: str) -> EventSpec: - """Set a cookie on the frontend. - - Args: - key: The key identifying the cookie. - value: The value contained in the cookie. - - Returns: - EventSpec: An event to set a cookie. - """ - console.deprecate( - feature_name=f"rx.set_cookie", - reason="and has been replaced by rx.Cookie, which can be used as a state var", - deprecation_version="0.2.9", - removal_version="0.3.0", - ) - return server_side( - "_set_cookie", - get_fn_signature(set_cookie), - key=key, - value=value, - ) - - -def remove_cookie(key: str, options: dict[str, Any] = {}) -> EventSpec: # noqa: B006 +def remove_cookie(key: str, options: dict[str, Any] | None = None) -> EventSpec: """Remove a cookie on the frontend. Args: @@ -354,6 +326,8 @@ def remove_cookie(key: str, options: dict[str, Any] = {}) -> EventSpec: # noqa: Returns: EventSpec: An event to remove a cookie. """ + options = options or {} + options["path"] = options.get("path", "/") return server_side( "_remove_cookie", get_fn_signature(remove_cookie), @@ -362,30 +336,6 @@ def remove_cookie(key: str, options: dict[str, Any] = {}) -> EventSpec: # noqa: ) -def set_local_storage(key: str, value: str) -> EventSpec: - """Set a value in the local storage on the frontend. - - Args: - key: The key identifying the variable in the local storage. - value: The value contained in the local storage. - - Returns: - EventSpec: An event to set a key-value in local storage. - """ - console.deprecate( - feature_name=f"rx.set_local_storage", - reason="and has been replaced by rx.LocalStorage, which can be used as a state var", - deprecation_version="0.2.9", - removal_version="0.3.0", - ) - return server_side( - "_set_local_storage", - get_fn_signature(set_local_storage), - key=key, - value=value, - ) - - def clear_local_storage() -> EventSpec: """Set a value in the local storage on the frontend. @@ -409,7 +359,7 @@ def remove_local_storage(key: str) -> EventSpec: """ return server_side( "_remove_local_storage", - get_fn_signature(clear_local_storage), + get_fn_signature(remove_local_storage), key=key, ) diff --git a/reflex/utils/format.py b/reflex/utils/format.py index 437b4c4650..cf65a86722 100644 --- a/reflex/utils/format.py +++ b/reflex/utils/format.py @@ -291,7 +291,7 @@ def format_prop( TypeError: If the prop is not valid. """ # import here to avoid circular import. - from reflex.event import EVENT_ARG, EventChain + from reflex.event import EventChain try: # Handle var props. @@ -304,17 +304,14 @@ def format_prop( # Handle event props. elif isinstance(prop, EventChain): - if prop.args_spec is None: - arg_def = f"{EVENT_ARG}" + sig = inspect.signature(prop.args_spec) # type: ignore + if sig.parameters: + arg_def = ",".join(f"_{p}" for p in sig.parameters) + arg_def = f"({arg_def})" else: - sig = inspect.signature(prop.args_spec) - if sig.parameters: - arg_def = ",".join(f"_{p}" for p in sig.parameters) - arg_def = f"({arg_def})" - else: - # add a default argument for addEvents if none were specified in prop.args_spec - # used to trigger the preventDefault() on the event. - arg_def = "(_e)" + # add a default argument for addEvents if none were specified in prop.args_spec + # used to trigger the preventDefault() on the event. + arg_def = "(_e)" chain = ",".join([format_event(event) for event in prop.events]) event = f"addEvents([{chain}], {arg_def})" diff --git a/reflex/vars.py b/reflex/vars.py index a1a3d72bc2..862d443376 100644 --- a/reflex/vars.py +++ b/reflex/vars.py @@ -1518,34 +1518,3 @@ class NoRenderImportVar(ImportVar): """A import that doesn't need to be rendered.""" render: Optional[bool] = False - - -def get_local_storage(key: Var | str | None = None) -> BaseVar: - """Provide a base var as payload to get local storage item(s). - - Args: - key: Key to obtain value in the local storage. - - Returns: - A BaseVar of the local storage method/function to call. - - Raises: - TypeError: if the wrong key type is provided. - """ - console.deprecate( - feature_name=f"rx.get_local_storage", - reason="and has been replaced by rx.LocalStorage, which can be used as a state var", - deprecation_version="0.2.9", - removal_version="0.3.0", - ) - if key is not None: - if not (isinstance(key, Var) and key._var_type == str) and not isinstance( - key, str - ): - type_ = type(key) if not isinstance(key, Var) else key._var_type - raise TypeError( - f"Local storage keys can only be of type `str` or `var` of type `str`. Got `{type_}` instead." - ) - key = key._var_full_name if isinstance(key, Var) else format.wrap(key, "'") - return BaseVar(_var_name=f"localStorage.getItem({key})", _var_type=str) - return BaseVar(_var_name="getAllLocalStorageItems()", _var_type=Dict) diff --git a/tests/components/test_component.py b/tests/components/test_component.py index f1979fa656..998f55c468 100644 --- a/tests/components/test_component.py +++ b/tests/components/test_component.py @@ -7,7 +7,7 @@ from reflex.components.component import Component, CustomComponent, custom_component from reflex.components.layout.box import Box from reflex.constants import EventTriggers -from reflex.event import EVENT_ARG, EventHandler +from reflex.event import EventHandler from reflex.state import State from reflex.style import Style from reflex.utils import imports @@ -64,15 +64,16 @@ class TestComponent2(Component): # A test list prop. arr: Var[List[str]] - def get_controlled_triggers(self) -> Dict[str, Var]: + def get_event_triggers(self) -> Dict[str, Any]: """Test controlled triggers. Returns: Test controlled triggers. """ return { - "on_open": EVENT_ARG, - "on_close": EVENT_ARG, + **super().get_event_triggers(), + "on_open": lambda e0: [e0], + "on_close": lambda e0: [e0], } def _get_imports(self) -> imports.ImportDict: @@ -361,17 +362,6 @@ def test_var_props(component1, test_state): assert c1.number.equals(test_state.num) -def test_get_controlled_triggers(component1, component2): - """Test that we can get the controlled triggers of a component. - - Args: - component1: A test component. - component2: A test component. - """ - assert component1().get_controlled_triggers() == dict() - assert set(component2().get_controlled_triggers()) == {"on_open", "on_close"} - - def test_get_event_triggers(component1, component2): """Test that we can get the triggers of a component. @@ -496,6 +486,10 @@ def test_invalid_event_handler_args(component2, test_state): # This is not okay. with pytest.raises(ValueError): component2.create(on_click=test_state.do_something_arg) + component2.create(on_open=test_state.do_something) + component2.create( + on_open=[test_state.do_something_arg, test_state.do_something] + ) # However lambdas are okay. component2.create(on_click=lambda: test_state.do_something_arg(1)) component2.create( @@ -509,10 +503,6 @@ def test_invalid_event_handler_args(component2, test_state): # This is okay. component2.create(on_open=test_state.do_something_arg) - # do_something is allowed and will simply run while ignoring the arg - component2.create(on_open=test_state.do_something) - component2.create(on_open=[test_state.do_something_arg, test_state.do_something]) - def test_get_hooks_nested(component1, component2, component3): """Test that a component returns hooks from child components. diff --git a/tests/test_event.py b/tests/test_event.py index b6d4d4def1..7dcb3ef188 100644 --- a/tests/test_event.py +++ b/tests/test_event.py @@ -206,21 +206,6 @@ def test_set_value(): ) -def test_set_cookie(): - """Test the event set_cookie.""" - spec = event.set_cookie("testkey", "testvalue") - assert isinstance(spec, EventSpec) - assert spec.handler.fn.__qualname__ == "_set_cookie" - assert spec.args[0][0].equals(Var.create_safe("key")) - assert spec.args[0][1].equals(Var.create_safe("testkey")) - assert spec.args[1][0].equals(Var.create_safe("value")) - assert spec.args[1][1].equals(Var.create_safe("testvalue")) - assert ( - format.format_event(spec) - == 'Event("_set_cookie", {key:`testkey`,value:`testvalue`})' - ) - - def test_remove_cookie(): """Test the event remove_cookie.""" spec = event.remove_cookie("testkey") @@ -229,17 +214,17 @@ def test_remove_cookie(): assert spec.args[0][0].equals(Var.create_safe("key")) assert spec.args[0][1].equals(Var.create_safe("testkey")) assert spec.args[1][0].equals(Var.create_safe("options")) - assert spec.args[1][1].equals(Var.create_safe({})) + assert spec.args[1][1].equals(Var.create_safe({"path": "/"})) assert ( format.format_event(spec) - == 'Event("_remove_cookie", {key:`testkey`,options:{}})' + == 'Event("_remove_cookie", {key:`testkey`,options:{"path": "/"}})' ) def test_remove_cookie_with_options(): """Test the event remove_cookie with options.""" options = { - "path": "/", + "path": "/foo", "domain": "example.com", "secure": True, "sameSite": "strict", @@ -257,21 +242,6 @@ def test_remove_cookie_with_options(): ) -def test_set_local_storage(): - """Test the event set_local_storage.""" - spec = event.set_local_storage("testkey", "testvalue") - assert isinstance(spec, EventSpec) - assert spec.handler.fn.__qualname__ == "_set_local_storage" - assert spec.args[0][0].equals(Var.create_safe("key")) - assert spec.args[0][1].equals(Var.create_safe("testkey")) - assert spec.args[1][0].equals(Var.create_safe("value")) - assert spec.args[1][1].equals(Var.create_safe("testvalue")) - assert ( - format.format_event(spec) - == 'Event("_set_local_storage", {key:`testkey`,value:`testvalue`})' - ) - - def test_clear_local_storage(): """Test the event clear_local_storage.""" spec = event.clear_local_storage() diff --git a/tests/test_var.py b/tests/test_var.py index 7dcfde050d..9efb5fb783 100644 --- a/tests/test_var.py +++ b/tests/test_var.py @@ -12,7 +12,6 @@ ComputedVar, ImportVar, Var, - get_local_storage, ) test_vars = [ @@ -626,62 +625,6 @@ def test_import_var(import_var, expected): assert import_var.name == expected -@pytest.mark.parametrize( - "key, expected", - [ - ( - "test_key", - BaseVar(_var_name="localStorage.getItem('test_key')", _var_type=str), - ), - ( - BaseVar(_var_name="key_var", _var_type=str), - BaseVar(_var_name="localStorage.getItem(key_var)", _var_type=str), - ), - ( - BaseState.val, - BaseVar(_var_name="localStorage.getItem(base_state.val)", _var_type=str), - ), - (None, BaseVar(_var_name="getAllLocalStorageItems()", _var_type=Dict)), - ], -) -def test_get_local_storage(key, expected): - """Test that the right BaseVar is return when get_local_storage is called. - - Args: - key: Local storage key. - expected: expected BaseVar. - - """ - local_storage = get_local_storage(key) - assert local_storage._var_name == expected._var_name - assert local_storage._var_type == expected._var_type - - -@pytest.mark.parametrize( - "key", - [ - ["list", "values"], - {"name": "dict"}, - 10, - BaseVar(_var_name="key_var", _var_type=List), - BaseVar(_var_name="key_var", _var_type=Dict[str, str]), - ], -) -def test_get_local_storage_raise_error(key): - """Test that a type error is thrown when the wrong key type is provided. - - Args: - key: Local storage key. - """ - with pytest.raises(TypeError) as err: - get_local_storage(key) - type_ = type(key) if not isinstance(key, Var) else key._var_type - assert ( - err.value.args[0] - == f"Local storage keys can only be of type `str` or `var` of type `str`. Got `{type_}` instead." - ) - - @pytest.mark.parametrize( "out, expected", [ diff --git a/tests/utils/test_format.py b/tests/utils/test_format.py index 79264d0cd6..a6809cf29e 100644 --- a/tests/utils/test_format.py +++ b/tests/utils/test_format.py @@ -4,7 +4,7 @@ import pytest from reflex.components.tags.tag import Tag -from reflex.event import EVENT_ARG, EventChain, EventHandler, EventSpec +from reflex.event import EventChain, EventHandler, EventSpec from reflex.style import Style from reflex.utils import format from reflex.vars import BaseVar, Var @@ -290,24 +290,6 @@ def test_format_cond(condition: str, true_value: str, false_value: str, expected }, r'{{"a": "foo \"{ \"bar\" }\" baz", "b": val}}', ), - ( - EventChain( - events=[EventSpec(handler=EventHandler(fn=mock_event))], args_spec=None - ), - '{_e => addEvents([Event("mock_event", {})], _e)}', - ), - ( - EventChain( - events=[ - EventSpec( - handler=EventHandler(fn=mock_event), - args=((Var.create_safe("arg"), EVENT_ARG.target.value),), - ) - ], - args_spec=None, - ), - '{_e => addEvents([Event("mock_event", {arg:_e.target.value})], _e)}', - ), ({"a": "red", "b": "blue"}, '{{"a": "red", "b": "blue"}}'), (BaseVar(_var_name="var", _var_type="int"), "{var}"), (