Hello !" })}/>'
+ )
+
+
+def test_html_fstring_create():
+ class TestState(State):
+ """The app state."""
+
+ myvar: str = "Blue"
+
+ html = Html.create(f"
Hello {TestState.myvar}!
")
+
+ assert (
+ str(html.dangerouslySetInnerHTML) # type: ignore
+ == f'({{ ["__html"] : ("
Hello "+{str(TestState.myvar)}+"!
") }})'
+ )
+ assert (
+ str(html)
+ == f'
' # type: ignore
)
diff --git a/tests/components/core/test_match.py b/tests/components/core/test_match.py
index 883386ebdb..1843b914d5 100644
--- a/tests/components/core/test_match.py
+++ b/tests/components/core/test_match.py
@@ -1,4 +1,4 @@
-from typing import Tuple
+from typing import Dict, List, Tuple
import pytest
@@ -6,7 +6,7 @@
from reflex.components.core.match import Match
from reflex.state import BaseState
from reflex.utils.exceptions import MatchTypeError
-from reflex.vars import BaseVar
+from reflex.vars import Var
class MatchState(BaseState):
@@ -35,7 +35,7 @@ def test_match_components():
[match_child] = match_dict["children"]
assert match_child["name"] == "match"
- assert str(match_child["cond"]) == f"{{{MatchState.get_name()}.value}}"
+ assert str(match_child["cond"]) == f"{MatchState.get_name()}.value"
match_cases = match_child["match_cases"]
assert len(match_cases) == 6
@@ -44,7 +44,7 @@ def test_match_components():
assert match_cases[0][0]._var_type == int
first_return_value_render = match_cases[0][1].render()
assert first_return_value_render["name"] == "RadixThemesText"
- assert first_return_value_render["children"][0]["contents"] == "{`first value`}"
+ assert first_return_value_render["children"][0]["contents"] == '{"first value"}'
assert match_cases[1][0]._var_name == "2"
assert match_cases[1][0]._var_type == int
@@ -52,36 +52,36 @@ def test_match_components():
assert match_cases[1][1]._var_type == int
second_return_value_render = match_cases[1][2].render()
assert second_return_value_render["name"] == "RadixThemesText"
- assert second_return_value_render["children"][0]["contents"] == "{`second value`}"
+ assert second_return_value_render["children"][0]["contents"] == '{"second value"}'
assert match_cases[2][0]._var_name == "[1, 2]"
- assert match_cases[2][0]._var_type == list
+ assert match_cases[2][0]._var_type == List[int]
third_return_value_render = match_cases[2][1].render()
assert third_return_value_render["name"] == "RadixThemesText"
- assert third_return_value_render["children"][0]["contents"] == "{`third value`}"
+ assert third_return_value_render["children"][0]["contents"] == '{"third value"}'
- assert match_cases[3][0]._var_name == "random"
+ assert match_cases[3][0]._var_name == '"random"'
assert match_cases[3][0]._var_type == str
fourth_return_value_render = match_cases[3][1].render()
assert fourth_return_value_render["name"] == "RadixThemesText"
- assert fourth_return_value_render["children"][0]["contents"] == "{`fourth value`}"
+ assert fourth_return_value_render["children"][0]["contents"] == '{"fourth value"}'
- assert match_cases[4][0]._var_name == '{"foo": "bar"}'
- assert match_cases[4][0]._var_type == dict
+ assert match_cases[4][0]._var_name == '({ ["foo"] : "bar" })'
+ assert match_cases[4][0]._var_type == Dict[str, str]
fifth_return_value_render = match_cases[4][1].render()
assert fifth_return_value_render["name"] == "RadixThemesText"
- assert fifth_return_value_render["children"][0]["contents"] == "{`fifth value`}"
+ assert fifth_return_value_render["children"][0]["contents"] == '{"fifth value"}'
- assert match_cases[5][0]._var_name == f"(({MatchState.get_name()}.num) + (1))"
+ assert match_cases[5][0]._var_name == f"({MatchState.get_name()}.num + 1)"
assert match_cases[5][0]._var_type == int
fifth_return_value_render = match_cases[5][1].render()
assert fifth_return_value_render["name"] == "RadixThemesText"
- assert fifth_return_value_render["children"][0]["contents"] == "{`sixth value`}"
+ assert fifth_return_value_render["children"][0]["contents"] == '{"sixth value"}'
default = match_child["default"].render()
assert default["name"] == "RadixThemesText"
- assert default["children"][0]["contents"] == "{`default value`}"
+ assert default["children"][0]["contents"] == '{"default value"}'
@pytest.mark.parametrize(
@@ -99,12 +99,12 @@ def test_match_components():
(MatchState.string, f"{MatchState.value} - string"),
"default value",
),
- f"(() => {{ switch (JSON.stringify({MatchState.get_name()}.value)) {{case JSON.stringify(1): return (`first`); break;case JSON.stringify(2): case JSON.stringify(3): return "
- "(`second value`); break;case JSON.stringify([1, 2]): return (`third-value`); break;case JSON.stringify(`random`): "
- 'return (`fourth_value`); break;case JSON.stringify({"foo": "bar"}): return (`fifth value`); '
- f"break;case JSON.stringify((({MatchState.get_name()}.num) + (1))): return (`sixth value`); break;case JSON.stringify(`${{{MatchState.get_name()}.value}} - string`): "
- f"return ({MatchState.get_name()}.string); break;case JSON.stringify({MatchState.get_name()}.string): return (`${{{MatchState.get_name()}.value}} - string`); break;default: "
- "return (`default value`); break;};})()",
+ f'(() => {{ switch (JSON.stringify({MatchState.get_name()}.value)) {{case JSON.stringify(1): return ("first"); break;case JSON.stringify(2): case JSON.stringify(3): return '
+ '("second value"); break;case JSON.stringify([1, 2]): return ("third-value"); break;case JSON.stringify("random"): '
+ 'return ("fourth_value"); break;case JSON.stringify(({ ["foo"] : "bar" })): return ("fifth value"); '
+ f'break;case JSON.stringify(({MatchState.get_name()}.num + 1)): return ("sixth value"); break;case JSON.stringify(({MatchState.get_name()}.value+" - string")): '
+ f'return ({MatchState.get_name()}.string); break;case JSON.stringify({MatchState.get_name()}.string): return (({MatchState.get_name()}.value+" - string")); break;default: '
+ 'return ("default value"); break;};})()',
),
(
(
@@ -118,11 +118,11 @@ def test_match_components():
(MatchState.string, f"{MatchState.value} - string"),
MatchState.string,
),
- f"(() => {{ switch (JSON.stringify({MatchState.get_name()}.value)) {{case JSON.stringify(1): return (`first`); break;case JSON.stringify(2): case JSON.stringify(3): return "
- "(`second value`); break;case JSON.stringify([1, 2]): return (`third-value`); break;case JSON.stringify(`random`): "
- 'return (`fourth_value`); break;case JSON.stringify({"foo": "bar"}): return (`fifth value`); '
- f"break;case JSON.stringify((({MatchState.get_name()}.num) + (1))): return (`sixth value`); break;case JSON.stringify(`${{{MatchState.get_name()}.value}} - string`): "
- f"return ({MatchState.get_name()}.string); break;case JSON.stringify({MatchState.get_name()}.string): return (`${{{MatchState.get_name()}.value}} - string`); break;default: "
+ f'(() => {{ switch (JSON.stringify({MatchState.get_name()}.value)) {{case JSON.stringify(1): return ("first"); break;case JSON.stringify(2): case JSON.stringify(3): return '
+ '("second value"); break;case JSON.stringify([1, 2]): return ("third-value"); break;case JSON.stringify("random"): '
+ 'return ("fourth_value"); break;case JSON.stringify(({ ["foo"] : "bar" })): return ("fifth value"); '
+ f'break;case JSON.stringify(({MatchState.get_name()}.num + 1)): return ("sixth value"); break;case JSON.stringify(({MatchState.get_name()}.value+" - string")): '
+ f'return ({MatchState.get_name()}.string); break;case JSON.stringify({MatchState.get_name()}.string): return (({MatchState.get_name()}.value+" - string")); break;default: '
f"return ({MatchState.get_name()}.string); break;}};}})()",
),
],
@@ -135,7 +135,7 @@ def test_match_vars(cases, expected):
expected: The expected var full name.
"""
match_comp = Match.create(MatchState.value, *cases)
- assert isinstance(match_comp, BaseVar)
+ assert isinstance(match_comp, Var)
assert match_comp._var_full_name == expected
@@ -247,8 +247,8 @@ def test_match_case_tuple_elements(match_case):
(MatchState.num + 1, "black"),
rx.text("default value"),
),
- "Match cases should have the same return types. Case 3 with return value `red` of type "
- " is not ",
+ 'Match cases should have the same return types. Case 3 with return value `"red"` of type '
+ " is not ",
),
(
(
@@ -260,8 +260,8 @@ def test_match_case_tuple_elements(match_case):
([1, 2], rx.text("third value")),
rx.text("default value"),
),
- "Match cases should have the same return types. Case 3 with return value ` {`first value`} ` "
- "of type is not ",
+ 'Match cases should have the same return types. Case 3 with return value ` {"first value"} ` '
+ "of type is not ",
),
],
)
diff --git a/tests/components/datadisplay/test_code.py b/tests/components/datadisplay/test_code.py
index 64452e90cd..49fbae09f5 100644
--- a/tests/components/datadisplay/test_code.py
+++ b/tests/components/datadisplay/test_code.py
@@ -4,7 +4,7 @@
@pytest.mark.parametrize(
- "theme, expected", [("light", "one-light"), ("dark", "one-dark")]
+ "theme, expected", [("light", '"one-light"'), ("dark", '"one-dark"')]
)
def test_code_light_dark_theme(theme, expected):
code_block = CodeBlock.create(theme=theme)
diff --git a/tests/components/forms/test_uploads.py b/tests/components/forms/test_uploads.py
index f8856a20f7..3b2ee014f2 100644
--- a/tests/components/forms/test_uploads.py
+++ b/tests/components/forms/test_uploads.py
@@ -83,11 +83,11 @@ def test_upload_root_component_render(upload_root_component):
# upload
assert upload["name"] == "ReactDropzone"
assert upload["props"] == [
- "id={`default`}",
+ 'id={"default"}',
"multiple={true}",
"onDrop={e => setFilesById(filesById => {\n"
" const updatedFilesById = Object.assign({}, filesById);\n"
- " updatedFilesById[`default`] = e;\n"
+ ' updatedFilesById["default"] = e;\n'
" return updatedFilesById;\n"
" })\n"
" }",
@@ -99,23 +99,23 @@ def test_upload_root_component_render(upload_root_component):
[box] = upload["children"]
assert box["name"] == "RadixThemesBox"
assert box["props"] == [
- "className={`rx-Upload`}",
- 'css={{"border": "1px dotted black"}}',
+ 'className={"rx-Upload"}',
+ 'css={({ ["border"] : "1px dotted black" })}',
"{...getRootProps()}",
]
# input, button and text inside of box
[input, button, text] = box["children"]
assert input["name"] == "input"
- assert input["props"] == ["type={`file`}", "{...getInputProps()}"]
+ assert input["props"] == ['type={"file"}', "{...getInputProps()}"]
assert button["name"] == "RadixThemesButton"
- assert button["children"][0]["contents"] == "{`select file`}"
+ assert button["children"][0]["contents"] == '{"select file"}'
assert text["name"] == "RadixThemesText"
assert (
text["children"][0]["contents"]
- == "{`Drag and drop files here or click to select files`}"
+ == '{"Drag and drop files here or click to select files"}'
)
@@ -130,11 +130,11 @@ def test_upload_component_render(upload_component):
# upload
assert upload["name"] == "ReactDropzone"
assert upload["props"] == [
- "id={`default`}",
+ 'id={"default"}',
"multiple={true}",
"onDrop={e => setFilesById(filesById => {\n"
" const updatedFilesById = Object.assign({}, filesById);\n"
- " updatedFilesById[`default`] = e;\n"
+ ' updatedFilesById["default"] = e;\n'
" return updatedFilesById;\n"
" })\n"
" }",
@@ -146,23 +146,23 @@ def test_upload_component_render(upload_component):
[box] = upload["children"]
assert box["name"] == "RadixThemesBox"
assert box["props"] == [
- "className={`rx-Upload`}",
- 'css={{"border": "1px dotted black", "padding": "5em", "textAlign": "center"}}',
+ 'className={"rx-Upload"}',
+ 'css={({ ["border"] : "1px dotted black", ["padding"] : "5em", ["textAlign"] : "center" })}',
"{...getRootProps()}",
]
# input, button and text inside of box
[input, button, text] = box["children"]
assert input["name"] == "input"
- assert input["props"] == ["type={`file`}", "{...getInputProps()}"]
+ assert input["props"] == ['type={"file"}', "{...getInputProps()}"]
assert button["name"] == "RadixThemesButton"
- assert button["children"][0]["contents"] == "{`select file`}"
+ assert button["children"][0]["contents"] == '{"select file"}'
assert text["name"] == "RadixThemesText"
assert (
text["children"][0]["contents"]
- == "{`Drag and drop files here or click to select files`}"
+ == '{"Drag and drop files here or click to select files"}'
)
@@ -175,13 +175,13 @@ def test_upload_component_with_props_render(upload_component_with_props):
upload = upload_component_with_props.render()
assert upload["props"] == [
- "id={`default`}",
+ 'id={"default"}',
"maxFiles={2}",
"multiple={true}",
"noDrag={true}",
"onDrop={e => setFilesById(filesById => {\n"
" const updatedFilesById = Object.assign({}, filesById);\n"
- " updatedFilesById[`default`] = e;\n"
+ ' updatedFilesById["default"] = e;\n'
" return updatedFilesById;\n"
" })\n"
" }",
@@ -193,11 +193,11 @@ def test_upload_component_id_with_special_chars(upload_component_id_special):
upload = upload_component_id_special.render()
assert upload["props"] == [
- r"id={`#spec!\`al-_98ID`}",
+ r'id={"#spec!`al-_98ID"}',
"multiple={true}",
"onDrop={e => setFilesById(filesById => {\n"
" const updatedFilesById = Object.assign({}, filesById);\n"
- " updatedFilesById[`#spec!\\`al-_98ID`] = e;\n"
+ ' updatedFilesById["#spec!`al-_98ID"] = e;\n'
" return updatedFilesById;\n"
" })\n"
" }",
diff --git a/tests/components/media/test_image.py b/tests/components/media/test_image.py
index a39895c679..ba8353260f 100644
--- a/tests/components/media/test_image.py
+++ b/tests/components/media/test_image.py
@@ -6,6 +6,7 @@
import reflex as rx
from reflex.components.next.image import Image # type: ignore
+from reflex.ivars.sequence import StringVar
from reflex.utils.serializers import serialize, serialize_image
@@ -36,9 +37,13 @@ def test_set_src_str():
"""Test that setting the src works."""
image = rx.image(src="pic2.jpeg")
# when using next/image, we explicitly create a _var_is_str Var
- # assert str(image.src) == "{`pic2.jpeg`}" # type: ignore
+ assert str(image.src) in ( # type: ignore
+ '"pic2.jpeg"',
+ "'pic2.jpeg'",
+ "`pic2.jpeg`",
+ )
# For plain rx.el.img, an explicit var is not created, so the quoting happens later
- assert str(image.src) == "pic2.jpeg" # type: ignore
+ # assert str(image.src) == "pic2.jpeg" # type: ignore
def test_set_src_img(pil_image: Img):
@@ -48,7 +53,7 @@ def test_set_src_img(pil_image: Img):
pil_image: The image to serialize.
"""
image = Image.create(src=pil_image)
- assert str(image.src._var_name) == serialize_image(pil_image) # type: ignore
+ assert str(image.src._var_name) == '"' + serialize_image(pil_image) + '"' # type: ignore
def test_render(pil_image: Img):
@@ -58,4 +63,4 @@ def test_render(pil_image: Img):
pil_image: The image to serialize.
"""
image = Image.create(src=pil_image)
- assert image.src._var_is_string # type: ignore
+ assert isinstance(image.src, StringVar) # type: ignore
diff --git a/tests/components/test_component.py b/tests/components/test_component.py
index 3d32a53d7a..45350a5c5f 100644
--- a/tests/components/test_component.py
+++ b/tests/components/test_component.py
@@ -18,6 +18,7 @@
)
from reflex.constants import EventTriggers
from reflex.event import EventChain, EventHandler, parse_args_spec
+from reflex.ivars.base import LiteralVar
from reflex.state import BaseState
from reflex.style import Style
from reflex.utils import imports
@@ -230,8 +231,8 @@ def test_set_style_attrs(component1):
component1: A test component.
"""
component = component1(color="white", text_align="center")
- assert component.style["color"] == "white"
- assert component.style["textAlign"] == "center"
+ assert str(component.style["color"]) == '"white"'
+ assert str(component.style["textAlign"]) == '"center"'
def test_custom_attrs(component1):
@@ -255,7 +256,10 @@ def test_create_component(component1):
c = component1.create(*children, **attrs)
assert isinstance(c, component1)
assert c.children == children
- assert c.style == {"color": "white", "textAlign": "center"}
+ assert (
+ str(LiteralVar.create(c.style))
+ == '({ ["color"] : "white", ["textAlign"] : "center" })'
+ )
@pytest.mark.parametrize(
@@ -419,8 +423,8 @@ def test_add_style(component1, component2):
}
c1 = component1()._add_style_recursive(style) # type: ignore
c2 = component2()._add_style_recursive(style) # type: ignore
- assert c1.style["color"] == "white"
- assert c2.style["color"] == "black"
+ assert str(c1.style["color"]) == '"white"'
+ assert str(c2.style["color"]) == '"black"'
def test_add_style_create(component1, component2):
@@ -436,8 +440,8 @@ def test_add_style_create(component1, component2):
}
c1 = component1()._add_style_recursive(style) # type: ignore
c2 = component2()._add_style_recursive(style) # type: ignore
- assert c1.style["color"] == "white"
- assert c2.style["color"] == "black"
+ assert str(c1.style["color"]) == '"white"'
+ assert str(c2.style["color"]) == '"black"'
def test_get_imports(component1, component2):
@@ -607,8 +611,8 @@ def test_create_filters_none_props(test_component):
assert "prop4" not in component.get_props()
# Assert that the style prop is present in the component's props
- assert component.style["color"] == "white"
- assert component.style["text-align"] == "center"
+ assert str(component.style["color"]) == '"white"'
+ assert str(component.style["text-align"]) == '"center"'
@pytest.mark.parametrize("children", [((None,),), ("foo", ("bar", (None,)))])
@@ -635,7 +639,7 @@ def test_component_create_unallowed_types(children, test_component):
"children": [
{
"name": "RadixThemesText",
- "props": ["as={`p`}"],
+ "props": ['as={"p"}'],
"contents": "",
"args": None,
"special_props": set(),
@@ -643,7 +647,7 @@ def test_component_create_unallowed_types(children, test_component):
{
"name": "",
"props": [],
- "contents": "{`first_text`}",
+ "contents": '{"first_text"}',
"args": None,
"special_props": set(),
"children": [],
@@ -670,7 +674,7 @@ def test_component_create_unallowed_types(children, test_component):
"args": None,
"autofocus": False,
"children": [],
- "contents": "{`first_text`}",
+ "contents": '{"first_text"}',
"name": "",
"props": [],
"special_props": set(),
@@ -678,7 +682,7 @@ def test_component_create_unallowed_types(children, test_component):
],
"contents": "",
"name": "RadixThemesText",
- "props": ["as={`p`}"],
+ "props": ['as={"p"}'],
"special_props": set(),
},
{
@@ -689,7 +693,7 @@ def test_component_create_unallowed_types(children, test_component):
"args": None,
"autofocus": False,
"children": [],
- "contents": "{`second_text`}",
+ "contents": '{"second_text"}',
"name": "",
"props": [],
"special_props": set(),
@@ -697,7 +701,7 @@ def test_component_create_unallowed_types(children, test_component):
],
"contents": "",
"name": "RadixThemesText",
- "props": ["as={`p`}"],
+ "props": ['as={"p"}'],
"special_props": set(),
},
],
@@ -721,7 +725,7 @@ def test_component_create_unallowed_types(children, test_component):
"args": None,
"autofocus": False,
"children": [],
- "contents": "{`first_text`}",
+ "contents": '{"first_text"}',
"name": "",
"props": [],
"special_props": set(),
@@ -729,7 +733,7 @@ def test_component_create_unallowed_types(children, test_component):
],
"contents": "",
"name": "RadixThemesText",
- "props": ["as={`p`}"],
+ "props": ['as={"p"}'],
"special_props": set(),
},
{
@@ -748,7 +752,7 @@ def test_component_create_unallowed_types(children, test_component):
"args": None,
"autofocus": False,
"children": [],
- "contents": "{`second_text`}",
+ "contents": '{"second_text"}',
"name": "",
"props": [],
"special_props": set(),
@@ -756,7 +760,7 @@ def test_component_create_unallowed_types(children, test_component):
],
"contents": "",
"name": "RadixThemesText",
- "props": ["as={`p`}"],
+ "props": ['as={"p"}'],
"special_props": set(),
}
],
@@ -825,9 +829,9 @@ def get_event_triggers(self) -> Dict[str, Any]:
comp = C1.create(on_foo=C1State.mock_handler)
assert comp.render()["props"][0] == (
- "onFoo={(__e,_alpha,_bravo,_charlie) => addEvents("
- f'[Event("{C1State.get_full_name()}.mock_handler", {{_e:__e.target.value,_bravo:_bravo["nested"],_charlie:((_charlie.custom) + (42))}})], '
- "[__e,_alpha,_bravo,_charlie], {})}"
+ "onFoo={((__e, _alpha, _bravo, _charlie) => ((addEvents("
+ f'[(Event("{C1State.get_full_name()}.mock_handler", ({{ ["_e"] : __e["target"]["value"], ["_bravo"] : _bravo["nested"], ["_charlie"] : (_charlie["custom"] + 42) }})))], '
+ "[__e, _alpha, _bravo, _charlie], ({ })))))}"
)
@@ -1003,10 +1007,10 @@ def test_component_with_only_valid_children(fixture, request):
@pytest.mark.parametrize(
"component,rendered",
[
- (rx.text("hi"), "\n {`hi`}\n"),
+ (rx.text("hi"), '\n {"hi"}\n'),
(
rx.box(rc.heading("test", size="md")),
- "\n \n {`test`}\n\n",
+ '\n \n {"test"}\n\n',
),
],
)
@@ -1061,7 +1065,7 @@ def test_stateful_banner():
assert isinstance(stateful_component, StatefulComponent)
-TEST_VAR = Var.create_safe("test")._replace(
+TEST_VAR = LiteralVar.create("test")._replace(
merge_var_data=VarData(
hooks={"useTest": None},
imports={"test": [ImportVar(tag="test")]},
@@ -1069,36 +1073,36 @@ def test_stateful_banner():
interpolations=[],
)
)
-FORMATTED_TEST_VAR = Var.create(f"foo{TEST_VAR}bar")
-STYLE_VAR = TEST_VAR._replace(_var_name="style", _var_is_local=False)
+FORMATTED_TEST_VAR = LiteralVar.create(f"foo{TEST_VAR}bar")
+STYLE_VAR = TEST_VAR._replace(_var_name="style")
EVENT_CHAIN_VAR = TEST_VAR._replace(_var_type=EventChain)
ARG_VAR = Var.create("arg")
-TEST_VAR_DICT_OF_DICT = Var.create_safe({"a": {"b": "test"}})._replace(
- merge_var_data=TEST_VAR._var_data
-)
-FORMATTED_TEST_VAR_DICT_OF_DICT = Var.create_safe({"a": {"b": f"footestbar"}})._replace(
+TEST_VAR_DICT_OF_DICT = LiteralVar.create({"a": {"b": "test"}})._replace(
merge_var_data=TEST_VAR._var_data
)
+FORMATTED_TEST_VAR_DICT_OF_DICT = LiteralVar.create(
+ {"a": {"b": f"footestbar"}}
+)._replace(merge_var_data=TEST_VAR._var_data)
-TEST_VAR_LIST_OF_LIST = Var.create_safe([["test"]])._replace(
+TEST_VAR_LIST_OF_LIST = LiteralVar.create([["test"]])._replace(
merge_var_data=TEST_VAR._var_data
)
-FORMATTED_TEST_VAR_LIST_OF_LIST = Var.create_safe([["footestbar"]])._replace(
+FORMATTED_TEST_VAR_LIST_OF_LIST = LiteralVar.create([["footestbar"]])._replace(
merge_var_data=TEST_VAR._var_data
)
-TEST_VAR_LIST_OF_LIST_OF_LIST = Var.create_safe([[["test"]]])._replace(
- merge_var_data=TEST_VAR._var_data
-)
-FORMATTED_TEST_VAR_LIST_OF_LIST_OF_LIST = Var.create_safe([[["footestbar"]]])._replace(
+TEST_VAR_LIST_OF_LIST_OF_LIST = LiteralVar.create([[["test"]]])._replace(
merge_var_data=TEST_VAR._var_data
)
+FORMATTED_TEST_VAR_LIST_OF_LIST_OF_LIST = LiteralVar.create(
+ [[["footestbar"]]]
+)._replace(merge_var_data=TEST_VAR._var_data)
-TEST_VAR_LIST_OF_DICT = Var.create_safe([{"a": "test"}])._replace(
+TEST_VAR_LIST_OF_DICT = LiteralVar.create([{"a": "test"}])._replace(
merge_var_data=TEST_VAR._var_data
)
-FORMATTED_TEST_VAR_LIST_OF_DICT = Var.create_safe([{"a": "footestbar"}])._replace(
+FORMATTED_TEST_VAR_LIST_OF_DICT = LiteralVar.create([{"a": "footestbar"}])._replace(
merge_var_data=TEST_VAR._var_data
)
@@ -1187,7 +1191,7 @@ def handler2(self, arg):
id="direct-special_props",
),
pytest.param(
- rx.fragment(special_props={Var.create(f"foo{TEST_VAR}bar")}),
+ rx.fragment(special_props={LiteralVar.create(f"foo{TEST_VAR}bar")}),
[FORMATTED_TEST_VAR],
id="fstring-special_props",
),
@@ -1296,6 +1300,8 @@ def test_get_vars(component, exp_vars):
comp_vars,
sorted(exp_vars, key=lambda v: v._var_name),
):
+ # print(str(comp_var), str(exp_var))
+ # print(comp_var._get_all_var_data(), exp_var._get_all_var_data())
assert comp_var.equals(exp_var)
@@ -1335,9 +1341,11 @@ def test_instantiate_all_components():
continue
component = getattr(
rx,
- component_name
- if not isinstance(component_name, tuple)
- else component_name[1],
+ (
+ component_name
+ if not isinstance(component_name, tuple)
+ else component_name[1]
+ ),
)
if isinstance(component, type) and issubclass(component, Component):
component.create()
@@ -1595,14 +1603,14 @@ class C2(C1):
c1 = C1.create(prop1="prop1_1", prop2="prop2_1")
rendered_c1 = c1.render()
- assert "renamed_prop1={`prop1_1`}" in rendered_c1["props"]
- assert "renamed_prop2={`prop2_1`}" in rendered_c1["props"]
+ assert 'renamed_prop1={"prop1_1"}' in rendered_c1["props"]
+ assert 'renamed_prop2={"prop2_1"}' in rendered_c1["props"]
c2 = C2.create(prop1="prop1_2", prop2="prop2_2", prop3="prop3_2")
rendered_c2 = c2.render()
- assert "renamed_prop1={`prop1_2`}" in rendered_c2["props"]
- assert "subclass_prop2={`prop2_2`}" in rendered_c2["props"]
- assert "renamed_prop3={`prop3_2`}" in rendered_c2["props"]
+ assert 'renamed_prop1={"prop1_2"}' in rendered_c2["props"]
+ assert 'subclass_prop2={"prop2_2"}' in rendered_c2["props"]
+ assert 'renamed_prop3={"prop3_2"}' in rendered_c2["props"]
def test_deprecated_props(capsys):
@@ -1626,9 +1634,9 @@ class C1(Component):
assert not out_err.out
c1_1_render = c1_1.render()
- assert "type={`type1`}" in c1_1_render["props"]
- assert "min={`min1`}" in c1_1_render["props"]
- assert "max={`max1`}" in c1_1_render["props"]
+ assert 'type={"type1"}' in c1_1_render["props"]
+ assert 'min={"min1"}' in c1_1_render["props"]
+ assert 'max={"max1"}' in c1_1_render["props"]
# Deprecation warning is emitted with underscore suffix,
# but the component still works.
@@ -1638,9 +1646,9 @@ class C1(Component):
assert not out_err.err
c1_2_render = c1_2.render()
- assert "type={`type2`}" in c1_2_render["props"]
- assert "min={`min2`}" in c1_2_render["props"]
- assert "max={`max2`}" in c1_2_render["props"]
+ assert 'type={"type2"}' in c1_2_render["props"]
+ assert 'min={"min2"}' in c1_2_render["props"]
+ assert 'max={"max2"}' in c1_2_render["props"]
class C2(Component):
tag = "C2"
@@ -1656,9 +1664,9 @@ class C2(Component):
assert not out_err.out
c2_1_render = c2_1.render()
- assert "type={`type1`}" in c2_1_render["props"]
- assert "min={`min1`}" in c2_1_render["props"]
- assert "max={`max1`}" in c2_1_render["props"]
+ assert 'type={"type1"}' in c2_1_render["props"]
+ assert 'min={"min1"}' in c2_1_render["props"]
+ assert 'max={"max1"}' in c2_1_render["props"]
def test_custom_component_get_imports():
@@ -2008,11 +2016,11 @@ def test_add_style_embedded_vars(test_state: BaseState):
Args:
test_state: A test state.
"""
- v0 = Var.create_safe("parent")._replace(
+ v0 = LiteralVar.create("parent")._replace(
merge_var_data=VarData(hooks={"useParent": None}), # type: ignore
)
v1 = rx.color("plum", 10)
- v2 = Var.create_safe("text")._replace(
+ v2 = LiteralVar.create("text")._replace(
merge_var_data=VarData(hooks={"useText": None}), # type: ignore
)
@@ -2045,7 +2053,7 @@ def add_style(self):
assert "useParent" in page._get_all_hooks_internal()
assert (
str(page).count(
- f'css={{{{"fakeParent": "parent", "color": "var(--plum-10)", "fake": "text", "margin": `${{{test_state.get_name()}.num}}%`}}}}'
+ f'css={{({{ ["fakeParent"] : "parent", ["color"] : "var(--plum-10)", ["fake"] : "text", ["margin"] : ({test_state.get_name()}.num+"%") }})}}'
)
== 1
)
@@ -2066,10 +2074,10 @@ def add_style(self):
assert len(page.children[0].children) == 1
# Expect the style to be added to the child of the foreach
- assert 'css={{"color": "red"}}' in str(page.children[0].children[0])
+ assert 'css={({ ["color"] : "red" })}' in str(page.children[0].children[0])
# Expect only one instance of this CSS dict in the rendered page
- assert str(page).count('css={{"color": "red"}}') == 1
+ assert str(page).count('css={({ ["color"] : "red" })}') == 1
class TriggerState(rx.State):
diff --git a/tests/components/test_component_state.py b/tests/components/test_component_state.py
index 0dc0956e24..574997ba53 100644
--- a/tests/components/test_component_state.py
+++ b/tests/components/test_component_state.py
@@ -35,8 +35,8 @@ def get_component(cls, *children, **props):
assert cs1.State.increment != cs2.State.increment
assert len(cs1.children) == 1
- assert cs1.children[0].render() == Bare.create("{`a`}").render()
+ assert cs1.children[0].render() == Bare.create("a").render()
assert cs1.id == "a"
assert len(cs2.children) == 1
- assert cs2.children[0].render() == Bare.create("{`b`}").render()
+ assert cs2.children[0].render() == Bare.create("b").render()
assert cs2.id == "b"
diff --git a/tests/components/test_tag.py b/tests/components/test_tag.py
index 2fb2f4563d..d43f73842b 100644
--- a/tests/components/test_tag.py
+++ b/tests/components/test_tag.py
@@ -3,6 +3,7 @@
import pytest
from reflex.components.tags import CondTag, Tag, tagless
+from reflex.ivars.base import LiteralVar
from reflex.vars import BaseVar, Var
@@ -12,8 +13,8 @@
({}, []),
({"key-hypen": 1}, ["key-hypen={1}"]),
({"key": 1}, ["key={1}"]),
- ({"key": "value"}, ["key={`value`}"]),
- ({"key": True, "key2": "value2"}, ["key={true}", "key2={`value2`}"]),
+ ({"key": "value"}, ['key={"value"}']),
+ ({"key": True, "key2": "value2"}, ["key={true}", 'key2={"value2"}']),
],
)
def test_format_props(props: Dict[str, Var], test_props: List):
@@ -53,8 +54,8 @@ def test_is_valid_prop(prop: Var, valid: bool):
def test_add_props():
"""Test that the props are added."""
tag = Tag().add_props(key="value", key2=42, invalid=None, invalid2={})
- assert tag.props["key"].equals(Var.create("value"))
- assert tag.props["key2"].equals(Var.create(42))
+ assert tag.props["key"].equals(LiteralVar.create("value"))
+ assert tag.props["key2"].equals(LiteralVar.create(42))
assert "invalid" not in tag.props
assert "invalid2" not in tag.props
@@ -102,7 +103,7 @@ def test_format_tag(tag: Tag, expected: Dict):
assert tag_dict["name"] == expected["name"]
assert tag_dict["contents"] == expected["contents"]
for prop, prop_value in tag_dict["props"].items():
- assert prop_value.equals(Var.create_safe(expected["props"][prop]))
+ assert prop_value.equals(LiteralVar.create(expected["props"][prop]))
def test_format_cond_tag():
diff --git a/tests/test_app.py b/tests/test_app.py
index 17afd2bb73..efaca4234d 100644
--- a/tests/test_app.py
+++ b/tests/test_app.py
@@ -1252,7 +1252,7 @@ def test_app_wrap_compile_theme(compilable_app: tuple[App, Path]):
"function AppWrap({children}) {"
"return ("
""
- ""
+ ""
""
"{children}"
""
@@ -1434,16 +1434,16 @@ def page2():
assert isinstance((fragment_wrapper := app.pages["index"].children[0]), Fragment)
assert isinstance((first_text := fragment_wrapper.children[0]), Text)
- assert str(first_text.children[0].contents) == "{`first`}" # type: ignore
+ assert str(first_text.children[0].contents) == '"first"' # type: ignore
assert isinstance((second_text := fragment_wrapper.children[1]), Text)
- assert str(second_text.children[0].contents) == "{`second`}" # type: ignore
+ assert str(second_text.children[0].contents) == '"second"' # type: ignore
# Test page with trailing comma.
assert isinstance(
(page2_fragment_wrapper := app.pages["page2"].children[0]), Fragment
)
assert isinstance((third_text := page2_fragment_wrapper.children[0]), Text)
- assert str(third_text.children[0].contents) == "{`third`}" # type: ignore
+ assert str(third_text.children[0].contents) == '"third"' # type: ignore
@pytest.mark.parametrize("export", (True, False))
diff --git a/tests/test_event.py b/tests/test_event.py
index 284542a434..a484e0a3c3 100644
--- a/tests/test_event.py
+++ b/tests/test_event.py
@@ -1,10 +1,10 @@
-import json
from typing import List
import pytest
from reflex import event
from reflex.event import Event, EventHandler, EventSpec, call_event_handler, fix_events
+from reflex.ivars.base import ImmutableVar, LiteralVar
from reflex.state import BaseState
from reflex.utils import format
from reflex.vars import Var
@@ -70,7 +70,7 @@ def test_fn_with_args(_, arg1, arg2):
event_spec = handler("first", "second") # type: ignore
assert (
format.format_event(event_spec)
- == 'Event("test_fn_with_args", {arg1:`first`,arg2:`second`})'
+ == 'Event("test_fn_with_args", {arg1:"first",arg2:"second"})'
)
first, second = 123, "456"
@@ -78,14 +78,14 @@ def test_fn_with_args(_, arg1, arg2):
event_spec = handler(first, second) # type: ignore
assert (
format.format_event(event_spec)
- == 'Event("test_fn_with_args", {arg1:123,arg2:`456`})'
+ == 'Event("test_fn_with_args", {arg1:123,arg2:"456"})'
)
assert event_spec.handler == handler
assert event_spec.args[0][0].equals(Var.create_safe("arg1"))
assert event_spec.args[0][1].equals(Var.create_safe(first))
assert event_spec.args[1][0].equals(Var.create_safe("arg2"))
- assert event_spec.args[1][1].equals(Var.create_safe(second))
+ assert event_spec.args[1][1].equals(LiteralVar.create(second))
handler = EventHandler(fn=test_fn_with_args)
with pytest.raises(TypeError):
@@ -160,15 +160,15 @@ def test_fn_with_args(_, arg1, arg2):
[
(
("/path", None, None),
- 'Event("_redirect", {path:`/path`,external:false,replace:false})',
+ 'Event("_redirect", {path:"/path",external:false,replace:false})',
),
(
("/path", True, None),
- 'Event("_redirect", {path:`/path`,external:true,replace:false})',
+ 'Event("_redirect", {path:"/path",external:true,replace:false})',
),
(
("/path", False, None),
- 'Event("_redirect", {path:`/path`,external:false,replace:false})',
+ 'Event("_redirect", {path:"/path",external:false,replace:false})',
),
(
(Var.create_safe("path"), None, None),
@@ -176,11 +176,11 @@ def test_fn_with_args(_, arg1, arg2):
),
(
("/path", None, True),
- 'Event("_redirect", {path:`/path`,external:false,replace:true})',
+ 'Event("_redirect", {path:"/path",external:false,replace:true})',
),
(
("/path", True, True),
- 'Event("_redirect", {path:`/path`,external:true,replace:true})',
+ 'Event("_redirect", {path:"/path",external:true,replace:true})',
),
],
)
@@ -213,10 +213,10 @@ def test_event_console_log():
spec = event.console_log("message")
assert isinstance(spec, EventSpec)
assert spec.handler.fn.__qualname__ == "_console"
- assert spec.args[0][0].equals(Var.create_safe("message"))
- assert spec.args[0][1].equals(Var.create_safe("message"))
- assert format.format_event(spec) == 'Event("_console", {message:`message`})'
- spec = event.console_log(Var.create_safe("message"))
+ assert spec.args[0][0].equals(ImmutableVar(_var_name="message", _var_type=str))
+ assert spec.args[0][1].equals(LiteralVar.create("message"))
+ assert format.format_event(spec) == 'Event("_console", {message:"message"})'
+ spec = event.console_log(ImmutableVar.create_safe("message"))
assert format.format_event(spec) == 'Event("_console", {message:message})'
@@ -225,10 +225,10 @@ def test_event_window_alert():
spec = event.window_alert("message")
assert isinstance(spec, EventSpec)
assert spec.handler.fn.__qualname__ == "_alert"
- assert spec.args[0][0].equals(Var.create_safe("message"))
- assert spec.args[0][1].equals(Var.create_safe("message"))
- assert format.format_event(spec) == 'Event("_alert", {message:`message`})'
- spec = event.window_alert(Var.create_safe("message"))
+ assert spec.args[0][0].equals(ImmutableVar(_var_name="message", _var_type=str))
+ assert spec.args[0][1].equals(LiteralVar.create("message"))
+ assert format.format_event(spec) == 'Event("_alert", {message:"message"})'
+ spec = event.window_alert(ImmutableVar.create_safe("message"))
assert format.format_event(spec) == 'Event("_alert", {message:message})'
@@ -238,10 +238,10 @@ def test_set_focus():
assert isinstance(spec, EventSpec)
assert spec.handler.fn.__qualname__ == "_set_focus"
assert spec.args[0][0].equals(Var.create_safe("ref"))
- assert spec.args[0][1].equals(Var.create_safe("ref_input1"))
- assert format.format_event(spec) == 'Event("_set_focus", {ref:`ref_input1`})'
+ assert spec.args[0][1].equals(LiteralVar.create("ref_input1"))
+ assert format.format_event(spec) == 'Event("_set_focus", {ref:"ref_input1"})'
spec = event.set_focus("input1")
- assert format.format_event(spec) == 'Event("_set_focus", {ref:`ref_input1`})'
+ assert format.format_event(spec) == 'Event("_set_focus", {ref:"ref_input1"})'
def test_set_value():
@@ -250,16 +250,16 @@ def test_set_value():
assert isinstance(spec, EventSpec)
assert spec.handler.fn.__qualname__ == "_set_value"
assert spec.args[0][0].equals(Var.create_safe("ref"))
- assert spec.args[0][1].equals(Var.create_safe("ref_input1"))
+ assert spec.args[0][1].equals(LiteralVar.create("ref_input1"))
assert spec.args[1][0].equals(Var.create_safe("value"))
- assert spec.args[1][1].equals(Var.create_safe(""))
+ assert spec.args[1][1].equals(LiteralVar.create(""))
assert (
- format.format_event(spec) == 'Event("_set_value", {ref:`ref_input1`,value:``})'
+ format.format_event(spec) == 'Event("_set_value", {ref:"ref_input1",value:""})'
)
- spec = event.set_value("input1", Var.create_safe("message"))
+ spec = event.set_value("input1", ImmutableVar.create_safe("message"))
assert (
format.format_event(spec)
- == 'Event("_set_value", {ref:`ref_input1`,value:message})'
+ == 'Event("_set_value", {ref:"ref_input1",value:message})'
)
@@ -269,12 +269,12 @@ def test_remove_cookie():
assert isinstance(spec, EventSpec)
assert spec.handler.fn.__qualname__ == "_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[0][1].equals(LiteralVar.create("testkey"))
assert spec.args[1][0].equals(Var.create_safe("options"))
- assert spec.args[1][1].equals(Var.create_safe({"path": "/"}))
+ assert spec.args[1][1].equals(LiteralVar.create({"path": "/"}))
assert (
format.format_event(spec)
- == 'Event("_remove_cookie", {key:`testkey`,options:{"path": "/"}})'
+ == 'Event("_remove_cookie", {key:"testkey",options:({ ["path"] : "/" })})'
)
@@ -290,12 +290,12 @@ def test_remove_cookie_with_options():
assert isinstance(spec, EventSpec)
assert spec.handler.fn.__qualname__ == "_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[0][1].equals(LiteralVar.create("testkey"))
assert spec.args[1][0].equals(Var.create_safe("options"))
- assert spec.args[1][1].equals(Var.create_safe(options))
+ assert spec.args[1][1].equals(LiteralVar.create(options))
assert (
format.format_event(spec)
- == f'Event("_remove_cookie", {{key:`testkey`,options:{json.dumps(options)}}})'
+ == f'Event("_remove_cookie", {{key:"testkey",options:{str(LiteralVar.create(options))}}})'
)
@@ -314,9 +314,9 @@ def test_remove_local_storage():
assert isinstance(spec, EventSpec)
assert spec.handler.fn.__qualname__ == "_remove_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[0][1].equals(LiteralVar.create("testkey"))
assert (
- format.format_event(spec) == 'Event("_remove_local_storage", {key:`testkey`})'
+ format.format_event(spec) == 'Event("_remove_local_storage", {key:"testkey"})'
)
diff --git a/tests/test_state.py b/tests/test_state.py
index 1a014739d5..d34e771cb8 100644
--- a/tests/test_state.py
+++ b/tests/test_state.py
@@ -40,7 +40,7 @@
from reflex.testing import chdir
from reflex.utils import format, prerequisites, types
from reflex.utils.format import json_dumps
-from reflex.vars import BaseVar, ComputedVar
+from reflex.vars import BaseVar, ComputedVar, Var
from tests.states.mutation import MutableSQLAModel, MutableTestState
from .states import GenState
@@ -266,8 +266,8 @@ def test_base_class_vars(test_state):
if field in test_state.get_skip_vars():
continue
prop = getattr(cls, field)
- assert isinstance(prop, BaseVar)
- assert prop._var_name == field
+ assert isinstance(prop, Var)
+ assert prop._var_name.split(".")[-1] == field
assert cls.num1._var_type == int
assert cls.num2._var_type == float
@@ -395,30 +395,27 @@ def test_default_setters(test_state):
def test_class_indexing_with_vars():
"""Test that we can index into a state var with another var."""
prop = TestState.array[TestState.num1]
- assert (
- str(prop) == f"{{{TestState.get_name()}.array.at({TestState.get_name()}.num1)}}"
- )
+ assert str(prop) == f"{TestState.get_name()}.array.at({TestState.get_name()}.num1)"
prop = TestState.mapping["a"][TestState.num1]
assert (
str(prop)
- == f'{{{TestState.get_name()}.mapping["a"].at({TestState.get_name()}.num1)}}'
+ == f'{TestState.get_name()}.mapping["a"].at({TestState.get_name()}.num1)'
)
prop = TestState.mapping[TestState.map_key]
assert (
- str(prop)
- == f"{{{TestState.get_name()}.mapping[{TestState.get_name()}.map_key]}}"
+ str(prop) == f"{TestState.get_name()}.mapping[{TestState.get_name()}.map_key]"
)
def test_class_attributes():
"""Test that we can get class attributes."""
prop = TestState.obj.prop1
- assert str(prop) == f"{{{TestState.get_name()}.obj.prop1}}"
+ assert str(prop) == f'{TestState.get_name()}.obj["prop1"]'
prop = TestState.complex[1].prop1
- assert str(prop) == f"{{{TestState.get_name()}.complex[1].prop1}}"
+ assert str(prop) == f'{TestState.get_name()}.complex[1]["prop1"]'
def test_get_parent_state():
@@ -1064,7 +1061,8 @@ def test_dirty_computed_var_from_backend_var(
Args:
interdependent_state: A state with varying Var dependencies.
"""
- assert InterdependentState._v3._backend is True
+ # Accessing ._v3 returns the immutable var it represents instead of the actual computed var
+ # assert InterdependentState._v3._backend is True
interdependent_state._v2 = 2
assert interdependent_state.get_delta() == {
interdependent_state.get_full_name(): {"v2x2": 4, "v3x2": 4},
@@ -2604,15 +2602,23 @@ class UnionState(BaseState):
c3r: Custom3 = Custom3(c2r=Custom2(c1r=Custom1(foo="")))
custom_union: Union[Custom1, Custom2, Custom3] = Custom1(foo="")
- assert UnionState.c3.c2._var_name == "c3?.c2" # type: ignore
- assert UnionState.c3.c2.c1._var_name == "c3?.c2?.c1" # type: ignore
- assert UnionState.c3.c2.c1.foo._var_name == "c3?.c2?.c1?.foo" # type: ignore
- assert UnionState.c3.c2.c1r.foo._var_name == "c3?.c2?.c1r.foo" # type: ignore
- assert UnionState.c3.c2r.c1._var_name == "c3?.c2r.c1" # type: ignore
- assert UnionState.c3.c2r.c1.foo._var_name == "c3?.c2r.c1?.foo" # type: ignore
- assert UnionState.c3.c2r.c1r.foo._var_name == "c3?.c2r.c1r.foo" # type: ignore
- assert UnionState.c3i.c2._var_name == "c3i.c2" # type: ignore
- assert UnionState.c3r.c2._var_name == "c3r.c2" # type: ignore
+ assert str(UnionState.c3.c2) == f'{str(UnionState.c3)}?.["c2"]' # type: ignore
+ assert str(UnionState.c3.c2.c1) == f'{str(UnionState.c3)}?.["c2"]?.["c1"]' # type: ignore
+ assert (
+ str(UnionState.c3.c2.c1.foo) == f'{str(UnionState.c3)}?.["c2"]?.["c1"]?.["foo"]' # type: ignore
+ )
+ assert (
+ str(UnionState.c3.c2.c1r.foo) == f'{str(UnionState.c3)}?.["c2"]?.["c1r"]["foo"]' # type: ignore
+ )
+ assert str(UnionState.c3.c2r.c1) == f'{str(UnionState.c3)}?.["c2r"]["c1"]' # type: ignore
+ assert (
+ str(UnionState.c3.c2r.c1.foo) == f'{str(UnionState.c3)}?.["c2r"]["c1"]?.["foo"]' # type: ignore
+ )
+ assert (
+ str(UnionState.c3.c2r.c1r.foo) == f'{str(UnionState.c3)}?.["c2r"]["c1r"]["foo"]' # type: ignore
+ )
+ assert str(UnionState.c3i.c2) == f'{str(UnionState.c3i)}["c2"]' # type: ignore
+ assert str(UnionState.c3r.c2) == f'{str(UnionState.c3r)}["c2"]' # type: ignore
assert UnionState.custom_union.foo is not None # type: ignore
assert UnionState.custom_union.c1 is not None # type: ignore
assert UnionState.custom_union.c1r is not None # type: ignore
diff --git a/tests/test_style.py b/tests/test_style.py
index 825d72a9d2..8fa443cdf6 100644
--- a/tests/test_style.py
+++ b/tests/test_style.py
@@ -1,18 +1,19 @@
from __future__ import annotations
-from typing import Any
+from typing import Any, Dict
import pytest
import reflex as rx
from reflex import style
from reflex.components.component import evaluate_style_namespaces
+from reflex.ivars.base import ImmutableVar, LiteralVar
from reflex.style import Style
-from reflex.vars import Var, VarData
+from reflex.vars import ImmutableVarData, Var, VarData
test_style = [
({"a": 1}, {"a": 1}),
- ({"a": Var.create("abc")}, {"a": "abc"}),
+ ({"a": LiteralVar.create("abc")}, {"a": "abc"}),
({"test_case": 1}, {"testCase": 1}),
({"test_case": {"a": 1}}, {"testCase": {"a": 1}}),
({":test_case": {"a": 1}}, {":testCase": {"a": 1}}),
@@ -21,8 +22,8 @@
{"::-webkit-scrollbar": {"display": "none"}},
{"::-webkit-scrollbar": {"display": "none"}},
),
- ({"margin_y": "2rem"}, {"marginBottom": "2rem", "marginTop": "2rem"}),
- ({"marginY": "2rem"}, {"marginBottom": "2rem", "marginTop": "2rem"}),
+ ({"margin_y": "2rem"}, {"marginTop": "2rem", "marginBottom": "2rem"}),
+ ({"marginY": "2rem"}, {"marginTop": "2rem", "marginBottom": "2rem"}),
(
{"::-webkit-scrollbar": {"bgColor": "red"}},
{"::-webkit-scrollbar": {"backgroundColor": "red"}},
@@ -49,7 +50,7 @@ def test_convert(style_dict, expected):
expected: The expected formatted style.
"""
converted_dict, _var_data = style.convert(style_dict)
- assert converted_dict == expected
+ assert LiteralVar.create(converted_dict).equals(LiteralVar.create(expected))
@pytest.mark.parametrize(
@@ -63,7 +64,9 @@ def test_create_style(style_dict, expected):
style_dict: The style to check.
expected: The expected formatted style.
"""
- assert style.Style(style_dict) == expected
+ assert LiteralVar.create(style.Style(style_dict)).equals(
+ LiteralVar.create(expected)
+ )
def compare_dict_of_var(d1: dict[str, Any], d2: dict[str, Any]):
@@ -87,39 +90,47 @@ def compare_dict_of_var(d1: dict[str, Any], d2: dict[str, Any]):
@pytest.mark.parametrize(
("kwargs", "style_dict", "expected_get_style"),
[
- ({}, {}, {"css": None}),
- ({"color": "hotpink"}, {}, {"css": Var.create(Style({"color": "hotpink"}))}),
- ({}, {"color": "red"}, {"css": Var.create(Style({"color": "red"}))}),
+ ({}, {}, {}),
+ (
+ {"color": "hotpink"},
+ {},
+ {"css": LiteralVar.create(Style({"color": "hotpink"}))},
+ ),
+ ({}, {"color": "red"}, {"css": LiteralVar.create(Style({"color": "red"}))}),
(
{"color": "hotpink"},
{"color": "red"},
- {"css": Var.create(Style({"color": "hotpink"}))},
+ {"css": LiteralVar.create(Style({"color": "hotpink"}))},
),
(
{"_hover": {"color": "hotpink"}},
{},
- {"css": Var.create(Style({"&:hover": {"color": "hotpink"}}))},
+ {"css": LiteralVar.create(Style({"&:hover": {"color": "hotpink"}}))},
),
(
{},
{"_hover": {"color": "red"}},
- {"css": Var.create(Style({"&:hover": {"color": "red"}}))},
+ {"css": LiteralVar.create(Style({"&:hover": {"color": "red"}}))},
),
(
{},
{":hover": {"color": "red"}},
- {"css": Var.create(Style({"&:hover": {"color": "red"}}))},
+ {"css": LiteralVar.create(Style({"&:hover": {"color": "red"}}))},
),
(
{},
{"::-webkit-scrollbar": {"display": "none"}},
- {"css": Var.create(Style({"&::-webkit-scrollbar": {"display": "none"}}))},
+ {
+ "css": LiteralVar.create(
+ Style({"&::-webkit-scrollbar": {"display": "none"}})
+ )
+ },
),
(
{},
{"::-moz-progress-bar": {"background_color": "red"}},
{
- "css": Var.create(
+ "css": LiteralVar.create(
Style({"&::-moz-progress-bar": {"backgroundColor": "red"}})
)
},
@@ -128,7 +139,7 @@ def compare_dict_of_var(d1: dict[str, Any], d2: dict[str, Any]):
{"color": ["#111", "#222", "#333", "#444", "#555"]},
{},
{
- "css": Var.create(
+ "css": LiteralVar.create(
Style(
{
"@media screen and (min-width: 0)": {"color": "#111"},
@@ -148,7 +159,7 @@ def compare_dict_of_var(d1: dict[str, Any], d2: dict[str, Any]):
},
{},
{
- "css": Var.create(
+ "css": LiteralVar.create(
Style(
{
"@media screen and (min-width: 0)": {"color": "#111"},
@@ -169,7 +180,7 @@ def compare_dict_of_var(d1: dict[str, Any], d2: dict[str, Any]):
},
{},
{
- "css": Var.create(
+ "css": LiteralVar.create(
Style(
{
"@media screen and (min-width: 0)": {
@@ -209,7 +220,7 @@ def compare_dict_of_var(d1: dict[str, Any], d2: dict[str, Any]):
},
{},
{
- "css": Var.create(
+ "css": LiteralVar.create(
Style(
{
"&:hover": {
@@ -236,7 +247,7 @@ def compare_dict_of_var(d1: dict[str, Any], d2: dict[str, Any]):
{"_hover": {"color": ["#111", "#222", "#333", "#444", "#555"]}},
{},
{
- "css": Var.create(
+ "css": LiteralVar.create(
Style(
{
"&:hover": {
@@ -268,7 +279,7 @@ def compare_dict_of_var(d1: dict[str, Any], d2: dict[str, Any]):
},
{},
{
- "css": Var.create(
+ "css": LiteralVar.create(
Style(
{
"&:hover": {
@@ -307,7 +318,7 @@ def compare_dict_of_var(d1: dict[str, Any], d2: dict[str, Any]):
},
{},
{
- "css": Var.create(
+ "css": LiteralVar.create(
Style(
{
"&:hover": {
@@ -361,20 +372,20 @@ class StyleState(rx.State):
[
(
{"color": StyleState.color},
- {"css": Var.create(Style({"color": StyleState.color}))},
+ {"css": LiteralVar.create(Style({"color": StyleState.color}))},
),
(
{"color": f"dark{StyleState.color}"},
{
- "css": Var.create_safe(f'{{"color": `dark{StyleState.color}`}}').to(
- Style
- )
+ "css": ImmutableVar.create_safe(
+ f'({{ ["color"] : ("dark"+{StyleState.color}) }})'
+ ).to(Dict[str, str])
},
),
(
{"color": StyleState.color, "_hover": {"color": StyleState.color2}},
{
- "css": Var.create(
+ "css": LiteralVar.create(
Style(
{
"color": StyleState.color,
@@ -387,7 +398,7 @@ class StyleState(rx.State):
(
{"color": [StyleState.color, "gray", StyleState.color2, "yellow", "blue"]},
{
- "css": Var.create(
+ "css": LiteralVar.create(
Style(
{
"@media screen and (min-width: 0)": {
@@ -415,7 +426,7 @@ class StyleState(rx.State):
]
},
{
- "css": Var.create(
+ "css": LiteralVar.create(
Style(
{
"&:hover": {
@@ -453,7 +464,7 @@ class StyleState(rx.State):
}
},
{
- "css": Var.create(
+ "css": LiteralVar.create(
Style(
{
"&:hover": {
@@ -492,7 +503,10 @@ def test_style_via_component_with_state(
"""
comp = rx.el.div(**kwargs)
- assert comp.style._var_data == expected_get_style["css"]._var_data
+ assert (
+ ImmutableVarData.merge(comp.style._var_data)
+ == expected_get_style["css"]._get_all_var_data()
+ )
# Assert that style values are equal.
compare_dict_of_var(comp._get_style(), expected_get_style)
@@ -507,10 +521,10 @@ def test_evaluate_style_namespaces():
def test_style_update_with_var_data():
"""Test that .update with a Style containing VarData works."""
- red_var = Var.create_safe("red")._replace(
+ red_var = LiteralVar.create("red")._replace(
merge_var_data=VarData(hooks={"const red = true": None}), # type: ignore
)
- blue_var = Var.create_safe("blue", _var_is_local=False)._replace(
+ blue_var = LiteralVar.create("blue")._replace(
merge_var_data=VarData(hooks={"const blue = true": None}), # type: ignore
)
@@ -521,7 +535,9 @@ def test_style_update_with_var_data():
)
s2 = Style()
s2.update(s1, background_color=f"{blue_var}ish")
- assert s2 == {"color": "red", "backgroundColor": "`${blue}ish`"}
+ assert str(LiteralVar.create(s2)) == str(
+ LiteralVar.create({"color": "red", "backgroundColor": "blueish"})
+ )
assert s2._var_data is not None
assert "const red = true" in s2._var_data.hooks
assert "const blue = true" in s2._var_data.hooks
diff --git a/tests/test_var.py b/tests/test_var.py
index 5c67d99247..cca6cbec47 100644
--- a/tests/test_var.py
+++ b/tests/test_var.py
@@ -8,19 +8,19 @@
from reflex.base import Base
from reflex.constants.base import REFLEX_VAR_CLOSING_TAG, REFLEX_VAR_OPENING_TAG
-from reflex.experimental.vars.base import (
+from reflex.ivars.base import (
ImmutableVar,
LiteralVar,
var_operation,
)
-from reflex.experimental.vars.function import ArgsFunctionOperation, FunctionStringVar
-from reflex.experimental.vars.number import (
+from reflex.ivars.function import ArgsFunctionOperation, FunctionStringVar
+from reflex.ivars.number import (
LiteralBooleanVar,
LiteralNumberVar,
NumberVar,
)
-from reflex.experimental.vars.object import LiteralObjectVar
-from reflex.experimental.vars.sequence import (
+from reflex.ivars.object import LiteralObjectVar
+from reflex.ivars.sequence import (
ArrayVar,
ConcatVarOperation,
LiteralArrayVar,
@@ -892,10 +892,10 @@ def test_literal_var():
def test_function_var():
- addition_func = FunctionStringVar("((a, b) => a + b)")
+ addition_func = FunctionStringVar.create("((a, b) => a + b)")
assert str(addition_func.call(1, 2)) == "(((a, b) => a + b)(1, 2))"
- manual_addition_func = ArgsFunctionOperation(
+ manual_addition_func = ArgsFunctionOperation.create(
("a", "b"),
{
"args": [ImmutableVar.create_safe("a"), ImmutableVar.create_safe("b")],
@@ -913,14 +913,14 @@ def test_function_var():
== "(((...args) => ((((a, b) => a + b)(1, ...args))))(2))"
)
- create_hello_statement = ArgsFunctionOperation(
+ create_hello_statement = ArgsFunctionOperation.create(
("name",), f"Hello, {ImmutableVar.create_safe('name')}!"
)
- first_name = LiteralStringVar("Steven")
- last_name = LiteralStringVar("Universe")
+ first_name = LiteralStringVar.create("Steven")
+ last_name = LiteralStringVar.create("Universe")
assert (
str(create_hello_statement.call(f"{first_name} {last_name}"))
- == '(((name) => (("Hello, "+name+"!")))(("Steven"+" "+"Universe")))'
+ == '(((name) => (("Hello, "+name+"!")))("Steven Universe"))'
)
@@ -932,7 +932,7 @@ def add(a: Union[NumberVar, int], b: Union[NumberVar, int]) -> str:
assert str(add(1, 2)) == "(1 + 2)"
assert str(add(a=4, b=-9)) == "(4 + -9)"
- five = LiteralNumberVar(5)
+ five = LiteralNumberVar.create(5)
seven = add(2, five)
assert isinstance(seven, NumberVar)
@@ -952,7 +952,7 @@ def test_string_operations():
def test_all_number_operations():
- starting_number = LiteralNumberVar(-5.4)
+ starting_number = LiteralNumberVar.create(-5.4)
complicated_number = (((-(starting_number + 1)) * 2 / 3) // 2 % 3) ** 2
@@ -967,19 +967,19 @@ def test_all_number_operations():
assert (
str(even_more_complicated_number)
- == "!(((Math.abs(Math.floor(((Math.floor(((-((-5.4 + 1)) * 2) / 3) / 2) % 3) ** 2))) != 0) || (true && (Math.round(((Math.floor(((-((-5.4 + 1)) * 2) / 3) / 2) % 3) ** 2)) != 0))))"
+ == "!(Boolean((Math.abs(Math.floor(((Math.floor(((-((-5.4 + 1)) * 2) / 3) / 2) % 3) ** 2))) || (2 && Math.round(((Math.floor(((-((-5.4 + 1)) * 2) / 3) / 2) % 3) ** 2))))))"
)
- assert str(LiteralNumberVar(5) > False) == "(5 > 0)"
- assert str(LiteralBooleanVar(False) < 5) == "((false ? 1 : 0) < 5)"
+ assert str(LiteralNumberVar.create(5) > False) == "(5 > 0)"
+ assert str(LiteralBooleanVar.create(False) < 5) == "((false ? 1 : 0) < 5)"
assert (
- str(LiteralBooleanVar(False) < LiteralBooleanVar(True))
+ str(LiteralBooleanVar.create(False) < LiteralBooleanVar.create(True))
== "((false ? 1 : 0) < (true ? 1 : 0))"
)
def test_index_operation():
- array_var = LiteralArrayVar([1, 2, 3, 4, 5])
+ array_var = LiteralArrayVar.create([1, 2, 3, 4, 5])
assert str(array_var[0]) == "[1, 2, 3, 4, 5].at(0)"
assert str(array_var[1:2]) == "[1, 2, 3, 4, 5].slice(1, 2)"
assert (
@@ -988,9 +988,9 @@ def test_index_operation():
)
assert (
str(array_var[::-1])
- == "[1, 2, 3, 4, 5].slice(0, [1, 2, 3, 4, 5].length).reverse().slice(undefined, undefined).filter((_, i) => i % 1 === 0)"
+ == "[1, 2, 3, 4, 5].slice(0, [1, 2, 3, 4, 5].length).slice().reverse().slice(undefined, undefined).filter((_, i) => i % 1 === 0)"
)
- assert str(array_var.reverse()) == "[1, 2, 3, 4, 5].reverse()"
+ assert str(array_var.reverse()) == "[1, 2, 3, 4, 5].slice().reverse()"
assert str(array_var[0].to(NumberVar) + 9) == "([1, 2, 3, 4, 5].at(0) + 9)"
@@ -999,7 +999,7 @@ def test_array_operations():
assert str(array_var.length()) == "[1, 2, 3, 4, 5].length"
assert str(array_var.contains(3)) == "[1, 2, 3, 4, 5].includes(3)"
- assert str(array_var.reverse()) == "[1, 2, 3, 4, 5].reverse()"
+ assert str(array_var.reverse()) == "[1, 2, 3, 4, 5].slice().reverse()"
assert (
str(ArrayVar.range(10))
== "Array.from({ length: (10 - 0) / 1 }, (_, i) => 0 + i * 1)"
@@ -1019,7 +1019,7 @@ def test_array_operations():
def test_object_operations():
- object_var = LiteralObjectVar({"a": 1, "b": 2, "c": 3})
+ object_var = LiteralObjectVar.create({"a": 1, "b": 2, "c": 3})
assert (
str(object_var.keys()) == 'Object.keys(({ ["a"] : 1, ["b"] : 2, ["c"] : 3 }))'
@@ -1035,13 +1035,13 @@ def test_object_operations():
assert str(object_var.a) == '({ ["a"] : 1, ["b"] : 2, ["c"] : 3 })["a"]'
assert str(object_var["a"]) == '({ ["a"] : 1, ["b"] : 2, ["c"] : 3 })["a"]'
assert (
- str(object_var.merge(LiteralObjectVar({"c": 4, "d": 5})))
- == 'Object.assign(({ ["a"] : 1, ["b"] : 2, ["c"] : 3 }), ({ ["c"] : 4, ["d"] : 5 }))'
+ str(object_var.merge(LiteralObjectVar.create({"c": 4, "d": 5})))
+ == '({...({ ["a"] : 1, ["b"] : 2, ["c"] : 3 }), ...({ ["c"] : 4, ["d"] : 5 })})'
)
def test_type_chains():
- object_var = LiteralObjectVar({"a": 1, "b": 2, "c": 3})
+ object_var = LiteralObjectVar.create({"a": 1, "b": 2, "c": 3})
assert (object_var._key_type(), object_var._value_type()) == (str, int)
assert (object_var.keys()._var_type, object_var.values()._var_type) == (
List[str],
@@ -1062,7 +1062,7 @@ def test_type_chains():
def test_nested_dict():
- arr = LiteralArrayVar([{"bar": ["foo", "bar"]}], List[Dict[str, List[str]]])
+ arr = LiteralArrayVar.create([{"bar": ["foo", "bar"]}], List[Dict[str, List[str]]])
assert (
str(arr[0]["bar"][0]) == '[({ ["bar"] : ["foo", "bar"] })].at(0)["bar"].at(0)'
@@ -1720,8 +1720,8 @@ def test_invalid_var_operations(operand1_var: Var, operand2_var, operators: List
f"{ATestState.get_full_name()}.value",
),
(
- Var.create(f"{ATestState.value} string", _var_is_string=True),
- f"`${{{ATestState.get_full_name()}.value}} string`",
+ LiteralVar.create(f"{ATestState.value} string"),
+ f'({ATestState.get_full_name()}.value+" string")',
),
(Var.create(ATestState.dict_val), f"{ATestState.get_full_name()}.dict_val"),
],
diff --git a/tests/utils/test_format.py b/tests/utils/test_format.py
index 95ebc047b6..4623f0fb28 100644
--- a/tests/utils/test_format.py
+++ b/tests/utils/test_format.py
@@ -8,6 +8,7 @@
from reflex.components.tags.tag import Tag
from reflex.event import EventChain, EventHandler, EventSpec, FrontendEvent
+from reflex.ivars.base import ImmutableVar, LiteralVar
from reflex.style import Style
from reflex.utils import format
from reflex.utils.serializers import serialize_figure
@@ -422,19 +423,19 @@ def test_format_cond(
(
"state__state.value",
[
- [Var.create(1), Var.create("red", _var_is_string=True)],
- [Var.create(2), Var.create(3), Var.create("blue", _var_is_string=True)],
+ [LiteralVar.create(1), LiteralVar.create("red")],
+ [LiteralVar.create(2), LiteralVar.create(3), LiteralVar.create("blue")],
[TestState.mapping, TestState.num1],
[
- Var.create(f"{TestState.map_key}-key", _var_is_string=True),
- Var.create("return-key", _var_is_string=True),
+ LiteralVar.create(f"{TestState.map_key}-key"),
+ LiteralVar.create("return-key"),
],
],
- Var.create("yellow", _var_is_string=True),
- "(() => { switch (JSON.stringify(state__state.value)) {case JSON.stringify(1): return (`red`); break;case JSON.stringify(2): case JSON.stringify(3): "
- f"return (`blue`); break;case JSON.stringify({TestState.get_full_name()}.mapping): return "
- f"({TestState.get_full_name()}.num1); break;case JSON.stringify(`${{{TestState.get_full_name()}.map_key}}-key`): return (`return-key`);"
- " break;default: return (`yellow`); break;};})()",
+ LiteralVar.create("yellow"),
+ '(() => { switch (JSON.stringify(state__state.value)) {case JSON.stringify(1): return ("red"); break;case JSON.stringify(2): case JSON.stringify(3): '
+ f'return ("blue"); break;case JSON.stringify({TestState.get_full_name()}.mapping): return '
+ f'({TestState.get_full_name()}.num1); break;case JSON.stringify(({TestState.get_full_name()}.map_key+"-key")): return ("return-key");'
+ ' break;default: return ("yellow"); break;};})()',
)
],
)
@@ -541,7 +542,7 @@ def test_format_match(
{
"h1": f"{{({{node, ...props}}) => }}"
},
- '{{"h1": ({node, ...props}) => }}',
+ '{{"h1": ({node, ...props}) => }}',
),
],
)
@@ -558,7 +559,11 @@ def test_format_prop(prop: Var, formatted: str):
@pytest.mark.parametrize(
"single_props,key_value_props,output",
[
- (["string"], {"key": 42}, ["key={42}", "string"]),
+ (
+ [ImmutableVar.create_safe("...props")],
+ {"key": 42},
+ ["key={42}", "{...props}"],
+ ),
],
)
def test_format_props(single_props, key_value_props, output):