get reflex-web to compile
This commit is contained in:
parent
81cd679802
commit
ea33c3987a
@ -324,7 +324,8 @@ _MAPPING: dict = {
|
||||
"style": ["Style", "toggle_color_mode"],
|
||||
"utils.imports": ["ImportVar"],
|
||||
"utils.serializers": ["serializer"],
|
||||
"vars": ["cached_var", "Var"],
|
||||
"vars": ["Var"],
|
||||
"ivars.base": ["cached_var"],
|
||||
}
|
||||
|
||||
_SUBMODULES: set[str] = {
|
||||
|
@ -175,6 +175,7 @@ from .event import stop_propagation as stop_propagation
|
||||
from .event import upload_files as upload_files
|
||||
from .event import window_alert as window_alert
|
||||
from .experimental import _x as _x
|
||||
from .ivars.base import cached_var as cached_var
|
||||
from .middleware import Middleware as Middleware
|
||||
from .middleware import middleware as middleware
|
||||
from .model import Model as Model
|
||||
@ -191,7 +192,6 @@ from .style import toggle_color_mode as toggle_color_mode
|
||||
from .utils.imports import ImportVar as ImportVar
|
||||
from .utils.serializers import serializer as serializer
|
||||
from .vars import Var as Var
|
||||
from .vars import cached_var as cached_var
|
||||
|
||||
del compat
|
||||
RADIX_THEMES_MAPPING: dict
|
||||
|
@ -442,7 +442,11 @@ class App(MiddlewareMixin, LifespanMixin, Base):
|
||||
raise
|
||||
except TypeError as e:
|
||||
message = str(e)
|
||||
if "BaseVar" in message or "ComputedVar" in message:
|
||||
if (
|
||||
"BaseVar" in message
|
||||
or "ComputedVar" in message
|
||||
or "ImmutableComputedVar" in message
|
||||
):
|
||||
raise VarOperationTypeError(
|
||||
"You may be trying to use an invalid Python function on a state var. "
|
||||
"When referencing a var inside your render code, only limited var operations are supported. "
|
||||
|
@ -28,7 +28,7 @@ class Bare(Component):
|
||||
"""
|
||||
if isinstance(contents, ImmutableVar):
|
||||
return cls(contents=contents)
|
||||
if isinstance(contents, Var) and contents._var_data:
|
||||
if isinstance(contents, Var) and contents._get_all_var_data():
|
||||
contents = contents.to(str)
|
||||
else:
|
||||
contents = str(contents) if contents is not None else ""
|
||||
|
@ -1121,7 +1121,8 @@ class Component(BaseComponent, ABC):
|
||||
for child in self.children:
|
||||
if not isinstance(child, Component):
|
||||
continue
|
||||
vars.extend(child._get_vars(include_children=include_children))
|
||||
child_vars = child._get_vars(include_children=include_children)
|
||||
vars.extend(child_vars)
|
||||
|
||||
return vars
|
||||
|
||||
@ -1326,13 +1327,13 @@ class Component(BaseComponent, ABC):
|
||||
|
||||
other_imports = []
|
||||
user_hooks = self._get_hooks()
|
||||
if (
|
||||
user_hooks is not None
|
||||
and isinstance(user_hooks, Var)
|
||||
and user_hooks._var_data is not None
|
||||
and user_hooks._var_data.imports
|
||||
):
|
||||
other_imports.append(user_hooks._var_data.imports)
|
||||
user_hooks_data = (
|
||||
VarData.merge(user_hooks._get_all_var_data())
|
||||
if user_hooks is not None and isinstance(user_hooks, Var)
|
||||
else None
|
||||
)
|
||||
if user_hooks_data is not None:
|
||||
other_imports.append(user_hooks_data.imports)
|
||||
other_imports.extend(
|
||||
hook_imports for hook_imports in self._get_added_hooks().values()
|
||||
)
|
||||
@ -1830,9 +1831,11 @@ class CustomComponent(Component):
|
||||
Returns:
|
||||
Each var referenced by the component (props, styles, event handlers).
|
||||
"""
|
||||
return super()._get_vars(include_children=include_children) + [
|
||||
prop for prop in self.props.values() if isinstance(prop, Var)
|
||||
]
|
||||
return (
|
||||
super()._get_vars(include_children=include_children)
|
||||
+ [prop for prop in self.props.values() if isinstance(prop, Var)]
|
||||
+ self.get_component(self)._get_vars(include_children=include_children)
|
||||
)
|
||||
|
||||
@lru_cache(maxsize=None) # noqa
|
||||
def get_component(self) -> Component:
|
||||
|
@ -153,7 +153,7 @@ class ConnectionToaster(Toaster):
|
||||
}}
|
||||
"""
|
||||
),
|
||||
LiteralArrayVar([connect_errors]),
|
||||
LiteralArrayVar.create([connect_errors]),
|
||||
),
|
||||
]
|
||||
|
||||
|
@ -29,7 +29,7 @@ class WebsocketTargetURL(Bare):
|
||||
def create( # type: ignore
|
||||
cls,
|
||||
*children,
|
||||
contents: Optional[Union[Var[str], str]] = None,
|
||||
contents: Optional[Union[Var[Any], Any]] = None,
|
||||
style: Optional[Style] = None,
|
||||
key: Optional[Any] = None,
|
||||
id: Optional[Any] = None,
|
||||
|
@ -104,7 +104,7 @@ class Cond(MemoizationLeaf):
|
||||
The import dict for the component.
|
||||
"""
|
||||
cond_imports: dict[str, str | ImportVar | list[str | ImportVar]] = getattr(
|
||||
self.cond._var_data, "imports", {}
|
||||
VarData.merge(self.cond._get_all_var_data()), "imports", {}
|
||||
)
|
||||
return {**cond_imports, **_IS_TRUE_IMPORT}
|
||||
|
||||
@ -135,6 +135,8 @@ def cond(condition: Any, c1: Any, c2: Any = None) -> Component | ImmutableVar:
|
||||
Raises:
|
||||
ValueError: If the arguments are invalid.
|
||||
"""
|
||||
if isinstance(condition, Var) and not isinstance(condition, ImmutableVar):
|
||||
condition._var_is_local = True
|
||||
# Convert the condition to a Var.
|
||||
cond_var = LiteralVar.create(condition)
|
||||
assert cond_var is not None, "The condition must be set."
|
||||
@ -161,8 +163,8 @@ def cond(condition: Any, c1: Any, c2: Any = None) -> Component | ImmutableVar:
|
||||
c2 = create_var(c2)
|
||||
|
||||
# Create the conditional var.
|
||||
return TernaryOperator(
|
||||
condition=cond_var,
|
||||
return TernaryOperator.create(
|
||||
condition=cond_var.to(bool),
|
||||
if_true=c1,
|
||||
if_false=c2,
|
||||
_var_data=VarData(imports=_IS_TRUE_IMPORT),
|
||||
|
@ -11,7 +11,7 @@ from reflex.style import Style
|
||||
from reflex.utils import format, types
|
||||
from reflex.utils.exceptions import MatchTypeError
|
||||
from reflex.utils.imports import ImportDict
|
||||
from reflex.vars import ImmutableVarData, Var
|
||||
from reflex.vars import ImmutableVarData, Var, VarData
|
||||
|
||||
|
||||
class Match(MemoizationLeaf):
|
||||
@ -264,7 +264,7 @@ class Match(MemoizationLeaf):
|
||||
Returns:
|
||||
The import dict.
|
||||
"""
|
||||
return getattr(self.cond._var_data, "imports", {})
|
||||
return getattr(VarData.merge(self.cond._get_all_var_data()), "imports", {})
|
||||
|
||||
|
||||
match = Match.create
|
||||
|
@ -22,7 +22,7 @@ from reflex.event import (
|
||||
from reflex.ivars.base import ImmutableCallableVar, ImmutableVar
|
||||
from reflex.ivars.sequence import LiteralStringVar
|
||||
from reflex.utils.imports import ImportVar
|
||||
from reflex.vars import Var, VarData
|
||||
from reflex.vars import ImmutableVarData, Var, VarData
|
||||
|
||||
DEFAULT_UPLOAD_ID: str = "default"
|
||||
|
||||
@ -61,7 +61,7 @@ def upload_file(id_: str = DEFAULT_UPLOAD_ID) -> ImmutableVar:
|
||||
return ImmutableVar(
|
||||
_var_name=var_name,
|
||||
_var_type=EventChain,
|
||||
_var_data=VarData.merge(
|
||||
_var_data=ImmutableVarData.merge(
|
||||
upload_files_context_var_data, id_var._get_all_var_data()
|
||||
),
|
||||
)
|
||||
@ -81,7 +81,7 @@ def selected_files(id_: str = DEFAULT_UPLOAD_ID) -> ImmutableVar:
|
||||
return ImmutableVar(
|
||||
_var_name=f"(filesById[{str(id_var)}] ? filesById[{str(id_var)}].map((f) => (f.path || f.name)) : [])",
|
||||
_var_type=List[str],
|
||||
_var_data=VarData.merge(
|
||||
_var_data=ImmutableVarData.merge(
|
||||
upload_files_context_var_data, id_var._get_all_var_data()
|
||||
),
|
||||
).guess_type()
|
||||
|
@ -12,16 +12,17 @@ from reflex.event import (
|
||||
EventHandler,
|
||||
EventSpec,
|
||||
)
|
||||
from reflex.ivars.base import ImmutableCallableVar, ImmutableVar
|
||||
from reflex.style import Style
|
||||
from reflex.vars import BaseVar, CallableVar, Var, VarData
|
||||
from reflex.vars import BaseVar, Var, VarData
|
||||
|
||||
DEFAULT_UPLOAD_ID: str
|
||||
upload_files_context_var_data: VarData
|
||||
|
||||
@CallableVar
|
||||
def upload_file(id_: str = DEFAULT_UPLOAD_ID) -> BaseVar: ...
|
||||
@CallableVar
|
||||
def selected_files(id_: str = DEFAULT_UPLOAD_ID) -> BaseVar: ...
|
||||
@ImmutableCallableVar
|
||||
def upload_file(id_: str = DEFAULT_UPLOAD_ID) -> ImmutableVar: ...
|
||||
@ImmutableCallableVar
|
||||
def selected_files(id_: str = DEFAULT_UPLOAD_ID) -> ImmutableVar: ...
|
||||
@CallableEventSpec
|
||||
def clear_selected_files(id_: str = DEFAULT_UPLOAD_ID) -> EventSpec: ...
|
||||
def cancel_upload(upload_id: str) -> EventSpec: ...
|
||||
|
@ -390,7 +390,7 @@ class CodeBlock(Component):
|
||||
The import dict.
|
||||
"""
|
||||
imports_: ImportDict = {}
|
||||
themes = re.findall(r"`(.*?)`", self.theme._var_name)
|
||||
themes = re.findall(r'"(.*?)"', self.theme._var_name)
|
||||
if not themes:
|
||||
themes = [self.theme._var_name]
|
||||
|
||||
@ -509,11 +509,8 @@ class CodeBlock(Component):
|
||||
style=ImmutableVar.create(
|
||||
format.to_camel_case(f"{predicate}{qmark}{value.replace('`', '')}"),
|
||||
)
|
||||
).remove_props("theme", "code")
|
||||
if self.code is not None:
|
||||
out.special_props.add(
|
||||
Var.create_safe(f"children={str(self.code)}", _var_is_string=False)
|
||||
)
|
||||
).remove_props("theme", "code").add_props(children=self.code)
|
||||
|
||||
return out
|
||||
|
||||
@staticmethod
|
||||
|
@ -14,7 +14,7 @@ from reflex.event import EventChain, EventHandler
|
||||
from reflex.ivars.base import ImmutableVar
|
||||
from reflex.utils.format import format_event_chain
|
||||
from reflex.utils.imports import ImportDict
|
||||
from reflex.vars import Var
|
||||
from reflex.vars import Var, VarData
|
||||
|
||||
from .base import BaseHTML
|
||||
|
||||
@ -218,7 +218,7 @@ class Form(BaseHTML):
|
||||
f"getRefValues({str(ref_var)})",
|
||||
_var_is_local=False,
|
||||
_var_is_string=False,
|
||||
_var_data=ref_var._var_data,
|
||||
_var_data=VarData.merge(ref_var._get_all_var_data()),
|
||||
)
|
||||
else:
|
||||
ref_var = Var.create_safe(ref, _var_is_string=False).as_ref()
|
||||
@ -226,7 +226,7 @@ class Form(BaseHTML):
|
||||
f"getRefValue({str(ref_var)})",
|
||||
_var_is_local=False,
|
||||
_var_is_string=False,
|
||||
_var_data=ref_var._var_data,
|
||||
_var_data=VarData.merge(ref_var._get_all_var_data()),
|
||||
)
|
||||
return form_refs
|
||||
|
||||
@ -632,7 +632,7 @@ class Textarea(BaseHTML):
|
||||
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,
|
||||
_var_data=VarData.merge(self.enter_key_submit._get_all_var_data()),
|
||||
)
|
||||
)
|
||||
if self.auto_height is not None:
|
||||
@ -641,7 +641,7 @@ class Textarea(BaseHTML):
|
||||
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,
|
||||
_var_data=VarData.merge(self.auto_height._get_all_var_data()),
|
||||
)
|
||||
)
|
||||
return tag
|
||||
|
@ -9,13 +9,14 @@ from jinja2 import Environment
|
||||
|
||||
from reflex.components.el.element import Element
|
||||
from reflex.event import EventHandler, EventSpec
|
||||
from reflex.ivars.base import ImmutableVar
|
||||
from reflex.style import Style
|
||||
from reflex.utils.imports import ImportDict
|
||||
from reflex.vars import BaseVar, Var
|
||||
|
||||
from .base import BaseHTML
|
||||
|
||||
FORM_DATA = Var.create("form_data", _var_is_string=False)
|
||||
FORM_DATA = ImmutableVar.create("form_data")
|
||||
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 "
|
||||
)
|
||||
|
@ -29,24 +29,49 @@ class Link(BaseHTML): # noqa: E742
|
||||
|
||||
tag = "link"
|
||||
|
||||
# Specifies the CORS settings for the linked resource
|
||||
cross_origin: Var[Union[str, int, bool]]
|
||||
|
||||
# Specifies the URL of the linked document/resource
|
||||
href: Var[Union[str, int, bool]]
|
||||
|
||||
# Specifies the language of the text in the linked document
|
||||
href_lang: Var[Union[str, int, bool]]
|
||||
|
||||
# Allows a browser to check the fetched link for integrity
|
||||
integrity: Var[Union[str, int, bool]]
|
||||
|
||||
# Specifies on what device the linked document will be displayed
|
||||
media: Var[Union[str, int, bool]]
|
||||
|
||||
# Specifies the referrer policy of the linked document
|
||||
referrer_policy: Var[Union[str, int, bool]]
|
||||
|
||||
# Specifies the relationship between the current document and the linked one
|
||||
rel: Var[Union[str, int, bool]]
|
||||
|
||||
# Specifies the sizes of icons for visual media
|
||||
sizes: Var[Union[str, int, bool]]
|
||||
|
||||
# Specifies the MIME type of the linked document
|
||||
type: Var[Union[str, int, bool]]
|
||||
|
||||
|
||||
class Meta(BaseHTML): # Inherits common attributes from BaseHTML
|
||||
"""Display the meta element."""
|
||||
|
||||
tag = "meta"
|
||||
tag = "meta" # The HTML tag for this element is <meta>
|
||||
|
||||
# Specifies the character encoding for the HTML document
|
||||
char_set: Var[Union[str, int, bool]]
|
||||
|
||||
# Defines the content of the metadata
|
||||
content: Var[Union[str, int, bool]]
|
||||
|
||||
# Provides an HTTP header for the information/value of the content attribute
|
||||
http_equiv: Var[Union[str, int, bool]]
|
||||
|
||||
# Specifies a name for the metadata
|
||||
name: Var[Union[str, int, bool]]
|
||||
|
||||
|
||||
|
@ -346,6 +346,15 @@ class Link(BaseHTML):
|
||||
|
||||
Args:
|
||||
*children: The children of the component.
|
||||
cross_origin: Specifies the CORS settings for the linked resource
|
||||
href: Specifies the URL of the linked document/resource
|
||||
href_lang: Specifies the language of the text in the linked document
|
||||
integrity: Allows a browser to check the fetched link for integrity
|
||||
media: Specifies on what device the linked document will be displayed
|
||||
referrer_policy: Specifies the referrer policy of the linked document
|
||||
rel: Specifies the relationship between the current document and the linked one
|
||||
sizes: Specifies the sizes of icons for visual media
|
||||
type: Specifies the MIME type of the linked document
|
||||
access_key: Provides a hint for generating a keyboard shortcut for the current element.
|
||||
auto_capitalize: Controls whether and how text input is automatically capitalized as it is entered/edited by the user.
|
||||
content_editable: Indicates whether the element's content is editable.
|
||||
@ -466,6 +475,10 @@ class Meta(BaseHTML):
|
||||
|
||||
Args:
|
||||
*children: The children of the component.
|
||||
char_set: Specifies the character encoding for the HTML document
|
||||
content: Defines the content of the metadata
|
||||
http_equiv: Provides an HTTP header for the information/value of the content attribute
|
||||
name: Specifies a name for the metadata
|
||||
access_key: Provides a hint for generating a keyboard shortcut for the current element.
|
||||
auto_capitalize: Controls whether and how text input is automatically capitalized as it is entered/edited by the user.
|
||||
content_editable: Indicates whether the element's content is editable.
|
||||
|
@ -6,6 +6,7 @@ from typing import Any, Dict, List, Union
|
||||
|
||||
from reflex.components.component import Component
|
||||
from reflex.components.tags import Tag
|
||||
from reflex.ivars.base import ImmutableComputedVar
|
||||
from reflex.utils import types
|
||||
from reflex.utils.imports import ImportDict
|
||||
from reflex.utils.serializers import serialize
|
||||
@ -65,14 +66,17 @@ class DataTable(Gridjs):
|
||||
|
||||
# The annotation should be provided if data is a computed var. We need this to know how to
|
||||
# render pandas dataframes.
|
||||
if isinstance(data, ComputedVar) and data._var_type == Any:
|
||||
if (
|
||||
isinstance(data, (ComputedVar, ImmutableComputedVar))
|
||||
and data._var_type == Any
|
||||
):
|
||||
raise ValueError(
|
||||
"Annotation of the computed var assigned to the data field should be provided."
|
||||
)
|
||||
|
||||
if (
|
||||
columns is not None
|
||||
and isinstance(columns, ComputedVar)
|
||||
and isinstance(columns, (ComputedVar, ImmutableComputedVar))
|
||||
and columns._var_type == Any
|
||||
):
|
||||
raise ValueError(
|
||||
|
@ -17,30 +17,26 @@ from reflex.components.radix.themes.typography.heading import Heading
|
||||
from reflex.components.radix.themes.typography.link import Link
|
||||
from reflex.components.radix.themes.typography.text import Text
|
||||
from reflex.components.tags.tag import Tag
|
||||
from reflex.ivars.base import LiteralVar
|
||||
from reflex.ivars.base import ImmutableVar, LiteralVar
|
||||
from reflex.utils import types
|
||||
from reflex.utils.imports import ImportDict, ImportVar
|
||||
from reflex.vars import Var
|
||||
|
||||
# Special vars used in the component map.
|
||||
_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)
|
||||
_CHILDREN = ImmutableVar.create_safe("children")
|
||||
_PROPS = ImmutableVar.create_safe("...props")
|
||||
_MOCK_ARG = ImmutableVar.create_safe("")
|
||||
|
||||
# Special remark plugins.
|
||||
_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])
|
||||
_REMARK_MATH = ImmutableVar.create_safe("remarkMath")
|
||||
_REMARK_GFM = ImmutableVar.create_safe("remarkGfm")
|
||||
_REMARK_UNWRAP_IMAGES = ImmutableVar.create_safe("remarkUnwrapImages")
|
||||
_REMARK_PLUGINS = LiteralVar.create([_REMARK_MATH, _REMARK_GFM, _REMARK_UNWRAP_IMAGES])
|
||||
|
||||
# Special rehype plugins.
|
||||
_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])
|
||||
_REHYPE_KATEX = ImmutableVar.create_safe("rehypeKatex")
|
||||
_REHYPE_RAW = ImmutableVar.create_safe("rehypeRaw")
|
||||
_REHYPE_PLUGINS = LiteralVar.create([_REHYPE_KATEX, _REHYPE_RAW])
|
||||
|
||||
# These tags do NOT get props passed to them
|
||||
NO_PROPS_TAGS = ("ul", "ol", "li")
|
||||
@ -209,10 +205,11 @@ class Markdown(Component):
|
||||
children_prop = props.pop("children", None)
|
||||
if children_prop is not None:
|
||||
special_props.add(
|
||||
Var.create_safe(f"children={str(children_prop)}", _var_is_string=False)
|
||||
Var.create_safe(
|
||||
f"children={{{str(children_prop)}}}", _var_is_string=False
|
||||
)
|
||||
)
|
||||
children = []
|
||||
|
||||
# Get the component.
|
||||
component = self.component_map[tag](*children, **props).set(
|
||||
special_props=special_props
|
||||
@ -238,7 +235,7 @@ class Markdown(Component):
|
||||
The formatted component map.
|
||||
"""
|
||||
components = {
|
||||
tag: f"{{({{node, {_CHILDREN._var_name}, {_PROPS._var_name}}}) => {self.format_component(tag)}}}"
|
||||
tag: f"{{({{node, {_CHILDREN._var_name}, {_PROPS._var_name}}}) => ({self.format_component(tag)})}}"
|
||||
for tag in self.component_map
|
||||
}
|
||||
|
||||
@ -261,7 +258,7 @@ class Markdown(Component):
|
||||
return inline ? (
|
||||
{self.format_component("code")}
|
||||
) : (
|
||||
{self.format_component("codeblock", language=Var.create_safe("language", _var_is_local=False, _var_is_string=False))}
|
||||
{self.format_component("codeblock", language=ImmutableVar.create_safe("language"))}
|
||||
);
|
||||
}}}}""".replace("\n", " ")
|
||||
|
||||
@ -288,7 +285,7 @@ class Markdown(Component):
|
||||
function {self._get_component_map_name()} () {{
|
||||
{formatted_hooks}
|
||||
return (
|
||||
{str(LiteralVar.create(self.format_component_map()))}
|
||||
{str(ImmutableVar.create_safe(self.format_component_map()))}
|
||||
)
|
||||
}}
|
||||
"""
|
||||
@ -300,14 +297,10 @@ class Markdown(Component):
|
||||
.add_props(
|
||||
remark_plugins=_REMARK_PLUGINS,
|
||||
rehype_plugins=_REHYPE_PLUGINS,
|
||||
components=ImmutableVar.create_safe(
|
||||
f"{self._get_component_map_name()}()"
|
||||
),
|
||||
)
|
||||
.remove_props("componentMap", "componentMapHash")
|
||||
)
|
||||
tag.special_props.add(
|
||||
Var.create_safe(
|
||||
f"components={{{self._get_component_map_name()}()}}",
|
||||
_var_is_local=True,
|
||||
_var_is_string=False,
|
||||
),
|
||||
)
|
||||
return tag
|
||||
|
@ -8,24 +8,21 @@ from typing import Any, Callable, Dict, Optional, Union, overload
|
||||
|
||||
from reflex.components.component import Component
|
||||
from reflex.event import EventHandler, EventSpec
|
||||
from reflex.ivars.base import ImmutableVar, LiteralVar
|
||||
from reflex.style import Style
|
||||
from reflex.utils.imports import ImportDict
|
||||
from reflex.vars import BaseVar, Var
|
||||
|
||||
_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, _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])
|
||||
_CHILDREN = ImmutableVar.create_safe("children")
|
||||
_PROPS = ImmutableVar.create_safe("...props")
|
||||
_MOCK_ARG = ImmutableVar.create_safe("")
|
||||
_REMARK_MATH = ImmutableVar.create_safe("remarkMath")
|
||||
_REMARK_GFM = ImmutableVar.create_safe("remarkGfm")
|
||||
_REMARK_UNWRAP_IMAGES = ImmutableVar.create_safe("remarkUnwrapImages")
|
||||
_REMARK_PLUGINS = LiteralVar.create([_REMARK_MATH, _REMARK_GFM, _REMARK_UNWRAP_IMAGES])
|
||||
_REHYPE_KATEX = ImmutableVar.create_safe("rehypeKatex")
|
||||
_REHYPE_RAW = ImmutableVar.create_safe("rehypeRaw")
|
||||
_REHYPE_PLUGINS = LiteralVar.create([_REHYPE_KATEX, _REHYPE_RAW])
|
||||
NO_PROPS_TAGS = ("ul", "ol", "li")
|
||||
|
||||
@lru_cache
|
||||
|
@ -206,5 +206,5 @@ class ColorModeNamespace(ImmutableVar):
|
||||
color_mode = color_mode_var_and_namespace = ColorModeNamespace(
|
||||
_var_name=color_mode._var_name,
|
||||
_var_type=color_mode._var_type,
|
||||
_var_data=color_mode._var_data,
|
||||
_var_data=color_mode.get_default_value(),
|
||||
)
|
||||
|
@ -3,7 +3,6 @@
|
||||
# ------------------- DO NOT EDIT ----------------------
|
||||
# This file was generated by `reflex/utils/pyi_generator.py`!
|
||||
# ------------------------------------------------------
|
||||
import dataclasses
|
||||
from typing import Any, Callable, Dict, Literal, Optional, Union, get_args, overload
|
||||
|
||||
from reflex.components.component import BaseComponent
|
||||
@ -12,6 +11,7 @@ from reflex.components.core.cond import Cond
|
||||
from reflex.components.lucide.icon import Icon
|
||||
from reflex.components.radix.themes.components.switch import Switch
|
||||
from reflex.event import EventHandler, EventSpec
|
||||
from reflex.ivars.base import ImmutableVar
|
||||
from reflex.style import (
|
||||
Style,
|
||||
color_mode,
|
||||
@ -533,11 +533,13 @@ class ColorModeSwitch(Switch):
|
||||
"""
|
||||
...
|
||||
|
||||
class ColorModeNamespace(BaseVar):
|
||||
class ColorModeNamespace(ImmutableVar):
|
||||
icon = staticmethod(ColorModeIcon.create)
|
||||
button = staticmethod(ColorModeIconButton.create)
|
||||
switch = staticmethod(ColorModeSwitch.create)
|
||||
|
||||
color_mode = color_mode_var_and_namespace = ColorModeNamespace(
|
||||
**dataclasses.asdict(color_mode)
|
||||
_var_name=color_mode._var_name,
|
||||
_var_type=color_mode._var_type,
|
||||
_var_data=color_mode.get_default_value(),
|
||||
)
|
||||
|
@ -7,6 +7,7 @@ from reflex.components.core.breakpoints import Responsive
|
||||
from reflex.components.radix.themes.layout.flex import Flex
|
||||
from reflex.components.radix.themes.typography.text import Text
|
||||
from reflex.event import EventHandler
|
||||
from reflex.ivars.base import LiteralVar
|
||||
from reflex.vars import Var
|
||||
|
||||
from ..base import (
|
||||
@ -115,9 +116,7 @@ class HighLevelCheckbox(RadixThemesComponent):
|
||||
on_change: EventHandler[lambda e0: [e0]]
|
||||
|
||||
@classmethod
|
||||
def create(
|
||||
cls, text: Var[str] = Var.create_safe("", _var_is_string=True), **props
|
||||
) -> Component:
|
||||
def create(cls, text: Var[str] = LiteralVar.create(""), **props) -> Component:
|
||||
"""Create a checkbox with a label.
|
||||
|
||||
Args:
|
||||
|
@ -11,7 +11,6 @@ from reflex.components.radix.themes.layout.flex import Flex
|
||||
from reflex.components.radix.themes.typography.text import Text
|
||||
from reflex.event import EventHandler
|
||||
from reflex.ivars.base import ImmutableVar, LiteralVar
|
||||
from reflex.ivars.function import JSON_STRINGIFY
|
||||
from reflex.ivars.sequence import StringVar
|
||||
from reflex.vars import Var
|
||||
|
||||
@ -30,14 +29,10 @@ class RadioGroupRoot(RadixThemesComponent):
|
||||
tag = "RadioGroup.Root"
|
||||
|
||||
# The size of the radio group: "1" | "2" | "3"
|
||||
size: Var[Responsive[Literal["1", "2", "3"]]] = Var.create_safe(
|
||||
"2", _var_is_string=True
|
||||
)
|
||||
size: Var[Responsive[Literal["1", "2", "3"]]] = LiteralVar.create("2")
|
||||
|
||||
# The variant of the radio group
|
||||
variant: Var[Literal["classic", "surface", "soft"]] = Var.create_safe(
|
||||
"classic", _var_is_string=True
|
||||
)
|
||||
variant: Var[Literal["classic", "surface", "soft"]] = LiteralVar.create("classic")
|
||||
|
||||
# The color of the radio group
|
||||
color_scheme: Var[LiteralAccentColor]
|
||||
@ -89,20 +84,16 @@ class HighLevelRadioGroup(RadixThemesComponent):
|
||||
items: Var[List[str]]
|
||||
|
||||
# The direction of the radio group.
|
||||
direction: Var[LiteralFlexDirection] = Var.create_safe(
|
||||
"column", _var_is_string=True
|
||||
)
|
||||
direction: Var[LiteralFlexDirection] = LiteralVar.create("column")
|
||||
|
||||
# The gap between the items of the radio group.
|
||||
spacing: Var[LiteralSpacing] = Var.create_safe("2", _var_is_string=True)
|
||||
spacing: Var[LiteralSpacing] = LiteralVar.create("2")
|
||||
|
||||
# The size of the radio group.
|
||||
size: Var[Literal["1", "2", "3"]] = Var.create_safe("2", _var_is_string=True)
|
||||
size: Var[Literal["1", "2", "3"]] = LiteralVar.create("2")
|
||||
|
||||
# The variant of the radio group
|
||||
variant: Var[Literal["classic", "surface", "soft"]] = Var.create_safe(
|
||||
"classic", _var_is_string=True
|
||||
)
|
||||
variant: Var[Literal["classic", "surface", "soft"]] = LiteralVar.create("classic")
|
||||
|
||||
# The color of the radio group
|
||||
color_scheme: Var[LiteralAccentColor]
|
||||
@ -159,13 +150,13 @@ class HighLevelRadioGroup(RadixThemesComponent):
|
||||
):
|
||||
default_value = LiteralVar.create(default_value) # type: ignore
|
||||
else:
|
||||
default_value = JSON_STRINGIFY.call(ImmutableVar.create(default_value))
|
||||
default_value = ImmutableVar.create_safe(default_value).to_string()
|
||||
|
||||
def radio_group_item(value: Var) -> Component:
|
||||
item_value = rx.cond(
|
||||
value._type() == "string",
|
||||
value,
|
||||
JSON_STRINGIFY.call(value),
|
||||
value.to_string(),
|
||||
).to(StringVar)
|
||||
|
||||
return Text.create(
|
||||
|
@ -3,6 +3,7 @@
|
||||
from typing import Literal
|
||||
|
||||
from reflex.components.core.breakpoints import Responsive
|
||||
from reflex.ivars.base import LiteralVar
|
||||
from reflex.vars import Var
|
||||
|
||||
from ..base import (
|
||||
@ -19,9 +20,7 @@ class Separator(RadixThemesComponent):
|
||||
tag = "Separator"
|
||||
|
||||
# The size of the select: "1" | "2" | "3" | "4"
|
||||
size: Var[Responsive[LiteralSeperatorSize]] = Var.create_safe(
|
||||
"4", _var_is_string=True
|
||||
)
|
||||
size: Var[Responsive[LiteralSeperatorSize]] = LiteralVar.create("4")
|
||||
|
||||
# The color of the select
|
||||
color_scheme: Var[LiteralAccentColor]
|
||||
|
@ -6,6 +6,7 @@ from typing import Literal
|
||||
|
||||
from reflex.components.core.breakpoints import Responsive
|
||||
from reflex.components.el import elements
|
||||
from reflex.ivars.base import LiteralVar
|
||||
from reflex.style import STACK_CHILDREN_FULL_WIDTH
|
||||
from reflex.vars import Var
|
||||
|
||||
@ -23,9 +24,7 @@ class Container(elements.Div, RadixThemesComponent):
|
||||
tag = "Container"
|
||||
|
||||
# The size of the container: "1" - "4" (default "3")
|
||||
size: Var[Responsive[LiteralContainerSize]] = Var.create_safe(
|
||||
"3", _var_is_string=True
|
||||
)
|
||||
size: Var[Responsive[LiteralContainerSize]] = LiteralVar.create("3")
|
||||
|
||||
@classmethod
|
||||
def create(
|
||||
|
@ -6,6 +6,7 @@ from typing import Literal
|
||||
|
||||
from reflex.components.core.breakpoints import Responsive
|
||||
from reflex.components.el import elements
|
||||
from reflex.ivars.base import LiteralVar
|
||||
from reflex.vars import Var
|
||||
|
||||
from ..base import RadixThemesComponent
|
||||
@ -19,9 +20,7 @@ class Section(elements.Section, RadixThemesComponent):
|
||||
tag = "Section"
|
||||
|
||||
# The size of the section: "1" - "3" (default "2")
|
||||
size: Var[Responsive[LiteralSectionSize]] = Var.create_safe(
|
||||
"2", _var_is_string=True
|
||||
)
|
||||
size: Var[Responsive[LiteralSectionSize]] = LiteralVar.create("2")
|
||||
|
||||
|
||||
section = Section.create
|
||||
|
@ -7,6 +7,7 @@ from typing import Any, Dict, List, Union
|
||||
from reflex.constants import EventTriggers
|
||||
from reflex.constants.colors import Color
|
||||
from reflex.event import EventHandler
|
||||
from reflex.ivars.base import LiteralVar
|
||||
from reflex.vars import Var
|
||||
|
||||
from .recharts import (
|
||||
@ -86,7 +87,7 @@ class Axis(Recharts):
|
||||
tick_count: Var[int]
|
||||
|
||||
# If set false, no axis tick lines will be drawn.
|
||||
tick_line: Var[bool] = Var.create_safe(False)
|
||||
tick_line: Var[bool] = LiteralVar.create(False)
|
||||
|
||||
# The length of tick line.
|
||||
tick_size: Var[int]
|
||||
@ -95,7 +96,7 @@ class Axis(Recharts):
|
||||
min_tick_gap: Var[int]
|
||||
|
||||
# The stroke color of axis
|
||||
stroke: Var[Union[str, Color]] = Var.create_safe(Color("gray", 9))
|
||||
stroke: Var[Union[str, Color]] = LiteralVar.create(Color("gray", 9))
|
||||
|
||||
# The text anchor of axis
|
||||
text_anchor: Var[str] # 'start', 'middle', 'end'
|
||||
@ -136,7 +137,7 @@ class XAxis(Axis):
|
||||
x_axis_id: Var[Union[str, int]]
|
||||
|
||||
# Ensures that all datapoints within a chart contribute to its domain calculation, even when they are hidden
|
||||
include_hidden: Var[bool] = Var.create_safe(False)
|
||||
include_hidden: Var[bool] = LiteralVar.create(False)
|
||||
|
||||
|
||||
class YAxis(Axis):
|
||||
@ -187,10 +188,10 @@ class Brush(Recharts):
|
||||
alias = "RechartsBrush"
|
||||
|
||||
# Stroke color
|
||||
stroke: Var[Union[str, Color]] = Var.create_safe(Color("gray", 9))
|
||||
stroke: Var[Union[str, Color]] = LiteralVar.create(Color("gray", 9))
|
||||
|
||||
# The fill color of brush.
|
||||
fill: Var[Union[str, Color]] = Var.create_safe(Color("gray", 2))
|
||||
fill: Var[Union[str, Color]] = LiteralVar.create(Color("gray", 2))
|
||||
|
||||
# The key of data displayed in the axis.
|
||||
data_key: Var[Union[str, int]]
|
||||
@ -290,22 +291,22 @@ class Area(Cartesian):
|
||||
alias = "RechartsArea"
|
||||
|
||||
# The color of the line stroke.
|
||||
stroke: Var[Union[str, Color]] = Var.create_safe(Color("accent", 9))
|
||||
stroke: Var[Union[str, Color]] = LiteralVar.create(Color("accent", 9))
|
||||
|
||||
# The width of the line stroke.
|
||||
stroke_width: Var[int] = Var.create_safe(1)
|
||||
stroke_width: Var[int] = LiteralVar.create(1)
|
||||
|
||||
# The color of the area fill.
|
||||
fill: Var[Union[str, Color]] = Var.create_safe(Color("accent", 5))
|
||||
fill: Var[Union[str, Color]] = LiteralVar.create(Color("accent", 5))
|
||||
|
||||
# The interpolation type of area. And customized interpolation function can be set to type. 'basis' | 'basisClosed' | 'basisOpen' | 'bumpX' | 'bumpY' | 'bump' | 'linear' | 'linearClosed' | 'natural' | 'monotoneX' | 'monotoneY' | 'monotone' | 'step' | 'stepBefore' | 'stepAfter' |
|
||||
type_: Var[LiteralAreaType] = Var.create_safe("monotone", _var_is_string=True)
|
||||
type_: Var[LiteralAreaType] = LiteralVar.create("monotone")
|
||||
|
||||
# If false set, dots will not be drawn. If true set, dots will be drawn which have the props calculated internally.
|
||||
dot: Var[Union[bool, Dict[str, Any]]]
|
||||
|
||||
# The dot is shown when user enter an area chart and this chart has tooltip. If false set, no active dot will not be drawn. If true set, active dot will be drawn which have the props calculated internally.
|
||||
active_dot: Var[Union[bool, Dict[str, Any]]] = Var.create_safe(
|
||||
active_dot: Var[Union[bool, Dict[str, Any]]] = LiteralVar.create(
|
||||
{
|
||||
"stroke": Color("accent", 2),
|
||||
"fill": Color("accent", 10),
|
||||
@ -342,7 +343,7 @@ class Bar(Cartesian):
|
||||
stroke_width: Var[int]
|
||||
|
||||
# The width of the line stroke.
|
||||
fill: Var[Union[str, Color]] = Var.create_safe(Color("accent", 9))
|
||||
fill: Var[Union[str, Color]] = LiteralVar.create(Color("accent", 9))
|
||||
# If false set, background of bars will not be drawn. If true set, background of bars will be drawn which have the props calculated internally.
|
||||
background: Var[bool]
|
||||
|
||||
@ -403,13 +404,13 @@ class Line(Cartesian):
|
||||
type_: Var[LiteralAreaType]
|
||||
|
||||
# The color of the line stroke.
|
||||
stroke: Var[Union[str, Color]] = Var.create_safe(Color("accent", 9))
|
||||
stroke: Var[Union[str, Color]] = LiteralVar.create(Color("accent", 9))
|
||||
|
||||
# The width of the line stroke.
|
||||
stroke_width: Var[int]
|
||||
|
||||
# The dot is shown when mouse enter a line chart and this chart has tooltip. If false set, no active dot will not be drawn. If true set, active dot will be drawn which have the props calculated internally.
|
||||
dot: Var[Union[bool, Dict[str, Any]]] = Var.create_safe(
|
||||
dot: Var[Union[bool, Dict[str, Any]]] = LiteralVar.create(
|
||||
{
|
||||
"stroke": Color("accent", 10),
|
||||
"fill": Color("accent", 4),
|
||||
@ -417,7 +418,7 @@ class Line(Cartesian):
|
||||
)
|
||||
|
||||
# The dot is shown when user enter an area chart and this chart has tooltip. If false set, no active dot will not be drawn. If true set, active dot will be drawn which have the props calculated internally.
|
||||
active_dot: Var[Union[bool, Dict[str, Any]]] = Var.create_safe(
|
||||
active_dot: Var[Union[bool, Dict[str, Any]]] = LiteralVar.create(
|
||||
{
|
||||
"stroke": Color("accent", 2),
|
||||
"fill": Color("accent", 10),
|
||||
@ -475,7 +476,7 @@ class Scatter(Recharts):
|
||||
line_type: Var[LiteralLineType]
|
||||
|
||||
# The fill
|
||||
fill: Var[Union[str, Color]] = Var.create_safe(Color("accent", 9))
|
||||
fill: Var[Union[str, Color]] = LiteralVar.create(Color("accent", 9))
|
||||
|
||||
# the name
|
||||
name: Var[Union[str, int]]
|
||||
@ -552,7 +553,7 @@ class Funnel(Recharts):
|
||||
animation_easing: Var[LiteralAnimationEasing]
|
||||
|
||||
# stroke color
|
||||
stroke: Var[Union[str, Color]] = Var.create_safe(Color("gray", 3))
|
||||
stroke: Var[Union[str, Color]] = LiteralVar.create(Color("gray", 3))
|
||||
|
||||
# Valid children components
|
||||
_valid_children: List[str] = ["LabelList", "Cell"]
|
||||
@ -605,7 +606,7 @@ class ErrorBar(Recharts):
|
||||
width: Var[int]
|
||||
|
||||
# The stroke color of error bar.
|
||||
stroke: Var[Union[str, Color]] = Var.create_safe(Color("gray", 8))
|
||||
stroke: Var[Union[str, Color]] = LiteralVar.create(Color("gray", 8))
|
||||
|
||||
# The stroke width of error bar.
|
||||
stroke_width: Var[int]
|
||||
@ -795,7 +796,7 @@ class CartesianGrid(Grid):
|
||||
stroke_dasharray: Var[str]
|
||||
|
||||
# the stroke color of grid
|
||||
stroke: Var[Union[str, Color]] = Var.create_safe(Color("gray", 7))
|
||||
stroke: Var[Union[str, Color]] = LiteralVar.create(Color("gray", 7))
|
||||
|
||||
|
||||
class CartesianAxis(Grid):
|
||||
|
@ -9,6 +9,7 @@ from reflex.components.recharts.general import ResponsiveContainer
|
||||
from reflex.constants import EventTriggers
|
||||
from reflex.constants.colors import Color
|
||||
from reflex.event import EventHandler
|
||||
from reflex.ivars.base import LiteralVar
|
||||
from reflex.vars import Var
|
||||
|
||||
from .recharts import (
|
||||
@ -156,10 +157,10 @@ 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%", _var_is_string=True) # type: ignore
|
||||
bar_category_gap: Var[Union[str, int]] = LiteralVar.create("10%")
|
||||
|
||||
# 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]] = LiteralVar.create(4) # type: ignore
|
||||
|
||||
# The width of all the bars in the chart. Number
|
||||
bar_size: Var[int]
|
||||
|
@ -7,6 +7,7 @@ from typing import Any, Dict, List, Union
|
||||
from reflex.components.component import MemoizationLeaf
|
||||
from reflex.constants.colors import Color
|
||||
from reflex.event import EventHandler
|
||||
from reflex.ivars.base import LiteralVar
|
||||
from reflex.vars import Var
|
||||
|
||||
from .recharts import (
|
||||
@ -139,7 +140,7 @@ class GraphingTooltip(Recharts):
|
||||
filter_null: Var[bool]
|
||||
|
||||
# If set false, no cursor will be drawn when tooltip is active.
|
||||
cursor: Var[Union[Dict[str, Any], bool]] = Var.create_safe(
|
||||
cursor: Var[Union[Dict[str, Any], bool]] = LiteralVar.create(
|
||||
{
|
||||
"strokeWidth": 1,
|
||||
"fill": Color("gray", 3),
|
||||
@ -150,7 +151,7 @@ class GraphingTooltip(Recharts):
|
||||
view_box: Var[Dict[str, Any]]
|
||||
|
||||
# The style of default tooltip content item which is a li element. DEFAULT: {}
|
||||
item_style: Var[Dict[str, Any]] = Var.create_safe(
|
||||
item_style: Var[Dict[str, Any]] = LiteralVar.create(
|
||||
{
|
||||
"color": Color("gray", 12),
|
||||
}
|
||||
@ -159,7 +160,7 @@ class GraphingTooltip(Recharts):
|
||||
# The style of tooltip wrapper which is a dom element. DEFAULT: {}
|
||||
wrapper_style: Var[Dict[str, Any]]
|
||||
# The style of tooltip content which is a dom element. DEFAULT: {}
|
||||
content_style: Var[Dict[str, Any]] = Var.create_safe(
|
||||
content_style: Var[Dict[str, Any]] = LiteralVar.create(
|
||||
{
|
||||
"background": Color("gray", 1),
|
||||
"borderColor": Color("gray", 4),
|
||||
@ -168,10 +169,10 @@ class GraphingTooltip(Recharts):
|
||||
)
|
||||
|
||||
# The style of default tooltip label which is a p element. DEFAULT: {}
|
||||
label_style: Var[Dict[str, Any]] = Var.create_safe({"color": Color("gray", 11)})
|
||||
label_style: Var[Dict[str, Any]] = LiteralVar.create({"color": Color("gray", 11)})
|
||||
|
||||
# This option allows the tooltip to extend beyond the viewBox of the chart itself. DEFAULT: { x: false, y: false }
|
||||
allow_escape_view_box: Var[Dict[str, bool]] = Var.create_safe(
|
||||
allow_escape_view_box: Var[Dict[str, bool]] = LiteralVar.create(
|
||||
{"x": False, "y": False}
|
||||
)
|
||||
|
||||
@ -231,10 +232,10 @@ class LabelList(Recharts):
|
||||
offset: Var[int]
|
||||
|
||||
# The fill color of each label
|
||||
fill: Var[Union[str, Color]] = Var.create_safe(Color("gray", 10))
|
||||
fill: Var[Union[str, Color]] = LiteralVar.create(Color("gray", 10))
|
||||
|
||||
# The stroke color of each label
|
||||
stroke: Var[Union[str, Color]] = Var.create_safe("none", _var_is_string=True)
|
||||
stroke: Var[Union[str, Color]] = LiteralVar.create("none")
|
||||
|
||||
|
||||
responsive_container = ResponsiveContainer.create
|
||||
|
@ -7,6 +7,7 @@ from typing import Any, Dict, List, Union
|
||||
from reflex.constants import EventTriggers
|
||||
from reflex.constants.colors import Color
|
||||
from reflex.event import EventHandler
|
||||
from reflex.ivars.base import LiteralVar
|
||||
from reflex.vars import Var
|
||||
|
||||
from .recharts import (
|
||||
@ -72,10 +73,10 @@ class Pie(Recharts):
|
||||
_valid_children: List[str] = ["Cell", "LabelList"]
|
||||
|
||||
# Stoke color
|
||||
stroke: Var[Union[str, Color]] = Var.create_safe(Color("accent", 9))
|
||||
stroke: Var[Union[str, Color]] = LiteralVar.create(Color("accent", 9))
|
||||
|
||||
# Fill color
|
||||
fill: Var[Union[str, Color]] = Var.create_safe(Color("accent", 3))
|
||||
fill: Var[Union[str, Color]] = LiteralVar.create(Color("accent", 3))
|
||||
|
||||
def get_event_triggers(self) -> dict[str, Union[Var, Any]]:
|
||||
"""Get the event triggers that pass the component's value to the handler.
|
||||
@ -110,13 +111,13 @@ class Radar(Recharts):
|
||||
dot: Var[bool]
|
||||
|
||||
# Stoke color
|
||||
stroke: Var[Union[str, Color]] = Var.create_safe(Color("accent", 9))
|
||||
stroke: Var[Union[str, Color]] = LiteralVar.create(Color("accent", 9))
|
||||
|
||||
# Fill color
|
||||
fill: Var[str] = Var.create_safe(Color("accent", 3))
|
||||
fill: Var[str] = LiteralVar.create(Color("accent", 3))
|
||||
|
||||
# opacity
|
||||
fill_opacity: Var[float] = Var.create_safe(0.6)
|
||||
fill_opacity: Var[float] = LiteralVar.create(0.6)
|
||||
|
||||
# The type of icon in legend. If set to 'none', no legend item will be rendered.
|
||||
legend_type: Var[str]
|
||||
@ -218,7 +219,7 @@ class PolarAngleAxis(Recharts):
|
||||
axis_line_type: Var[str]
|
||||
|
||||
# If false set, tick lines will not be drawn. If true set, tick lines will be drawn which have the props calculated internally. If object set, tick lines will be drawn which have the props mergered by the internal calculated props and the option.
|
||||
tick_line: Var[Union[bool, Dict[str, Any]]] = Var.create_safe(False)
|
||||
tick_line: Var[Union[bool, Dict[str, Any]]] = LiteralVar.create(False)
|
||||
|
||||
# The width or height of tick.
|
||||
tick: Var[Union[int, str]]
|
||||
@ -230,7 +231,7 @@ class PolarAngleAxis(Recharts):
|
||||
orient: Var[str]
|
||||
|
||||
# The stroke color of axis
|
||||
stroke: Var[Union[str, Color]] = Var.create_safe(Color("gray", 10))
|
||||
stroke: Var[Union[str, Color]] = LiteralVar.create(Color("gray", 10))
|
||||
|
||||
# Allow the axis has duplicated categorys or not when the type of axis is "category".
|
||||
allow_duplicated_category: Var[bool]
|
||||
@ -292,7 +293,7 @@ class PolarGrid(Recharts):
|
||||
grid_type: Var[LiteralGridType]
|
||||
|
||||
# The stroke color of grid
|
||||
stroke: Var[Union[str, Color]] = Var.create_safe(Color("gray", 10))
|
||||
stroke: Var[Union[str, Color]] = LiteralVar.create(Color("gray", 10))
|
||||
|
||||
# Valid children components
|
||||
_valid_children: List[str] = ["RadarChart", "RadiarBarChart"]
|
||||
@ -342,10 +343,10 @@ class PolarRadiusAxis(Recharts):
|
||||
_valid_children: List[str] = ["Label"]
|
||||
|
||||
# The domain of the polar radius axis, specifying the minimum and maximum values.
|
||||
domain: Var[List[int]] = Var.create_safe([0, 250])
|
||||
domain: Var[List[int]] = LiteralVar.create([0, 250])
|
||||
|
||||
# The stroke color of axis
|
||||
stroke: Var[Union[str, Color]] = Var.create_safe(Color("gray", 10))
|
||||
stroke: Var[Union[str, Color]] = LiteralVar.create(Color("gray", 10))
|
||||
|
||||
def get_event_triggers(self) -> dict[str, Union[Var, Any]]:
|
||||
"""Get the event triggers that pass the component's value to the handler.
|
||||
|
@ -12,6 +12,7 @@ from reflex.event import (
|
||||
EventSpec,
|
||||
call_script,
|
||||
)
|
||||
from reflex.ivars.base import LiteralVar
|
||||
from reflex.style import Style, resolved_color_mode
|
||||
from reflex.utils import format
|
||||
from reflex.utils.imports import ImportVar
|
||||
@ -171,21 +172,19 @@ class Toaster(Component):
|
||||
theme: Var[str] = resolved_color_mode
|
||||
|
||||
# whether to show rich colors
|
||||
rich_colors: Var[bool] = Var.create_safe(True)
|
||||
rich_colors: Var[bool] = LiteralVar.create(True)
|
||||
|
||||
# whether to expand the toast
|
||||
expand: Var[bool] = Var.create_safe(True)
|
||||
expand: Var[bool] = LiteralVar.create(True)
|
||||
|
||||
# the number of toasts that are currently visible
|
||||
visible_toasts: Var[int]
|
||||
|
||||
# the position of the toast
|
||||
position: Var[LiteralPosition] = Var.create_safe(
|
||||
"bottom-right", _var_is_string=True
|
||||
)
|
||||
position: Var[LiteralPosition] = LiteralVar.create("bottom-right")
|
||||
|
||||
# whether to show the close button
|
||||
close_button: Var[bool] = Var.create_safe(False)
|
||||
close_button: Var[bool] = LiteralVar.create(False)
|
||||
|
||||
# offset of the toast
|
||||
offset: Var[str]
|
||||
@ -330,7 +329,7 @@ class Toaster(Component):
|
||||
|
||||
if isinstance(id, Var):
|
||||
dismiss = f"{toast_ref}.dismiss({id._var_name_unwrapped})"
|
||||
dismiss_var_data = id._var_data
|
||||
dismiss_var_data = id._get_all_var_data()
|
||||
elif isinstance(id, str):
|
||||
dismiss = f"{toast_ref}.dismiss('{id}')"
|
||||
else:
|
||||
@ -339,7 +338,7 @@ class Toaster(Component):
|
||||
dismiss,
|
||||
_var_is_string=False,
|
||||
_var_is_local=True,
|
||||
_var_data=dismiss_var_data,
|
||||
_var_data=VarData.merge(dismiss_var_data),
|
||||
)
|
||||
return call_script(dismiss_action)
|
||||
|
||||
|
@ -714,15 +714,11 @@ def download(
|
||||
url = "data:text/plain," + urllib.parse.quote(data)
|
||||
elif isinstance(data, Var):
|
||||
# Need to check on the frontend if the Var already looks like a data: URI.
|
||||
is_data_url = data._replace(
|
||||
_var_name=(
|
||||
f"typeof {data._var_full_name} == 'string' && "
|
||||
f"{data._var_full_name}.startsWith('data:')"
|
||||
),
|
||||
_var_type=bool,
|
||||
_var_is_string=False,
|
||||
_var_full_name_needs_state_prefix=False,
|
||||
|
||||
is_data_url = (data._type() == "string") & (
|
||||
data.to(str).startswith("data:")
|
||||
)
|
||||
|
||||
# If it's a data: URI, use it as is, otherwise convert the Var to JSON in a data: URI.
|
||||
url = cond( # type: ignore
|
||||
is_data_url,
|
||||
|
@ -2,10 +2,15 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
import dataclasses
|
||||
import datetime
|
||||
import dis
|
||||
import functools
|
||||
import inspect
|
||||
import json
|
||||
import sys
|
||||
from types import CodeType, FunctionType
|
||||
from typing import (
|
||||
TYPE_CHECKING,
|
||||
Any,
|
||||
@ -20,17 +25,22 @@ from typing import (
|
||||
Type,
|
||||
TypeVar,
|
||||
Union,
|
||||
cast,
|
||||
get_args,
|
||||
overload,
|
||||
override,
|
||||
)
|
||||
|
||||
from typing_extensions import ParamSpec, get_origin
|
||||
from typing_extensions import ParamSpec, get_origin, get_type_hints
|
||||
|
||||
from reflex import constants
|
||||
from reflex.base import Base
|
||||
from reflex.constants.colors import Color
|
||||
from reflex.utils import console, imports, serializers, types
|
||||
from reflex.utils.exceptions import VarTypeError
|
||||
from reflex.utils.exceptions import VarDependencyError, VarTypeError, VarValueError
|
||||
from reflex.utils.format import format_state_name
|
||||
from reflex.vars import (
|
||||
ComputedVar,
|
||||
ImmutableVarData,
|
||||
Var,
|
||||
VarData,
|
||||
@ -320,11 +330,15 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
||||
|
||||
@overload
|
||||
def to(
|
||||
self, output: Type[OUTPUT], var_type: types.GenericType | None = None
|
||||
self,
|
||||
output: Type[OUTPUT] | types.GenericType,
|
||||
var_type: types.GenericType | None = None,
|
||||
) -> OUTPUT: ...
|
||||
|
||||
def to(
|
||||
self, output: Type[OUTPUT], var_type: types.GenericType | None = None
|
||||
self,
|
||||
output: Type[OUTPUT] | types.GenericType,
|
||||
var_type: types.GenericType | None = None,
|
||||
) -> Var:
|
||||
"""Convert the var to a different type.
|
||||
|
||||
@ -338,12 +352,15 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
||||
Returns:
|
||||
The converted var.
|
||||
"""
|
||||
from .function import FunctionVar, ToFunctionOperation
|
||||
from .number import (
|
||||
BooleanVar,
|
||||
NumberVar,
|
||||
ToBooleanVarOperation,
|
||||
ToNumberVarOperation,
|
||||
)
|
||||
from .object import ObjectVar, ToObjectOperation
|
||||
from .sequence import ArrayVar, StringVar, ToArrayOperation, ToStringOperation
|
||||
|
||||
fixed_type = (
|
||||
var_type
|
||||
@ -351,16 +368,28 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
||||
else get_origin(var_type)
|
||||
)
|
||||
|
||||
fixed_output_type = output if inspect.isclass(output) else get_origin(output)
|
||||
|
||||
if fixed_output_type is dict:
|
||||
return self.to(ObjectVar, output)
|
||||
if fixed_output_type in (list, tuple, set):
|
||||
return self.to(ArrayVar, output)
|
||||
if fixed_output_type in (int, float):
|
||||
return self.to(NumberVar, output)
|
||||
if fixed_output_type is str:
|
||||
return self.to(StringVar, output)
|
||||
if fixed_output_type is bool:
|
||||
return self.to(BooleanVar, output)
|
||||
|
||||
if issubclass(output, NumberVar):
|
||||
if fixed_type is not None and not issubclass(fixed_type, (int, float)):
|
||||
raise TypeError(
|
||||
f"Unsupported type {var_type} for NumberVar. Must be int or float."
|
||||
)
|
||||
return ToNumberVarOperation(self, var_type or float)
|
||||
if issubclass(output, BooleanVar):
|
||||
return ToBooleanVarOperation(self)
|
||||
return ToNumberVarOperation.create(self, var_type or float)
|
||||
|
||||
from .sequence import ArrayVar, StringVar, ToArrayOperation, ToStringOperation
|
||||
if issubclass(output, BooleanVar):
|
||||
return ToBooleanVarOperation.create(self)
|
||||
|
||||
if issubclass(output, ArrayVar):
|
||||
if fixed_type is not None and not issubclass(
|
||||
@ -369,28 +398,30 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
||||
raise TypeError(
|
||||
f"Unsupported type {var_type} for ArrayVar. Must be list, tuple, or set."
|
||||
)
|
||||
return ToArrayOperation(self, var_type or list)
|
||||
return ToArrayOperation.create(self, var_type or list)
|
||||
|
||||
if issubclass(output, StringVar):
|
||||
return ToStringOperation(self)
|
||||
return ToStringOperation.create(self)
|
||||
|
||||
from .object import ObjectVar, ToObjectOperation
|
||||
|
||||
if issubclass(output, ObjectVar):
|
||||
return ToObjectOperation(self, var_type or dict)
|
||||
|
||||
from .function import FunctionVar, ToFunctionOperation
|
||||
if issubclass(output, (ObjectVar, Base)):
|
||||
return ToObjectOperation.create(self, var_type or dict)
|
||||
|
||||
if issubclass(output, FunctionVar):
|
||||
# if fixed_type is not None and not issubclass(fixed_type, Callable):
|
||||
# raise TypeError(
|
||||
# f"Unsupported type {var_type} for FunctionVar. Must be Callable."
|
||||
# )
|
||||
return ToFunctionOperation(self, var_type or Callable)
|
||||
return ToFunctionOperation.create(self, var_type or Callable)
|
||||
|
||||
return output(
|
||||
_var_name=self._var_name,
|
||||
_var_type=self._var_type if var_type is None else var_type,
|
||||
_var_data=self._var_data,
|
||||
if not issubclass(output, Var) and var_type is None:
|
||||
return dataclasses.replace(
|
||||
self,
|
||||
_var_type=output,
|
||||
)
|
||||
|
||||
return dataclasses.replace(
|
||||
self,
|
||||
_var_type=var_type,
|
||||
)
|
||||
|
||||
def guess_type(self) -> ImmutableVar:
|
||||
@ -413,6 +444,9 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
||||
if fixed_type is Union:
|
||||
return self
|
||||
|
||||
if not inspect.isclass(fixed_type):
|
||||
raise TypeError(f"Unsupported type {var_type} for guess_type.")
|
||||
|
||||
if issubclass(fixed_type, (int, float)):
|
||||
return self.to(NumberVar, var_type)
|
||||
if issubclass(fixed_type, dict):
|
||||
@ -477,12 +511,12 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
||||
Returns:
|
||||
The name of the setter function.
|
||||
"""
|
||||
setter = constants.SETTER_PREFIX + self._var_name
|
||||
var_name_parts = self._var_name.split(".")
|
||||
setter = constants.SETTER_PREFIX + var_name_parts[-1]
|
||||
if self._var_data is None:
|
||||
return setter
|
||||
if not include_state or self._var_data.state == "":
|
||||
return setter
|
||||
print("get_setter_name", self._var_data.state, setter)
|
||||
return ".".join((self._var_data.state, setter))
|
||||
|
||||
def get_setter(self) -> Callable[[BaseState, Any], None]:
|
||||
@ -491,6 +525,7 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
||||
Returns:
|
||||
A function that that creates a setter for the var.
|
||||
"""
|
||||
actual_name = self._var_name.split(".")[-1]
|
||||
|
||||
def setter(state: BaseState, value: Any):
|
||||
"""Get the setter for the var.
|
||||
@ -502,13 +537,13 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
||||
if self._var_type in [int, float]:
|
||||
try:
|
||||
value = self._var_type(value)
|
||||
setattr(state, self._var_name, value)
|
||||
setattr(state, actual_name, value)
|
||||
except ValueError:
|
||||
console.debug(
|
||||
f"{type(state).__name__}.{self._var_name}: Failed conversion of {value} to '{self._var_type.__name__}'. Value not set.",
|
||||
)
|
||||
else:
|
||||
setattr(state, self._var_name, value)
|
||||
setattr(state, actual_name, value)
|
||||
|
||||
setter.__qualname__ = self.get_setter_name()
|
||||
|
||||
@ -525,7 +560,7 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
||||
"""
|
||||
from .number import EqualOperation
|
||||
|
||||
return EqualOperation(self, other)
|
||||
return EqualOperation.create(self, other)
|
||||
|
||||
def __ne__(self, other: Var | Any) -> BooleanVar:
|
||||
"""Check if the current object is not equal to the given object.
|
||||
@ -538,7 +573,7 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
||||
"""
|
||||
from .number import EqualOperation
|
||||
|
||||
return ~EqualOperation(self, other)
|
||||
return ~EqualOperation.create(self, other)
|
||||
|
||||
def __gt__(self, other: Var | Any) -> BooleanVar:
|
||||
"""Compare the current instance with another variable and return a BooleanVar representing the result of the greater than operation.
|
||||
@ -551,7 +586,7 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
||||
"""
|
||||
from .number import GreaterThanOperation
|
||||
|
||||
return GreaterThanOperation(self, other)
|
||||
return GreaterThanOperation.create(self, other)
|
||||
|
||||
def __ge__(self, other: Var | Any) -> BooleanVar:
|
||||
"""Check if the value of this variable is greater than or equal to the value of another variable or object.
|
||||
@ -564,7 +599,7 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
||||
"""
|
||||
from .number import GreaterThanOrEqualOperation
|
||||
|
||||
return GreaterThanOrEqualOperation(self, other)
|
||||
return GreaterThanOrEqualOperation.create(self, other)
|
||||
|
||||
def __lt__(self, other: Var | Any) -> BooleanVar:
|
||||
"""Compare the current instance with another variable using the less than (<) operator.
|
||||
@ -577,7 +612,7 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
||||
"""
|
||||
from .number import LessThanOperation
|
||||
|
||||
return LessThanOperation(self, other)
|
||||
return LessThanOperation.create(self, other)
|
||||
|
||||
def __le__(self, other: Var | Any) -> BooleanVar:
|
||||
"""Compare if the current instance is less than or equal to the given value.
|
||||
@ -590,7 +625,7 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
||||
"""
|
||||
from .number import LessThanOrEqualOperation
|
||||
|
||||
return LessThanOrEqualOperation(self, other)
|
||||
return LessThanOrEqualOperation.create(self, other)
|
||||
|
||||
def bool(self) -> BooleanVar:
|
||||
"""Convert the var to a boolean.
|
||||
@ -600,7 +635,7 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
||||
"""
|
||||
from .number import ToBooleanVarOperation
|
||||
|
||||
return ToBooleanVarOperation(self)
|
||||
return ToBooleanVarOperation.create(self)
|
||||
|
||||
def __and__(self, other: Var | Any) -> ImmutableVar:
|
||||
"""Perform a logical AND operation on the current instance and another variable.
|
||||
@ -611,7 +646,7 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
||||
Returns:
|
||||
A `BooleanVar` object representing the result of the logical AND operation.
|
||||
"""
|
||||
return AndOperation(self, other)
|
||||
return AndOperation.create(self, other)
|
||||
|
||||
def __rand__(self, other: Var | Any) -> ImmutableVar:
|
||||
"""Perform a logical AND operation on the current instance and another variable.
|
||||
@ -622,7 +657,7 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
||||
Returns:
|
||||
A `BooleanVar` object representing the result of the logical AND operation.
|
||||
"""
|
||||
return AndOperation(other, self)
|
||||
return AndOperation.create(other, self)
|
||||
|
||||
def __or__(self, other: Var | Any) -> ImmutableVar:
|
||||
"""Perform a logical OR operation on the current instance and another variable.
|
||||
@ -633,7 +668,7 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
||||
Returns:
|
||||
A `BooleanVar` object representing the result of the logical OR operation.
|
||||
"""
|
||||
return OrOperation(self, other)
|
||||
return OrOperation.create(self, other)
|
||||
|
||||
def __ror__(self, other: Var | Any) -> ImmutableVar:
|
||||
"""Perform a logical OR operation on the current instance and another variable.
|
||||
@ -644,7 +679,7 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
||||
Returns:
|
||||
A `BooleanVar` object representing the result of the logical OR operation.
|
||||
"""
|
||||
return OrOperation(other, self)
|
||||
return OrOperation.create(other, self)
|
||||
|
||||
def __invert__(self) -> BooleanVar:
|
||||
"""Perform a logical NOT operation on the current instance.
|
||||
@ -654,7 +689,7 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
||||
"""
|
||||
from .number import BooleanNotOperation
|
||||
|
||||
return BooleanNotOperation(self.bool())
|
||||
return BooleanNotOperation.create(self.bool())
|
||||
|
||||
def to_string(self) -> ImmutableVar:
|
||||
"""Convert the var to a string.
|
||||
@ -663,8 +698,9 @@ class ImmutableVar(Var, Generic[VAR_TYPE]):
|
||||
The string var.
|
||||
"""
|
||||
from .function import JSON_STRINGIFY
|
||||
from .sequence import StringVar
|
||||
|
||||
return JSON_STRINGIFY.call(self)
|
||||
return JSON_STRINGIFY.call(self).to(StringVar)
|
||||
|
||||
def as_ref(self) -> ImmutableVar:
|
||||
"""Get a reference to the var.
|
||||
@ -732,35 +768,97 @@ class LiteralVar(ImmutableVar):
|
||||
if value is None:
|
||||
return ImmutableVar.create_safe("null", _var_data=_var_data)
|
||||
|
||||
from reflex.event import EventChain, EventSpec
|
||||
from reflex.utils.format import get_event_handler_parts
|
||||
|
||||
from .function import ArgsFunctionOperation, FunctionStringVar
|
||||
from .object import LiteralObjectVar
|
||||
|
||||
if isinstance(value, EventSpec):
|
||||
event_name = LiteralVar.create(
|
||||
".".join(get_event_handler_parts(value.handler))
|
||||
)
|
||||
event_args = LiteralVar.create({name: value for name, value in value.args})
|
||||
event_client_name = LiteralVar.create(value.client_handler_name)
|
||||
return FunctionStringVar("Event").call(
|
||||
event_name, event_args, event_client_name
|
||||
)
|
||||
|
||||
if isinstance(value, EventChain):
|
||||
sig = inspect.signature(value.args_spec) # type: ignore
|
||||
if sig.parameters:
|
||||
arg_def = tuple((f"_{p}" for p in sig.parameters))
|
||||
arg_def_expr = LiteralVar.create(
|
||||
[ImmutableVar.create_safe(arg) for arg in arg_def]
|
||||
)
|
||||
else:
|
||||
# add a default argument for addEvents if none were specified in value.args_spec
|
||||
# used to trigger the preventDefault() on the event.
|
||||
arg_def = ("...args",)
|
||||
arg_def_expr = ImmutableVar.create_safe("args")
|
||||
|
||||
return ArgsFunctionOperation.create(
|
||||
arg_def,
|
||||
FunctionStringVar.create("addEvents").call(
|
||||
LiteralVar.create(
|
||||
[LiteralVar.create(event) for event in value.events]
|
||||
),
|
||||
arg_def_expr,
|
||||
LiteralVar.create(value.event_actions),
|
||||
),
|
||||
)
|
||||
|
||||
from plotly.graph_objects import Figure, layout
|
||||
from plotly.io import to_json
|
||||
|
||||
if isinstance(value, Figure):
|
||||
return LiteralObjectVar.create(
|
||||
json.loads(to_json(value)), _var_type=Figure, _var_data=_var_data
|
||||
)
|
||||
|
||||
if isinstance(value, layout.Template):
|
||||
return LiteralObjectVar.create(
|
||||
{
|
||||
"data": json.loads(to_json(value.data)),
|
||||
"layout": json.loads(to_json(value.layout)),
|
||||
},
|
||||
_var_type=layout.Template,
|
||||
_var_data=_var_data,
|
||||
)
|
||||
|
||||
if isinstance(value, Base):
|
||||
return LiteralObjectVar(
|
||||
return LiteralObjectVar.create(
|
||||
value.dict(), _var_type=type(value), _var_data=_var_data
|
||||
)
|
||||
|
||||
if isinstance(value, dict):
|
||||
return LiteralObjectVar(value, _var_data=_var_data)
|
||||
return LiteralObjectVar.create(value, _var_data=_var_data)
|
||||
|
||||
from .number import LiteralBooleanVar, LiteralNumberVar
|
||||
from .sequence import LiteralArrayVar, LiteralStringVar
|
||||
|
||||
if isinstance(value, str):
|
||||
return LiteralStringVar.create(value, _var_data=_var_data)
|
||||
|
||||
if isinstance(value, Color):
|
||||
return LiteralStringVar.create(f"{value}", _var_data=_var_data)
|
||||
|
||||
from .number import LiteralBooleanVar, LiteralNumberVar
|
||||
|
||||
type_mapping = {
|
||||
int: LiteralNumberVar,
|
||||
float: LiteralNumberVar,
|
||||
bool: LiteralBooleanVar,
|
||||
list: LiteralArrayVar,
|
||||
tuple: LiteralArrayVar,
|
||||
set: LiteralArrayVar,
|
||||
int: LiteralNumberVar.create,
|
||||
float: LiteralNumberVar.create,
|
||||
bool: LiteralBooleanVar.create,
|
||||
list: LiteralArrayVar.create,
|
||||
tuple: LiteralArrayVar.create,
|
||||
set: LiteralArrayVar.create,
|
||||
}
|
||||
|
||||
constructor = type_mapping.get(type(value))
|
||||
|
||||
if constructor is None:
|
||||
raise TypeError(f"Unsupported type {type(value)} for LiteralVar.")
|
||||
raise TypeError(
|
||||
f"Unsupported type {type(value)} for LiteralVar. Tried to create a LiteralVar from {value}."
|
||||
)
|
||||
|
||||
return constructor(value, _var_data=_var_data)
|
||||
|
||||
@ -881,27 +979,8 @@ class AndOperation(ImmutableVar):
|
||||
# The second var.
|
||||
_var2: Var = dataclasses.field(default_factory=lambda: LiteralVar.create(None))
|
||||
|
||||
def __init__(
|
||||
self, var1: Var | Any, var2: Var | Any, _var_data: VarData | None = None
|
||||
):
|
||||
"""Initialize the AndOperation.
|
||||
|
||||
Args:
|
||||
var1: The first var.
|
||||
var2: The second var.
|
||||
_var_data: Additional hooks and imports associated with the Var.
|
||||
"""
|
||||
super(AndOperation, self).__init__(
|
||||
_var_name="",
|
||||
_var_type=Union[var1._var_type, var2._var_type],
|
||||
_var_data=ImmutableVarData.merge(_var_data),
|
||||
)
|
||||
object.__setattr__(
|
||||
self, "_var1", var1 if isinstance(var1, Var) else LiteralVar.create(var1)
|
||||
)
|
||||
object.__setattr__(
|
||||
self, "_var2", var2 if isinstance(var2, Var) else LiteralVar.create(var2)
|
||||
)
|
||||
def __post_init__(self):
|
||||
"""Post-initialize the AndOperation."""
|
||||
object.__delattr__(self, "_var_name")
|
||||
|
||||
@functools.cached_property
|
||||
@ -955,6 +1034,29 @@ class AndOperation(ImmutableVar):
|
||||
"""
|
||||
return hash((self.__class__.__name__, self._var1, self._var2))
|
||||
|
||||
@classmethod
|
||||
def create(
|
||||
cls, var1: Var | Any, var2: Var | Any, _var_data: VarData | None = None
|
||||
) -> AndOperation:
|
||||
"""Create an AndOperation.
|
||||
|
||||
Args:
|
||||
var1: The first var.
|
||||
var2: The second var.
|
||||
_var_data: Additional hooks and imports associated with the Var.
|
||||
|
||||
Returns:
|
||||
The AndOperation.
|
||||
"""
|
||||
var1, var2 = map(LiteralVar.create, (var1, var2))
|
||||
return AndOperation(
|
||||
_var_name="",
|
||||
_var_type=unionize(var1._var_type, var2._var_type),
|
||||
_var_data=ImmutableVarData.merge(_var_data),
|
||||
_var1=var1,
|
||||
_var2=var2,
|
||||
)
|
||||
|
||||
|
||||
@dataclasses.dataclass(
|
||||
eq=False,
|
||||
@ -970,27 +1072,8 @@ class OrOperation(ImmutableVar):
|
||||
# The second var.
|
||||
_var2: Var = dataclasses.field(default_factory=lambda: LiteralVar.create(None))
|
||||
|
||||
def __init__(
|
||||
self, var1: Var | Any, var2: Var | Any, _var_data: VarData | None = None
|
||||
):
|
||||
"""Initialize the OrOperation.
|
||||
|
||||
Args:
|
||||
var1: The first var.
|
||||
var2: The second var.
|
||||
_var_data: Additional hooks and imports associated with the Var.
|
||||
"""
|
||||
super(OrOperation, self).__init__(
|
||||
_var_name="",
|
||||
_var_type=Union[var1._var_type, var2._var_type],
|
||||
_var_data=ImmutableVarData.merge(_var_data),
|
||||
)
|
||||
object.__setattr__(
|
||||
self, "_var1", var1 if isinstance(var1, Var) else LiteralVar.create(var1)
|
||||
)
|
||||
object.__setattr__(
|
||||
self, "_var2", var2 if isinstance(var2, Var) else LiteralVar.create(var2)
|
||||
)
|
||||
def __post_init__(self):
|
||||
"""Post-initialize the OrOperation."""
|
||||
object.__delattr__(self, "_var_name")
|
||||
|
||||
@functools.cached_property
|
||||
@ -1044,6 +1127,29 @@ class OrOperation(ImmutableVar):
|
||||
"""
|
||||
return hash((self.__class__.__name__, self._var1, self._var2))
|
||||
|
||||
@classmethod
|
||||
def create(
|
||||
cls, var1: Var | Any, var2: Var | Any, _var_data: VarData | None = None
|
||||
) -> OrOperation:
|
||||
"""Create an OrOperation.
|
||||
|
||||
Args:
|
||||
var1: The first var.
|
||||
var2: The second var.
|
||||
_var_data: Additional hooks and imports associated with the Var.
|
||||
|
||||
Returns:
|
||||
The OrOperation.
|
||||
"""
|
||||
var1, var2 = map(LiteralVar.create, (var1, var2))
|
||||
return OrOperation(
|
||||
_var_name="",
|
||||
_var_type=unionize(var1._var_type, var2._var_type),
|
||||
_var_data=ImmutableVarData.merge(_var_data),
|
||||
_var1=var1,
|
||||
_var2=var2,
|
||||
)
|
||||
|
||||
|
||||
@dataclasses.dataclass(
|
||||
eq=False,
|
||||
@ -1057,14 +1163,14 @@ class ImmutableCallableVar(ImmutableVar):
|
||||
API with functions that return a family of Var.
|
||||
"""
|
||||
|
||||
fn: Callable[..., ImmutableVar] = dataclasses.field(
|
||||
default_factory=lambda: lambda: LiteralVar.create(None)
|
||||
fn: Callable[..., Var] = dataclasses.field(
|
||||
default_factory=lambda: lambda: ImmutableVar(_var_name="undefined")
|
||||
)
|
||||
original_var: ImmutableVar = dataclasses.field(
|
||||
default_factory=lambda: LiteralVar.create(None)
|
||||
original_var: Var = dataclasses.field(
|
||||
default_factory=lambda: ImmutableVar(_var_name="undefined")
|
||||
)
|
||||
|
||||
def __init__(self, fn: Callable[..., ImmutableVar]):
|
||||
def __init__(self, fn: Callable[..., Var]):
|
||||
"""Initialize a CallableVar.
|
||||
|
||||
Args:
|
||||
@ -1074,12 +1180,12 @@ class ImmutableCallableVar(ImmutableVar):
|
||||
super(ImmutableCallableVar, self).__init__(
|
||||
_var_name=original_var._var_name,
|
||||
_var_type=original_var._var_type,
|
||||
_var_data=original_var._var_data,
|
||||
_var_data=ImmutableVarData.merge(original_var._var_data),
|
||||
)
|
||||
object.__setattr__(self, "fn", fn)
|
||||
object.__setattr__(self, "original_var", original_var)
|
||||
|
||||
def __call__(self, *args, **kwargs) -> ImmutableVar:
|
||||
def __call__(self, *args, **kwargs) -> Var:
|
||||
"""Call the decorated function.
|
||||
|
||||
Args:
|
||||
@ -1098,3 +1204,433 @@ class ImmutableCallableVar(ImmutableVar):
|
||||
The hash of the object.
|
||||
"""
|
||||
return hash((self.__class__.__name__, self.original_var))
|
||||
|
||||
|
||||
@dataclasses.dataclass(
|
||||
eq=False,
|
||||
frozen=True,
|
||||
**{"slots": True} if sys.version_info >= (3, 10) else {},
|
||||
)
|
||||
class ImmutableComputedVar(ImmutableVar):
|
||||
"""A field with computed getters."""
|
||||
|
||||
# Whether to track dependencies and cache computed values
|
||||
_cache: bool = dataclasses.field(default=False)
|
||||
|
||||
# Whether the computed var is a backend var
|
||||
_backend: bool = dataclasses.field(default=False)
|
||||
|
||||
# The initial value of the computed var
|
||||
_initial_value: Any | types.Unset = dataclasses.field(default=types.Unset())
|
||||
|
||||
# Explicit var dependencies to track
|
||||
_static_deps: set[str] = dataclasses.field(default_factory=set)
|
||||
|
||||
# Whether var dependencies should be auto-determined
|
||||
_auto_deps: bool = dataclasses.field(default=True)
|
||||
|
||||
# Interval at which the computed var should be updated
|
||||
_update_interval: Optional[datetime.timedelta] = dataclasses.field(default=None)
|
||||
|
||||
_fget: Callable[[BaseState], Any] = dataclasses.field(
|
||||
default_factory=lambda: lambda _: None
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
fget: Callable[[BaseState], Any],
|
||||
initial_value: Any | types.Unset = types.Unset(),
|
||||
cache: bool = False,
|
||||
deps: Optional[List[Union[str, Var]]] = None,
|
||||
auto_deps: bool = True,
|
||||
interval: Optional[Union[int, datetime.timedelta]] = None,
|
||||
backend: bool | None = None,
|
||||
**kwargs,
|
||||
):
|
||||
"""Initialize a ComputedVar.
|
||||
|
||||
Args:
|
||||
fget: The getter function.
|
||||
initial_value: The initial value of the computed var.
|
||||
cache: Whether to cache the computed value.
|
||||
deps: Explicit var dependencies to track.
|
||||
auto_deps: Whether var dependencies should be auto-determined.
|
||||
interval: Interval at which the computed var should be updated.
|
||||
backend: Whether the computed var is a backend var.
|
||||
**kwargs: additional attributes to set on the instance
|
||||
|
||||
Raises:
|
||||
TypeError: If the computed var dependencies are not Var instances or var names.
|
||||
"""
|
||||
hints = get_type_hints(fget)
|
||||
hint = hints.get("return", Any)
|
||||
|
||||
kwargs["_var_name"] = kwargs.pop("_var_name", fget.__name__)
|
||||
kwargs["_var_type"] = kwargs.pop("_var_type", hint)
|
||||
|
||||
super(ImmutableComputedVar, self).__init__(
|
||||
_var_name=kwargs.pop("_var_name"),
|
||||
_var_type=kwargs.pop("_var_type"),
|
||||
_var_data=ImmutableVarData.merge(kwargs.pop("_var_data", None)),
|
||||
)
|
||||
|
||||
if backend is None:
|
||||
backend = fget.__name__.startswith("_")
|
||||
|
||||
object.__setattr__(self, "_backend", backend)
|
||||
object.__setattr__(self, "_initial_value", initial_value)
|
||||
object.__setattr__(self, "_cache", cache)
|
||||
|
||||
if isinstance(interval, int):
|
||||
interval = datetime.timedelta(seconds=interval)
|
||||
|
||||
object.__setattr__(self, "_update_interval", interval)
|
||||
|
||||
if deps is None:
|
||||
deps = []
|
||||
else:
|
||||
for dep in deps:
|
||||
if isinstance(dep, Var):
|
||||
continue
|
||||
if isinstance(dep, str) and dep != "":
|
||||
continue
|
||||
raise TypeError(
|
||||
"ComputedVar dependencies must be Var instances or var names (non-empty strings)."
|
||||
)
|
||||
object.__setattr__(
|
||||
self,
|
||||
"_static_deps",
|
||||
{dep._var_name if isinstance(dep, Var) else dep for dep in deps},
|
||||
)
|
||||
object.__setattr__(self, "_auto_deps", auto_deps)
|
||||
|
||||
object.__setattr__(self, "_fget", fget)
|
||||
|
||||
@override
|
||||
def _replace(self, merge_var_data=None, **kwargs: Any) -> ImmutableComputedVar:
|
||||
"""Replace the attributes of the ComputedVar.
|
||||
|
||||
Args:
|
||||
merge_var_data: VarData to merge into the existing VarData.
|
||||
**kwargs: Var fields to update.
|
||||
|
||||
Returns:
|
||||
The new ComputedVar instance.
|
||||
|
||||
Raises:
|
||||
TypeError: If kwargs contains keys that are not allowed.
|
||||
"""
|
||||
field_values = dict(
|
||||
fget=kwargs.pop("fget", self._fget),
|
||||
initial_value=kwargs.pop("initial_value", self._initial_value),
|
||||
cache=kwargs.pop("cache", self._cache),
|
||||
deps=kwargs.pop("deps", self._static_deps),
|
||||
auto_deps=kwargs.pop("auto_deps", self._auto_deps),
|
||||
interval=kwargs.pop("interval", self._update_interval),
|
||||
backend=kwargs.pop("backend", self._backend),
|
||||
_var_name=kwargs.pop("_var_name", self._var_name),
|
||||
_var_type=kwargs.pop("_var_type", self._var_type),
|
||||
_var_is_local=kwargs.pop("_var_is_local", self._var_is_local),
|
||||
_var_is_string=kwargs.pop("_var_is_string", self._var_is_string),
|
||||
_var_full_name_needs_state_prefix=kwargs.pop(
|
||||
"_var_full_name_needs_state_prefix",
|
||||
self._var_full_name_needs_state_prefix,
|
||||
),
|
||||
_var_data=kwargs.pop(
|
||||
"_var_data", VarData.merge(self._var_data, merge_var_data)
|
||||
),
|
||||
)
|
||||
|
||||
if kwargs:
|
||||
unexpected_kwargs = ", ".join(kwargs.keys())
|
||||
raise TypeError(f"Unexpected keyword arguments: {unexpected_kwargs}")
|
||||
|
||||
return ImmutableComputedVar(**field_values)
|
||||
|
||||
@property
|
||||
def _cache_attr(self) -> str:
|
||||
"""Get the attribute used to cache the value on the instance.
|
||||
|
||||
Returns:
|
||||
An attribute name.
|
||||
"""
|
||||
return f"__cached_{self._var_name}"
|
||||
|
||||
@property
|
||||
def _last_updated_attr(self) -> str:
|
||||
"""Get the attribute used to store the last updated timestamp.
|
||||
|
||||
Returns:
|
||||
An attribute name.
|
||||
"""
|
||||
return f"__last_updated_{self._var_name}"
|
||||
|
||||
def needs_update(self, instance: BaseState) -> bool:
|
||||
"""Check if the computed var needs to be updated.
|
||||
|
||||
Args:
|
||||
instance: The state instance that the computed var is attached to.
|
||||
|
||||
Returns:
|
||||
True if the computed var needs to be updated, False otherwise.
|
||||
"""
|
||||
if self._update_interval is None:
|
||||
return False
|
||||
last_updated = getattr(instance, self._last_updated_attr, None)
|
||||
if last_updated is None:
|
||||
return True
|
||||
return datetime.datetime.now() - last_updated > self._update_interval
|
||||
|
||||
def __get__(self, instance: BaseState | None, owner):
|
||||
"""Get the ComputedVar value.
|
||||
|
||||
If the value is already cached on the instance, return the cached value.
|
||||
|
||||
Args:
|
||||
instance: the instance of the class accessing this computed var.
|
||||
owner: the class that this descriptor is attached to.
|
||||
|
||||
Returns:
|
||||
The value of the var for the given instance.
|
||||
"""
|
||||
if instance is None:
|
||||
return self._replace(
|
||||
_var_name=format_state_name(owner.get_full_name())
|
||||
+ "."
|
||||
+ self._var_name,
|
||||
merge_var_data=ImmutableVarData.from_state(owner),
|
||||
).guess_type()
|
||||
|
||||
if not self._cache:
|
||||
return self.fget(instance)
|
||||
|
||||
# handle caching
|
||||
if not hasattr(instance, self._cache_attr) or self.needs_update(instance):
|
||||
# Set cache attr on state instance.
|
||||
setattr(instance, self._cache_attr, self.fget(instance))
|
||||
# Ensure the computed var gets serialized to redis.
|
||||
instance._was_touched = True
|
||||
# Set the last updated timestamp on the state instance.
|
||||
setattr(instance, self._last_updated_attr, datetime.datetime.now())
|
||||
return getattr(instance, self._cache_attr)
|
||||
|
||||
def _deps(
|
||||
self,
|
||||
objclass: Type,
|
||||
obj: FunctionType | CodeType | None = None,
|
||||
self_name: Optional[str] = None,
|
||||
) -> set[str]:
|
||||
"""Determine var dependencies of this ComputedVar.
|
||||
|
||||
Save references to attributes accessed on "self". Recursively called
|
||||
when the function makes a method call on "self" or define comprehensions
|
||||
or nested functions that may reference "self".
|
||||
|
||||
Args:
|
||||
objclass: the class obj this ComputedVar is attached to.
|
||||
obj: the object to disassemble (defaults to the fget function).
|
||||
self_name: if specified, look for this name in LOAD_FAST and LOAD_DEREF instructions.
|
||||
|
||||
Returns:
|
||||
A set of variable names accessed by the given obj.
|
||||
|
||||
Raises:
|
||||
VarValueError: if the function references the get_state, parent_state, or substates attributes
|
||||
(cannot track deps in a related state, only implicitly via parent state).
|
||||
"""
|
||||
if not self._auto_deps:
|
||||
return self._static_deps
|
||||
d = self._static_deps.copy()
|
||||
if obj is None:
|
||||
fget = self._fget
|
||||
if fget is not None:
|
||||
obj = cast(FunctionType, fget)
|
||||
else:
|
||||
return set()
|
||||
with contextlib.suppress(AttributeError):
|
||||
# unbox functools.partial
|
||||
obj = cast(FunctionType, obj.func) # type: ignore
|
||||
with contextlib.suppress(AttributeError):
|
||||
# unbox EventHandler
|
||||
obj = cast(FunctionType, obj.fn) # type: ignore
|
||||
|
||||
if self_name is None and isinstance(obj, FunctionType):
|
||||
try:
|
||||
# the first argument to the function is the name of "self" arg
|
||||
self_name = obj.__code__.co_varnames[0]
|
||||
except (AttributeError, IndexError):
|
||||
self_name = None
|
||||
if self_name is None:
|
||||
# cannot reference attributes on self if method takes no args
|
||||
return set()
|
||||
|
||||
invalid_names = ["get_state", "parent_state", "substates", "get_substate"]
|
||||
self_is_top_of_stack = False
|
||||
for instruction in dis.get_instructions(obj):
|
||||
if (
|
||||
instruction.opname in ("LOAD_FAST", "LOAD_DEREF")
|
||||
and instruction.argval == self_name
|
||||
):
|
||||
# bytecode loaded the class instance to the top of stack, next load instruction
|
||||
# is referencing an attribute on self
|
||||
self_is_top_of_stack = True
|
||||
continue
|
||||
if self_is_top_of_stack and instruction.opname in (
|
||||
"LOAD_ATTR",
|
||||
"LOAD_METHOD",
|
||||
):
|
||||
try:
|
||||
ref_obj = getattr(objclass, instruction.argval)
|
||||
except Exception:
|
||||
ref_obj = None
|
||||
if instruction.argval in invalid_names:
|
||||
raise VarValueError(
|
||||
f"Cached var {self._var_full_name} cannot access arbitrary state via `{instruction.argval}`."
|
||||
)
|
||||
if callable(ref_obj):
|
||||
# recurse into callable attributes
|
||||
d.update(
|
||||
self._deps(
|
||||
objclass=objclass,
|
||||
obj=ref_obj,
|
||||
)
|
||||
)
|
||||
# recurse into property fget functions
|
||||
elif isinstance(ref_obj, property) and not isinstance(
|
||||
ref_obj, ImmutableComputedVar
|
||||
):
|
||||
d.update(
|
||||
self._deps(
|
||||
objclass=objclass,
|
||||
obj=ref_obj.fget, # type: ignore
|
||||
)
|
||||
)
|
||||
elif (
|
||||
instruction.argval in objclass.backend_vars
|
||||
or instruction.argval in objclass.vars
|
||||
):
|
||||
# var access
|
||||
d.add(instruction.argval)
|
||||
elif instruction.opname == "LOAD_CONST" and isinstance(
|
||||
instruction.argval, CodeType
|
||||
):
|
||||
# recurse into nested functions / comprehensions, which can reference
|
||||
# instance attributes from the outer scope
|
||||
d.update(
|
||||
self._deps(
|
||||
objclass=objclass,
|
||||
obj=instruction.argval,
|
||||
self_name=self_name,
|
||||
)
|
||||
)
|
||||
self_is_top_of_stack = False
|
||||
return d
|
||||
|
||||
def mark_dirty(self, instance) -> None:
|
||||
"""Mark this ComputedVar as dirty.
|
||||
|
||||
Args:
|
||||
instance: the state instance that needs to recompute the value.
|
||||
"""
|
||||
with contextlib.suppress(AttributeError):
|
||||
delattr(instance, self._cache_attr)
|
||||
|
||||
def _determine_var_type(self) -> Type:
|
||||
"""Get the type of the var.
|
||||
|
||||
Returns:
|
||||
The type of the var.
|
||||
"""
|
||||
hints = get_type_hints(self._fget)
|
||||
if "return" in hints:
|
||||
return hints["return"]
|
||||
return Any
|
||||
|
||||
@property
|
||||
def __class__(self) -> Type:
|
||||
"""Get the class of the var.
|
||||
|
||||
Returns:
|
||||
The class of the var.
|
||||
"""
|
||||
return ComputedVar
|
||||
|
||||
@property
|
||||
def fget(self) -> Callable[[BaseState], Any]:
|
||||
"""Get the getter function.
|
||||
|
||||
Returns:
|
||||
The getter function.
|
||||
"""
|
||||
return self._fget
|
||||
|
||||
|
||||
def immutable_computed_var(
|
||||
fget: Callable[[BaseState], Any] | None = None,
|
||||
initial_value: Any | types.Unset = types.Unset(),
|
||||
cache: bool = False,
|
||||
deps: Optional[List[Union[str, Var]]] = None,
|
||||
auto_deps: bool = True,
|
||||
interval: Optional[Union[datetime.timedelta, int]] = None,
|
||||
backend: bool | None = None,
|
||||
_deprecated_cached_var: bool = False,
|
||||
**kwargs,
|
||||
) -> (
|
||||
ImmutableComputedVar | Callable[[Callable[[BaseState], Any]], ImmutableComputedVar]
|
||||
):
|
||||
"""A ComputedVar decorator with or without kwargs.
|
||||
|
||||
Args:
|
||||
fget: The getter function.
|
||||
initial_value: The initial value of the computed var.
|
||||
cache: Whether to cache the computed value.
|
||||
deps: Explicit var dependencies to track.
|
||||
auto_deps: Whether var dependencies should be auto-determined.
|
||||
interval: Interval at which the computed var should be updated.
|
||||
backend: Whether the computed var is a backend var.
|
||||
_deprecated_cached_var: Indicate usage of deprecated cached_var partial function.
|
||||
**kwargs: additional attributes to set on the instance
|
||||
|
||||
Returns:
|
||||
A ComputedVar instance.
|
||||
|
||||
Raises:
|
||||
ValueError: If caching is disabled and an update interval is set.
|
||||
VarDependencyError: If user supplies dependencies without caching.
|
||||
"""
|
||||
if _deprecated_cached_var:
|
||||
console.deprecate(
|
||||
feature_name="cached_var",
|
||||
reason=("Use @rx.var(cache=True) instead of @rx.cached_var."),
|
||||
deprecation_version="0.5.6",
|
||||
removal_version="0.6.0",
|
||||
)
|
||||
|
||||
if cache is False and interval is not None:
|
||||
raise ValueError("Cannot set update interval without caching.")
|
||||
|
||||
if cache is False and (deps is not None or auto_deps is False):
|
||||
raise VarDependencyError("Cannot track dependencies without caching.")
|
||||
|
||||
if fget is not None:
|
||||
return ImmutableComputedVar(fget, cache=cache)
|
||||
|
||||
def wrapper(fget: Callable[[BaseState], Any]) -> ImmutableComputedVar:
|
||||
return ImmutableComputedVar(
|
||||
fget,
|
||||
initial_value=initial_value,
|
||||
cache=cache,
|
||||
deps=deps,
|
||||
auto_deps=auto_deps,
|
||||
interval=interval,
|
||||
backend=backend,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
# Partial function of computed_var with cache=True
|
||||
cached_var = functools.partial(
|
||||
immutable_computed_var, cache=True, _deprecated_cached_var=True
|
||||
)
|
||||
|
@ -7,6 +7,7 @@ import sys
|
||||
from functools import cached_property
|
||||
from typing import Any, Callable, Optional, Tuple, Type, Union
|
||||
|
||||
from reflex.utils.types import GenericType
|
||||
from reflex.vars import ImmutableVarData, Var, VarData
|
||||
|
||||
from .base import ImmutableVar, LiteralVar
|
||||
@ -24,9 +25,9 @@ class FunctionVar(ImmutableVar[Callable]):
|
||||
Returns:
|
||||
The function call operation.
|
||||
"""
|
||||
return ArgsFunctionOperation(
|
||||
return ArgsFunctionOperation.create(
|
||||
("...args",),
|
||||
VarOperationCall(self, *args, ImmutableVar.create_safe("...args")),
|
||||
VarOperationCall.create(self, *args, ImmutableVar.create_safe("...args")),
|
||||
)
|
||||
|
||||
def call(self, *args: Var | Any) -> VarOperationCall:
|
||||
@ -38,22 +39,31 @@ class FunctionVar(ImmutableVar[Callable]):
|
||||
Returns:
|
||||
The function call operation.
|
||||
"""
|
||||
return VarOperationCall(self, *args)
|
||||
return VarOperationCall.create(self, *args)
|
||||
|
||||
|
||||
class FunctionStringVar(FunctionVar):
|
||||
"""Base class for immutable function vars from a string."""
|
||||
|
||||
def __init__(self, func: str, _var_data: VarData | None = None) -> None:
|
||||
"""Initialize the function var.
|
||||
@classmethod
|
||||
def create(
|
||||
cls,
|
||||
func: str,
|
||||
_var_type: Type[Callable] = Callable,
|
||||
_var_data: VarData | None = None,
|
||||
) -> FunctionStringVar:
|
||||
"""Create a new function var from a string.
|
||||
|
||||
Args:
|
||||
func: The function to call.
|
||||
_var_data: Additional hooks and imports associated with the Var.
|
||||
|
||||
Returns:
|
||||
The function var.
|
||||
"""
|
||||
super(FunctionVar, self).__init__(
|
||||
return cls(
|
||||
_var_name=func,
|
||||
_var_type=Callable,
|
||||
_var_type=_var_type,
|
||||
_var_data=ImmutableVarData.merge(_var_data),
|
||||
)
|
||||
|
||||
@ -69,25 +79,6 @@ class VarOperationCall(ImmutableVar):
|
||||
_func: Optional[FunctionVar] = dataclasses.field(default=None)
|
||||
_args: Tuple[Union[Var, Any], ...] = dataclasses.field(default_factory=tuple)
|
||||
|
||||
def __init__(
|
||||
self, func: FunctionVar, *args: Var | Any, _var_data: VarData | None = None
|
||||
):
|
||||
"""Initialize the function call var.
|
||||
|
||||
Args:
|
||||
func: The function to call.
|
||||
*args: The arguments to call the function with.
|
||||
_var_data: Additional hooks and imports associated with the Var.
|
||||
"""
|
||||
super(VarOperationCall, self).__init__(
|
||||
_var_name="",
|
||||
_var_type=Any,
|
||||
_var_data=ImmutableVarData.merge(_var_data),
|
||||
)
|
||||
object.__setattr__(self, "_func", func)
|
||||
object.__setattr__(self, "_args", args)
|
||||
object.__delattr__(self, "_var_name")
|
||||
|
||||
def __getattr__(self, name):
|
||||
"""Get an attribute of the var.
|
||||
|
||||
@ -133,7 +124,7 @@ class VarOperationCall(ImmutableVar):
|
||||
|
||||
def __post_init__(self):
|
||||
"""Post-initialize the var."""
|
||||
pass
|
||||
object.__delattr__(self, "_var_name")
|
||||
|
||||
def __hash__(self):
|
||||
"""Hash the var.
|
||||
@ -143,6 +134,32 @@ class VarOperationCall(ImmutableVar):
|
||||
"""
|
||||
return hash((self.__class__.__name__, self._func, self._args))
|
||||
|
||||
@classmethod
|
||||
def create(
|
||||
cls,
|
||||
func: FunctionVar,
|
||||
*args: Var | Any,
|
||||
_var_type: GenericType = Any,
|
||||
_var_data: VarData | None = None,
|
||||
) -> VarOperationCall:
|
||||
"""Create a new function call var.
|
||||
|
||||
Args:
|
||||
func: The function to call.
|
||||
*args: The arguments to call the function with.
|
||||
_var_data: Additional hooks and imports associated with the Var.
|
||||
|
||||
Returns:
|
||||
The function call var.
|
||||
"""
|
||||
return cls(
|
||||
_var_name="",
|
||||
_var_type=_var_type,
|
||||
_var_data=ImmutableVarData.merge(_var_data),
|
||||
_func=func,
|
||||
_args=args,
|
||||
)
|
||||
|
||||
|
||||
@dataclasses.dataclass(
|
||||
eq=False,
|
||||
@ -155,28 +172,6 @@ class ArgsFunctionOperation(FunctionVar):
|
||||
_args_names: Tuple[str, ...] = dataclasses.field(default_factory=tuple)
|
||||
_return_expr: Union[Var, Any] = dataclasses.field(default=None)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
args_names: Tuple[str, ...],
|
||||
return_expr: Var | Any,
|
||||
_var_data: VarData | None = None,
|
||||
) -> None:
|
||||
"""Initialize the function with arguments var.
|
||||
|
||||
Args:
|
||||
args_names: The names of the arguments.
|
||||
return_expr: The return expression of the function.
|
||||
_var_data: Additional hooks and imports associated with the Var.
|
||||
"""
|
||||
super(ArgsFunctionOperation, self).__init__(
|
||||
_var_name=f"",
|
||||
_var_type=Callable,
|
||||
_var_data=ImmutableVarData.merge(_var_data),
|
||||
)
|
||||
object.__setattr__(self, "_args_names", args_names)
|
||||
object.__setattr__(self, "_return_expr", return_expr)
|
||||
object.__delattr__(self, "_var_name")
|
||||
|
||||
def __getattr__(self, name):
|
||||
"""Get an attribute of the var.
|
||||
|
||||
@ -221,6 +216,7 @@ class ArgsFunctionOperation(FunctionVar):
|
||||
|
||||
def __post_init__(self):
|
||||
"""Post-initialize the var."""
|
||||
object.__delattr__(self, "_var_name")
|
||||
|
||||
def __hash__(self):
|
||||
"""Hash the var.
|
||||
@ -230,6 +226,32 @@ class ArgsFunctionOperation(FunctionVar):
|
||||
"""
|
||||
return hash((self.__class__.__name__, self._args_names, self._return_expr))
|
||||
|
||||
@classmethod
|
||||
def create(
|
||||
cls,
|
||||
args_names: Tuple[str, ...],
|
||||
return_expr: Var | Any,
|
||||
_var_type: GenericType = Callable,
|
||||
_var_data: VarData | None = None,
|
||||
) -> ArgsFunctionOperation:
|
||||
"""Create a new function var.
|
||||
|
||||
Args:
|
||||
args_names: The names of the arguments.
|
||||
return_expr: The return expression of the function.
|
||||
_var_data: Additional hooks and imports associated with the Var.
|
||||
|
||||
Returns:
|
||||
The function var.
|
||||
"""
|
||||
return cls(
|
||||
_var_name="",
|
||||
_var_type=_var_type,
|
||||
_var_data=ImmutableVarData.merge(_var_data),
|
||||
_args_names=args_names,
|
||||
_return_expr=return_expr,
|
||||
)
|
||||
|
||||
|
||||
@dataclasses.dataclass(
|
||||
eq=False,
|
||||
@ -243,25 +265,8 @@ class ToFunctionOperation(FunctionVar):
|
||||
default_factory=lambda: LiteralVar.create(None)
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
original_var: Var,
|
||||
_var_type: Type[Callable] = Callable,
|
||||
_var_data: VarData | None = None,
|
||||
) -> None:
|
||||
"""Initialize the function with arguments var.
|
||||
|
||||
Args:
|
||||
original_var: The original var to convert to a function.
|
||||
_var_type: The type of the function.
|
||||
_var_data: Additional hooks and imports associated with the Var.
|
||||
"""
|
||||
super(ToFunctionOperation, self).__init__(
|
||||
_var_name=f"",
|
||||
_var_type=_var_type,
|
||||
_var_data=ImmutableVarData.merge(_var_data),
|
||||
)
|
||||
object.__setattr__(self, "_original_var", original_var)
|
||||
def __post_init__(self):
|
||||
"""Post-initialize the var."""
|
||||
object.__delattr__(self, "_var_name")
|
||||
|
||||
def __getattr__(self, name):
|
||||
@ -314,5 +319,29 @@ class ToFunctionOperation(FunctionVar):
|
||||
"""
|
||||
return hash((self.__class__.__name__, self._original_var))
|
||||
|
||||
@classmethod
|
||||
def create(
|
||||
cls,
|
||||
original_var: Var,
|
||||
_var_type: GenericType = Callable,
|
||||
_var_data: VarData | None = None,
|
||||
) -> ToFunctionOperation:
|
||||
"""Create a new function var.
|
||||
|
||||
JSON_STRINGIFY = FunctionStringVar("JSON.stringify")
|
||||
Args:
|
||||
original_var: The original var to convert to a function.
|
||||
_var_type: The type of the function.
|
||||
_var_data: Additional hooks and imports associated with the Var.
|
||||
|
||||
Returns:
|
||||
The function var.
|
||||
"""
|
||||
return cls(
|
||||
_var_name="",
|
||||
_var_type=_var_type,
|
||||
_var_data=ImmutableVarData.merge(_var_data),
|
||||
_original_var=original_var,
|
||||
)
|
||||
|
||||
|
||||
JSON_STRINGIFY = FunctionStringVar.create("JSON.stringify")
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -34,7 +34,7 @@ from .base import (
|
||||
from .number import BooleanVar, NumberVar
|
||||
from .sequence import ArrayVar, StringVar
|
||||
|
||||
OBJECT_TYPE = TypeVar("OBJECT_TYPE")
|
||||
OBJECT_TYPE = TypeVar("OBJECT_TYPE", bound=Dict)
|
||||
|
||||
KEY_TYPE = TypeVar("KEY_TYPE")
|
||||
VALUE_TYPE = TypeVar("VALUE_TYPE")
|
||||
@ -79,7 +79,7 @@ class ObjectVar(ImmutableVar[OBJECT_TYPE]):
|
||||
Returns:
|
||||
The keys of the object.
|
||||
"""
|
||||
return ObjectKeysOperation(self)
|
||||
return ObjectKeysOperation.create(self)
|
||||
|
||||
@overload
|
||||
def values(
|
||||
@ -95,7 +95,7 @@ class ObjectVar(ImmutableVar[OBJECT_TYPE]):
|
||||
Returns:
|
||||
The values of the object.
|
||||
"""
|
||||
return ObjectValuesOperation(self)
|
||||
return ObjectValuesOperation.create(self)
|
||||
|
||||
@overload
|
||||
def entries(
|
||||
@ -111,7 +111,7 @@ class ObjectVar(ImmutableVar[OBJECT_TYPE]):
|
||||
Returns:
|
||||
The entries of the object.
|
||||
"""
|
||||
return ObjectEntriesOperation(self)
|
||||
return ObjectEntriesOperation.create(self)
|
||||
|
||||
def merge(self, other: ObjectVar) -> ObjectMergeOperation:
|
||||
"""Merge two objects.
|
||||
@ -122,7 +122,7 @@ class ObjectVar(ImmutableVar[OBJECT_TYPE]):
|
||||
Returns:
|
||||
The merged object.
|
||||
"""
|
||||
return ObjectMergeOperation(self, other)
|
||||
return ObjectMergeOperation.create(self, other)
|
||||
|
||||
# NoReturn is used here to catch when key value is Any
|
||||
@overload
|
||||
@ -180,7 +180,7 @@ class ObjectVar(ImmutableVar[OBJECT_TYPE]):
|
||||
Returns:
|
||||
The item from the object.
|
||||
"""
|
||||
return ObjectItemOperation(self, key).guess_type()
|
||||
return ObjectItemOperation.create(self, key).guess_type()
|
||||
|
||||
# NoReturn is used here to catch when key value is Any
|
||||
@overload
|
||||
@ -253,9 +253,9 @@ class ObjectVar(ImmutableVar[OBJECT_TYPE]):
|
||||
f"The State var `{self._var_name}` has no attribute '{name}' or may have been annotated "
|
||||
f"wrongly."
|
||||
)
|
||||
return ObjectItemOperation(self, name, attribute_type).guess_type()
|
||||
return ObjectItemOperation.create(self, name, attribute_type).guess_type()
|
||||
else:
|
||||
return ObjectItemOperation(self, name).guess_type()
|
||||
return ObjectItemOperation.create(self, name).guess_type()
|
||||
|
||||
def contains(self, key: Var | Any) -> BooleanVar:
|
||||
"""Check if the object contains a key.
|
||||
@ -266,7 +266,7 @@ class ObjectVar(ImmutableVar[OBJECT_TYPE]):
|
||||
Returns:
|
||||
The result of the check.
|
||||
"""
|
||||
return ObjectHasOwnProperty(self, key)
|
||||
return ObjectHasOwnProperty.create(self, key)
|
||||
|
||||
|
||||
@dataclasses.dataclass(
|
||||
@ -281,29 +281,8 @@ class LiteralObjectVar(LiteralVar, ObjectVar[OBJECT_TYPE]):
|
||||
default_factory=dict
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self: LiteralObjectVar[OBJECT_TYPE],
|
||||
_var_value: OBJECT_TYPE,
|
||||
_var_type: Type[OBJECT_TYPE] | None = None,
|
||||
_var_data: VarData | None = None,
|
||||
):
|
||||
"""Initialize the object var.
|
||||
|
||||
Args:
|
||||
_var_value: The value of the var.
|
||||
_var_type: The type of the var.
|
||||
_var_data: Additional hooks and imports associated with the Var.
|
||||
"""
|
||||
super(LiteralObjectVar, self).__init__(
|
||||
_var_name="",
|
||||
_var_type=(figure_out_type(_var_value) if _var_type is None else _var_type),
|
||||
_var_data=ImmutableVarData.merge(_var_data),
|
||||
)
|
||||
object.__setattr__(
|
||||
self,
|
||||
"_var_value",
|
||||
_var_value,
|
||||
)
|
||||
def __post_init__(self):
|
||||
"""Post initialization."""
|
||||
object.__delattr__(self, "_var_name")
|
||||
|
||||
def _key_type(self) -> Type:
|
||||
@ -409,6 +388,30 @@ class LiteralObjectVar(LiteralVar, ObjectVar[OBJECT_TYPE]):
|
||||
"""
|
||||
return hash((self.__class__.__name__, self._var_name))
|
||||
|
||||
@classmethod
|
||||
def create(
|
||||
cls,
|
||||
_var_value: OBJECT_TYPE,
|
||||
_var_type: GenericType | None = None,
|
||||
_var_data: VarData | None = None,
|
||||
) -> LiteralObjectVar[OBJECT_TYPE]:
|
||||
"""Create the literal object var.
|
||||
|
||||
Args:
|
||||
_var_value: The value of the var.
|
||||
_var_type: The type of the var.
|
||||
_var_data: Additional hooks and imports associated with the Var.
|
||||
|
||||
Returns:
|
||||
The literal object var.
|
||||
"""
|
||||
return LiteralObjectVar(
|
||||
_var_name="",
|
||||
_var_type=(figure_out_type(_var_value) if _var_type is None else _var_type),
|
||||
_var_data=ImmutableVarData.merge(_var_data),
|
||||
_var_value=_var_value,
|
||||
)
|
||||
|
||||
|
||||
@dataclasses.dataclass(
|
||||
eq=False,
|
||||
@ -418,26 +421,12 @@ class LiteralObjectVar(LiteralVar, ObjectVar[OBJECT_TYPE]):
|
||||
class ObjectToArrayOperation(ArrayVar):
|
||||
"""Base class for object to array operations."""
|
||||
|
||||
value: ObjectVar = dataclasses.field(default_factory=lambda: LiteralObjectVar({}))
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
_var_value: ObjectVar,
|
||||
_var_type: Type = list,
|
||||
_var_data: VarData | None = None,
|
||||
):
|
||||
"""Initialize the object to array operation.
|
||||
|
||||
Args:
|
||||
_var_value: The value of the operation.
|
||||
_var_data: Additional hooks and imports associated with the operation.
|
||||
"""
|
||||
super(ObjectToArrayOperation, self).__init__(
|
||||
_var_name="",
|
||||
_var_type=_var_type,
|
||||
_var_data=ImmutableVarData.merge(_var_data),
|
||||
_value: ObjectVar = dataclasses.field(
|
||||
default_factory=lambda: LiteralObjectVar.create({})
|
||||
)
|
||||
object.__setattr__(self, "value", _var_value)
|
||||
|
||||
def __post_init__(self):
|
||||
"""Post initialization."""
|
||||
object.__delattr__(self, "_var_name")
|
||||
|
||||
@cached_property
|
||||
@ -472,7 +461,7 @@ class ObjectToArrayOperation(ArrayVar):
|
||||
The VarData of the components and all of its children.
|
||||
"""
|
||||
return ImmutableVarData.merge(
|
||||
self.value._get_all_var_data(),
|
||||
self._value._get_all_var_data(),
|
||||
self._var_data,
|
||||
)
|
||||
|
||||
@ -490,26 +479,37 @@ class ObjectToArrayOperation(ArrayVar):
|
||||
Returns:
|
||||
The hash of the operation.
|
||||
"""
|
||||
return hash((self.__class__.__name__, self.value))
|
||||
return hash((self.__class__.__name__, self._value))
|
||||
|
||||
@classmethod
|
||||
def create(
|
||||
cls,
|
||||
value: ObjectVar,
|
||||
_var_type: GenericType | None = None,
|
||||
_var_data: VarData | None = None,
|
||||
) -> ObjectToArrayOperation:
|
||||
"""Create the object to array operation.
|
||||
|
||||
Args:
|
||||
value: The value of the operation.
|
||||
_var_data: Additional hooks and imports associated with the operation.
|
||||
|
||||
Returns:
|
||||
The object to array operation.
|
||||
"""
|
||||
return cls(
|
||||
_var_name="",
|
||||
_var_type=list if _var_type is None else _var_type,
|
||||
_var_data=ImmutableVarData.merge(_var_data),
|
||||
_value=value,
|
||||
)
|
||||
|
||||
|
||||
class ObjectKeysOperation(ObjectToArrayOperation):
|
||||
"""Operation to get the keys of an object."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
value: ObjectVar,
|
||||
_var_data: VarData | None = None,
|
||||
):
|
||||
"""Initialize the object keys operation.
|
||||
|
||||
Args:
|
||||
value: The value of the operation.
|
||||
_var_data: Additional hooks and imports associated with the operation.
|
||||
"""
|
||||
super(ObjectKeysOperation, self).__init__(
|
||||
value, List[value._key_type()], _var_data
|
||||
)
|
||||
# value, List[value._key_type()], _var_data
|
||||
# )
|
||||
|
||||
@cached_property
|
||||
def _cached_var_name(self) -> str:
|
||||
@ -518,27 +518,34 @@ class ObjectKeysOperation(ObjectToArrayOperation):
|
||||
Returns:
|
||||
The name of the operation.
|
||||
"""
|
||||
return f"Object.keys({self.value._var_name})"
|
||||
return f"Object.keys({str(self._value)})"
|
||||
|
||||
@classmethod
|
||||
def create(
|
||||
cls,
|
||||
value: ObjectVar,
|
||||
_var_data: VarData | None = None,
|
||||
) -> ObjectKeysOperation:
|
||||
"""Create the object keys operation.
|
||||
|
||||
Args:
|
||||
value: The value of the operation.
|
||||
_var_data: Additional hooks and imports associated with the operation.
|
||||
|
||||
Returns:
|
||||
The object keys operation.
|
||||
"""
|
||||
return cls(
|
||||
_var_name="",
|
||||
_var_type=List[str],
|
||||
_var_data=ImmutableVarData.merge(_var_data),
|
||||
_value=value,
|
||||
)
|
||||
|
||||
|
||||
class ObjectValuesOperation(ObjectToArrayOperation):
|
||||
"""Operation to get the values of an object."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
value: ObjectVar,
|
||||
_var_data: VarData | None = None,
|
||||
):
|
||||
"""Initialize the object values operation.
|
||||
|
||||
Args:
|
||||
value: The value of the operation.
|
||||
_var_data: Additional hooks and imports associated with the operation.
|
||||
"""
|
||||
super(ObjectValuesOperation, self).__init__(
|
||||
value, List[value._value_type()], _var_data
|
||||
)
|
||||
|
||||
@cached_property
|
||||
def _cached_var_name(self) -> str:
|
||||
"""The name of the operation.
|
||||
@ -546,27 +553,34 @@ class ObjectValuesOperation(ObjectToArrayOperation):
|
||||
Returns:
|
||||
The name of the operation.
|
||||
"""
|
||||
return f"Object.values({self.value._var_name})"
|
||||
return f"Object.values({self._value._var_name})"
|
||||
|
||||
@classmethod
|
||||
def create(
|
||||
cls,
|
||||
value: ObjectVar,
|
||||
_var_data: VarData | None = None,
|
||||
) -> ObjectValuesOperation:
|
||||
"""Create the object values operation.
|
||||
|
||||
Args:
|
||||
value: The value of the operation.
|
||||
_var_data: Additional hooks and imports associated with the operation.
|
||||
|
||||
Returns:
|
||||
The object values operation.
|
||||
"""
|
||||
return cls(
|
||||
_var_name="",
|
||||
_var_type=List[value._value_type()],
|
||||
_var_data=ImmutableVarData.merge(_var_data),
|
||||
_value=value,
|
||||
)
|
||||
|
||||
|
||||
class ObjectEntriesOperation(ObjectToArrayOperation):
|
||||
"""Operation to get the entries of an object."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
value: ObjectVar,
|
||||
_var_data: VarData | None = None,
|
||||
):
|
||||
"""Initialize the object entries operation.
|
||||
|
||||
Args:
|
||||
value: The value of the operation.
|
||||
_var_data: Additional hooks and imports associated with the operation.
|
||||
"""
|
||||
super(ObjectEntriesOperation, self).__init__(
|
||||
value, List[Tuple[value._key_type(), value._value_type()]], _var_data
|
||||
)
|
||||
|
||||
@cached_property
|
||||
def _cached_var_name(self) -> str:
|
||||
"""The name of the operation.
|
||||
@ -574,7 +588,29 @@ class ObjectEntriesOperation(ObjectToArrayOperation):
|
||||
Returns:
|
||||
The name of the operation.
|
||||
"""
|
||||
return f"Object.entries({self.value._var_name})"
|
||||
return f"Object.entries({self._value._var_name})"
|
||||
|
||||
@classmethod
|
||||
def create(
|
||||
cls,
|
||||
value: ObjectVar,
|
||||
_var_data: VarData | None = None,
|
||||
) -> ObjectEntriesOperation:
|
||||
"""Create the object entries operation.
|
||||
|
||||
Args:
|
||||
value: The value of the operation.
|
||||
_var_data: Additional hooks and imports associated with the operation.
|
||||
|
||||
Returns:
|
||||
The object entries operation.
|
||||
"""
|
||||
return cls(
|
||||
_var_name="",
|
||||
_var_type=List[Tuple[str, value._value_type()]],
|
||||
_var_data=ImmutableVarData.merge(_var_data),
|
||||
_value=value,
|
||||
)
|
||||
|
||||
|
||||
@dataclasses.dataclass(
|
||||
@ -585,30 +621,12 @@ class ObjectEntriesOperation(ObjectToArrayOperation):
|
||||
class ObjectMergeOperation(ObjectVar):
|
||||
"""Operation to merge two objects."""
|
||||
|
||||
left: ObjectVar = dataclasses.field(default_factory=lambda: LiteralObjectVar({}))
|
||||
right: ObjectVar = dataclasses.field(default_factory=lambda: LiteralObjectVar({}))
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
left: ObjectVar,
|
||||
right: ObjectVar,
|
||||
_var_data: VarData | None = None,
|
||||
):
|
||||
"""Initialize the object merge operation.
|
||||
|
||||
Args:
|
||||
left: The left object to merge.
|
||||
right: The right object to merge.
|
||||
_var_data: Additional hooks and imports associated with the operation.
|
||||
"""
|
||||
super(ObjectMergeOperation, self).__init__(
|
||||
_var_name="",
|
||||
_var_type=left._var_type,
|
||||
_var_data=ImmutableVarData.merge(_var_data),
|
||||
_lhs: ObjectVar = dataclasses.field(
|
||||
default_factory=lambda: LiteralObjectVar.create({})
|
||||
)
|
||||
_rhs: ObjectVar = dataclasses.field(
|
||||
default_factory=lambda: LiteralObjectVar.create({})
|
||||
)
|
||||
object.__setattr__(self, "left", left)
|
||||
object.__setattr__(self, "right", right)
|
||||
object.__delattr__(self, "_var_name")
|
||||
|
||||
@cached_property
|
||||
def _cached_var_name(self) -> str:
|
||||
@ -617,7 +635,7 @@ class ObjectMergeOperation(ObjectVar):
|
||||
Returns:
|
||||
The name of the operation.
|
||||
"""
|
||||
return f"Object.assign({self.left._var_name}, {self.right._var_name})"
|
||||
return f"Object.assign({self._lhs._var_name}, {self._rhs._var_name})"
|
||||
|
||||
def __getattr__(self, name):
|
||||
"""Get an attribute of the operation.
|
||||
@ -640,8 +658,8 @@ class ObjectMergeOperation(ObjectVar):
|
||||
The VarData of the components and all of its children.
|
||||
"""
|
||||
return ImmutableVarData.merge(
|
||||
self.left._get_all_var_data(),
|
||||
self.right._get_all_var_data(),
|
||||
self._lhs._get_all_var_data(),
|
||||
self._rhs._get_all_var_data(),
|
||||
self._var_data,
|
||||
)
|
||||
|
||||
@ -659,7 +677,33 @@ class ObjectMergeOperation(ObjectVar):
|
||||
Returns:
|
||||
The hash of the operation.
|
||||
"""
|
||||
return hash((self.__class__.__name__, self.left, self.right))
|
||||
return hash((self.__class__.__name__, self._lhs, self._rhs))
|
||||
|
||||
@classmethod
|
||||
def create(
|
||||
cls,
|
||||
lhs: ObjectVar,
|
||||
rhs: ObjectVar,
|
||||
_var_data: VarData | None = None,
|
||||
) -> ObjectMergeOperation:
|
||||
"""Create the object merge operation.
|
||||
|
||||
Args:
|
||||
lhs: The left object to merge.
|
||||
rhs: The right object to merge.
|
||||
_var_data: Additional hooks and imports associated with the operation.
|
||||
|
||||
Returns:
|
||||
The object merge operation.
|
||||
"""
|
||||
# TODO: Figure out how to merge the types
|
||||
return cls(
|
||||
_var_name="",
|
||||
_var_type=lhs._var_type,
|
||||
_var_data=ImmutableVarData.merge(_var_data),
|
||||
_lhs=lhs,
|
||||
_rhs=rhs,
|
||||
)
|
||||
|
||||
|
||||
@dataclasses.dataclass(
|
||||
@ -670,33 +714,10 @@ class ObjectMergeOperation(ObjectVar):
|
||||
class ObjectItemOperation(ImmutableVar):
|
||||
"""Operation to get an item from an object."""
|
||||
|
||||
value: ObjectVar = dataclasses.field(default_factory=lambda: LiteralObjectVar({}))
|
||||
key: Var | Any = dataclasses.field(default_factory=lambda: LiteralVar.create(None))
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
value: ObjectVar,
|
||||
key: Var | Any,
|
||||
_var_type: GenericType | None = None,
|
||||
_var_data: VarData | None = None,
|
||||
):
|
||||
"""Initialize the object item operation.
|
||||
|
||||
Args:
|
||||
value: The value of the operation.
|
||||
key: The key to get from the object.
|
||||
_var_data: Additional hooks and imports associated with the operation.
|
||||
"""
|
||||
super(ObjectItemOperation, self).__init__(
|
||||
_var_name="",
|
||||
_var_type=value._value_type() if _var_type is None else _var_type,
|
||||
_var_data=ImmutableVarData.merge(_var_data),
|
||||
_object: ObjectVar = dataclasses.field(
|
||||
default_factory=lambda: LiteralObjectVar.create({})
|
||||
)
|
||||
object.__setattr__(self, "value", value)
|
||||
object.__setattr__(
|
||||
self, "key", key if isinstance(key, Var) else LiteralVar.create(key)
|
||||
)
|
||||
object.__delattr__(self, "_var_name")
|
||||
_key: Var | Any = dataclasses.field(default_factory=lambda: LiteralVar.create(None))
|
||||
|
||||
@cached_property
|
||||
def _cached_var_name(self) -> str:
|
||||
@ -705,7 +726,7 @@ class ObjectItemOperation(ImmutableVar):
|
||||
Returns:
|
||||
The name of the operation.
|
||||
"""
|
||||
return f"{str(self.value)}[{str(self.key)}]"
|
||||
return f"{str(self._object)}[{str(self._key)}]"
|
||||
|
||||
def __getattr__(self, name):
|
||||
"""Get an attribute of the operation.
|
||||
@ -728,8 +749,8 @@ class ObjectItemOperation(ImmutableVar):
|
||||
The VarData of the components and all of its children.
|
||||
"""
|
||||
return ImmutableVarData.merge(
|
||||
self.value._get_all_var_data(),
|
||||
self.key._get_all_var_data(),
|
||||
self._object._get_all_var_data(),
|
||||
self._key._get_all_var_data(),
|
||||
self._var_data,
|
||||
)
|
||||
|
||||
@ -747,7 +768,38 @@ class ObjectItemOperation(ImmutableVar):
|
||||
Returns:
|
||||
The hash of the operation.
|
||||
"""
|
||||
return hash((self.__class__.__name__, self.value, self.key))
|
||||
return hash((self.__class__.__name__, self._object, self._key))
|
||||
|
||||
def __post_init__(self):
|
||||
"""Post initialization."""
|
||||
object.__delattr__(self, "_var_name")
|
||||
|
||||
@classmethod
|
||||
def create(
|
||||
cls,
|
||||
object: ObjectVar,
|
||||
key: Var | Any,
|
||||
_var_type: GenericType | None = None,
|
||||
_var_data: VarData | None = None,
|
||||
) -> ObjectItemOperation:
|
||||
"""Create the object item operation.
|
||||
|
||||
Args:
|
||||
object: The object to get the item from.
|
||||
key: The key to get from the object.
|
||||
_var_type: The type of the item.
|
||||
_var_data: Additional hooks and imports associated with the operation.
|
||||
|
||||
Returns:
|
||||
The object item operation.
|
||||
"""
|
||||
return cls(
|
||||
_var_name="",
|
||||
_var_type=object._value_type() if _var_type is None else _var_type,
|
||||
_var_data=ImmutableVarData.merge(_var_data),
|
||||
_object=object,
|
||||
_key=key if isinstance(key, Var) else LiteralVar.create(key),
|
||||
)
|
||||
|
||||
|
||||
@dataclasses.dataclass(
|
||||
@ -758,28 +810,9 @@ class ObjectItemOperation(ImmutableVar):
|
||||
class ToObjectOperation(ObjectVar):
|
||||
"""Operation to convert a var to an object."""
|
||||
|
||||
_original_var: Var = dataclasses.field(default_factory=lambda: LiteralObjectVar({}))
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
_original_var: Var,
|
||||
_var_type: Type = dict,
|
||||
_var_data: VarData | None = None,
|
||||
):
|
||||
"""Initialize the to object operation.
|
||||
|
||||
Args:
|
||||
_original_var: The original var to convert.
|
||||
_var_type: The type of the var.
|
||||
_var_data: Additional hooks and imports associated with the operation.
|
||||
"""
|
||||
super(ToObjectOperation, self).__init__(
|
||||
_var_name="",
|
||||
_var_type=_var_type,
|
||||
_var_data=ImmutableVarData.merge(_var_data),
|
||||
_original_var: Var = dataclasses.field(
|
||||
default_factory=lambda: LiteralObjectVar.create({})
|
||||
)
|
||||
object.__setattr__(self, "_original_var", _original_var)
|
||||
object.__delattr__(self, "_var_name")
|
||||
|
||||
@cached_property
|
||||
def _cached_var_name(self) -> str:
|
||||
@ -831,6 +864,34 @@ class ToObjectOperation(ObjectVar):
|
||||
"""
|
||||
return hash((self.__class__.__name__, self._original_var))
|
||||
|
||||
def __post_init__(self):
|
||||
"""Post initialization."""
|
||||
object.__delattr__(self, "_var_name")
|
||||
|
||||
@classmethod
|
||||
def create(
|
||||
cls,
|
||||
original_var: Var,
|
||||
_var_type: GenericType | None = None,
|
||||
_var_data: VarData | None = None,
|
||||
) -> ToObjectOperation:
|
||||
"""Create the to object operation.
|
||||
|
||||
Args:
|
||||
original_var: The original var to convert.
|
||||
_var_type: The type of the var.
|
||||
_var_data: Additional hooks and imports associated with the operation.
|
||||
|
||||
Returns:
|
||||
The to object operation.
|
||||
"""
|
||||
return cls(
|
||||
_var_name="",
|
||||
_var_type=dict if _var_type is None else _var_type,
|
||||
_var_data=ImmutableVarData.merge(_var_data),
|
||||
_original_var=original_var,
|
||||
)
|
||||
|
||||
|
||||
@dataclasses.dataclass(
|
||||
eq=False,
|
||||
@ -840,30 +901,13 @@ class ToObjectOperation(ObjectVar):
|
||||
class ObjectHasOwnProperty(BooleanVar):
|
||||
"""Operation to check if an object has a property."""
|
||||
|
||||
value: ObjectVar = dataclasses.field(default_factory=lambda: LiteralObjectVar({}))
|
||||
key: Var | Any = dataclasses.field(default_factory=lambda: LiteralVar.create(None))
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
value: ObjectVar,
|
||||
key: Var | Any,
|
||||
_var_data: VarData | None = None,
|
||||
):
|
||||
"""Initialize the object has own property operation.
|
||||
|
||||
Args:
|
||||
value: The value of the operation.
|
||||
key: The key to check.
|
||||
_var_data: Additional hooks and imports associated with the operation.
|
||||
"""
|
||||
super(ObjectHasOwnProperty, self).__init__(
|
||||
_var_name="",
|
||||
_var_data=ImmutableVarData.merge(_var_data),
|
||||
)
|
||||
object.__setattr__(self, "value", value)
|
||||
object.__setattr__(
|
||||
self, "key", key if isinstance(key, Var) else LiteralVar.create(key)
|
||||
_object: ObjectVar = dataclasses.field(
|
||||
default_factory=lambda: LiteralObjectVar.create({})
|
||||
)
|
||||
_key: Var | Any = dataclasses.field(default_factory=lambda: LiteralVar.create(None))
|
||||
|
||||
def __post_init__(self):
|
||||
"""Post initialization."""
|
||||
object.__delattr__(self, "_var_name")
|
||||
|
||||
@cached_property
|
||||
@ -873,7 +917,7 @@ class ObjectHasOwnProperty(BooleanVar):
|
||||
Returns:
|
||||
The name of the operation.
|
||||
"""
|
||||
return f"{str(self.value)}.hasOwnProperty({str(self.key)})"
|
||||
return f"{str(self._object)}.hasOwnProperty({str(self._key)})"
|
||||
|
||||
def __getattr__(self, name):
|
||||
"""Get an attribute of the operation.
|
||||
@ -896,8 +940,8 @@ class ObjectHasOwnProperty(BooleanVar):
|
||||
The VarData of the components and all of its children.
|
||||
"""
|
||||
return ImmutableVarData.merge(
|
||||
self.value._get_all_var_data(),
|
||||
self.key._get_all_var_data(),
|
||||
self._object._get_all_var_data(),
|
||||
self._key._get_all_var_data(),
|
||||
self._var_data,
|
||||
)
|
||||
|
||||
@ -915,4 +959,29 @@ class ObjectHasOwnProperty(BooleanVar):
|
||||
Returns:
|
||||
The hash of the operation.
|
||||
"""
|
||||
return hash((self.__class__.__name__, self.value, self.key))
|
||||
return hash((self.__class__.__name__, self._object, self._key))
|
||||
|
||||
@classmethod
|
||||
def create(
|
||||
cls,
|
||||
object: ObjectVar,
|
||||
key: Var | Any,
|
||||
_var_data: VarData | None = None,
|
||||
) -> ObjectHasOwnProperty:
|
||||
"""Create the object has own property operation.
|
||||
|
||||
Args:
|
||||
object: The object to check.
|
||||
key: The key to check.
|
||||
_var_data: Additional hooks and imports associated with the operation.
|
||||
|
||||
Returns:
|
||||
The object has own property operation.
|
||||
"""
|
||||
return cls(
|
||||
_var_name="",
|
||||
_var_type=bool,
|
||||
_var_data=ImmutableVarData.merge(_var_data),
|
||||
_object=object,
|
||||
_key=key if isinstance(key, Var) else LiteralVar.create(key),
|
||||
)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -32,7 +32,7 @@ import dill
|
||||
from sqlalchemy.orm import DeclarativeBase
|
||||
|
||||
from reflex.config import get_config
|
||||
from reflex.ivars.base import ImmutableVar
|
||||
from reflex.ivars.base import ImmutableComputedVar, ImmutableVar, immutable_computed_var
|
||||
|
||||
try:
|
||||
import pydantic.v1 as pydantic
|
||||
@ -60,7 +60,6 @@ from reflex.vars import (
|
||||
ComputedVar,
|
||||
ImmutableVarData,
|
||||
Var,
|
||||
computed_var,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@ -68,7 +67,7 @@ if TYPE_CHECKING:
|
||||
|
||||
|
||||
Delta = Dict[str, Any]
|
||||
var = computed_var
|
||||
var = immutable_computed_var
|
||||
|
||||
|
||||
# If the state is this large, it's considered a performance issue.
|
||||
@ -307,7 +306,7 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
||||
base_vars: ClassVar[Dict[str, ImmutableVar]] = {}
|
||||
|
||||
# The computed vars of the class.
|
||||
computed_vars: ClassVar[Dict[str, ComputedVar]] = {}
|
||||
computed_vars: ClassVar[Dict[str, Union[ComputedVar, ImmutableComputedVar]]] = {}
|
||||
|
||||
# Vars inherited by the parent state.
|
||||
inherited_vars: ClassVar[Dict[str, Var]] = {}
|
||||
@ -420,7 +419,7 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
||||
return f"{self.__class__.__name__}({self.dict()})"
|
||||
|
||||
@classmethod
|
||||
def _get_computed_vars(cls) -> list[ComputedVar]:
|
||||
def _get_computed_vars(cls) -> list[Union[ComputedVar, ImmutableComputedVar]]:
|
||||
"""Helper function to get all computed vars of a instance.
|
||||
|
||||
Returns:
|
||||
@ -430,7 +429,7 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
||||
v
|
||||
for mixin in cls._mixins() + [cls]
|
||||
for v in mixin.__dict__.values()
|
||||
if isinstance(v, ComputedVar)
|
||||
if isinstance(v, (ComputedVar, ImmutableComputedVar))
|
||||
]
|
||||
|
||||
@classmethod
|
||||
@ -534,7 +533,10 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
||||
for f in cls.get_fields().values()
|
||||
if f.name not in cls.get_skip_vars()
|
||||
}
|
||||
cls.computed_vars = {v._var_name: v._var_set_state(cls) for v in computed_vars}
|
||||
cls.computed_vars = {
|
||||
v._var_name: v._replace(merge_var_data=ImmutableVarData.from_state(cls))
|
||||
for v in computed_vars
|
||||
}
|
||||
cls.vars = {
|
||||
**cls.inherited_vars,
|
||||
**cls.base_vars,
|
||||
@ -555,12 +557,12 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
||||
|
||||
for mixin in cls._mixins():
|
||||
for name, value in mixin.__dict__.items():
|
||||
if isinstance(value, ComputedVar):
|
||||
if isinstance(value, (ComputedVar, ImmutableComputedVar)):
|
||||
fget = cls._copy_fn(value.fget)
|
||||
newcv = value._replace(fget=fget)
|
||||
newcv = value._replace(
|
||||
fget=fget, _var_data=ImmutableVarData.from_state(cls)
|
||||
)
|
||||
# cleanup refs to mixin cls in var_data
|
||||
newcv._var_data = None
|
||||
newcv._var_set_state(cls)
|
||||
setattr(cls, name, newcv)
|
||||
cls.computed_vars[newcv._var_name] = newcv
|
||||
cls.vars[newcv._var_name] = newcv
|
||||
@ -897,8 +899,9 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
||||
)
|
||||
|
||||
# create the variable based on name and type
|
||||
var = ImmutableVar(_var_name=name, _var_type=type_).guess_type()
|
||||
var._var_set_state(cls)
|
||||
var = ImmutableVar(
|
||||
_var_name=name, _var_type=type_, _var_data=ImmutableVarData.from_state(cls)
|
||||
).guess_type()
|
||||
|
||||
# add the pydantic field dynamically (must be done before _init_var)
|
||||
cls.add_field(var, default_value)
|
||||
@ -983,7 +986,7 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
||||
and not types.is_optional(prop._var_type)
|
||||
):
|
||||
# Ensure frontend uses null coalescing when accessing.
|
||||
prop._var_type = Optional[prop._var_type]
|
||||
object.__setattr__(prop, "_var_type", Optional[prop._var_type])
|
||||
|
||||
@staticmethod
|
||||
def _get_base_functions() -> dict[str, FunctionType]:
|
||||
@ -1783,7 +1786,7 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
||||
# Include initial computed vars.
|
||||
prop_name: (
|
||||
cv._initial_value
|
||||
if isinstance(cv, ComputedVar)
|
||||
if isinstance(cv, (ComputedVar, ImmutableComputedVar))
|
||||
and not isinstance(cv._initial_value, types.Unset)
|
||||
else self.get_value(getattr(self, prop_name))
|
||||
)
|
||||
|
@ -9,8 +9,6 @@ import re
|
||||
from typing import TYPE_CHECKING, Any, Callable, List, Optional, Union
|
||||
|
||||
from reflex import constants
|
||||
from reflex.ivars.base import ImmutableVar
|
||||
from reflex.ivars.function import FunctionVar
|
||||
from reflex.utils import exceptions, types
|
||||
from reflex.vars import BaseVar, Var
|
||||
|
||||
@ -274,8 +272,10 @@ def format_f_string_prop(prop: BaseVar) -> str:
|
||||
Returns:
|
||||
The formatted string.
|
||||
"""
|
||||
from reflex.ivars.base import VarData
|
||||
|
||||
s = prop._var_full_name
|
||||
var_data = prop._var_data
|
||||
var_data = VarData.merge(prop._get_all_var_data())
|
||||
interps = var_data.interpolations if var_data else []
|
||||
parts: List[str] = []
|
||||
|
||||
@ -423,6 +423,7 @@ def format_prop(
|
||||
# import here to avoid circular import.
|
||||
from reflex.event import EventChain
|
||||
from reflex.utils import serializers
|
||||
from reflex.vars import VarData
|
||||
|
||||
try:
|
||||
# Handle var props.
|
||||
@ -430,7 +431,8 @@ def format_prop(
|
||||
if not prop._var_is_local or prop._var_is_string:
|
||||
return str(prop)
|
||||
if isinstance(prop, BaseVar) and types._issubclass(prop._var_type, str):
|
||||
if prop._var_data and prop._var_data.interpolations:
|
||||
var_data = VarData.merge(prop._get_all_var_data())
|
||||
if var_data and var_data.interpolations:
|
||||
return format_f_string_prop(prop)
|
||||
return format_string(prop._var_full_name)
|
||||
prop = prop._var_full_name
|
||||
@ -485,17 +487,38 @@ def format_props(*single_props, **key_value_props) -> list[str]:
|
||||
The formatted props list.
|
||||
"""
|
||||
# Format all the props.
|
||||
from reflex.ivars.base import ImmutableVar
|
||||
from reflex.ivars.base import ImmutableVar, LiteralVar
|
||||
|
||||
# print(
|
||||
# *[
|
||||
# f"{name}={{{format_prop(prop if isinstance(prop, Var) else LiteralVar.create(prop))}}}"
|
||||
# for name, prop in sorted(key_value_props.items())
|
||||
# if prop is not None
|
||||
# ],
|
||||
# sep="\n",
|
||||
# )
|
||||
|
||||
# if single_props:
|
||||
# print("single_props", single_props)
|
||||
|
||||
return [
|
||||
(
|
||||
f"{name}={{{format_prop(prop)}}}"
|
||||
if isinstance(prop, ImmutableVar)
|
||||
else f"{name}={format_prop(prop)}"
|
||||
f"{name}={format_prop(prop)}"
|
||||
if isinstance(prop, Var) and not isinstance(prop, ImmutableVar)
|
||||
else (
|
||||
f"{name}={{{format_prop(prop if isinstance(prop, Var) else LiteralVar.create(prop))}}}"
|
||||
)
|
||||
)
|
||||
for name, prop in sorted(key_value_props.items())
|
||||
if prop is not None
|
||||
] + [str(prop) for prop in single_props]
|
||||
] + [
|
||||
(
|
||||
str(prop)
|
||||
if isinstance(prop, Var) and not isinstance(prop, ImmutableVar)
|
||||
else f"{{{str(LiteralVar.create(prop))}}}"
|
||||
)
|
||||
for prop in single_props
|
||||
]
|
||||
|
||||
|
||||
def get_event_handler_parts(handler: EventHandler) -> tuple[str, str]:
|
||||
@ -510,13 +533,13 @@ def get_event_handler_parts(handler: EventHandler) -> tuple[str, str]:
|
||||
# Get the class that defines the event handler.
|
||||
parts = handler.fn.__qualname__.split(".")
|
||||
|
||||
# If there's no enclosing class, just return the function name.
|
||||
if len(parts) == 1:
|
||||
return ("", parts[-1])
|
||||
|
||||
# Get the state full name
|
||||
state_full_name = handler.state_full_name
|
||||
|
||||
# If there's no enclosing class, just return the function name.
|
||||
if not state_full_name:
|
||||
return ("", parts[-1])
|
||||
|
||||
# Get the function name
|
||||
name = parts[-1]
|
||||
|
||||
@ -655,6 +678,7 @@ def format_queue_events(
|
||||
call_event_fn,
|
||||
call_event_handler,
|
||||
)
|
||||
from reflex.ivars.base import FunctionVar, ImmutableVar
|
||||
|
||||
if not events:
|
||||
return ImmutableVar("(() => null)").to(FunctionVar, EventChain)
|
||||
@ -944,6 +968,8 @@ def format_data_editor_cell(cell: Any):
|
||||
Returns:
|
||||
The formatted cell.
|
||||
"""
|
||||
from reflex.ivars.base import ImmutableVar
|
||||
|
||||
return {
|
||||
"kind": ImmutableVar.create("GridCellKind.Text"),
|
||||
"data": cell,
|
||||
|
@ -491,10 +491,18 @@ def is_backend_base_variable(name: str, cls: Type) -> bool:
|
||||
return False
|
||||
if callable(value):
|
||||
return False
|
||||
from reflex.ivars.base import ImmutableComputedVar
|
||||
from reflex.vars import ComputedVar
|
||||
|
||||
if isinstance(
|
||||
value, (types.FunctionType, property, cached_property, ComputedVar)
|
||||
value,
|
||||
(
|
||||
types.FunctionType,
|
||||
property,
|
||||
cached_property,
|
||||
ComputedVar,
|
||||
ImmutableComputedVar,
|
||||
),
|
||||
):
|
||||
return False
|
||||
|
||||
|
@ -892,6 +892,7 @@ class Var:
|
||||
Raises:
|
||||
VarTypeError: If the var is not indexable.
|
||||
"""
|
||||
print(repr(self))
|
||||
from reflex.utils import format
|
||||
|
||||
# Indexing is only supported for strings, lists, tuples, dicts, and dataframes.
|
||||
|
@ -154,6 +154,7 @@ class Var:
|
||||
def _var_set_state(self, state: Type[BaseState] | str) -> Any: ...
|
||||
def _get_all_var_data(self) -> VarData | ImmutableVarData: ...
|
||||
def json(self) -> str: ...
|
||||
def _type(self) -> Var: ...
|
||||
|
||||
@dataclass(eq=False)
|
||||
class BaseVar(Var):
|
||||
|
Loading…
Reference in New Issue
Block a user