diff --git a/reflex/components/chakra/base.py b/reflex/components/chakra/base.py index 9e1f3f698..b0f43b313 100644 --- a/reflex/components/chakra/base.py +++ b/reflex/components/chakra/base.py @@ -65,7 +65,9 @@ class ChakraProvider(ChakraComponent): A new ChakraProvider component. """ return super().create( - theme=Var.create("extendTheme(theme)", _var_is_local=False), + theme=Var.create( + "extendTheme(theme)", _var_is_local=False, _var_is_string=False + ), ) def _get_imports(self) -> imports.ImportDict: diff --git a/reflex/components/chakra/forms/checkbox.py b/reflex/components/chakra/forms/checkbox.py index b0e29ea16..a998f754a 100644 --- a/reflex/components/chakra/forms/checkbox.py +++ b/reflex/components/chakra/forms/checkbox.py @@ -51,7 +51,7 @@ class Checkbox(ChakraComponent): name: Var[str] # The value of the input field when checked (use is_checked prop for a bool) - value: Var[str] = Var.create("true") # type: ignore + value: Var[str] = Var.create("true", _var_is_string=True) # type: ignore # The spacing between the checkbox and its label text (0.5rem) spacing: Var[str] diff --git a/reflex/components/chakra/forms/pininput.py b/reflex/components/chakra/forms/pininput.py index 653bfb90a..0df35a7fe 100644 --- a/reflex/components/chakra/forms/pininput.py +++ b/reflex/components/chakra/forms/pininput.py @@ -122,7 +122,7 @@ class PinInput(ChakraComponent): if ref: return ( f"const {ref} = {str(refs_declaration)}; " - f"{str(Var.create_safe(ref).as_ref())} = {ref}" + f"{str(Var.create_safe(ref, _var_is_string=False).as_ref())} = {ref}" ) return super()._get_ref_hook() diff --git a/reflex/components/chakra/forms/rangeslider.py b/reflex/components/chakra/forms/rangeslider.py index 0b42ad6a5..3eaa8832a 100644 --- a/reflex/components/chakra/forms/rangeslider.py +++ b/reflex/components/chakra/forms/rangeslider.py @@ -80,7 +80,7 @@ class RangeSlider(ChakraComponent): if ref: return ( f"const {ref} = Array.from({{length:2}}, () => useRef(null)); " - f"{str(Var.create_safe(ref).as_ref())} = {ref}" + f"{str(Var.create_safe(ref, _var_is_string=False).as_ref())} = {ref}" ) return super()._get_ref_hook() diff --git a/reflex/components/chakra/navigation/link.py b/reflex/components/chakra/navigation/link.py index a524202df..238473b39 100644 --- a/reflex/components/chakra/navigation/link.py +++ b/reflex/components/chakra/navigation/link.py @@ -25,7 +25,9 @@ class Link(ChakraComponent): text: Var[str] # What the link renders to. - as_: Var[str] = BaseVar.create(value="{NextLink}", _var_is_local=False) # type: ignore + as_: Var[str] = BaseVar.create( + value="{NextLink}", _var_is_local=False, _var_is_string=False + ) # type: ignore # If true, the link will open in new tab. is_external: Var[bool] diff --git a/reflex/components/component.py b/reflex/components/component.py index 516aba929..e465e2091 100644 --- a/reflex/components/component.py +++ b/reflex/components/component.py @@ -319,7 +319,9 @@ class Component(BaseComponent, ABC): # Set default values for any props. if types._issubclass(field.type_, Var): field.required = False - field.default = Var.create(field.default) + field.default = Var.create( + field.default, _var_is_string=isinstance(field.default, str) + ) elif types._issubclass(field.type_, EventHandler): field.required = False @@ -348,7 +350,10 @@ class Component(BaseComponent, ABC): "id": kwargs.get("id"), "children": children, **{ - prop: Var.create(kwargs[prop]) + prop: Var.create( + kwargs[prop], + _var_is_string=False, + ) for prop in self.get_initial_props() if prop in kwargs }, @@ -395,7 +400,7 @@ class Component(BaseComponent, ABC): passed_types = None try: # Try to create a var from the value. - kwargs[key] = Var.create(value) + kwargs[key] = Var.create(value, _var_is_string=False) # Check that the var type is not None. if kwargs[key] is None: @@ -672,7 +677,9 @@ class Component(BaseComponent, ABC): # Add ref to element if `id` is not None. ref = self.get_ref() if ref is not None: - props["ref"] = Var.create(ref, _var_is_local=False) + props["ref"] = Var.create( + ref, _var_is_local=False, _var_is_string=False + ) else: props = props.copy() @@ -1091,7 +1098,9 @@ class Component(BaseComponent, ABC): vars.append(comp_prop) elif isinstance(comp_prop, str): # Collapse VarData encoded in f-strings. - var = Var.create_safe(comp_prop) + var = Var.create_safe( + comp_prop, _var_is_string=isinstance(comp_prop, str) + ) if var._var_data is not None: vars.append(var) @@ -1388,7 +1397,7 @@ class Component(BaseComponent, ABC): """ ref = self.get_ref() if ref is not None: - return f"const {ref} = useRef(null); {str(Var.create_safe(ref).as_ref())} = {ref};" + return f"const {ref} = useRef(null); {str(Var.create_safe(ref, _var_is_string=False).as_ref())} = {ref};" def _get_vars_hooks(self) -> dict[str, None]: """Get the hooks required by vars referenced in this component. @@ -2147,7 +2156,7 @@ class StatefulComponent(BaseComponent): # Store the memoized function name and hook code for this event trigger. trigger_memo[event_trigger] = ( - Var.create_safe(memo_name)._replace( + Var.create_safe(memo_name, _var_is_string=False)._replace( _var_type=EventChain, merge_var_data=memo_var_data ), f"const {memo_name} = useCallback({rendered_chain}, [{', '.join(var_deps)}])", diff --git a/reflex/components/core/banner.py b/reflex/components/core/banner.py index 07d2143c5..33a6f0dee 100644 --- a/reflex/components/core/banner.py +++ b/reflex/components/core/banner.py @@ -132,7 +132,8 @@ useEffect(() => {{ toast.dismiss("{toast_id}"); setUserDismissed(false); // after reconnection reset dismissed state }} -}}, [{connect_errors}]);""" +}}, [{connect_errors}]);""", + _var_is_string=False, ) hook._var_data = VarData.merge( # type: ignore diff --git a/reflex/components/core/client_side_routing.py b/reflex/components/core/client_side_routing.py index 4482f0e9f..d55d66c93 100644 --- a/reflex/components/core/client_side_routing.py +++ b/reflex/components/core/client_side_routing.py @@ -14,7 +14,7 @@ from reflex.components.component import Component from reflex.components.core.cond import cond from reflex.vars import Var -route_not_found: Var = Var.create_safe(constants.ROUTE_NOT_FOUND) +route_not_found: Var = Var.create_safe(constants.ROUTE_NOT_FOUND, _var_is_string=False) class ClientSideRouting(Component): diff --git a/reflex/components/core/debounce.py b/reflex/components/core/debounce.py index d34981426..987ca257c 100644 --- a/reflex/components/core/debounce.py +++ b/reflex/components/core/debounce.py @@ -99,7 +99,9 @@ class DebounceInput(Component): props["class_name"] = f"{props.get('class_name', '')} {child.class_name}" child_ref = child.get_ref() if props.get("input_ref") is None and child_ref: - props["input_ref"] = Var.create_safe(child_ref, _var_is_local=False) + props["input_ref"] = Var.create_safe( + child_ref, _var_is_local=False, _var_is_string=False + ) props["id"] = child.id # Set the child element to wrap, including any imports/hooks from the child. diff --git a/reflex/components/core/foreach.py b/reflex/components/core/foreach.py index b62764444..8804ee19b 100644 --- a/reflex/components/core/foreach.py +++ b/reflex/components/core/foreach.py @@ -60,7 +60,7 @@ class Foreach(Component): deprecation_version="0.5.0", removal_version="0.6.0", ) - iterable = Var.create_safe(iterable) + iterable = Var.create_safe(iterable, _var_is_string=False) if iterable._var_type == Any: raise ForeachVarError( f"Could not foreach over var `{iterable._var_full_name}` of type Any. " diff --git a/reflex/components/core/upload.py b/reflex/components/core/upload.py index d87aa8851..1bcfa3b54 100644 --- a/reflex/components/core/upload.py +++ b/reflex/components/core/upload.py @@ -119,6 +119,7 @@ def get_upload_dir() -> Path: uploaded_files_url_prefix: Var = Var.create_safe( "${getBackendURL(env.UPLOAD)}", + _var_is_string=False, _var_data=VarData( imports={ f"/{Dirs.STATE_PATH}": [imports.ImportVar(tag="getBackendURL")], diff --git a/reflex/components/datadisplay/code.py b/reflex/components/datadisplay/code.py index 8e150c691..d706ec6f3 100644 --- a/reflex/components/datadisplay/code.py +++ b/reflex/components/datadisplay/code.py @@ -504,10 +504,13 @@ class CodeBlock(Component): style=Var.create( format.to_camel_case(f"{predicate}{qmark}{value.replace('`', '')}"), _var_is_local=False, + _var_is_string=False, ) ).remove_props("theme", "code") if self.code is not None: - out.special_props.add(Var.create_safe(f"children={str(self.code)}")) + out.special_props.add( + Var.create_safe(f"children={str(self.code)}", _var_is_string=False) + ) return out @staticmethod diff --git a/reflex/components/datadisplay/dataeditor.py b/reflex/components/datadisplay/dataeditor.py index 429cc3878..16c289f88 100644 --- a/reflex/components/datadisplay/dataeditor.py +++ b/reflex/components/datadisplay/dataeditor.py @@ -263,7 +263,9 @@ class DataEditor(NoSSRComponent): # Define the name of the getData callback associated with this component and assign to get_cell_content. data_callback = f"getData_{editor_id}" - self.get_cell_content = Var.create(data_callback, _var_is_local=False) # type: ignore + self.get_cell_content = Var.create( + data_callback, _var_is_local=False, _var_is_string=False + ) # type: ignore code = [f"function {data_callback}([col, row])" "{"] @@ -301,11 +303,7 @@ class DataEditor(NoSSRComponent): # If rows is not provided, determine from data. if rows is None: - props["rows"] = ( - data.length() # BaseVar.create(value=f"{data}.length()", is_local=False) - if isinstance(data, Var) - else len(data) - ) + props["rows"] = data.length() if isinstance(data, Var) else len(data) if not isinstance(columns, Var) and len(columns): if ( diff --git a/reflex/components/el/elements/forms.py b/reflex/components/el/elements/forms.py index a7760d612..750c4cdb4 100644 --- a/reflex/components/el/elements/forms.py +++ b/reflex/components/el/elements/forms.py @@ -17,7 +17,7 @@ from reflex.vars import BaseVar, Var from .base import BaseHTML -FORM_DATA = Var.create("form_data") +FORM_DATA = Var.create("form_data", _var_is_string=False) HANDLE_SUBMIT_JS_JINJA2 = Environment().from_string( """ const handleSubmit_{{ handle_submit_unique_name }} = useCallback((ev) => { @@ -221,17 +221,19 @@ class Form(BaseHTML): # when ref start with refs_ it's an array of refs, so we need different method # to collect data if ref.startswith("refs_"): - ref_var = Var.create_safe(ref[:-3]).as_ref() + ref_var = Var.create_safe(ref[:-3], _var_is_string=False).as_ref() form_refs[ref[5:-3]] = Var.create_safe( f"getRefValues({str(ref_var)})", _var_is_local=False, + _var_is_string=False, _var_data=ref_var._var_data, ) else: - ref_var = Var.create_safe(ref).as_ref() + ref_var = Var.create_safe(ref, _var_is_string=False).as_ref() form_refs[ref[4:]] = Var.create_safe( f"getRefValue({str(ref_var)})", _var_is_local=False, + _var_is_string=False, _var_data=ref_var._var_data, ) return form_refs @@ -630,6 +632,7 @@ class Textarea(BaseHTML): on_key_down=Var.create_safe( f"(e) => enterKeySubmitOnKeyDown(e, {self.enter_key_submit._var_name_unwrapped})", _var_is_local=False, + _var_is_string=False, _var_data=self.enter_key_submit._var_data, ) ) @@ -638,6 +641,7 @@ class Textarea(BaseHTML): on_input=Var.create_safe( f"(e) => autoHeightOnInput(e, {self.auto_height._var_name_unwrapped})", _var_is_local=False, + _var_is_string=False, _var_data=self.auto_height._var_data, ) ) diff --git a/reflex/components/el/elements/forms.pyi b/reflex/components/el/elements/forms.pyi index 7f15d82a3..4655f3d0a 100644 --- a/reflex/components/el/elements/forms.pyi +++ b/reflex/components/el/elements/forms.pyi @@ -19,7 +19,7 @@ from reflex.utils.format import format_event_chain from reflex.vars import BaseVar, Var from .base import BaseHTML -FORM_DATA = Var.create("form_data") +FORM_DATA = Var.create("form_data", _var_is_string=False) HANDLE_SUBMIT_JS_JINJA2 = Environment().from_string( "\n const handleSubmit_{{ handle_submit_unique_name }} = useCallback((ev) => {\n const $form = ev.target\n ev.preventDefault()\n const {{ form_data }} = {...Object.fromEntries(new FormData($form).entries()), ...{{ field_ref_mapping }}}\n\n {{ on_submit_event_chain }}\n\n if ({{ reset_on_submit }}) {\n $form.reset()\n }\n })\n " ) diff --git a/reflex/components/markdown/markdown.py b/reflex/components/markdown/markdown.py index c61f473b6..68ed6b42f 100644 --- a/reflex/components/markdown/markdown.py +++ b/reflex/components/markdown/markdown.py @@ -23,19 +23,23 @@ from reflex.utils.imports import ImportVar from reflex.vars import Var # Special vars used in the component map. -_CHILDREN = Var.create_safe("children", _var_is_local=False) -_PROPS = Var.create_safe("...props", _var_is_local=False) -_MOCK_ARG = Var.create_safe("") +_CHILDREN = Var.create_safe("children", _var_is_local=False, _var_is_string=False) +_PROPS = Var.create_safe("...props", _var_is_local=False, _var_is_string=False) +_MOCK_ARG = Var.create_safe("", _var_is_string=False) # Special remark plugins. -_REMARK_MATH = Var.create_safe("remarkMath", _var_is_local=False) -_REMARK_GFM = Var.create_safe("remarkGfm", _var_is_local=False) -_REMARK_UNWRAP_IMAGES = Var.create_safe("remarkUnwrapImages", _var_is_local=False) +_REMARK_MATH = Var.create_safe("remarkMath", _var_is_local=False, _var_is_string=False) +_REMARK_GFM = Var.create_safe("remarkGfm", _var_is_local=False, _var_is_string=False) +_REMARK_UNWRAP_IMAGES = Var.create_safe( + "remarkUnwrapImages", _var_is_local=False, _var_is_string=False +) _REMARK_PLUGINS = Var.create_safe([_REMARK_MATH, _REMARK_GFM, _REMARK_UNWRAP_IMAGES]) # Special rehype plugins. -_REHYPE_KATEX = Var.create_safe("rehypeKatex", _var_is_local=False) -_REHYPE_RAW = Var.create_safe("rehypeRaw", _var_is_local=False) +_REHYPE_KATEX = Var.create_safe( + "rehypeKatex", _var_is_local=False, _var_is_string=False +) +_REHYPE_RAW = Var.create_safe("rehypeRaw", _var_is_local=False, _var_is_string=False) _REHYPE_PLUGINS = Var.create_safe([_REHYPE_KATEX, _REHYPE_RAW]) # These tags do NOT get props passed to them @@ -210,7 +214,9 @@ class Markdown(Component): # If the children are set as a prop, don't pass them as children. children_prop = props.pop("children", None) if children_prop is not None: - special_props.add(Var.create_safe(f"children={str(children_prop)}")) + special_props.add( + Var.create_safe(f"children={str(children_prop)}", _var_is_string=False) + ) children = [] # Get the component. @@ -259,7 +265,7 @@ class Markdown(Component): return inline ? ( {self.format_component("code")} ) : ( - {self.format_component("codeblock", language=Var.create_safe("language", _var_is_local=False))} + {self.format_component("codeblock", language=Var.create_safe("language", _var_is_local=False, _var_is_string=False))} ); }}}}""".replace("\n", " ") diff --git a/reflex/components/markdown/markdown.pyi b/reflex/components/markdown/markdown.pyi index 9ca8b11b0..8dec6400a 100644 --- a/reflex/components/markdown/markdown.pyi +++ b/reflex/components/markdown/markdown.pyi @@ -26,15 +26,19 @@ from reflex.utils import imports, types from reflex.utils.imports import ImportVar from reflex.vars import Var -_CHILDREN = Var.create_safe("children", _var_is_local=False) -_PROPS = Var.create_safe("...props", _var_is_local=False) -_MOCK_ARG = Var.create_safe("") -_REMARK_MATH = Var.create_safe("remarkMath", _var_is_local=False) -_REMARK_GFM = Var.create_safe("remarkGfm", _var_is_local=False) -_REMARK_UNWRAP_IMAGES = Var.create_safe("remarkUnwrapImages", _var_is_local=False) +_CHILDREN = Var.create_safe("children", _var_is_local=False, _var_is_string=False) +_PROPS = Var.create_safe("...props", _var_is_local=False, _var_is_string=False) +_MOCK_ARG = Var.create_safe("", _var_is_string=False) +_REMARK_MATH = Var.create_safe("remarkMath", _var_is_local=False, _var_is_string=False) +_REMARK_GFM = Var.create_safe("remarkGfm", _var_is_local=False, _var_is_string=False) +_REMARK_UNWRAP_IMAGES = Var.create_safe( + "remarkUnwrapImages", _var_is_local=False, _var_is_string=False +) _REMARK_PLUGINS = Var.create_safe([_REMARK_MATH, _REMARK_GFM, _REMARK_UNWRAP_IMAGES]) -_REHYPE_KATEX = Var.create_safe("rehypeKatex", _var_is_local=False) -_REHYPE_RAW = Var.create_safe("rehypeRaw", _var_is_local=False) +_REHYPE_KATEX = Var.create_safe( + "rehypeKatex", _var_is_local=False, _var_is_string=False +) +_REHYPE_RAW = Var.create_safe("rehypeRaw", _var_is_local=False, _var_is_string=False) _REHYPE_PLUGINS = Var.create_safe([_REHYPE_KATEX, _REHYPE_RAW]) NO_PROPS_TAGS = ("ul", "ol", "li") diff --git a/reflex/components/plotly/plotly.py b/reflex/components/plotly/plotly.py index 4554dfd28..c0ae6c9fa 100644 --- a/reflex/components/plotly/plotly.py +++ b/reflex/components/plotly/plotly.py @@ -29,7 +29,7 @@ def _event_data_signature(e0: Var) -> List[Any]: Returns: The event key extracted from the event data (if defined). """ - return [Var.create_safe(f"{e0}?.event")] + return [Var.create_safe(f"{e0}?.event", _var_is_string=False)] def _event_points_data_signature(e0: Var) -> List[Any]: @@ -42,9 +42,10 @@ def _event_points_data_signature(e0: Var) -> List[Any]: The event data and the extracted points. """ return [ - Var.create_safe(f"{e0}?.event"), + Var.create_safe(f"{e0}?.event", _var_is_string=False), Var.create_safe( f"extractPoints({e0}?.points)", + _var_is_string=False, ), ] @@ -277,11 +278,14 @@ const extractPoints = (points) => { Var.create_safe( f"{{...mergician({figure._var_name_unwrapped}," f"{','.join(md._var_name_unwrapped for md in merge_dicts)})}}", + _var_is_string=False, ), ) else: # Spread the figure dict over props, nothing to merge. tag.special_props.add( - Var.create_safe(f"{{...{figure._var_name_unwrapped}}}") + Var.create_safe( + f"{{...{figure._var_name_unwrapped}}}", _var_is_string=False + ) ) return tag diff --git a/reflex/components/radix/primitives/accordion.py b/reflex/components/radix/primitives/accordion.py index 12eb8de39..b2ea91a26 100644 --- a/reflex/components/radix/primitives/accordion.py +++ b/reflex/components/radix/primitives/accordion.py @@ -105,7 +105,7 @@ class AccordionRoot(AccordionComponent): duration: Var[int] = Var.create_safe(DEFAULT_ANIMATION_DURATION) # The easing function to use for the animation. - easing: Var[str] = Var.create_safe(DEFAULT_ANIMATION_EASING) + easing: Var[str] = Var.create_safe(DEFAULT_ANIMATION_EASING, _var_is_string=True) # Whether to show divider lines between items. show_dividers: Var[bool] diff --git a/reflex/components/radix/themes/base.py b/reflex/components/radix/themes/base.py index 3b2fd44d7..cf61b1704 100644 --- a/reflex/components/radix/themes/base.py +++ b/reflex/components/radix/themes/base.py @@ -233,6 +233,7 @@ class Theme(RadixThemesComponent): css=Var.create( "{{...theme.styles.global[':root'], ...theme.styles.global.body}}", _var_is_local=False, + _var_is_string=False, ), ) return tag diff --git a/reflex/components/radix/themes/color_mode.py b/reflex/components/radix/themes/color_mode.py index 7a26d960b..716f59ba5 100644 --- a/reflex/components/radix/themes/color_mode.py +++ b/reflex/components/radix/themes/color_mode.py @@ -73,7 +73,7 @@ position_map = { # needed to inverse contains for find def _find(const, var): - return Var.create_safe(const).contains(var) + return Var.create_safe(const, _var_is_string=False).contains(var) def _set_var_default(props, position, prop, default1, default2=""): diff --git a/reflex/components/radix/themes/components/checkbox.py b/reflex/components/radix/themes/components/checkbox.py index 250a1da4c..eb1a73c69 100644 --- a/reflex/components/radix/themes/components/checkbox.py +++ b/reflex/components/radix/themes/components/checkbox.py @@ -130,7 +130,9 @@ class HighLevelCheckbox(RadixThemesComponent): } @classmethod - def create(cls, text: Var[str] = Var.create_safe(""), **props) -> Component: + def create( + cls, text: Var[str] = Var.create_safe("", _var_is_string=True), **props + ) -> Component: """Create a checkbox with a label. Args: diff --git a/reflex/components/radix/themes/components/radio_group.py b/reflex/components/radix/themes/components/radio_group.py index 223b04cfe..b25412e5b 100644 --- a/reflex/components/radix/themes/components/radio_group.py +++ b/reflex/components/radix/themes/components/radio_group.py @@ -91,10 +91,10 @@ class HighLevelRadioGroup(RadixThemesComponent): direction: Var[LiteralFlexDirection] # The gap between the items of the radio group. - spacing: Var[LiteralSpacing] = Var.create_safe("2") + spacing: Var[LiteralSpacing] = Var.create_safe("2", _var_is_string=True) # The size of the radio group. - size: Var[Literal["1", "2", "3"]] = Var.create_safe("2") + size: Var[Literal["1", "2", "3"]] = Var.create_safe("2", _var_is_string=True) # The variant of the radio group variant: Var[Literal["classic", "surface", "soft"]] @@ -151,11 +151,13 @@ class HighLevelRadioGroup(RadixThemesComponent): default_value = Var.create(default_value, _var_is_string=True) # type: ignore else: default_value = ( - Var.create(default_value).to_string()._replace(_var_is_local=False) # type: ignore + Var.create(default_value, _var_is_string=False) + .to_string() # type: ignore + ._replace(_var_is_local=False) ) def radio_group_item(value: str | Var) -> Component: - item_value = Var.create(value) # type: ignore + item_value = Var.create(value, _var_is_string=False) # type: ignore item_value = rx.cond( item_value._type() == str, # type: ignore item_value, diff --git a/reflex/components/radix/themes/components/separator.py b/reflex/components/radix/themes/components/separator.py index 92d2e8b85..b87fea9ec 100644 --- a/reflex/components/radix/themes/components/separator.py +++ b/reflex/components/radix/themes/components/separator.py @@ -17,7 +17,7 @@ class Separator(RadixThemesComponent): tag = "Separator" # The size of the select: "1" | "2" | "3" | "4" - size: Var[LiteralSeperatorSize] = Var.create_safe("4") + size: Var[LiteralSeperatorSize] = Var.create_safe("4", _var_is_string=True) # The color of the select color_scheme: Var[LiteralAccentColor] diff --git a/reflex/components/radix/themes/layout/container.py b/reflex/components/radix/themes/layout/container.py index 9abf1c0d6..f4badefc5 100644 --- a/reflex/components/radix/themes/layout/container.py +++ b/reflex/components/radix/themes/layout/container.py @@ -21,7 +21,7 @@ class Container(elements.Div, RadixThemesComponent): tag = "Container" # The size of the container: "1" - "4" (default "3") - size: Var[LiteralContainerSize] = Var.create_safe("3") + size: Var[LiteralContainerSize] = Var.create_safe("3", _var_is_string=True) @classmethod def create( diff --git a/reflex/components/radix/themes/layout/section.py b/reflex/components/radix/themes/layout/section.py index b1bd743a4..f5c7d4175 100644 --- a/reflex/components/radix/themes/layout/section.py +++ b/reflex/components/radix/themes/layout/section.py @@ -17,7 +17,7 @@ class Section(elements.Section, RadixThemesComponent): tag = "Section" # The size of the section: "1" - "3" (default "2") - size: Var[LiteralSectionSize] = Var.create_safe("2") + size: Var[LiteralSectionSize] = Var.create_safe("2", _var_is_string=True) section = Section.create diff --git a/reflex/components/recharts/charts.py b/reflex/components/recharts/charts.py index 7cfa35a5a..71a1b4feb 100644 --- a/reflex/components/recharts/charts.py +++ b/reflex/components/recharts/charts.py @@ -154,7 +154,7 @@ class BarChart(CategoricalChartBase): alias = "RechartsBarChart" # The gap between two bar categories, which can be a percent value or a fixed value. Percentage | Number - bar_category_gap: Var[Union[str, int]] = Var.create_safe("10%") # type: ignore + bar_category_gap: Var[Union[str, int]] = Var.create_safe("10%", _var_is_string=True) # type: ignore # The gap between two bars in the same category, which can be a percent value or a fixed value. Percentage | Number bar_gap: Var[Union[str, int]] = Var.create_safe(4) # type: ignore diff --git a/reflex/components/sonner/toast.py b/reflex/components/sonner/toast.py index f35b77515..771aab6ae 100644 --- a/reflex/components/sonner/toast.py +++ b/reflex/components/sonner/toast.py @@ -28,7 +28,7 @@ LiteralPosition = Literal[ ] -toast_ref = Var.create_safe("refs['__toast']") +toast_ref = Var.create_safe("refs['__toast']", _var_is_string=False) class ToastAction(Base): @@ -65,7 +65,8 @@ def _toast_callback_signature(toast: Var) -> list[Var]: """ return [ Var.create_safe( - f"(() => {{let {{action, cancel, onDismiss, onAutoClose, ...rest}} = {toast}; return rest}})()" + f"(() => {{let {{action, cancel, onDismiss, onAutoClose, ...rest}} = {toast}; return rest}})()", + _var_is_string=False, ) ] @@ -179,7 +180,9 @@ class Toaster(Component): visible_toasts: Var[int] # the position of the toast - position: Var[LiteralPosition] = Var.create_safe("bottom-right") + position: Var[LiteralPosition] = Var.create_safe( + "bottom-right", _var_is_string=True + ) # whether to show the close button close_button: Var[bool] = Var.create_safe(False) @@ -217,6 +220,7 @@ class Toaster(Component): hook = Var.create_safe( f"{toast_ref} = toast", _var_is_local=True, + _var_is_string=False, _var_data=VarData( imports={ "/utils/state": [ImportVar(tag="refs")], diff --git a/reflex/components/sonner/toast.pyi b/reflex/components/sonner/toast.pyi index 25273d8e6..a69b59090 100644 --- a/reflex/components/sonner/toast.pyi +++ b/reflex/components/sonner/toast.pyi @@ -27,7 +27,7 @@ LiteralPosition = Literal[ "bottom-center", "bottom-right", ] -toast_ref = Var.create_safe("refs['__toast']") +toast_ref = Var.create_safe("refs['__toast']", _var_is_string=False) class ToastAction(Base): label: str diff --git a/reflex/components/tags/tag.py b/reflex/components/tags/tag.py index 27b5dc7c1..bacea6a41 100644 --- a/reflex/components/tags/tag.py +++ b/reflex/components/tags/tag.py @@ -41,7 +41,8 @@ class Tag(Base): # Convert any props to vars. if "props" in kwargs: kwargs["props"] = { - name: Var.create(value) for name, value in kwargs["props"].items() + name: Var.create(value, _var_is_string=False) + for name, value in kwargs["props"].items() } super().__init__(*args, **kwargs) diff --git a/reflex/event.py b/reflex/event.py index cc2d6b42b..5d2a32190 100644 --- a/reflex/event.py +++ b/reflex/event.py @@ -186,7 +186,7 @@ class EventHandler(EventActionsMixin): # Get the function args. fn_args = inspect.getfullargspec(self.fn).args[1:] - fn_args = (Var.create_safe(arg) for arg in fn_args) + fn_args = (Var.create_safe(arg, _var_is_string=False) for arg in fn_args) # Construct the payload. values = [] @@ -264,7 +264,7 @@ class EventSpec(EventActionsMixin): # Get the remaining unfilled function args. fn_args = inspect.getfullargspec(self.handler.fn).args[1 + len(self.args) :] - fn_args = (Var.create_safe(arg) for arg in fn_args) + fn_args = (Var.create_safe(arg, _var_is_string=False) for arg in fn_args) # Construct the payload. values = [] @@ -389,13 +389,13 @@ class FileUpload(Base): spec_args = [ ( - Var.create_safe("files"), - Var.create_safe(f"filesById.{upload_id}")._replace( - _var_data=upload_files_context_var_data - ), + Var.create_safe("files", _var_is_string=False), + Var.create_safe( + f"filesById.{upload_id}", _var_is_string=False + )._replace(_var_data=upload_files_context_var_data), ), ( - Var.create_safe("upload_id"), + Var.create_safe("upload_id", _var_is_string=False), Var.create_safe(upload_id, _var_is_string=True), ), ] @@ -424,7 +424,7 @@ class FileUpload(Base): formatted_chain = str(format.format_prop(on_upload_progress_chain)) spec_args.append( ( - Var.create_safe("on_upload_progress"), + Var.create_safe("on_upload_progress", _var_is_string=False), BaseVar( _var_name=formatted_chain.strip("{}"), _var_type=EventChain, @@ -464,7 +464,10 @@ def server_side(name: str, sig: inspect.Signature, **kwargs) -> EventSpec: return EventSpec( handler=EventHandler(fn=fn), args=tuple( - (Var.create_safe(k), Var.create_safe(v, _var_is_string=isinstance(v, str))) + ( + Var.create_safe(k, _var_is_string=False), + Var.create_safe(v, _var_is_string=isinstance(v, str)), + ) for k, v in kwargs.items() ), ) diff --git a/reflex/experimental/hooks.py b/reflex/experimental/hooks.py index 352935574..c1845d87e 100644 --- a/reflex/experimental/hooks.py +++ b/reflex/experimental/hooks.py @@ -20,8 +20,10 @@ def const(name, value) -> Var: The constant Var. """ if isinstance(name, list): - return Var.create_safe(f"const [{', '.join(name)}] = {value}") - return Var.create_safe(f"const {name} = {value}") + return Var.create_safe( + f"const [{', '.join(name)}] = {value}", _var_is_string=False + ) + return Var.create_safe(f"const {name} = {value}", _var_is_string=False) def useCallback(func, deps) -> Var: @@ -36,6 +38,7 @@ def useCallback(func, deps) -> Var: """ return Var.create_safe( f"useCallback({func}, {deps})" if deps else f"useCallback({func})", + _var_is_string=False, _var_data=VarData(imports=_compose_react_imports(["useCallback"])), ) @@ -51,6 +54,7 @@ def useContext(context) -> Var: """ return Var.create_safe( f"useContext({context})", + _var_is_string=False, _var_data=VarData(imports=_compose_react_imports(["useContext"])), ) @@ -66,6 +70,7 @@ def useRef(default) -> Var: """ return Var.create_safe( f"useRef({default})", + _var_is_string=False, _var_data=VarData(imports=_compose_react_imports(["useRef"])), ) @@ -84,6 +89,7 @@ def useState(var_name, default=None) -> Var: [var_name, f"set{var_name.capitalize()}"], Var.create_safe( f"useState({default})", + _var_is_string=False, _var_data=VarData(imports=_compose_react_imports(["useState"])), ), ) diff --git a/reflex/experimental/layout.py b/reflex/experimental/layout.py index 88a842ba7..cf39ccb6c 100644 --- a/reflex/experimental/layout.py +++ b/reflex/experimental/layout.py @@ -52,7 +52,11 @@ class Sidebar(Box, MemoizationLeaf): """ sidebar: Component = self.children[-2] # type: ignore spacer: Component = self.children[-1] # type: ignore - open = self.State.open if self.State else Var.create("open") # type: ignore + open = ( + self.State.open # type: ignore + if self.State + else Var.create_safe("open", _var_is_string=False) + ) sidebar.style["display"] = spacer.style["display"] = cond(open, "block", "none") return Style( @@ -167,7 +171,10 @@ class SidebarTrigger(Fragment): if sidebar.State: open, toggle = sidebar.State.open, sidebar.State.toggle # type: ignore else: - open, toggle = Var.create("open"), call_script(Var.create("setOpen(!open)")) # type: ignore + open, toggle = ( + Var.create_safe("open", _var_is_string=False), + call_script(Var.create_safe("setOpen(!open)", _var_is_string=False)), + ) trigger_props["left"] = cond(open, f"calc({sidebar_width} - 32px)", "0") diff --git a/reflex/style.py b/reflex/style.py index 86f81cf97..03380107f 100644 --- a/reflex/style.py +++ b/reflex/style.py @@ -79,7 +79,7 @@ def convert_item(style_item: str | Var) -> tuple[str, VarData | None]: return str(style_item), style_item._var_data # Otherwise, convert to Var to collapse VarData encoded in f-string. - new_var = Var.create(style_item) + new_var = Var.create(style_item, _var_is_string=False) if new_var is not None and new_var._var_data: # The wrapped backtick is used to identify the Var for interpolation. return f"`{str(new_var)}`", new_var._var_data @@ -204,7 +204,7 @@ class Style(dict): value: The value to set. """ # Create a Var to collapse VarData encoded in f-string. - _var = Var.create(value) + _var = Var.create(value, _var_is_string=False) if _var is not None: # Carry the imports/hooks when setting a Var as a value. self._var_data = VarData.merge(self._var_data, _var._var_data) diff --git a/reflex/utils/format.py b/reflex/utils/format.py index 9df51b433..207de1edb 100644 --- a/reflex/utils/format.py +++ b/reflex/utils/format.py @@ -916,4 +916,7 @@ def format_data_editor_cell(cell: Any): Returns: The formatted cell. """ - return {"kind": Var.create(value="GridCellKind.Text"), "data": cell} + return { + "kind": Var.create(value="GridCellKind.Text", _var_is_string=False), + "data": cell, + } diff --git a/reflex/vars.py b/reflex/vars.py index c79acc386..438fa6c1c 100644 --- a/reflex/vars.py +++ b/reflex/vars.py @@ -535,7 +535,7 @@ class Var: if other is None: return self._replace() if not isinstance(other, Var): - other = Var.create(other) + other = Var.create(other, _var_is_string=False) return self._replace( _var_name=f"{{...{self._var_name}, ...{other._var_name}}}" # type: ignore ) @@ -831,9 +831,9 @@ class Var: from reflex.utils import format if isinstance(other, str): - other = Var.create(json.dumps(other)) + other = Var.create(json.dumps(other), _var_is_string=False) else: - other = Var.create(other) + other = Var.create(other, _var_is_string=False) type_ = type_ or self._var_type @@ -1416,7 +1416,7 @@ class Var: if isinstance(other, str): other = Var.create(json.dumps(other), _var_is_string=True) elif not isinstance(other, Var): - other = Var.create(other) + other = Var.create(other, _var_is_string=False) if types._issubclass(self._var_type, Dict): return self._replace( _var_name=f"{self._var_name}.{method}({other._var_full_name})", @@ -1520,7 +1520,11 @@ class Var: if not types._issubclass(self._var_type, str): raise VarTypeError(f"Cannot strip non-string var {self._var_full_name}.") - other = Var.create_safe(json.dumps(other)) if isinstance(other, str) else other + other = ( + Var.create_safe(json.dumps(other), _var_is_string=False) + if isinstance(other, str) + else other + ) return self._replace( _var_name=f"{self._var_name}.replace(/^${other._var_full_name}|${other._var_full_name}$/g, '')", @@ -1543,7 +1547,11 @@ class Var: if not types._issubclass(self._var_type, str): raise VarTypeError(f"Cannot split non-string var {self._var_full_name}.") - other = Var.create_safe(json.dumps(other)) if isinstance(other, str) else other + other = ( + Var.create_safe(json.dumps(other), _var_is_string=False) + if isinstance(other, str) + else other + ) return self._replace( _var_name=f"{self._var_name}.split({other._var_full_name})", @@ -1568,11 +1576,11 @@ class Var: raise VarTypeError(f"Cannot join non-list var {self._var_full_name}.") if other is None: - other = Var.create_safe('""') + other = Var.create_safe('""', _var_is_string=False) if isinstance(other, str): - other = Var.create_safe(json.dumps(other)) + other = Var.create_safe(json.dumps(other), _var_is_string=False) else: - other = Var.create_safe(other) + other = Var.create_safe(other, _var_is_string=False) return self._replace( _var_name=f"{self._var_name}.join({other._var_full_name})", @@ -1641,7 +1649,7 @@ class Var: if not isinstance(v2, Var): v2 = Var.create(v2) if v2 is None: - v2 = Var.create_safe("undefined") + v2 = Var.create_safe("undefined", _var_is_string=False) elif v2._var_type != int: raise VarTypeError(f"Cannot get range on non-int var {v2._var_full_name}.")