Pass _var_is_string parameter to Var.create (#3470)

This commit is contained in:
Masen Furer 2024-06-10 14:32:32 -07:00 committed by GitHub
parent ccf617ba85
commit 66f0a49b75
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
36 changed files with 163 additions and 90 deletions

View File

@ -65,7 +65,9 @@ class ChakraProvider(ChakraComponent):
A new ChakraProvider component. A new ChakraProvider component.
""" """
return super().create( 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: def _get_imports(self) -> imports.ImportDict:

View File

@ -51,7 +51,7 @@ class Checkbox(ChakraComponent):
name: Var[str] name: Var[str]
# The value of the input field when checked (use is_checked prop for a bool) # 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) # The spacing between the checkbox and its label text (0.5rem)
spacing: Var[str] spacing: Var[str]

View File

@ -122,7 +122,7 @@ class PinInput(ChakraComponent):
if ref: if ref:
return ( return (
f"const {ref} = {str(refs_declaration)}; " 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() return super()._get_ref_hook()

View File

@ -80,7 +80,7 @@ class RangeSlider(ChakraComponent):
if ref: if ref:
return ( return (
f"const {ref} = Array.from({{length:2}}, () => useRef(null)); " 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() return super()._get_ref_hook()

View File

@ -25,7 +25,9 @@ class Link(ChakraComponent):
text: Var[str] text: Var[str]
# What the link renders to. # 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. # If true, the link will open in new tab.
is_external: Var[bool] is_external: Var[bool]

View File

@ -319,7 +319,9 @@ class Component(BaseComponent, ABC):
# Set default values for any props. # Set default values for any props.
if types._issubclass(field.type_, Var): if types._issubclass(field.type_, Var):
field.required = False 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): elif types._issubclass(field.type_, EventHandler):
field.required = False field.required = False
@ -348,7 +350,10 @@ class Component(BaseComponent, ABC):
"id": kwargs.get("id"), "id": kwargs.get("id"),
"children": children, "children": children,
**{ **{
prop: Var.create(kwargs[prop]) prop: Var.create(
kwargs[prop],
_var_is_string=False,
)
for prop in self.get_initial_props() for prop in self.get_initial_props()
if prop in kwargs if prop in kwargs
}, },
@ -395,7 +400,7 @@ class Component(BaseComponent, ABC):
passed_types = None passed_types = None
try: try:
# Try to create a var from the value. # 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. # Check that the var type is not None.
if kwargs[key] is None: if kwargs[key] is None:
@ -672,7 +677,9 @@ class Component(BaseComponent, ABC):
# Add ref to element if `id` is not None. # Add ref to element if `id` is not None.
ref = self.get_ref() ref = self.get_ref()
if ref is not None: 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: else:
props = props.copy() props = props.copy()
@ -1091,7 +1098,9 @@ class Component(BaseComponent, ABC):
vars.append(comp_prop) vars.append(comp_prop)
elif isinstance(comp_prop, str): elif isinstance(comp_prop, str):
# Collapse VarData encoded in f-strings. # 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: if var._var_data is not None:
vars.append(var) vars.append(var)
@ -1388,7 +1397,7 @@ class Component(BaseComponent, ABC):
""" """
ref = self.get_ref() ref = self.get_ref()
if ref is not None: 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]: def _get_vars_hooks(self) -> dict[str, None]:
"""Get the hooks required by vars referenced in this component. """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. # Store the memoized function name and hook code for this event trigger.
trigger_memo[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 _var_type=EventChain, merge_var_data=memo_var_data
), ),
f"const {memo_name} = useCallback({rendered_chain}, [{', '.join(var_deps)}])", f"const {memo_name} = useCallback({rendered_chain}, [{', '.join(var_deps)}])",

View File

@ -132,7 +132,8 @@ useEffect(() => {{
toast.dismiss("{toast_id}"); toast.dismiss("{toast_id}");
setUserDismissed(false); // after reconnection reset dismissed state setUserDismissed(false); // after reconnection reset dismissed state
}} }}
}}, [{connect_errors}]);""" }}, [{connect_errors}]);""",
_var_is_string=False,
) )
hook._var_data = VarData.merge( # type: ignore hook._var_data = VarData.merge( # type: ignore

View File

@ -14,7 +14,7 @@ from reflex.components.component import Component
from reflex.components.core.cond import cond from reflex.components.core.cond import cond
from reflex.vars import Var 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): class ClientSideRouting(Component):

View File

@ -99,7 +99,9 @@ class DebounceInput(Component):
props["class_name"] = f"{props.get('class_name', '')} {child.class_name}" props["class_name"] = f"{props.get('class_name', '')} {child.class_name}"
child_ref = child.get_ref() child_ref = child.get_ref()
if props.get("input_ref") is None and child_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 props["id"] = child.id
# Set the child element to wrap, including any imports/hooks from the child. # Set the child element to wrap, including any imports/hooks from the child.

View File

@ -60,7 +60,7 @@ class Foreach(Component):
deprecation_version="0.5.0", deprecation_version="0.5.0",
removal_version="0.6.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: if iterable._var_type == Any:
raise ForeachVarError( raise ForeachVarError(
f"Could not foreach over var `{iterable._var_full_name}` of type Any. " f"Could not foreach over var `{iterable._var_full_name}` of type Any. "

View File

@ -119,6 +119,7 @@ def get_upload_dir() -> Path:
uploaded_files_url_prefix: Var = Var.create_safe( uploaded_files_url_prefix: Var = Var.create_safe(
"${getBackendURL(env.UPLOAD)}", "${getBackendURL(env.UPLOAD)}",
_var_is_string=False,
_var_data=VarData( _var_data=VarData(
imports={ imports={
f"/{Dirs.STATE_PATH}": [imports.ImportVar(tag="getBackendURL")], f"/{Dirs.STATE_PATH}": [imports.ImportVar(tag="getBackendURL")],

View File

@ -504,10 +504,13 @@ class CodeBlock(Component):
style=Var.create( style=Var.create(
format.to_camel_case(f"{predicate}{qmark}{value.replace('`', '')}"), format.to_camel_case(f"{predicate}{qmark}{value.replace('`', '')}"),
_var_is_local=False, _var_is_local=False,
_var_is_string=False,
) )
).remove_props("theme", "code") ).remove_props("theme", "code")
if self.code is not None: 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 return out
@staticmethod @staticmethod

View File

@ -263,7 +263,9 @@ class DataEditor(NoSSRComponent):
# Define the name of the getData callback associated with this component and assign to get_cell_content. # Define the name of the getData callback associated with this component and assign to get_cell_content.
data_callback = f"getData_{editor_id}" 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])" "{"] 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 not provided, determine from data.
if rows is None: if rows is None:
props["rows"] = ( props["rows"] = data.length() if isinstance(data, Var) else len(data)
data.length() # BaseVar.create(value=f"{data}.length()", is_local=False)
if isinstance(data, Var)
else len(data)
)
if not isinstance(columns, Var) and len(columns): if not isinstance(columns, Var) and len(columns):
if ( if (

View File

@ -17,7 +17,7 @@ from reflex.vars import BaseVar, Var
from .base import BaseHTML 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( HANDLE_SUBMIT_JS_JINJA2 = Environment().from_string(
""" """
const handleSubmit_{{ handle_submit_unique_name }} = useCallback((ev) => { 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 # when ref start with refs_ it's an array of refs, so we need different method
# to collect data # to collect data
if ref.startswith("refs_"): 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( form_refs[ref[5:-3]] = Var.create_safe(
f"getRefValues({str(ref_var)})", f"getRefValues({str(ref_var)})",
_var_is_local=False, _var_is_local=False,
_var_is_string=False,
_var_data=ref_var._var_data, _var_data=ref_var._var_data,
) )
else: 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( form_refs[ref[4:]] = Var.create_safe(
f"getRefValue({str(ref_var)})", f"getRefValue({str(ref_var)})",
_var_is_local=False, _var_is_local=False,
_var_is_string=False,
_var_data=ref_var._var_data, _var_data=ref_var._var_data,
) )
return form_refs return form_refs
@ -630,6 +632,7 @@ class Textarea(BaseHTML):
on_key_down=Var.create_safe( on_key_down=Var.create_safe(
f"(e) => enterKeySubmitOnKeyDown(e, {self.enter_key_submit._var_name_unwrapped})", f"(e) => enterKeySubmitOnKeyDown(e, {self.enter_key_submit._var_name_unwrapped})",
_var_is_local=False, _var_is_local=False,
_var_is_string=False,
_var_data=self.enter_key_submit._var_data, _var_data=self.enter_key_submit._var_data,
) )
) )
@ -638,6 +641,7 @@ class Textarea(BaseHTML):
on_input=Var.create_safe( on_input=Var.create_safe(
f"(e) => autoHeightOnInput(e, {self.auto_height._var_name_unwrapped})", f"(e) => autoHeightOnInput(e, {self.auto_height._var_name_unwrapped})",
_var_is_local=False, _var_is_local=False,
_var_is_string=False,
_var_data=self.auto_height._var_data, _var_data=self.auto_height._var_data,
) )
) )

View File

@ -19,7 +19,7 @@ from reflex.utils.format import format_event_chain
from reflex.vars import BaseVar, Var from reflex.vars import BaseVar, Var
from .base import BaseHTML 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( 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 " "\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 "
) )

View File

@ -23,19 +23,23 @@ from reflex.utils.imports import ImportVar
from reflex.vars import Var from reflex.vars import Var
# Special vars used in the component map. # Special vars used in the component map.
_CHILDREN = Var.create_safe("children", _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) _PROPS = Var.create_safe("...props", _var_is_local=False, _var_is_string=False)
_MOCK_ARG = Var.create_safe("") _MOCK_ARG = Var.create_safe("", _var_is_string=False)
# Special remark plugins. # Special remark plugins.
_REMARK_MATH = Var.create_safe("remarkMath", _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) _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) _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]) _REMARK_PLUGINS = Var.create_safe([_REMARK_MATH, _REMARK_GFM, _REMARK_UNWRAP_IMAGES])
# Special rehype plugins. # Special rehype plugins.
_REHYPE_KATEX = Var.create_safe("rehypeKatex", _var_is_local=False) _REHYPE_KATEX = Var.create_safe(
_REHYPE_RAW = Var.create_safe("rehypeRaw", _var_is_local=False) "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]) _REHYPE_PLUGINS = Var.create_safe([_REHYPE_KATEX, _REHYPE_RAW])
# These tags do NOT get props passed to them # 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. # If the children are set as a prop, don't pass them as children.
children_prop = props.pop("children", None) children_prop = props.pop("children", None)
if children_prop is not 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 = [] children = []
# Get the component. # Get the component.
@ -259,7 +265,7 @@ class Markdown(Component):
return inline ? ( return inline ? (
{self.format_component("code")} {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", " ") }}}}""".replace("\n", " ")

View File

@ -26,15 +26,19 @@ from reflex.utils import imports, types
from reflex.utils.imports import ImportVar from reflex.utils.imports import ImportVar
from reflex.vars import Var from reflex.vars import Var
_CHILDREN = Var.create_safe("children", _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) _PROPS = Var.create_safe("...props", _var_is_local=False, _var_is_string=False)
_MOCK_ARG = Var.create_safe("") _MOCK_ARG = Var.create_safe("", _var_is_string=False)
_REMARK_MATH = Var.create_safe("remarkMath", _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) _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) _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]) _REMARK_PLUGINS = Var.create_safe([_REMARK_MATH, _REMARK_GFM, _REMARK_UNWRAP_IMAGES])
_REHYPE_KATEX = Var.create_safe("rehypeKatex", _var_is_local=False) _REHYPE_KATEX = Var.create_safe(
_REHYPE_RAW = Var.create_safe("rehypeRaw", _var_is_local=False) "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]) _REHYPE_PLUGINS = Var.create_safe([_REHYPE_KATEX, _REHYPE_RAW])
NO_PROPS_TAGS = ("ul", "ol", "li") NO_PROPS_TAGS = ("ul", "ol", "li")

View File

@ -29,7 +29,7 @@ def _event_data_signature(e0: Var) -> List[Any]:
Returns: Returns:
The event key extracted from the event data (if defined). 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]: 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. The event data and the extracted points.
""" """
return [ return [
Var.create_safe(f"{e0}?.event"), Var.create_safe(f"{e0}?.event", _var_is_string=False),
Var.create_safe( Var.create_safe(
f"extractPoints({e0}?.points)", f"extractPoints({e0}?.points)",
_var_is_string=False,
), ),
] ]
@ -277,11 +278,14 @@ const extractPoints = (points) => {
Var.create_safe( Var.create_safe(
f"{{...mergician({figure._var_name_unwrapped}," f"{{...mergician({figure._var_name_unwrapped},"
f"{','.join(md._var_name_unwrapped for md in merge_dicts)})}}", f"{','.join(md._var_name_unwrapped for md in merge_dicts)})}}",
_var_is_string=False,
), ),
) )
else: else:
# Spread the figure dict over props, nothing to merge. # Spread the figure dict over props, nothing to merge.
tag.special_props.add( 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 return tag

View File

@ -105,7 +105,7 @@ class AccordionRoot(AccordionComponent):
duration: Var[int] = Var.create_safe(DEFAULT_ANIMATION_DURATION) duration: Var[int] = Var.create_safe(DEFAULT_ANIMATION_DURATION)
# The easing function to use for the animation. # 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. # Whether to show divider lines between items.
show_dividers: Var[bool] show_dividers: Var[bool]

View File

@ -233,6 +233,7 @@ class Theme(RadixThemesComponent):
css=Var.create( css=Var.create(
"{{...theme.styles.global[':root'], ...theme.styles.global.body}}", "{{...theme.styles.global[':root'], ...theme.styles.global.body}}",
_var_is_local=False, _var_is_local=False,
_var_is_string=False,
), ),
) )
return tag return tag

View File

@ -73,7 +73,7 @@ position_map = {
# needed to inverse contains for find # needed to inverse contains for find
def _find(const, var): 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=""): def _set_var_default(props, position, prop, default1, default2=""):

View File

@ -130,7 +130,9 @@ class HighLevelCheckbox(RadixThemesComponent):
} }
@classmethod @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. """Create a checkbox with a label.
Args: Args:

View File

@ -91,10 +91,10 @@ class HighLevelRadioGroup(RadixThemesComponent):
direction: Var[LiteralFlexDirection] direction: Var[LiteralFlexDirection]
# The gap between the items of the radio group. # 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. # 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 # The variant of the radio group
variant: Var[Literal["classic", "surface", "soft"]] 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 default_value = Var.create(default_value, _var_is_string=True) # type: ignore
else: else:
default_value = ( 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: 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 = rx.cond(
item_value._type() == str, # type: ignore item_value._type() == str, # type: ignore
item_value, item_value,

View File

@ -17,7 +17,7 @@ class Separator(RadixThemesComponent):
tag = "Separator" tag = "Separator"
# The size of the select: "1" | "2" | "3" | "4" # 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 # The color of the select
color_scheme: Var[LiteralAccentColor] color_scheme: Var[LiteralAccentColor]

View File

@ -21,7 +21,7 @@ class Container(elements.Div, RadixThemesComponent):
tag = "Container" tag = "Container"
# The size of the container: "1" - "4" (default "3") # 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 @classmethod
def create( def create(

View File

@ -17,7 +17,7 @@ class Section(elements.Section, RadixThemesComponent):
tag = "Section" tag = "Section"
# The size of the section: "1" - "3" (default "2") # 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 section = Section.create

View File

@ -154,7 +154,7 @@ class BarChart(CategoricalChartBase):
alias = "RechartsBarChart" alias = "RechartsBarChart"
# The gap between two bar categories, which can be a percent value or a fixed value. Percentage | Number # 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 # 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 bar_gap: Var[Union[str, int]] = Var.create_safe(4) # type: ignore

View File

@ -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): class ToastAction(Base):
@ -65,7 +65,8 @@ def _toast_callback_signature(toast: Var) -> list[Var]:
""" """
return [ return [
Var.create_safe( 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] visible_toasts: Var[int]
# the position of the toast # 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 # whether to show the close button
close_button: Var[bool] = Var.create_safe(False) close_button: Var[bool] = Var.create_safe(False)
@ -217,6 +220,7 @@ class Toaster(Component):
hook = Var.create_safe( hook = Var.create_safe(
f"{toast_ref} = toast", f"{toast_ref} = toast",
_var_is_local=True, _var_is_local=True,
_var_is_string=False,
_var_data=VarData( _var_data=VarData(
imports={ imports={
"/utils/state": [ImportVar(tag="refs")], "/utils/state": [ImportVar(tag="refs")],

View File

@ -27,7 +27,7 @@ LiteralPosition = Literal[
"bottom-center", "bottom-center",
"bottom-right", "bottom-right",
] ]
toast_ref = Var.create_safe("refs['__toast']") toast_ref = Var.create_safe("refs['__toast']", _var_is_string=False)
class ToastAction(Base): class ToastAction(Base):
label: str label: str

View File

@ -41,7 +41,8 @@ class Tag(Base):
# Convert any props to vars. # Convert any props to vars.
if "props" in kwargs: if "props" in kwargs:
kwargs["props"] = { 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) super().__init__(*args, **kwargs)

View File

@ -186,7 +186,7 @@ class EventHandler(EventActionsMixin):
# Get the function args. # Get the function args.
fn_args = inspect.getfullargspec(self.fn).args[1:] 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. # Construct the payload.
values = [] values = []
@ -264,7 +264,7 @@ class EventSpec(EventActionsMixin):
# Get the remaining unfilled function args. # Get the remaining unfilled function args.
fn_args = inspect.getfullargspec(self.handler.fn).args[1 + len(self.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. # Construct the payload.
values = [] values = []
@ -389,13 +389,13 @@ class FileUpload(Base):
spec_args = [ spec_args = [
( (
Var.create_safe("files"), Var.create_safe("files", _var_is_string=False),
Var.create_safe(f"filesById.{upload_id}")._replace( Var.create_safe(
_var_data=upload_files_context_var_data 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), 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)) formatted_chain = str(format.format_prop(on_upload_progress_chain))
spec_args.append( spec_args.append(
( (
Var.create_safe("on_upload_progress"), Var.create_safe("on_upload_progress", _var_is_string=False),
BaseVar( BaseVar(
_var_name=formatted_chain.strip("{}"), _var_name=formatted_chain.strip("{}"),
_var_type=EventChain, _var_type=EventChain,
@ -464,7 +464,10 @@ def server_side(name: str, sig: inspect.Signature, **kwargs) -> EventSpec:
return EventSpec( return EventSpec(
handler=EventHandler(fn=fn), handler=EventHandler(fn=fn),
args=tuple( 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() for k, v in kwargs.items()
), ),
) )

View File

@ -20,8 +20,10 @@ def const(name, value) -> Var:
The constant Var. The constant Var.
""" """
if isinstance(name, list): if isinstance(name, list):
return Var.create_safe(f"const [{', '.join(name)}] = {value}") return Var.create_safe(
return Var.create_safe(f"const {name} = {value}") 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: def useCallback(func, deps) -> Var:
@ -36,6 +38,7 @@ def useCallback(func, deps) -> Var:
""" """
return Var.create_safe( return Var.create_safe(
f"useCallback({func}, {deps})" if deps else f"useCallback({func})", f"useCallback({func}, {deps})" if deps else f"useCallback({func})",
_var_is_string=False,
_var_data=VarData(imports=_compose_react_imports(["useCallback"])), _var_data=VarData(imports=_compose_react_imports(["useCallback"])),
) )
@ -51,6 +54,7 @@ def useContext(context) -> Var:
""" """
return Var.create_safe( return Var.create_safe(
f"useContext({context})", f"useContext({context})",
_var_is_string=False,
_var_data=VarData(imports=_compose_react_imports(["useContext"])), _var_data=VarData(imports=_compose_react_imports(["useContext"])),
) )
@ -66,6 +70,7 @@ def useRef(default) -> Var:
""" """
return Var.create_safe( return Var.create_safe(
f"useRef({default})", f"useRef({default})",
_var_is_string=False,
_var_data=VarData(imports=_compose_react_imports(["useRef"])), _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_name, f"set{var_name.capitalize()}"],
Var.create_safe( Var.create_safe(
f"useState({default})", f"useState({default})",
_var_is_string=False,
_var_data=VarData(imports=_compose_react_imports(["useState"])), _var_data=VarData(imports=_compose_react_imports(["useState"])),
), ),
) )

View File

@ -52,7 +52,11 @@ class Sidebar(Box, MemoizationLeaf):
""" """
sidebar: Component = self.children[-2] # type: ignore sidebar: Component = self.children[-2] # type: ignore
spacer: Component = self.children[-1] # 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") sidebar.style["display"] = spacer.style["display"] = cond(open, "block", "none")
return Style( return Style(
@ -167,7 +171,10 @@ class SidebarTrigger(Fragment):
if sidebar.State: if sidebar.State:
open, toggle = sidebar.State.open, sidebar.State.toggle # type: ignore open, toggle = sidebar.State.open, sidebar.State.toggle # type: ignore
else: 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") trigger_props["left"] = cond(open, f"calc({sidebar_width} - 32px)", "0")

View File

@ -79,7 +79,7 @@ def convert_item(style_item: str | Var) -> tuple[str, VarData | None]:
return str(style_item), style_item._var_data return str(style_item), style_item._var_data
# Otherwise, convert to Var to collapse VarData encoded in f-string. # 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: if new_var is not None and new_var._var_data:
# The wrapped backtick is used to identify the Var for interpolation. # The wrapped backtick is used to identify the Var for interpolation.
return f"`{str(new_var)}`", new_var._var_data return f"`{str(new_var)}`", new_var._var_data
@ -204,7 +204,7 @@ class Style(dict):
value: The value to set. value: The value to set.
""" """
# Create a Var to collapse VarData encoded in f-string. # 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: if _var is not None:
# Carry the imports/hooks when setting a Var as a value. # Carry the imports/hooks when setting a Var as a value.
self._var_data = VarData.merge(self._var_data, _var._var_data) self._var_data = VarData.merge(self._var_data, _var._var_data)

View File

@ -916,4 +916,7 @@ def format_data_editor_cell(cell: Any):
Returns: Returns:
The formatted cell. 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,
}

View File

@ -535,7 +535,7 @@ class Var:
if other is None: if other is None:
return self._replace() return self._replace()
if not isinstance(other, Var): if not isinstance(other, Var):
other = Var.create(other) other = Var.create(other, _var_is_string=False)
return self._replace( return self._replace(
_var_name=f"{{...{self._var_name}, ...{other._var_name}}}" # type: ignore _var_name=f"{{...{self._var_name}, ...{other._var_name}}}" # type: ignore
) )
@ -831,9 +831,9 @@ class Var:
from reflex.utils import format from reflex.utils import format
if isinstance(other, str): if isinstance(other, str):
other = Var.create(json.dumps(other)) other = Var.create(json.dumps(other), _var_is_string=False)
else: else:
other = Var.create(other) other = Var.create(other, _var_is_string=False)
type_ = type_ or self._var_type type_ = type_ or self._var_type
@ -1416,7 +1416,7 @@ class Var:
if isinstance(other, str): if isinstance(other, str):
other = Var.create(json.dumps(other), _var_is_string=True) other = Var.create(json.dumps(other), _var_is_string=True)
elif not isinstance(other, Var): elif not isinstance(other, Var):
other = Var.create(other) other = Var.create(other, _var_is_string=False)
if types._issubclass(self._var_type, Dict): if types._issubclass(self._var_type, Dict):
return self._replace( return self._replace(
_var_name=f"{self._var_name}.{method}({other._var_full_name})", _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): if not types._issubclass(self._var_type, str):
raise VarTypeError(f"Cannot strip non-string var {self._var_full_name}.") 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( return self._replace(
_var_name=f"{self._var_name}.replace(/^${other._var_full_name}|${other._var_full_name}$/g, '')", _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): if not types._issubclass(self._var_type, str):
raise VarTypeError(f"Cannot split non-string var {self._var_full_name}.") 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( return self._replace(
_var_name=f"{self._var_name}.split({other._var_full_name})", _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}.") raise VarTypeError(f"Cannot join non-list var {self._var_full_name}.")
if other is None: if other is None:
other = Var.create_safe('""') other = Var.create_safe('""', _var_is_string=False)
if isinstance(other, str): if isinstance(other, str):
other = Var.create_safe(json.dumps(other)) other = Var.create_safe(json.dumps(other), _var_is_string=False)
else: else:
other = Var.create_safe(other) other = Var.create_safe(other, _var_is_string=False)
return self._replace( return self._replace(
_var_name=f"{self._var_name}.join({other._var_full_name})", _var_name=f"{self._var_name}.join({other._var_full_name})",
@ -1641,7 +1649,7 @@ class Var:
if not isinstance(v2, Var): if not isinstance(v2, Var):
v2 = Var.create(v2) v2 = Var.create(v2)
if v2 is None: if v2 is None:
v2 = Var.create_safe("undefined") v2 = Var.create_safe("undefined", _var_is_string=False)
elif v2._var_type != int: elif v2._var_type != int:
raise VarTypeError(f"Cannot get range on non-int var {v2._var_full_name}.") raise VarTypeError(f"Cannot get range on non-int var {v2._var_full_name}.")