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.
"""
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:

View File

@ -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]

View File

@ -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()

View File

@ -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()

View File

@ -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]

View File

@ -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)}])",

View File

@ -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

View File

@ -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):

View File

@ -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.

View File

@ -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. "

View File

@ -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")],

View File

@ -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

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.
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 (

View File

@ -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,
)
)

View File

@ -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 "
)

View File

@ -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", " ")

View File

@ -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")

View File

@ -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

View File

@ -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]

View File

@ -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

View File

@ -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=""):

View File

@ -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:

View File

@ -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,

View File

@ -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]

View File

@ -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(

View File

@ -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

View File

@ -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

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):
@ -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")],

View File

@ -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

View File

@ -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)

View File

@ -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()
),
)

View File

@ -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"])),
),
)

View File

@ -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")

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
# 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)

View File

@ -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,
}

View File

@ -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}.")