Browse Source

Var field cleanup (#1943)

Masen Furer 1 year ago
parent
commit
024cb5fa9b

+ 2 - 2
integration/test_event_chain.py

@@ -131,8 +131,8 @@ def EventChain():
     @app.add_page
     def index():
         return rx.fragment(
-            rx.input(value=State.token, readonly=True, id="token"),
-            rx.input(value=State.interim_value, readonly=True, id="interim_value"),
+            rx.input(value=State.token, is_read_only=True, id="token"),
+            rx.input(value=State.interim_value, is_read_only=True, id="interim_value"),
             rx.button(
                 "Return Event",
                 id="return_event",

+ 3 - 3
reflex/base.py

@@ -65,13 +65,13 @@ class Base(pydantic.BaseModel):
             default_value: The default value of the field
         """
         new_field = ModelField.infer(
-            name=var.name,
+            name=var._var_name,
             value=default_value,
-            annotation=var.type_,
+            annotation=var._var_type,
             class_validators=None,
             config=cls.__config__,
         )
-        cls.__fields__.update({var.name: new_field})
+        cls.__fields__.update({var._var_name: new_field})
 
     def get_value(self, key: str) -> Any:
         """Get the value of a field.

+ 1 - 1
reflex/compiler/utils.py

@@ -243,7 +243,7 @@ def compile_custom_component(
     }
 
     # Concatenate the props.
-    props = [prop.name for prop in component.get_prop_vars()]
+    props = [prop._var_name for prop in component.get_prop_vars()]
 
     # Compile the component.
     return (

+ 1 - 1
reflex/components/base/script.py

@@ -94,4 +94,4 @@ def client_side(javascript_code) -> Var[EventChain]:
         deprecation_version="0.2.9",
         removal_version="0.3.0",
     )
-    return BaseVar(name=f"...args => {{{javascript_code}}}", type_=EventChain)
+    return BaseVar(_var_name=f"...args => {{{javascript_code}}}", _var_type=EventChain)

+ 12 - 8
reflex/components/component.py

@@ -155,7 +155,7 @@ class Component(Base, ABC):
                         raise TypeError
 
                     # Get the passed type and the var type.
-                    passed_type = kwargs[key].type_
+                    passed_type = kwargs[key]._var_type
                     expected_type = fields[key].outer_type_.__args__[0]
                 except TypeError:
                     # If it is not a valid var, check the base types.
@@ -222,7 +222,7 @@ class Component(Base, ABC):
 
         # If it's an event chain var, return it.
         if isinstance(value, Var):
-            if value.type_ is not EventChain:
+            if value._var_type is not EventChain:
                 raise ValueError(f"Invalid event chain: {value}")
             return value
 
@@ -388,7 +388,7 @@ class Component(Base, ABC):
         # Add ref to element if `id` is not None.
         ref = self.get_ref()
         if ref is not None:
-            props["ref"] = Var.create(ref, is_local=False)
+            props["ref"] = Var.create(ref, _var_is_local=False)
 
         return tag.add_props(**props)
 
@@ -440,7 +440,7 @@ class Component(Base, ABC):
         children = [
             child
             if isinstance(child, Component)
-            else Bare.create(contents=Var.create(child, is_string=True))
+            else Bare.create(contents=Var.create(child, _var_is_string=True))
             for child in children
         ]
 
@@ -808,11 +808,13 @@ class CustomComponent(Component):
             # Handle subclasses of Base.
             if types._issubclass(type_, Base):
                 try:
-                    value = BaseVar(name=value.json(), type_=type_, is_local=True)
+                    value = BaseVar(
+                        _var_name=value.json(), _var_type=type_, _var_is_local=True
+                    )
                 except Exception:
                     value = Var.create(value)
             else:
-                value = Var.create(value, is_string=type(value) is str)
+                value = Var.create(value, _var_is_string=type(value) is str)
 
             # Set the prop.
             self.props[format.to_camel_case(key)] = value
@@ -888,8 +890,10 @@ class CustomComponent(Component):
         """
         return [
             BaseVar(
-                name=name,
-                type_=prop.type_ if types._isinstance(prop, Var) else type(prop),
+                _var_name=name,
+                _var_type=prop._var_type
+                if types._isinstance(prop, Var)
+                else type(prop),
             )
             for name, prop in self.props.items()
         ]

+ 3 - 2
reflex/components/datadisplay/code.py

@@ -48,7 +48,8 @@ class CodeBlock(Component):
         merged_imports = super()._get_imports()
         if self.theme is not None:
             merged_imports = imports.merge_imports(
-                merged_imports, {PRISM_STYLES_PATH: {ImportVar(tag=self.theme.name)}}
+                merged_imports,
+                {PRISM_STYLES_PATH: {ImportVar(tag=self.theme._var_name)}},
             )
         return merged_imports
 
@@ -113,7 +114,7 @@ class CodeBlock(Component):
         out = super()._render()
         if self.theme is not None:
             out.add_props(
-                style=Var.create(self.theme.name, is_local=False)
+                style=Var.create(self.theme._var_name, _var_is_local=False)
             ).remove_props("theme")
         return out
 

+ 11 - 11
reflex/components/datadisplay/datatable.py

@@ -64,7 +64,7 @@ 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.type_ == Any:
+        if isinstance(data, ComputedVar) and data._var_type == Any:
             raise ValueError(
                 "Annotation of the computed var assigned to the data field should be provided."
             )
@@ -72,7 +72,7 @@ class DataTable(Gridjs):
         if (
             columns is not None
             and isinstance(columns, ComputedVar)
-            and columns.type_ == Any
+            and columns._var_type == Any
         ):
             raise ValueError(
                 "Annotation of the computed var assigned to the column field should be provided."
@@ -81,7 +81,7 @@ class DataTable(Gridjs):
         # If data is a pandas dataframe and columns are provided throw an error.
         if (
             types.is_dataframe(type(data))
-            or (isinstance(data, Var) and types.is_dataframe(data.type_))
+            or (isinstance(data, Var) and types.is_dataframe(data._var_type))
         ) and columns is not None:
             raise ValueError(
                 "Cannot pass in both a pandas dataframe and columns to the data_table component."
@@ -89,7 +89,7 @@ class DataTable(Gridjs):
 
         # If data is a list and columns are not provided, throw an error
         if (
-            (isinstance(data, Var) and types._issubclass(data.type_, List))
+            (isinstance(data, Var) and types._issubclass(data._var_type, List))
             or issubclass(type(data), List)
         ) and columns is None:
             raise ValueError(
@@ -109,16 +109,16 @@ class DataTable(Gridjs):
         )
 
     def _render(self) -> Tag:
-        if isinstance(self.data, Var) and types.is_dataframe(self.data.type_):
+        if isinstance(self.data, Var) and types.is_dataframe(self.data._var_type):
             self.columns = BaseVar(
-                name=f"{self.data.name}.columns",
-                type_=List[Any],
-                state=self.data.state,
+                _var_name=f"{self.data._var_name}.columns",
+                _var_type=List[Any],
+                _var_state=self.data._var_state,
             )
             self.data = BaseVar(
-                name=f"{self.data.name}.data",
-                type_=List[List[Any]],
-                state=self.data.state,
+                _var_name=f"{self.data._var_name}.data",
+                _var_type=List[List[Any]],
+                _var_state=self.data._var_state,
             )
         if types.is_dataframe(type(self.data)):
             # If given a pandas df break up the data and columns

+ 7 - 3
reflex/components/datadisplay/table.py

@@ -101,7 +101,9 @@ class Thead(ChakraComponent):
         if (
             (
                 isinstance(headers, Var)
-                and not types.check_type_in_allowed_types(headers.type_, allowed_types)
+                and not types.check_type_in_allowed_types(
+                    headers._var_type, allowed_types
+                )
             )
             or not isinstance(headers, Var)
             and not types.check_type_in_allowed_types(type(headers), allowed_types)
@@ -156,7 +158,7 @@ class Tbody(ChakraComponent):
         """
         allowed_subclasses = (List, Tuple)
         if isinstance(rows, Var):
-            outer_type = rows.type_
+            outer_type = rows._var_type
             inner_type = (
                 outer_type.__args__[0] if hasattr(outer_type, "__args__") else None
             )
@@ -222,7 +224,9 @@ class Tfoot(ChakraComponent):
         if (
             (
                 isinstance(footers, Var)
-                and not types.check_type_in_allowed_types(footers.type_, allowed_types)
+                and not types.check_type_in_allowed_types(
+                    footers._var_type, allowed_types
+                )
             )
             or not isinstance(footers, Var)
             and not types.check_type_in_allowed_types(type(footers), allowed_types)

+ 4 - 2
reflex/components/forms/debounce.py

@@ -58,7 +58,7 @@ class DebounceInput(Component):
             raise ValueError("DebounceInput child requires an on_change handler")
         child_ref = child.get_ref()
         if child_ref and not props.get("ref"):
-            props["input_ref"] = Var.create(child_ref, is_local=False)
+            props["input_ref"] = Var.create(child_ref, _var_is_local=False)
         self.children = []
         tag = super()._render()
         tag.add_props(
@@ -67,7 +67,9 @@ class DebounceInput(Component):
             sx=child.style,
             id=child.id,
             class_name=child.class_name,
-            element=Var.create("{%s}" % child.tag, is_local=False, is_string=False),
+            element=Var.create(
+                "{%s}" % child.tag, _var_is_local=False, _var_is_string=False
+            ),
         )
         # do NOT render the child, DebounceInput will create it
         object.__setattr__(child, "render", lambda: "")

+ 4 - 2
reflex/components/forms/form.py

@@ -29,10 +29,12 @@ class Form(ChakraComponent):
             # to collect data
             if ref.startswith("refs_"):
                 form_refs[ref[5:-3]] = Var.create(
-                    f"getRefValues({ref[:-3]})", is_local=False
+                    f"getRefValues({ref[:-3]})", _var_is_local=False
                 )
             else:
-                form_refs[ref[4:]] = Var.create(f"getRefValue({ref})", is_local=False)
+                form_refs[ref[4:]] = Var.create(
+                    f"getRefValue({ref})", _var_is_local=False
+                )
 
         return {
             **super().get_event_triggers(),

+ 3 - 1
reflex/components/forms/multiselect.py

@@ -308,7 +308,9 @@ class Select(Component):
         return {
             **super().get_event_triggers(),
             EventTriggers.ON_CHANGE: (
-                lambda e0: [Var.create_safe(f"{e0}.map(e => e.value)", is_local=True)]
+                lambda e0: [
+                    Var.create_safe(f"{e0}.map(e => e.value)", _var_is_local=True)
+                ]
                 if self.is_multi
                 else lambda e0: [e0]
             ),

+ 11 - 5
reflex/components/forms/upload.py

@@ -11,13 +11,17 @@ from reflex.event import EventChain
 from reflex.vars import BaseVar, Var
 
 files_state: str = "const [files, setFiles] = useState([]);"
-upload_file: BaseVar = BaseVar(name="e => setFiles((files) => e)", type_=EventChain)
+upload_file: BaseVar = BaseVar(
+    _var_name="e => setFiles((files) => e)", _var_type=EventChain
+)
 
 # Use this var along with the Upload component to render the list of selected files.
-selected_files: BaseVar = BaseVar(name="files.map((f) => f.name)", type_=List[str])
+selected_files: BaseVar = BaseVar(
+    _var_name="files.map((f) => f.name)", _var_type=List[str]
+)
 
 clear_selected_files: BaseVar = BaseVar(
-    name="_e => setFiles((files) => [])", type_=EventChain
+    _var_name="_e => setFiles((files) => [])", _var_type=EventChain
 )
 
 
@@ -77,7 +81,9 @@ class Upload(Component):
         }
         # The file input to use.
         upload = Input.create(type_="file")
-        upload.special_props = {BaseVar(name="{...getInputProps()}", type_=None)}
+        upload.special_props = {
+            BaseVar(_var_name="{...getInputProps()}", _var_type=None)
+        }
 
         # The dropzone to use.
         zone = Box.create(
@@ -85,7 +91,7 @@ class Upload(Component):
             *children,
             **{k: v for k, v in props.items() if k not in supported_props},
         )
-        zone.special_props = {BaseVar(name="{...getRootProps()}", type_=None)}
+        zone.special_props = {BaseVar(_var_name="{...getRootProps()}", _var_type=None)}
 
         # Create the component.
         return super().create(zone, on_drop=upload_file, **upload_props)

+ 4 - 4
reflex/components/layout/cond.py

@@ -77,7 +77,7 @@ class Cond(Component):
             ).set(
                 props=tag.format_props(),
             ),
-            cond_state=f"isTrue({self.cond.full_name})",
+            cond_state=f"isTrue({self.cond._var_full_name})",
         )
 
 
@@ -118,11 +118,11 @@ def cond(condition: Any, c1: Any, c2: Any = None):
 
     # Create the conditional var.
     return BaseVar(
-        name=format.format_cond(
-            cond=cond_var.full_name,
+        _var_name=format.format_cond(
+            cond=cond_var._var_full_name,
             true_value=c1,
             false_value=c2,
             is_prop=True,
         ),
-        type_=c1.type_ if isinstance(c1, BaseVar) else type(c1),
+        _var_type=c1._var_type if isinstance(c1, BaseVar) else type(c1),
     )

+ 13 - 13
reflex/components/layout/foreach.py

@@ -35,18 +35,18 @@ class Foreach(Component):
         """
         try:
             type_ = (
-                iterable.type_
-                if iterable.type_.mro()[0] == dict
-                else iterable.type_.__args__[0]
+                iterable._var_type
+                if iterable._var_type.mro()[0] == dict
+                else iterable._var_type.__args__[0]
             )
         except Exception:
             type_ = Any
         iterable = Var.create(iterable)  # type: ignore
-        if iterable.type_ == Any:
+        if iterable._var_type == Any:
             raise TypeError(
                 f"Could not foreach over var of type Any. (If you are trying to foreach over a state var, add a type annotation to the var.)"
             )
-        arg = BaseVar(name="_", type_=type_, is_local=True)
+        arg = BaseVar(_var_name="_", _var_type=type_, _var_is_local=True)
         return cls(
             iterable=iterable,
             render_fn=render_fn,
@@ -66,15 +66,15 @@ class Foreach(Component):
         tag = self._render()
         try:
             type_ = (
-                self.iterable.type_
-                if self.iterable.type_.mro()[0] == dict
-                else self.iterable.type_.__args__[0]
+                self.iterable._var_type
+                if self.iterable._var_type.mro()[0] == dict
+                else self.iterable._var_type.__args__[0]
             )
         except Exception:
             type_ = Any
         arg = BaseVar(
-            name=get_unique_variable_name(),
-            type_=type_,
+            _var_name=get_unique_variable_name(),
+            _var_type=type_,
         )
         index_arg = tag.get_index_var_arg()
         component = tag.render_component(self.render_fn, arg)
@@ -89,8 +89,8 @@ class Foreach(Component):
                 children=[component.render()],
                 props=tag.format_props(),
             ),
-            iterable_state=tag.iterable.full_name,
-            arg_name=arg.name,
+            iterable_state=tag.iterable._var_full_name,
+            arg_name=arg._var_name,
             arg_index=index_arg,
-            iterable_type=tag.iterable.type_.mro()[0].__name__,
+            iterable_type=tag.iterable._var_type.mro()[0].__name__,
         )

+ 1 - 1
reflex/components/media/image.py

@@ -77,7 +77,7 @@ class Image(ChakraComponent):
         """
         src = props.get("src", None)
         if src is not None and not isinstance(src, (Var)):
-            props["src"] = Var.create(value=src, is_string=True)
+            props["src"] = Var.create(value=src, _var_is_string=True)
         return super().create(*children, **props)
 
 

+ 1 - 1
reflex/components/navigation/link.py

@@ -23,7 +23,7 @@ class Link(ChakraComponent):
     text: Var[str]
 
     # What the link renders to.
-    as_: Var[str] = BaseVar.create("{NextLink}", is_local=False)  # type: ignore
+    as_: Var[str] = BaseVar.create(value="{NextLink}", _var_is_local=False)  # type: ignore
 
     # If true, the link will open in new tab.
     is_external: Var[bool]

+ 4 - 4
reflex/components/overlay/banner.py

@@ -13,14 +13,14 @@ from reflex.vars import ImportVar, Var
 
 connection_error: Var = Var.create_safe(
     value="(connectError !== null) ? connectError.message : ''",
-    is_local=False,
-    is_string=False,
+    _var_is_local=False,
+    _var_is_string=False,
 )
 has_connection_error: Var = Var.create_safe(
     value="connectError !== null",
-    is_string=False,
+    _var_is_string=False,
 )
-has_connection_error.type_ = bool
+has_connection_error._var_type = bool
 
 
 class WebsocketTargetURL(Bare):

+ 5 - 5
reflex/components/tags/iter_tag.py

@@ -31,8 +31,8 @@ class IterTag(Tag):
             The index var.
         """
         return BaseVar(
-            name=INDEX_VAR,
-            type_=int,
+            _var_name=INDEX_VAR,
+            _var_type=int,
         )
 
     @staticmethod
@@ -43,9 +43,9 @@ class IterTag(Tag):
             The index var.
         """
         return BaseVar(
-            name=INDEX_VAR,
-            type_=int,
-            is_local=True,
+            _var_name=INDEX_VAR,
+            _var_type=int,
+            _var_is_local=True,
         )
 
     @staticmethod

+ 17 - 13
reflex/components/typography/markdown.py

@@ -17,18 +17,18 @@ from reflex.utils import console, imports, types
 from reflex.vars import ImportVar, Var
 
 # Special vars used in the component map.
-_CHILDREN = Var.create_safe("children", is_local=False)
-_PROPS = Var.create_safe("...props", is_local=False)
+_CHILDREN = Var.create_safe("children", _var_is_local=False)
+_PROPS = Var.create_safe("...props", _var_is_local=False)
 _MOCK_ARG = Var.create_safe("")
 
 # Special remark plugins.
-_REMARK_MATH = Var.create_safe("remarkMath", is_local=False)
-_REMARK_GFM = Var.create_safe("remarkGfm", is_local=False)
+_REMARK_MATH = Var.create_safe("remarkMath", _var_is_local=False)
+_REMARK_GFM = Var.create_safe("remarkGfm", _var_is_local=False)
 _REMARK_PLUGINS = Var.create_safe([_REMARK_MATH, _REMARK_GFM])
 
 # Special rehype plugins.
-_REHYPE_KATEX = Var.create_safe("rehypeKatex", is_local=False)
-_REHYPE_RAW = Var.create_safe("rehypeRaw", is_local=False)
+_REHYPE_KATEX = Var.create_safe("rehypeKatex", _var_is_local=False)
+_REHYPE_RAW = Var.create_safe("rehypeRaw", _var_is_local=False)
 _REHYPE_PLUGINS = Var.create_safe([_REHYPE_KATEX, _REHYPE_RAW])
 
 # Component Mapping
@@ -153,13 +153,17 @@ class Markdown(Component):
             {
                 "": {ImportVar(tag="katex/dist/katex.min.css")},
                 "remark-math@5.1.1": {
-                    ImportVar(tag=_REMARK_MATH.name, is_default=True)
+                    ImportVar(tag=_REMARK_MATH._var_name, is_default=True)
+                },
+                "remark-gfm@3.0.1": {
+                    ImportVar(tag=_REMARK_GFM._var_name, is_default=True)
                 },
-                "remark-gfm@3.0.1": {ImportVar(tag=_REMARK_GFM.name, is_default=True)},
                 "rehype-katex@6.0.3": {
-                    ImportVar(tag=_REHYPE_KATEX.name, is_default=True)
+                    ImportVar(tag=_REHYPE_KATEX._var_name, is_default=True)
+                },
+                "rehype-raw@6.1.1": {
+                    ImportVar(tag=_REHYPE_RAW._var_name, is_default=True)
                 },
-                "rehype-raw@6.1.1": {ImportVar(tag=_REHYPE_RAW.name, is_default=True)},
             }
         )
 
@@ -226,20 +230,20 @@ class Markdown(Component):
             The formatted component map.
         """
         components = {
-            tag: f"{{({{{_CHILDREN.name}, {_PROPS.name}}}) => {self.format_component(tag)}}}"
+            tag: f"{{({{{_CHILDREN._var_name}, {_PROPS._var_name}}}) => {self.format_component(tag)}}}"
             for tag in self.component_map
         }
 
         # Separate out inline code and code blocks.
         components[
             "code"
-        ] = f"""{{({{inline, className, {_CHILDREN.name}, {_PROPS.name}}}) => {{
+        ] = f"""{{({{inline, className, {_CHILDREN._var_name}, {_PROPS._var_name}}}) => {{
     const match = (className || '').match(/language-(?<lang>.*)/);
     const language = match ? match[1] : '';
     return inline ? (
         {self.format_component("code")}
     ) : (
-        {self.format_component("codeblock", language=Var.create_safe("language", is_local=False), children=Var.create_safe("String(children)", is_local=False))}
+        {self.format_component("codeblock", language=Var.create_safe("language", _var_is_local=False), children=Var.create_safe("String(children)", _var_is_local=False))}
     );
       }}}}""".replace(
             "\n", " "

+ 7 - 7
reflex/event.py

@@ -153,7 +153,7 @@ class EventHandler(Base):
 
             # Otherwise, convert to JSON.
             try:
-                values.append(Var.create(arg, is_string=type(arg) is str))
+                values.append(Var.create(arg, _var_is_string=type(arg) is str))
             except TypeError as e:
                 raise TypeError(
                     f"Arguments to event handlers must be Vars or JSON-serializable. Got {arg} of type {type(arg)}."
@@ -211,7 +211,7 @@ class FrontendEvent(Base):
 
 
 # The default event argument.
-EVENT_ARG = BaseVar(name="_e", type_=FrontendEvent, is_local=True)
+EVENT_ARG = BaseVar(_var_name="_e", _var_type=FrontendEvent, _var_is_local=True)
 
 
 class FileUpload(Base):
@@ -241,7 +241,7 @@ def server_side(name: str, sig: inspect.Signature, **kwargs) -> EventSpec:
     return EventSpec(
         handler=EventHandler(fn=fn),
         args=tuple(
-            (Var.create_safe(k), Var.create_safe(v, is_string=type(v) is str))
+            (Var.create_safe(k), Var.create_safe(v, _var_is_string=type(v) is str))
             for k, v in kwargs.items()
         ),
     )
@@ -560,9 +560,9 @@ def parse_args_spec(arg_spec: ArgsSpec):
     return arg_spec(
         *[
             BaseVar(
-                name=f"_{l_arg}",
-                type_=spec.annotations.get(l_arg, FrontendEvent),
-                is_local=True,
+                _var_name=f"_{l_arg}",
+                _var_type=spec.annotations.get(l_arg, FrontendEvent),
+                _var_is_local=True,
             )
             for l_arg in spec.args
         ]
@@ -675,7 +675,7 @@ def fix_events(
             e = e()
         assert isinstance(e, EventSpec), f"Unexpected event type, {type(e)}."
         name = format.format_event_handler(e.handler)
-        payload = {k.name: v._decode() for k, v in e.args}  # type: ignore
+        payload = {k._var_name: v._decode() for k, v in e.args}  # type: ignore
 
         # Create an event and append it to the list.
         out.append(

+ 15 - 12
reflex/state.py

@@ -132,7 +132,7 @@ class State(Base, ABC, extra=pydantic.Extra.allow):
         )
         for cvar_name, cvar in self.computed_vars.items():
             # Add the dependencies.
-            for var in cvar.deps(objclass=type(self)):
+            for var in cvar._deps(objclass=type(self)):
                 self.computed_var_dependencies[var].add(cvar_name)
                 if var in inherited_vars:
                     # track that this substate depends on its parent for this var
@@ -211,12 +211,14 @@ class State(Base, ABC, extra=pydantic.Extra.allow):
 
         # Set the base and computed vars.
         cls.base_vars = {
-            f.name: BaseVar(name=f.name, type_=f.outer_type_).set_state(cls)
+            f.name: BaseVar(_var_name=f.name, _var_type=f.outer_type_)._var_set_state(
+                cls
+            )
             for f in cls.get_fields().values()
             if f.name not in cls.get_skip_vars()
         }
         cls.computed_vars = {
-            v.name: v.set_state(cls)
+            v._var_name: v._var_set_state(cls)
             for v in cls.__dict__.values()
             if isinstance(v, ComputedVar)
         }
@@ -389,12 +391,12 @@ class State(Base, ABC, extra=pydantic.Extra.allow):
         Raises:
             TypeError: if the variable has an incorrect type
         """
-        if not types.is_valid_var_type(prop.type_):
+        if not types.is_valid_var_type(prop._var_type):
             raise TypeError(
                 "State vars must be primitive Python types, "
                 "Plotly figures, Pandas dataframes, "
                 "or subclasses of rx.Base. "
-                f'Found var "{prop.name}" with type {prop.type_}.'
+                f'Found var "{prop._var_name}" with type {prop._var_type}.'
             )
         cls._set_var(prop)
         cls._create_setter(prop)
@@ -421,8 +423,8 @@ class State(Base, ABC, extra=pydantic.Extra.allow):
             )
 
         # create the variable based on name and type
-        var = BaseVar(name=name, type_=type_)
-        var.set_state(cls)
+        var = BaseVar(_var_name=name, _var_type=type_)
+        var._var_set_state(cls)
 
         # add the pydantic field dynamically (must be done before _init_var)
         cls.add_field(var, default_value)
@@ -444,7 +446,7 @@ class State(Base, ABC, extra=pydantic.Extra.allow):
         Args:
             prop: The var instance to set.
         """
-        setattr(cls, prop.name, prop)
+        setattr(cls, prop._var_name, prop)
 
     @classmethod
     def _create_setter(cls, prop: BaseVar):
@@ -467,7 +469,7 @@ class State(Base, ABC, extra=pydantic.Extra.allow):
             prop: The var to set the default value for.
         """
         # Get the pydantic field for the var.
-        field = cls.get_fields()[prop.name]
+        field = cls.get_fields()[prop._var_name]
         default_value = prop.get_default_value()
         if field.required and default_value is not None:
             field.required = False
@@ -599,8 +601,9 @@ class State(Base, ABC, extra=pydantic.Extra.allow):
                 func = arglist_factory(param)
             else:
                 continue
-            func.fget.__name__ = param  # to allow passing as a prop # type: ignore
-            cls.vars[param] = cls.computed_vars[param] = func.set_state(cls)  # type: ignore
+            # to allow passing as a prop
+            func._var_name = param
+            cls.vars[param] = cls.computed_vars[param] = func._var_set_state(cls)  # type: ignore
             setattr(cls, param, func)
 
     def __getattribute__(self, name: str) -> Any:
@@ -912,7 +915,7 @@ class State(Base, ABC, extra=pydantic.Extra.allow):
         return set(
             cvar_name
             for cvar_name, cvar in self.computed_vars.items()
-            if not cvar.cache
+            if not cvar._cache
         )
 
     def _mark_dirty_computed_vars(self) -> None:

+ 2 - 2
reflex/style.py

@@ -7,8 +7,8 @@ from reflex.event import EventChain
 from reflex.utils import format
 from reflex.vars import BaseVar, Var
 
-color_mode = BaseVar(name=constants.ColorMode.NAME, type_="str")
-toggle_color_mode = BaseVar(name=constants.ColorMode.TOGGLE, type_=EventChain)
+color_mode = BaseVar(_var_name=constants.ColorMode.NAME, _var_type="str")
+toggle_color_mode = BaseVar(_var_name=constants.ColorMode.TOGGLE, _var_type=EventChain)
 
 
 def convert(style_dict):

+ 15 - 0
reflex/testing.py

@@ -106,6 +106,7 @@ class AppHarness:
     app_instance: Optional[reflex.App] = None
     frontend_process: Optional[subprocess.Popen] = None
     frontend_url: Optional[str] = None
+    frontend_output_thread: Optional[threading.Thread] = None
     backend_thread: Optional[threading.Thread] = None
     backend: Optional[uvicorn.Server] = None
     state_manager: Optional[StateManagerMemory | StateManagerRedis] = None
@@ -230,6 +231,18 @@ class AppHarness:
         if self.frontend_url is None:
             raise RuntimeError("Frontend did not start")
 
+        def consume_frontend_output():
+            while True:
+                line = (
+                    self.frontend_process.stdout.readline()  # pyright: ignore [reportOptionalMemberAccess]
+                )
+                if not line:
+                    break
+                print(line)
+
+        self.frontend_output_thread = threading.Thread(target=consume_frontend_output)
+        self.frontend_output_thread.start()
+
     def start(self) -> "AppHarness":
         """Start the backend in a new thread and dev frontend as a separate process.
 
@@ -278,6 +291,8 @@ class AppHarness:
             self.frontend_process.communicate()
         if self.backend_thread is not None:
             self.backend_thread.join()
+        if self.frontend_output_thread is not None:
+            self.frontend_output_thread.join()
         for driver in self._frontends:
             driver.quit()
 

+ 28 - 19
reflex/utils/format.py

@@ -203,13 +203,13 @@ def format_var(var: Var) -> str:
     Returns:
         The formatted Var.
     """
-    if not var.is_local or var.is_string:
+    if not var._var_is_local or var._var_is_string:
         return str(var)
-    if types._issubclass(var.type_, str):
-        return format_string(var.full_name)
-    if is_wrapped(var.full_name, "{"):
-        return var.full_name
-    return json_dumps(var.full_name)
+    if types._issubclass(var._var_type, str):
+        return format_string(var._var_full_name)
+    if is_wrapped(var._var_full_name, "{"):
+        return var._var_full_name
+    return json_dumps(var._var_full_name)
 
 
 def format_route(route: str, format_case=True) -> str:
@@ -259,12 +259,16 @@ def format_cond(
 
     # Format prop conds.
     if is_prop:
-        prop1 = Var.create_safe(true_value, is_string=type(true_value) is str).set(
-            is_local=True
-        )  # type: ignore
-        prop2 = Var.create_safe(false_value, is_string=type(false_value) is str).set(
-            is_local=True
-        )  # type: ignore
+        prop1 = Var.create_safe(
+            true_value,
+            _var_is_string=type(true_value) is str,
+        )
+        prop1._var_is_local = True
+        prop2 = Var.create_safe(
+            false_value,
+            _var_is_string=type(false_value) is str,
+        )
+        prop2._var_is_local = True
         return f"{cond} ? {prop1} : {prop2}".replace("{", "").replace("}", "")
 
     # Format component conds.
@@ -292,11 +296,11 @@ def format_prop(
     try:
         # Handle var props.
         if isinstance(prop, Var):
-            if not prop.is_local or prop.is_string:
+            if not prop._var_is_local or prop._var_is_string:
                 return str(prop)
-            if types._issubclass(prop.type_, str):
-                return format_string(prop.full_name)
-            prop = prop.full_name
+            if types._issubclass(prop._var_type, str):
+                return format_string(prop._var_full_name)
+            prop = prop._var_full_name
 
         # Handle event props.
         elif isinstance(prop, EventChain):
@@ -414,7 +418,12 @@ def format_event(event_spec: EventSpec) -> str:
     args = ",".join(
         [
             ":".join(
-                (name.name, json.dumps(val.name) if val.is_string else val.full_name)
+                (
+                    name._var_name,
+                    json.dumps(val._var_name)
+                    if val._var_is_string
+                    else val._var_full_name,
+                )
             )
             for name, val in event_spec.args
         ]
@@ -448,7 +457,7 @@ def format_event_chain(
     if isinstance(event_chain, Var):
         from reflex.event import EventChain
 
-        if event_chain.type_ is not EventChain:
+        if event_chain._var_type is not EventChain:
             raise ValueError(f"Invalid event chain: {event_chain}")
         return "".join(
             [
@@ -540,7 +549,7 @@ def format_array_ref(refs: str, idx: Var | None) -> str:
     """
     clean_ref = re.sub(r"[^\w]+", "_", refs)
     if idx is not None:
-        idx.is_local = True
+        idx._var_is_local = True
         return f"refs_{clean_ref}[{idx}]"
     return f"refs_{clean_ref}"
 

+ 277 - 204
reflex/vars.py

@@ -2,11 +2,12 @@
 from __future__ import annotations
 
 import contextlib
+import dataclasses
 import dis
 import json
 import random
 import string
-from abc import ABC
+import sys
 from types import CodeType, FunctionType
 from typing import (
     TYPE_CHECKING,
@@ -64,6 +65,18 @@ OPERATION_MAPPING = {
     (list, list): {"+", ">", "<", "<=", ">="},
 }
 
+# These names were changed in reflex 0.3.0
+REPLACED_NAMES = {
+    "full_name": "_var_full_name",
+    "name": "_var_name",
+    "state": "_var_state",
+    "type_": "_var_type",
+    "is_local": "_var_is_local",
+    "is_string": "_var_is_string",
+    "set_state": "_var_set_state",
+    "deps": "_deps",
+}
+
 
 def get_unique_variable_name() -> str:
     """Get a unique variable name.
@@ -78,34 +91,34 @@ def get_unique_variable_name() -> str:
     return get_unique_variable_name()
 
 
-class Var(ABC):
+class Var:
     """An abstract var."""
 
     # The name of the var.
-    name: str
+    _var_name: str
 
     # The type of the var.
-    type_: Type
+    _var_type: Type
 
     # The name of the enclosing state.
-    state: str = ""
+    _var_state: str
 
     # Whether this is a local javascript variable.
-    is_local: bool = False
+    _var_is_local: bool
 
     # Whether the var is a string literal.
-    is_string: bool = False
+    _var_is_string: bool
 
     @classmethod
     def create(
-        cls, value: Any, is_local: bool = True, is_string: bool = False
+        cls, value: Any, _var_is_local: bool = True, _var_is_string: bool = False
     ) -> Var | None:
         """Create a var from a value.
 
         Args:
             value: The value to create the var from.
-            is_local: Whether the var is local.
-            is_string: Whether the var is a string literal.
+            _var_is_local: Whether the var is local.
+            _var_is_string: Whether the var is a string literal.
 
         Returns:
             The var.
@@ -130,23 +143,32 @@ class Var(ABC):
             )
         name = name if isinstance(name, str) else format.json_dumps(name)
 
-        return BaseVar(name=name, type_=type_, is_local=is_local, is_string=is_string)
+        return BaseVar(
+            _var_name=name,
+            _var_type=type_,
+            _var_is_local=_var_is_local,
+            _var_is_string=_var_is_string,
+        )
 
     @classmethod
     def create_safe(
-        cls, value: Any, is_local: bool = True, is_string: bool = False
+        cls, value: Any, _var_is_local: bool = True, _var_is_string: bool = False
     ) -> Var:
-        """Create a var from a value, guaranteeing that it is not None.
+        """Create a var from a value, asserting that it is not None.
 
         Args:
             value: The value to create the var from.
-            is_local: Whether the var is local.
-            is_string: Whether the var is a string literal.
+            _var_is_local: Whether the var is local.
+            _var_is_string: Whether the var is a string literal.
 
         Returns:
             The var.
         """
-        var = cls.create(value, is_local=is_local, is_string=is_string)
+        var = cls.create(
+            value,
+            _var_is_local=_var_is_local,
+            _var_is_string=_var_is_string,
+        )
         assert var is not None
         return var
 
@@ -171,14 +193,14 @@ class Var(ABC):
         Returns:
             The decoded value or the Var name.
         """
-        if self.state:
-            return self.full_name
-        if self.is_string:
-            return self.name
+        if self._var_state:
+            return self._var_full_name
+        if self._var_is_string:
+            return self._var_name
         try:
-            return json.loads(self.name)
+            return json.loads(self._var_name)
         except ValueError:
-            return self.name
+            return self._var_name
 
     def equals(self, other: Var) -> bool:
         """Check if two vars are equal.
@@ -190,10 +212,10 @@ class Var(ABC):
             Whether the vars are equal.
         """
         return (
-            self.name == other.name
-            and self.type_ == other.type_
-            and self.state == other.state
-            and self.is_local == other.is_local
+            self._var_name == other._var_name
+            and self._var_type == other._var_type
+            and self._var_state == other._var_state
+            and self._var_is_local == other._var_is_local
         )
 
     def to_string(self, json: bool = True) -> Var:
@@ -214,7 +236,7 @@ class Var(ABC):
         Returns:
             The hash of the var.
         """
-        return hash((self.name, str(self.type_)))
+        return hash((self._var_name, str(self._var_type)))
 
     def __str__(self) -> str:
         """Wrap the var so it can be used in templates.
@@ -222,8 +244,12 @@ class Var(ABC):
         Returns:
             The wrapped var, i.e. {state.var}.
         """
-        out = self.full_name if self.is_local else format.wrap(self.full_name, "{")
-        if self.is_string:
+        out = (
+            self._var_full_name
+            if self._var_is_local
+            else format.wrap(self._var_full_name, "{")
+        )
+        if self._var_is_string:
             out = format.format_string(out)
         return out
 
@@ -234,7 +260,7 @@ class Var(ABC):
             TypeError: when attempting to bool-ify the Var.
         """
         raise TypeError(
-            f"Cannot convert Var {self.full_name!r} to bool for use with `if`, `and`, `or`, and `not`. "
+            f"Cannot convert Var {self._var_full_name!r} to bool for use with `if`, `and`, `or`, and `not`. "
             "Instead use `rx.cond` and bitwise operators `&` (and), `|` (or), `~` (invert)."
         )
 
@@ -245,7 +271,7 @@ class Var(ABC):
             TypeError: when attempting to iterate over the Var.
         """
         raise TypeError(
-            f"Cannot iterate over Var {self.full_name!r}. Instead use `rx.foreach`."
+            f"Cannot iterate over Var {self._var_full_name!r}. Instead use `rx.foreach`."
         )
 
     def __format__(self, format_spec: str) -> str:
@@ -257,7 +283,7 @@ class Var(ABC):
         Returns:
             The formatted var.
         """
-        if self.is_local:
+        if self._var_is_local:
             return str(self)
         return f"${str(self)}"
 
@@ -275,16 +301,16 @@ class Var(ABC):
         """
         # Indexing is only supported for strings, lists, tuples, dicts, and dataframes.
         if not (
-            types._issubclass(self.type_, Union[List, Dict, Tuple, str])
-            or types.is_dataframe(self.type_)
+            types._issubclass(self._var_type, Union[List, Dict, Tuple, str])
+            or types.is_dataframe(self._var_type)
         ):
-            if self.type_ == Any:
+            if self._var_type == Any:
                 raise TypeError(
                     "Could not index into var of type Any. (If you are trying to index into a state var, "
                     "add the correct type annotation to the var.)"
                 )
             raise TypeError(
-                f"Var {self.name} of type {self.type_} does not support indexing."
+                f"Var {self._var_name} of type {self._var_type} does not support indexing."
             )
 
         # The type of the indexed var.
@@ -292,15 +318,20 @@ class Var(ABC):
 
         # Convert any vars to local vars.
         if isinstance(i, Var):
-            i = BaseVar(name=i.name, type_=i.type_, state=i.state, is_local=True)
+            i = BaseVar(
+                _var_name=i._var_name,
+                _var_type=i._var_type,
+                _var_state=i._var_state,
+                _var_is_local=True,
+            )
 
         # Handle list/tuple/str indexing.
-        if types._issubclass(self.type_, Union[List, Tuple, str]):
+        if types._issubclass(self._var_type, Union[List, Tuple, str]):
             # List/Tuple/String indices must be ints, slices, or vars.
             if (
                 not isinstance(i, types.get_args(Union[int, slice, Var]))
                 or isinstance(i, Var)
-                and not i.type_ == int
+                and not i._var_type == int
             ):
                 raise TypeError("Index must be an integer or an integer var.")
 
@@ -312,35 +343,40 @@ class Var(ABC):
 
                 # Use the slice function.
                 return BaseVar(
-                    name=f"{self.name}.slice({start}, {stop})",
-                    type_=self.type_,
-                    state=self.state,
-                    is_local=self.is_local,
+                    _var_name=f"{self._var_name}.slice({start}, {stop})",
+                    _var_type=self._var_type,
+                    _var_state=self._var_state,
+                    _var_is_local=self._var_is_local,
                 )
 
             # Get the type of the indexed var.
             type_ = (
-                types.get_args(self.type_)[0]
-                if types.is_generic_alias(self.type_)
+                types.get_args(self._var_type)[0]
+                if types.is_generic_alias(self._var_type)
                 else Any
             )
 
             # Use `at` to support negative indices.
             return BaseVar(
-                name=f"{self.name}.at({i})",
-                type_=type_,
-                state=self.state,
-                is_local=self.is_local,
+                _var_name=f"{self._var_name}.at({i})",
+                _var_type=type_,
+                _var_state=self._var_state,
+                _var_is_local=self._var_is_local,
             )
 
         # Dictionary / dataframe indexing.
         # Tuples are currently not supported as indexes.
         if (
-            (types._issubclass(self.type_, Dict) or types.is_dataframe(self.type_))
+            (
+                types._issubclass(self._var_type, Dict)
+                or types.is_dataframe(self._var_type)
+            )
             and not isinstance(i, types.get_args(Union[int, str, float, Var]))
         ) or (
             isinstance(i, Var)
-            and not types._issubclass(i.type_, types.get_args(Union[int, str, float]))
+            and not types._issubclass(
+                i._var_type, types.get_args(Union[int, str, float])
+            )
         ):
             raise TypeError(
                 "Index must be one of the following types: int, str, int or str Var"
@@ -349,18 +385,20 @@ class Var(ABC):
         if isinstance(i, str):
             i = format.wrap(i, '"')
         type_ = (
-            types.get_args(self.type_)[1] if types.is_generic_alias(self.type_) else Any
+            types.get_args(self._var_type)[1]
+            if types.is_generic_alias(self._var_type)
+            else Any
         )
 
         # Use normal indexing here.
         return BaseVar(
-            name=f"{self.name}[{i}]",
-            type_=type_,
-            state=self.state,
-            is_local=self.is_local,
+            _var_name=f"{self._var_name}[{i}]",
+            _var_type=type_,
+            _var_state=self._var_state,
+            _var_is_local=self._var_is_local,
         )
 
-    def __getattribute__(self, name: str) -> Var:
+    def __getattr__(self, name: str) -> Var:
         """Get a var attribute.
 
         Args:
@@ -373,30 +411,39 @@ class Var(ABC):
             AttributeError: If the var is wrongly annotated or can't find attribute.
             TypeError: If an annotation to the var isn't provided.
         """
-        try:
-            return super().__getattribute__(name)
-        except Exception as e:
-            # Check if the attribute is one of the class fields.
-            if not name.startswith("_"):
-                if self.type_ == Any:
-                    raise TypeError(
-                        f"You must provide an annotation for the state var `{self.full_name}`. Annotation cannot be `{self.type_}`"
-                    ) from None
-                if hasattr(self.type_, "__fields__") and name in self.type_.__fields__:
-                    type_ = self.type_.__fields__[name].outer_type_
-                    if isinstance(type_, ModelField):
-                        type_ = type_.type_
-                    return BaseVar(
-                        name=f"{self.name}.{name}",
-                        type_=type_,
-                        state=self.state,
-                        is_local=self.is_local,
-                    )
+        # Check if the attribute is one of the class fields.
+        if not name.startswith("_"):
+            if self._var_type == Any:
+                raise TypeError(
+                    f"You must provide an annotation for the state var `{self._var_full_name}`. Annotation cannot be `{self._var_type}`"
+                ) from None
+            if (
+                hasattr(self._var_type, "__fields__")
+                and name in self._var_type.__fields__
+            ):
+                type_ = self._var_type.__fields__[name].outer_type_
+                if isinstance(type_, ModelField):
+                    type_ = type_.type_
+                return BaseVar(
+                    _var_name=f"{self._var_name}.{name}",
+                    _var_type=type_,
+                    _var_state=self._var_state,
+                    _var_is_local=self._var_is_local,
+                )
+
+            if name in REPLACED_NAMES:
+                raise AttributeError(
+                    f"Field {name!r} was renamed to {REPLACED_NAMES[name]!r}"
+                )
+
             raise AttributeError(
-                f"The State var `{self.full_name}` has no attribute '{name}' or may have been annotated "
-                f"wrongly.\n"
-                f"original message: {e.args[0]}"
-            ) from e
+                f"The State var `{self._var_full_name}` has no attribute '{name}' or may have been annotated "
+                f"wrongly."
+            )
+
+        raise AttributeError(
+            f"The State var has no attribute '{name}' or may have been annotated wrongly.",
+        )
 
     def operation(
         self,
@@ -429,7 +476,7 @@ class Var(ABC):
         else:
             other = Var.create(other)
 
-        type_ = type_ or self.type_
+        type_ = type_ or self._var_type
 
         if other is None and flip:
             raise ValueError(
@@ -441,42 +488,42 @@ class Var(ABC):
         if other is not None:
             # check if the operation between operands is valid.
             if op and not self.is_valid_operation(
-                types.get_base_class(left_operand.type_),  # type: ignore
-                types.get_base_class(right_operand.type_),  # type: ignore
+                types.get_base_class(left_operand._var_type),  # type: ignore
+                types.get_base_class(right_operand._var_type),  # type: ignore
                 op,
             ):
                 raise TypeError(
-                    f"Unsupported Operand type(s) for {op}: `{left_operand.full_name}` of type {left_operand.type_.__name__} and `{right_operand.full_name}` of type {right_operand.type_.__name__}"  # type: ignore
+                    f"Unsupported Operand type(s) for {op}: `{left_operand._var_full_name}` of type {left_operand._var_type.__name__} and `{right_operand._var_full_name}` of type {right_operand._var_type.__name__}"  # type: ignore
                 )
 
             # apply function to operands
             if fn is not None:
                 if invoke_fn:
                     # invoke the function on left operand.
-                    operation_name = f"{left_operand.full_name}.{fn}({right_operand.full_name})"  # type: ignore
+                    operation_name = f"{left_operand._var_full_name}.{fn}({right_operand._var_full_name})"  # type: ignore
                 else:
                     # pass the operands as arguments to the function.
-                    operation_name = f"{left_operand.full_name} {op} {right_operand.full_name}"  # type: ignore
+                    operation_name = f"{left_operand._var_full_name} {op} {right_operand._var_full_name}"  # type: ignore
                     operation_name = f"{fn}({operation_name})"
             else:
                 # apply operator to operands (left operand <operator> right_operand)
-                operation_name = f"{left_operand.full_name} {op} {right_operand.full_name}"  # type: ignore
+                operation_name = f"{left_operand._var_full_name} {op} {right_operand._var_full_name}"  # type: ignore
                 operation_name = format.wrap(operation_name, "(")
         else:
             # apply operator to left operand (<operator> left_operand)
-            operation_name = f"{op}{self.full_name}"
+            operation_name = f"{op}{self._var_full_name}"
             # apply function to operands
             if fn is not None:
                 operation_name = (
                     f"{fn}({operation_name})"
                     if not invoke_fn
-                    else f"{self.full_name}.{fn}()"
+                    else f"{self._var_full_name}.{fn}()"
                 )
 
         return BaseVar(
-            name=operation_name,
-            type_=type_,
-            is_local=self.is_local,
+            _var_name=operation_name,
+            _var_type=type_,
+            _var_is_local=self._var_is_local,
         )
 
     @staticmethod
@@ -554,12 +601,12 @@ class Var(ABC):
         Raises:
             TypeError: If the var is not a list.
         """
-        if not types._issubclass(self.type_, List):
+        if not types._issubclass(self._var_type, List):
             raise TypeError(f"Cannot get length of non-list var {self}.")
         return BaseVar(
-            name=f"{self.full_name}.length",
-            type_=int,
-            is_local=self.is_local,
+            _var_name=f"{self._var_full_name}.length",
+            _var_type=int,
+            _var_is_local=self._var_is_local,
         )
 
     def __eq__(self, other: Var) -> Var:
@@ -638,12 +685,12 @@ class Var(ABC):
         Returns:
             A var representing the sum.
         """
-        other_type = other.type_ if isinstance(other, Var) else type(other)
+        other_type = other._var_type if isinstance(other, Var) else type(other)
         # For list-list addition, javascript concatenates the content of the lists instead of
         # merging the list, and for that reason we use the spread operator available through spreadArraysOrObjects
         # utility function
         if (
-            types.get_base_class(self.type_) == list
+            types.get_base_class(self._var_type) == list
             and types.get_base_class(other_type) == list
         ):
             return self.operation(",", other, fn="spreadArraysOrObjects", flip=flip)
@@ -692,10 +739,10 @@ class Var(ABC):
         Returns:
             A var representing the product.
         """
-        other_type = other.type_ if isinstance(other, Var) else type(other)
+        other_type = other._var_type if isinstance(other, Var) else type(other)
         # For str-int multiplication, we use the repeat function.
         # i.e "hello" * 2 is equivalent to "hello".repeat(2) in js.
-        if (types.get_base_class(self.type_), types.get_base_class(other_type)) in [
+        if (types.get_base_class(self._var_type), types.get_base_class(other_type)) in [
             (int, str),
             (str, int),
         ]:
@@ -703,16 +750,16 @@ class Var(ABC):
 
         # For list-int multiplication, we use the Array function.
         # i.e ["hello"] * 2 is equivalent to Array(2).fill().map(() => ["hello"]).flat() in js.
-        if (types.get_base_class(self.type_), types.get_base_class(other_type)) in [
+        if (types.get_base_class(self._var_type), types.get_base_class(other_type)) in [
             (int, list),
             (list, int),
         ]:
-            other_name = other.full_name if isinstance(other, Var) else other
-            name = f"Array({other_name}).fill().map(() => {self.full_name}).flat()"
+            other_name = other._var_full_name if isinstance(other, Var) else other
+            name = f"Array({other_name}).fill().map(() => {self._var_full_name}).flat()"
             return BaseVar(
-                name=name,
-                type_=str,
-                is_local=self.is_local,
+                _var_name=name,
+                _var_type=str,
+                _var_is_local=self._var_is_local,
             )
 
         return self.operation("*", other)
@@ -830,7 +877,7 @@ class Var(ABC):
         >>> var1 = Var.create(True)
         >>> var2 = Var.create(False)
         >>> js_code = var1 & var2
-        >>> print(js_code.full_name)
+        >>> print(js_code._var_full_name)
         '(true && false)'
         """
         return self.operation("&&", other, type_=bool)
@@ -860,7 +907,7 @@ class Var(ABC):
         >>> var1 = Var.create(True)
         >>> var2 = Var.create(False)
         >>> js_code = var1 & var2
-        >>> print(js_code.full_name)
+        >>> print(js_code._var_full_name)
         '(false && true)'
         """
         return self.operation("&&", other, type_=bool, flip=True)
@@ -888,7 +935,7 @@ class Var(ABC):
         >>> var1 = Var.create(True)
         >>> var2 = Var.create(False)
         >>> js_code = var1 | var2
-        >>> print(js_code.full_name)
+        >>> print(js_code._var_full_name)
         '(true || false)'
         """
         return self.operation("||", other, type_=bool)
@@ -943,35 +990,37 @@ class Var(ABC):
         Returns:
             A var representing the contain check.
         """
-        if not (types._issubclass(self.type_, Union[dict, list, tuple, str])):
+        if not (types._issubclass(self._var_type, Union[dict, list, tuple, str])):
             raise TypeError(
-                f"Var {self.full_name} of type {self.type_} does not support contains check."
+                f"Var {self._var_full_name} of type {self._var_type} does not support contains check."
             )
         method = (
-            "hasOwnProperty" if types.get_base_class(self.type_) == dict else "includes"
+            "hasOwnProperty"
+            if types.get_base_class(self._var_type) == dict
+            else "includes"
         )
         if isinstance(other, str):
-            other = Var.create(json.dumps(other), is_string=True)
+            other = Var.create(json.dumps(other), _var_is_string=True)
         elif not isinstance(other, Var):
             other = Var.create(other)
-        if types._issubclass(self.type_, Dict):
+        if types._issubclass(self._var_type, Dict):
             return BaseVar(
-                name=f"{self.full_name}.{method}({other.full_name})",
-                type_=bool,
-                is_local=self.is_local,
+                _var_name=f"{self._var_full_name}.{method}({other._var_full_name})",
+                _var_type=bool,
+                _var_is_local=self._var_is_local,
             )
         else:  # str, list, tuple
             # For strings, the left operand must be a string.
-            if types._issubclass(self.type_, str) and not types._issubclass(
-                other.type_, str
+            if types._issubclass(self._var_type, str) and not types._issubclass(
+                other._var_type, str
             ):
                 raise TypeError(
-                    f"'in <string>' requires string as left operand, not {other.type_}"
+                    f"'in <string>' requires string as left operand, not {other._var_type}"
                 )
             return BaseVar(
-                name=f"{self.full_name}.includes({other.full_name})",
-                type_=bool,
-                is_local=self.is_local,
+                _var_name=f"{self._var_full_name}.includes({other._var_full_name})",
+                _var_type=bool,
+                _var_is_local=self._var_is_local,
             )
 
     def reverse(self) -> Var:
@@ -983,13 +1032,13 @@ class Var(ABC):
         Returns:
             A var with the reversed list.
         """
-        if not types._issubclass(self.type_, list):
-            raise TypeError(f"Cannot reverse non-list var {self.full_name}.")
+        if not types._issubclass(self._var_type, list):
+            raise TypeError(f"Cannot reverse non-list var {self._var_full_name}.")
 
         return BaseVar(
-            name=f"[...{self.full_name}].reverse()",
-            type_=self.type_,
-            is_local=self.is_local,
+            _var_name=f"[...{self._var_full_name}].reverse()",
+            _var_type=self._var_type,
+            _var_is_local=self._var_is_local,
         )
 
     def lower(self) -> Var:
@@ -1001,15 +1050,15 @@ class Var(ABC):
         Raises:
             TypeError: If the var is not a string.
         """
-        if not types._issubclass(self.type_, str):
+        if not types._issubclass(self._var_type, str):
             raise TypeError(
-                f"Cannot convert non-string var {self.full_name} to lowercase."
+                f"Cannot convert non-string var {self._var_full_name} to lowercase."
             )
 
         return BaseVar(
-            name=f"{self.full_name}.toLowerCase()",
-            type_=str,
-            is_local=self.is_local,
+            _var_name=f"{self._var_full_name}.toLowerCase()",
+            _var_type=str,
+            _var_is_local=self._var_is_local,
         )
 
     def upper(self) -> Var:
@@ -1021,15 +1070,15 @@ class Var(ABC):
         Raises:
             TypeError: If the var is not a string.
         """
-        if not types._issubclass(self.type_, str):
+        if not types._issubclass(self._var_type, str):
             raise TypeError(
-                f"Cannot convert non-string var {self.full_name} to uppercase."
+                f"Cannot convert non-string var {self._var_full_name} to uppercase."
             )
 
         return BaseVar(
-            name=f"{self.full_name}.toUpperCase()",
-            type_=str,
-            is_local=self.is_local,
+            _var_name=f"{self._var_full_name}.toUpperCase()",
+            _var_type=str,
+            _var_is_local=self._var_is_local,
         )
 
     def split(self, other: str | Var[str] = " ") -> Var:
@@ -1044,15 +1093,15 @@ class Var(ABC):
         Raises:
             TypeError: If the var is not a string.
         """
-        if not types._issubclass(self.type_, str):
-            raise TypeError(f"Cannot split non-string var {self.full_name}.")
+        if not types._issubclass(self._var_type, str):
+            raise TypeError(f"Cannot split non-string var {self._var_full_name}.")
 
         other = Var.create_safe(json.dumps(other)) if isinstance(other, str) else other
 
         return BaseVar(
-            name=f"{self.full_name}.split({other.full_name})",
-            type_=list[str],
-            is_local=self.is_local,
+            _var_name=f"{self._var_full_name}.split({other._var_full_name})",
+            _var_type=list[str],
+            _var_is_local=self._var_is_local,
         )
 
     def join(self, other: str | Var[str] | None = None) -> Var:
@@ -1067,8 +1116,8 @@ class Var(ABC):
         Raises:
             TypeError: If the var is not a list.
         """
-        if not types._issubclass(self.type_, list):
-            raise TypeError(f"Cannot join non-list var {self.full_name}.")
+        if not types._issubclass(self._var_type, list):
+            raise TypeError(f"Cannot join non-list var {self._var_full_name}.")
 
         if other is None:
             other = Var.create_safe("")
@@ -1078,9 +1127,9 @@ class Var(ABC):
             other = Var.create_safe(other)
 
         return BaseVar(
-            name=f"{self.full_name}.join({other.full_name})",
-            type_=str,
-            is_local=self.is_local,
+            _var_name=f"{self._var_full_name}.join({other._var_full_name})",
+            _var_type=str,
+            _var_is_local=self._var_is_local,
         )
 
     def foreach(self, fn: Callable) -> Var:
@@ -1093,13 +1142,13 @@ class Var(ABC):
             A var representing foreach operation.
         """
         arg = BaseVar(
-            name=get_unique_variable_name(),
-            type_=self.type_,
+            _var_name=get_unique_variable_name(),
+            _var_type=self._var_type,
         )
         return BaseVar(
-            name=f"{self.full_name}.map(({arg.name}, i) => {fn(arg, key='i')})",
-            type_=self.type_,
-            is_local=self.is_local,
+            _var_name=f"{self._var_full_name}.map(({arg._var_name}, i) => {fn(arg, key='i')})",
+            _var_type=self._var_type,
+            _var_is_local=self._var_is_local,
         )
 
     def to(self, type_: Type) -> Var:
@@ -1112,22 +1161,26 @@ class Var(ABC):
             The converted var.
         """
         return BaseVar(
-            name=self.name,
-            type_=type_,
-            state=self.state,
-            is_local=self.is_local,
+            _var_name=self._var_name,
+            _var_type=type_,
+            _var_state=self._var_state,
+            _var_is_local=self._var_is_local,
         )
 
     @property
-    def full_name(self) -> str:
+    def _var_full_name(self) -> str:
         """Get the full name of the var.
 
         Returns:
             The full name of the var.
         """
-        return self.name if self.state == "" else ".".join([self.state, self.name])
+        return (
+            self._var_name
+            if self._var_state == ""
+            else ".".join([self._var_state, self._var_name])
+        )
 
-    def set_state(self, state: Type[State]) -> Any:
+    def _var_set_state(self, state: Type[State]) -> Any:
         """Set the state of the var.
 
         Args:
@@ -1136,27 +1189,31 @@ class Var(ABC):
         Returns:
             The var with the set state.
         """
-        self.state = state.get_full_name()
+        self._var_state = state.get_full_name()
         return self
 
 
-class BaseVar(Var, Base):
+@dataclasses.dataclass(
+    eq=False,
+    **{"slots": True} if sys.version_info >= (3, 10) else {},
+)
+class BaseVar(Var):
     """A base (non-computed) var of the app state."""
 
     # The name of the var.
-    name: str
+    _var_name: str = dataclasses.field()
 
     # The type of the var.
-    type_: Any
+    _var_type: Type = dataclasses.field(default=Any)
 
     # The name of the enclosing state.
-    state: str = ""
+    _var_state: str = dataclasses.field(default="")
 
     # Whether this is a local javascript variable.
-    is_local: bool = False
+    _var_is_local: bool = dataclasses.field(default=False)
 
-    # Whether this var is a raw string.
-    is_string: bool = False
+    # Whether the var is a string literal.
+    _var_is_string: bool = dataclasses.field(default=False)
 
     def __hash__(self) -> int:
         """Define a hash function for a var.
@@ -1164,7 +1221,7 @@ class BaseVar(Var, Base):
         Returns:
             The hash of the var.
         """
-        return hash((self.name, str(self.type_)))
+        return hash((self._var_name, str(self._var_type)))
 
     def get_default_value(self) -> Any:
         """Get the default value of the var.
@@ -1176,7 +1233,9 @@ class BaseVar(Var, Base):
             ImportError: If the var is a dataframe and pandas is not installed.
         """
         type_ = (
-            self.type_.__origin__ if types.is_generic_alias(self.type_) else self.type_
+            self._var_type.__origin__
+            if types.is_generic_alias(self._var_type)
+            else self._var_type
         )
         if issubclass(type_, str):
             return ""
@@ -1210,10 +1269,10 @@ class BaseVar(Var, Base):
         Returns:
             The name of the setter function.
         """
-        setter = constants.SETTER_PREFIX + self.name
-        if not include_state or self.state == "":
+        setter = constants.SETTER_PREFIX + self._var_name
+        if not include_state or self._var_state == "":
             return setter
-        return ".".join((self.state, setter))
+        return ".".join((self._var_state, setter))
 
     def get_setter(self) -> Callable[[State, Any], None]:
         """Get the var's setter function.
@@ -1229,46 +1288,59 @@ class BaseVar(Var, Base):
                 state: The state within which we add the setter function.
                 value: The value to set.
             """
-            if self.type_ in [int, float]:
+            if self._var_type in [int, float]:
                 try:
-                    value = self.type_(value)
-                    setattr(state, self.name, value)
+                    value = self._var_type(value)
+                    setattr(state, self._var_name, value)
                 except ValueError:
                     console.warn(
-                        f"{self.name}: Failed conversion of {value} to '{self.type_.__name__}'. Value not set.",
+                        f"{self._var_name}: Failed conversion of {value} to '{self._var_type.__name__}'. Value not set.",
                     )
             else:
-                setattr(state, self.name, value)
+                setattr(state, self._var_name, value)
 
         setter.__qualname__ = self.get_setter_name()
 
         return setter
 
 
+@dataclasses.dataclass(init=False, eq=False)
 class ComputedVar(Var, property):
     """A field with computed getters."""
 
     # Whether to track dependencies and cache computed values
-    cache: bool = False
+    _cache: bool = dataclasses.field(default=False)
 
-    @property
-    def name(self) -> str:
-        """Get the name of the var.
+    def __init__(
+        self,
+        fget: Callable[[State], Any],
+        fset: Callable[[State, Any], None] | None = None,
+        fdel: Callable[[State], Any] | None = None,
+        doc: str | None = None,
+        **kwargs,
+    ):
+        """Initialize a ComputedVar.
 
-        Returns:
-            The name of the var.
+        Args:
+            fget: The getter function.
+            fset: The setter function.
+            fdel: The deleter function.
+            doc: The docstring.
+            **kwargs: additional attributes to set on the instance
         """
-        assert self.fget is not None, "Var must have a getter."
-        return self.fget.__name__
+        property.__init__(self, fget, fset, fdel, doc)
+        kwargs["_var_name"] = kwargs.pop("_var_name", fget.__name__)
+        kwargs["_var_type"] = kwargs.pop("_var_type", self._determine_var_type())
+        BaseVar.__init__(self, **kwargs)  # type: ignore
 
     @property
-    def cache_attr(self) -> str:
+    def _cache_attr(self) -> str:
         """Get the attribute used to cache the value on the instance.
 
         Returns:
             An attribute name.
         """
-        return f"__cached_{self.name}"
+        return f"__cached_{self._var_name}"
 
     def __get__(self, instance, owner):
         """Get the ComputedVar value.
@@ -1282,15 +1354,15 @@ class ComputedVar(Var, property):
         Returns:
             The value of the var for the given instance.
         """
-        if instance is None or not self.cache:
+        if instance is None or not self._cache:
             return super().__get__(instance, owner)
 
         # handle caching
-        if not hasattr(instance, self.cache_attr):
-            setattr(instance, self.cache_attr, super().__get__(instance, owner))
-        return getattr(instance, self.cache_attr)
+        if not hasattr(instance, self._cache_attr):
+            setattr(instance, self._cache_attr, super().__get__(instance, owner))
+        return getattr(instance, self._cache_attr)
 
-    def deps(
+    def _deps(
         self,
         objclass: Type,
         obj: FunctionType | CodeType | None = None,
@@ -1348,7 +1420,7 @@ class ComputedVar(Var, property):
             elif self_is_top_of_stack and instruction.opname == "LOAD_METHOD":
                 # method call on self
                 d.update(
-                    self.deps(
+                    self._deps(
                         objclass=objclass,
                         obj=getattr(objclass, instruction.argval),
                     )
@@ -1359,7 +1431,7 @@ class ComputedVar(Var, property):
                 # recurse into nested functions / comprehensions, which can reference
                 # instance attributes from the outer scope
                 d.update(
-                    self.deps(
+                    self._deps(
                         objclass=objclass,
                         obj=instruction.argval,
                         self_name=self_name,
@@ -1375,10 +1447,9 @@ class ComputedVar(Var, property):
             instance: the state instance that needs to recompute the value.
         """
         with contextlib.suppress(AttributeError):
-            delattr(instance, self.cache_attr)
+            delattr(instance, self._cache_attr)
 
-    @property
-    def type_(self):
+    def _determine_var_type(self) -> Type:
         """Get the type of the var.
 
         Returns:
@@ -1403,7 +1474,7 @@ def cached_var(fget: Callable[[Any], Any]) -> ComputedVar:
         ComputedVar that is recomputed when dependencies change.
     """
     cvar = ComputedVar(fget=fget)
-    cvar.cache = True
+    cvar._cache = True
     return cvar
 
 
@@ -1468,11 +1539,13 @@ def get_local_storage(key: Var | str | None = None) -> BaseVar:
         removal_version="0.3.0",
     )
     if key is not None:
-        if not (isinstance(key, Var) and key.type_ == str) and not isinstance(key, str):
-            type_ = type(key) if not isinstance(key, Var) else key.type_
+        if not (isinstance(key, Var) and key._var_type == str) and not isinstance(
+            key, str
+        ):
+            type_ = type(key) if not isinstance(key, Var) else key._var_type
             raise TypeError(
                 f"Local storage keys can only be of type `str` or `var` of type `str`. Got `{type_}` instead."
             )
-        key = key.full_name if isinstance(key, Var) else format.wrap(key, "'")
-        return BaseVar(name=f"localStorage.getItem({key})", type_=str)
-    return BaseVar(name="getAllLocalStorageItems()", type_=Dict)
+        key = key._var_full_name if isinstance(key, Var) else format.wrap(key, "'")
+        return BaseVar(_var_name=f"localStorage.getItem({key})", _var_type=str)
+    return BaseVar(_var_name="getAllLocalStorageItems()", _var_type=Dict)

+ 24 - 24
reflex/vars.pyi

@@ -1,7 +1,7 @@
 """ Generated with stubgen from mypy, then manually edited, do not regen."""
 
+from dataclasses import dataclass
 from _typeshed import Incomplete
-from abc import ABC
 from reflex import constants as constants
 from reflex.base import Base as Base
 from reflex.state import State as State
@@ -23,19 +23,19 @@ USED_VARIABLES: Incomplete
 
 def get_unique_variable_name() -> str: ...
 
-class Var(ABC):
-    name: str
-    type_: Type
-    state: str = ""
-    is_local: bool = False
-    is_string: bool = False
+class Var:
+    _var_name: str
+    _var_type: Type
+    _var_state: str = ""
+    _var_is_local: bool = False
+    _var_is_string: bool = False
     @classmethod
     def create(
-        cls, value: Any, is_local: bool = False, is_string: bool = False
+        cls, value: Any, _var_is_local: bool = False, _var_is_string: bool = False
     ) -> Optional[Var]: ...
     @classmethod
     def create_safe(
-        cls, value: Any, is_local: bool = False, is_string: bool = False
+        cls, value: Any, _var_is_local: bool = False, _var_is_string: bool = False
     ) -> Var: ...
     @classmethod
     def __class_getitem__(cls, type_: str) -> _GenericAlias: ...
@@ -87,31 +87,31 @@ class Var(ABC):
     def foreach(self, fn: Callable) -> Var: ...
     def to(self, type_: Type) -> Var: ...
     @property
-    def full_name(self) -> str: ...
-    def set_state(self, state: Type[State]) -> Any: ...
+    def _var_full_name(self) -> str: ...
+    def _var_set_state(self, state: Type[State]) -> Any: ...
 
-class BaseVar(Var, Base):
-    name: str
-    type_: Any
-    state: str = ""
-    is_local: bool = False
-    is_string: bool = False
+@dataclass(eq=False)
+class BaseVar(Var):
+    _var_name: str
+    _var_type: Any
+    _var_state: str = ""
+    _var_is_local: bool = False
+    _var_is_string: bool = False
     def __hash__(self) -> int: ...
     def get_default_value(self) -> Any: ...
     def get_setter_name(self, include_state: bool = ...) -> str: ...
     def get_setter(self) -> Callable[[State, Any], None]: ...
 
+@dataclass(init=False)
 class ComputedVar(Var):
-    cache: bool
+    _var_cache: bool
+    fget: FunctionType
     @property
-    def name(self) -> str: ...
-    @property
-    def cache_attr(self) -> str: ...
+    def _cache_attr(self) -> str: ...
     def __get__(self, instance, owner): ...
-    def deps(self, objclass: Type, obj: Optional[FunctionType] = ...) -> Set[str]: ...
+    def _deps(self, objclass: Type, obj: Optional[FunctionType] = ...) -> Set[str]: ...
     def mark_dirty(self, instance) -> None: ...
-    @property
-    def type_(self): ...
+    def _determine_var_type(self) -> Type: ...
     def __init__(self, func) -> None: ...
 
 def cached_var(fget: Callable[[Any], Any]) -> ComputedVar: ...

+ 1 - 1
tests/components/datadisplay/test_datatable.py

@@ -34,7 +34,7 @@ def test_validate_data_table(data_table_state: rx.Var, expected):
         expected: expected var name.
 
     """
-    if not types.is_dataframe(data_table_state.data.type_):
+    if not types.is_dataframe(data_table_state.data._var_type):
         data_table_component = DataTable.create(
             data=data_table_state.data, columns=data_table_state.columns
         )

+ 11 - 7
tests/components/forms/test_debounce.py

@@ -51,7 +51,9 @@ def test_render_child_props():
     )._render()
     assert tag.props["sx"] == {"foo": "bar", "baz": "quuc"}
     assert tag.props["value"].equals(
-        BaseVar(name="real", type_=str, is_local=True, is_string=False)
+        BaseVar(
+            _var_name="real", _var_type=str, _var_is_local=True, _var_is_string=False
+        )
     )
     assert len(tag.props["onChange"].events) == 1
     assert tag.props["onChange"].events[0].handler == S.on_change
@@ -86,11 +88,13 @@ def test_render_child_props_recursive():
     )._render()
     assert tag.props["sx"] == {"foo": "bar", "baz": "quuc"}
     assert tag.props["value"].equals(
-        BaseVar(name="outer", type_=str, is_local=True, is_string=False)
+        BaseVar(
+            _var_name="outer", _var_type=str, _var_is_local=True, _var_is_string=False
+        )
     )
-    assert tag.props["forceNotifyOnBlur"].name == "false"
-    assert tag.props["forceNotifyByEnter"].name == "false"
-    assert tag.props["debounceTimeout"].name == "42"
+    assert tag.props["forceNotifyOnBlur"]._var_name == "false"
+    assert tag.props["forceNotifyByEnter"]._var_name == "false"
+    assert tag.props["debounceTimeout"]._var_name == "42"
     assert len(tag.props["onChange"].events) == 1
     assert tag.props["onChange"].events[0].handler == S.on_change
     assert tag.contents == ""
@@ -102,7 +106,7 @@ def test_full_control_implicit_debounce():
         value=S.value,
         on_change=S.on_change,
     )._render()
-    assert tag.props["debounceTimeout"].name == "50"
+    assert tag.props["debounceTimeout"]._var_name == "50"
     assert len(tag.props["onChange"].events) == 1
     assert tag.props["onChange"].events[0].handler == S.on_change
     assert tag.contents == ""
@@ -114,7 +118,7 @@ def test_full_control_implicit_debounce_text_area():
         value=S.value,
         on_change=S.on_change,
     )._render()
-    assert tag.props["debounceTimeout"].name == "50"
+    assert tag.props["debounceTimeout"]._var_name == "50"
     assert len(tag.props["onChange"].events) == 1
     assert tag.props["onChange"].events[0].handler == S.on_change
     assert tag.contents == ""

+ 1 - 1
tests/components/layout/test_cond.py

@@ -105,7 +105,7 @@ def test_cond_no_else():
     comp = comp.children[0]
     assert isinstance(comp, Cond)
     assert comp.cond._decode() is True  # type: ignore
-    assert comp.comp1 == Fragment.create(Text.create("hello"))
+    assert comp.comp1.render() == Fragment.create(Text.create("hello")).render()
     assert comp.comp2 == Fragment.create()
 
     # Props do not support the use of cond without else

+ 2 - 2
tests/components/layout/test_foreach.py

@@ -186,6 +186,6 @@ def test_foreach_render(state_var, render_fn, render_dict):
     rend = component.render()
     arg_index = rend["arg_index"]
     assert rend["iterable_state"] == render_dict["iterable_state"]
-    assert arg_index.name == render_dict["arg_index"]
-    assert arg_index.type_ == int
+    assert arg_index._var_name == render_dict["arg_index"]
+    assert arg_index._var_type == int
     assert rend["iterable_type"] == render_dict["iterable_type"]

+ 2 - 2
tests/components/media/test_image.py

@@ -43,7 +43,7 @@ try:
             pil_image: The image to serialize.
         """
         image = Image.create(src=pil_image)
-        assert str(image.src.name) == serialize_image(pil_image)  # type: ignore
+        assert str(image.src._var_name) == serialize_image(pil_image)  # type: ignore
 
     def test_render(pil_image: Img):
         """Test that rendering an image works.
@@ -52,7 +52,7 @@ try:
             pil_image: The image to serialize.
         """
         image = Image.create(src=pil_image)
-        assert image.src.is_string  # type: ignore
+        assert image.src._var_is_string  # type: ignore
 
 except ImportError:
 

+ 3 - 3
tests/components/test_tag.py

@@ -109,7 +109,7 @@ def test_format_cond_tag():
     tag = CondTag(
         true_value=dict(Tag(name="h1", contents="True content")),
         false_value=dict(Tag(name="h2", contents="False content")),
-        cond=BaseVar(name="logged_in", type_=bool),
+        cond=BaseVar(_var_name="logged_in", _var_type=bool),
     )
     tag_dict = dict(tag)
     cond, true_value, false_value = (
@@ -117,8 +117,8 @@ def test_format_cond_tag():
         tag_dict["true_value"],
         tag_dict["false_value"],
     )
-    assert cond.name == "logged_in"
-    assert cond.type_ == bool
+    assert cond._var_name == "logged_in"
+    assert cond._var_type == bool
 
     assert true_value["name"] == "h1"
     assert true_value["contents"] == "True content"

+ 2 - 2
tests/test_app.py

@@ -250,7 +250,7 @@ def test_add_page_set_route_dynamic(app: App, index_page, windows_platform: bool
     app.add_page(index_page, route=route)
     assert set(app.pages.keys()) == {"test/[dynamic]"}
     assert "dynamic" in app.state.computed_vars
-    assert app.state.computed_vars["dynamic"].deps(objclass=DefaultState) == {
+    assert app.state.computed_vars["dynamic"]._deps(objclass=DefaultState) == {
         constants.ROUTER_DATA
     }
     assert constants.ROUTER_DATA in app.state().computed_var_dependencies
@@ -869,7 +869,7 @@ async def test_dynamic_route_var_route_change_completed_on_load(
     app.add_page(index_page, route=route, on_load=DynamicState.on_load)  # type: ignore
     assert arg_name in app.state.vars
     assert arg_name in app.state.computed_vars
-    assert app.state.computed_vars[arg_name].deps(objclass=DynamicState) == {
+    assert app.state.computed_vars[arg_name]._deps(objclass=DynamicState) == {
         constants.ROUTER_DATA
     }
     assert constants.ROUTER_DATA in app.state().computed_var_dependencies

+ 12 - 10
tests/test_state.py

@@ -197,11 +197,11 @@ def test_base_class_vars(test_state):
             continue
         prop = getattr(cls, field)
         assert isinstance(prop, BaseVar)
-        assert prop.name == field
+        assert prop._var_name == field
 
-    assert cls.num1.type_ == int
-    assert cls.num2.type_ == float
-    assert cls.key.type_ == str
+    assert cls.num1._var_type == int
+    assert cls.num2._var_type == float
+    assert cls.key._var_type == str
 
 
 def test_computed_class_var(test_state):
@@ -211,7 +211,7 @@ def test_computed_class_var(test_state):
         test_state: A state.
     """
     cls = type(test_state)
-    vars = [(prop.name, prop.type_) for prop in cls.computed_vars.values()]
+    vars = [(prop._var_name, prop._var_type) for prop in cls.computed_vars.values()]
     assert ("sum", float) in vars
     assert ("upper", str) in vars
 
@@ -416,11 +416,13 @@ def test_set_class_var():
     """Test setting the var of a class."""
     with pytest.raises(AttributeError):
         TestState.num3  # type: ignore
-    TestState._set_var(BaseVar(name="num3", type_=int).set_state(TestState))
+    TestState._set_var(
+        BaseVar(_var_name="num3", _var_type=int)._var_set_state(TestState)
+    )
     var = TestState.num3  # type: ignore
-    assert var.name == "num3"
-    assert var.type_ == int
-    assert var.state == TestState.get_full_name()
+    assert var._var_name == "num3"
+    assert var._var_type == int
+    assert var._var_state == TestState.get_full_name()
 
 
 def test_set_parent_and_substates(test_state, child_state, grandchild_state):
@@ -984,7 +986,7 @@ def test_conditional_computed_vars():
     assert ms._dirty_computed_vars(from_vars={"flag"}) == {"rendered_var"}
     assert ms._dirty_computed_vars(from_vars={"t2"}) == {"rendered_var"}
     assert ms._dirty_computed_vars(from_vars={"t1"}) == {"rendered_var"}
-    assert ms.computed_vars["rendered_var"].deps(objclass=MainState) == {
+    assert ms.computed_vars["rendered_var"]._deps(objclass=MainState) == {
         "flag",
         "t1",
         "t2",

+ 160 - 133
tests/test_var.py

@@ -16,11 +16,11 @@ from reflex.vars import (
 )
 
 test_vars = [
-    BaseVar(name="prop1", type_=int),
-    BaseVar(name="key", type_=str),
-    BaseVar(name="value", type_=str, state="state"),
-    BaseVar(name="local", type_=str, state="state", is_local=True),
-    BaseVar(name="local2", type_=str, is_local=True),
+    BaseVar(_var_name="prop1", _var_type=int),
+    BaseVar(_var_name="key", _var_type=str),
+    BaseVar(_var_name="value", _var_type=str, _var_state="state"),
+    BaseVar(_var_name="local", _var_type=str, _var_state="state", _var_is_local=True),
+    BaseVar(_var_name="local2", _var_type=str, _var_is_local=True),
 ]
 
 test_import_vars = [ImportVar(tag="DataGrid"), ImportVar(tag="DataGrid", alias="Grid")]
@@ -124,7 +124,7 @@ def test_full_name(prop, expected):
         prop: The var to test.
         expected: The expected full name.
     """
-    assert prop.full_name == expected
+    assert prop._var_full_name == expected
 
 
 @pytest.mark.parametrize(
@@ -147,14 +147,14 @@ def test_str(prop, expected):
 @pytest.mark.parametrize(
     "prop,expected",
     [
-        (BaseVar(name="p", type_=int), 0),
-        (BaseVar(name="p", type_=float), 0.0),
-        (BaseVar(name="p", type_=str), ""),
-        (BaseVar(name="p", type_=bool), False),
-        (BaseVar(name="p", type_=list), []),
-        (BaseVar(name="p", type_=dict), {}),
-        (BaseVar(name="p", type_=tuple), ()),
-        (BaseVar(name="p", type_=set), set()),
+        (BaseVar(_var_name="p", _var_type=int), 0),
+        (BaseVar(_var_name="p", _var_type=float), 0.0),
+        (BaseVar(_var_name="p", _var_type=str), ""),
+        (BaseVar(_var_name="p", _var_type=bool), False),
+        (BaseVar(_var_name="p", _var_type=list), []),
+        (BaseVar(_var_name="p", _var_type=dict), {}),
+        (BaseVar(_var_name="p", _var_type=tuple), ()),
+        (BaseVar(_var_name="p", _var_type=set), set()),
     ],
 )
 def test_default_value(prop, expected):
@@ -194,13 +194,13 @@ def test_get_setter(prop, expected):
     "value,expected",
     [
         (None, None),
-        (1, BaseVar(name="1", type_=int, is_local=True)),
-        ("key", BaseVar(name="key", type_=str, is_local=True)),
-        (3.14, BaseVar(name="3.14", type_=float, is_local=True)),
-        ([1, 2, 3], BaseVar(name="[1, 2, 3]", type_=list, is_local=True)),
+        (1, BaseVar(_var_name="1", _var_type=int, _var_is_local=True)),
+        ("key", BaseVar(_var_name="key", _var_type=str, _var_is_local=True)),
+        (3.14, BaseVar(_var_name="3.14", _var_type=float, _var_is_local=True)),
+        ([1, 2, 3], BaseVar(_var_name="[1, 2, 3]", _var_type=list, _var_is_local=True)),
         (
             {"a": 1, "b": 2},
-            BaseVar(name='{"a": 1, "b": 2}', type_=dict, is_local=True),
+            BaseVar(_var_name='{"a": 1, "b": 2}', _var_type=dict, _var_is_local=True),
         ),
     ],
 )
@@ -232,9 +232,9 @@ def test_create_type_error():
 
 def v(value) -> Var:
     val = (
-        Var.create(json.dumps(value), is_string=True, is_local=False)
+        Var.create(json.dumps(value), _var_is_string=True, _var_is_local=False)
         if isinstance(value, str)
-        else Var.create(value, is_local=False)
+        else Var.create(value, _var_is_local=False)
     )
     assert val is not None
     return val
@@ -264,7 +264,8 @@ def test_basic_operations(TestObj):
     assert str(v([1, 2, 3])[v(0)]) == "{[1, 2, 3].at(0)}"
     assert str(v({"a": 1, "b": 2})["a"]) == '{{"a": 1, "b": 2}["a"]}'
     assert (
-        str(BaseVar(name="foo", state="state", type_=TestObj).bar) == "{state.foo.bar}"
+        str(BaseVar(_var_name="foo", _var_state="state", _var_type=TestObj).bar)
+        == "{state.foo.bar}"
     )
     assert str(abs(v(1))) == "{Math.abs(1)}"
     assert str(v([1, 2, 3]).length()) == "{[1, 2, 3].length}"
@@ -274,10 +275,13 @@ def test_basic_operations(TestObj):
     assert str(v([1, 2, 3]).reverse()) == "{[...[1, 2, 3]].reverse()}"
     assert str(v(["1", "2", "3"]).reverse()) == '{[...["1", "2", "3"]].reverse()}'
     assert (
-        str(BaseVar(name="foo", state="state", type_=list).reverse())
+        str(BaseVar(_var_name="foo", _var_state="state", _var_type=list).reverse())
         == "{[...state.foo].reverse()}"
     )
-    assert str(BaseVar(name="foo", type_=list).reverse()) == "{[...foo].reverse()}"
+    assert (
+        str(BaseVar(_var_name="foo", _var_type=list).reverse())
+        == "{[...foo].reverse()}"
+    )
 
 
 @pytest.mark.parametrize(
@@ -285,12 +289,12 @@ def test_basic_operations(TestObj):
     [
         (v([1, 2, 3]), "[1, 2, 3]"),
         (v(["1", "2", "3"]), '["1", "2", "3"]'),
-        (BaseVar(name="foo", state="state", type_=list), "state.foo"),
-        (BaseVar(name="foo", type_=list), "foo"),
+        (BaseVar(_var_name="foo", _var_state="state", _var_type=list), "state.foo"),
+        (BaseVar(_var_name="foo", _var_type=list), "foo"),
         (v((1, 2, 3)), "[1, 2, 3]"),
         (v(("1", "2", "3")), '["1", "2", "3"]'),
-        (BaseVar(name="foo", state="state", type_=tuple), "state.foo"),
-        (BaseVar(name="foo", type_=tuple), "foo"),
+        (BaseVar(_var_name="foo", _var_state="state", _var_type=tuple), "state.foo"),
+        (BaseVar(_var_name="foo", _var_type=tuple), "foo"),
     ],
 )
 def test_list_tuple_contains(var, expected):
@@ -298,8 +302,8 @@ def test_list_tuple_contains(var, expected):
     assert str(var.contains("1")) == f'{{{expected}.includes("1")}}'
     assert str(var.contains(v(1))) == f"{{{expected}.includes(1)}}"
     assert str(var.contains(v("1"))) == f'{{{expected}.includes("1")}}'
-    other_state_var = BaseVar(name="other", state="state", type_=str)
-    other_var = BaseVar(name="other", type_=str)
+    other_state_var = BaseVar(_var_name="other", _var_state="state", _var_type=str)
+    other_var = BaseVar(_var_name="other", _var_type=str)
     assert str(var.contains(other_state_var)) == f"{{{expected}.includes(state.other)}}"
     assert str(var.contains(other_var)) == f"{{{expected}.includes(other)}}"
 
@@ -308,15 +312,15 @@ def test_list_tuple_contains(var, expected):
     "var, expected",
     [
         (v("123"), json.dumps("123")),
-        (BaseVar(name="foo", state="state", type_=str), "state.foo"),
-        (BaseVar(name="foo", type_=str), "foo"),
+        (BaseVar(_var_name="foo", _var_state="state", _var_type=str), "state.foo"),
+        (BaseVar(_var_name="foo", _var_type=str), "foo"),
     ],
 )
 def test_str_contains(var, expected):
     assert str(var.contains("1")) == f'{{{expected}.includes("1")}}'
     assert str(var.contains(v("1"))) == f'{{{expected}.includes("1")}}'
-    other_state_var = BaseVar(name="other", state="state", type_=str)
-    other_var = BaseVar(name="other", type_=str)
+    other_state_var = BaseVar(_var_name="other", _var_state="state", _var_type=str)
+    other_var = BaseVar(_var_name="other", _var_type=str)
     assert str(var.contains(other_state_var)) == f"{{{expected}.includes(state.other)}}"
     assert str(var.contains(other_var)) == f"{{{expected}.includes(other)}}"
 
@@ -325,8 +329,8 @@ def test_str_contains(var, expected):
     "var, expected",
     [
         (v({"a": 1, "b": 2}), '{"a": 1, "b": 2}'),
-        (BaseVar(name="foo", state="state", type_=dict), "state.foo"),
-        (BaseVar(name="foo", type_=dict), "foo"),
+        (BaseVar(_var_name="foo", _var_state="state", _var_type=dict), "state.foo"),
+        (BaseVar(_var_name="foo", _var_type=dict), "foo"),
     ],
 )
 def test_dict_contains(var, expected):
@@ -334,8 +338,8 @@ def test_dict_contains(var, expected):
     assert str(var.contains("1")) == f'{{{expected}.hasOwnProperty("1")}}'
     assert str(var.contains(v(1))) == f"{{{expected}.hasOwnProperty(1)}}"
     assert str(var.contains(v("1"))) == f'{{{expected}.hasOwnProperty("1")}}'
-    other_state_var = BaseVar(name="other", state="state", type_=str)
-    other_var = BaseVar(name="other", type_=str)
+    other_state_var = BaseVar(_var_name="other", _var_state="state", _var_type=str)
+    other_var = BaseVar(_var_name="other", _var_type=str)
     assert (
         str(var.contains(other_state_var))
         == f"{{{expected}.hasOwnProperty(state.other)}}"
@@ -346,9 +350,9 @@ def test_dict_contains(var, expected):
 @pytest.mark.parametrize(
     "var",
     [
-        BaseVar(name="list", type_=List[int]),
-        BaseVar(name="tuple", type_=Tuple[int, int]),
-        BaseVar(name="str", type_=str),
+        BaseVar(_var_name="list", _var_type=List[int]),
+        BaseVar(_var_name="tuple", _var_type=Tuple[int, int]),
+        BaseVar(_var_name="str", _var_type=str),
     ],
 )
 def test_var_indexing_lists(var):
@@ -358,49 +362,70 @@ def test_var_indexing_lists(var):
         var : The str, list or tuple base var.
     """
     # Test basic indexing.
-    assert str(var[0]) == f"{{{var.name}.at(0)}}"
-    assert str(var[1]) == f"{{{var.name}.at(1)}}"
+    assert str(var[0]) == f"{{{var._var_name}.at(0)}}"
+    assert str(var[1]) == f"{{{var._var_name}.at(1)}}"
 
     # Test negative indexing.
-    assert str(var[-1]) == f"{{{var.name}.at(-1)}}"
+    assert str(var[-1]) == f"{{{var._var_name}.at(-1)}}"
 
 
 @pytest.mark.parametrize(
     "var, index",
     [
-        (BaseVar(name="lst", type_=List[int]), [1, 2]),
-        (BaseVar(name="lst", type_=List[int]), {"name": "dict"}),
-        (BaseVar(name="lst", type_=List[int]), {"set"}),
+        (BaseVar(_var_name="lst", _var_type=List[int]), [1, 2]),
+        (BaseVar(_var_name="lst", _var_type=List[int]), {"name": "dict"}),
+        (BaseVar(_var_name="lst", _var_type=List[int]), {"set"}),
         (
-            BaseVar(name="lst", type_=List[int]),
+            BaseVar(_var_name="lst", _var_type=List[int]),
             (
                 1,
                 2,
             ),
         ),
-        (BaseVar(name="lst", type_=List[int]), 1.5),
-        (BaseVar(name="lst", type_=List[int]), "str"),
-        (BaseVar(name="lst", type_=List[int]), BaseVar(name="string_var", type_=str)),
-        (BaseVar(name="lst", type_=List[int]), BaseVar(name="float_var", type_=float)),
+        (BaseVar(_var_name="lst", _var_type=List[int]), 1.5),
+        (BaseVar(_var_name="lst", _var_type=List[int]), "str"),
+        (
+            BaseVar(_var_name="lst", _var_type=List[int]),
+            BaseVar(_var_name="string_var", _var_type=str),
+        ),
+        (
+            BaseVar(_var_name="lst", _var_type=List[int]),
+            BaseVar(_var_name="float_var", _var_type=float),
+        ),
+        (
+            BaseVar(_var_name="lst", _var_type=List[int]),
+            BaseVar(_var_name="list_var", _var_type=List[int]),
+        ),
+        (
+            BaseVar(_var_name="lst", _var_type=List[int]),
+            BaseVar(_var_name="set_var", _var_type=Set[str]),
+        ),
+        (
+            BaseVar(_var_name="lst", _var_type=List[int]),
+            BaseVar(_var_name="dict_var", _var_type=Dict[str, str]),
+        ),
+        (BaseVar(_var_name="str", _var_type=str), [1, 2]),
+        (BaseVar(_var_name="lst", _var_type=str), {"name": "dict"}),
+        (BaseVar(_var_name="lst", _var_type=str), {"set"}),
+        (
+            BaseVar(_var_name="lst", _var_type=str),
+            BaseVar(_var_name="string_var", _var_type=str),
+        ),
         (
-            BaseVar(name="lst", type_=List[int]),
-            BaseVar(name="list_var", type_=List[int]),
+            BaseVar(_var_name="lst", _var_type=str),
+            BaseVar(_var_name="float_var", _var_type=float),
         ),
-        (BaseVar(name="lst", type_=List[int]), BaseVar(name="set_var", type_=Set[str])),
+        (BaseVar(_var_name="str", _var_type=Tuple[str]), [1, 2]),
+        (BaseVar(_var_name="lst", _var_type=Tuple[str]), {"name": "dict"}),
+        (BaseVar(_var_name="lst", _var_type=Tuple[str]), {"set"}),
         (
-            BaseVar(name="lst", type_=List[int]),
-            BaseVar(name="dict_var", type_=Dict[str, str]),
+            BaseVar(_var_name="lst", _var_type=Tuple[str]),
+            BaseVar(_var_name="string_var", _var_type=str),
+        ),
+        (
+            BaseVar(_var_name="lst", _var_type=Tuple[str]),
+            BaseVar(_var_name="float_var", _var_type=float),
         ),
-        (BaseVar(name="str", type_=str), [1, 2]),
-        (BaseVar(name="lst", type_=str), {"name": "dict"}),
-        (BaseVar(name="lst", type_=str), {"set"}),
-        (BaseVar(name="lst", type_=str), BaseVar(name="string_var", type_=str)),
-        (BaseVar(name="lst", type_=str), BaseVar(name="float_var", type_=float)),
-        (BaseVar(name="str", type_=Tuple[str]), [1, 2]),
-        (BaseVar(name="lst", type_=Tuple[str]), {"name": "dict"}),
-        (BaseVar(name="lst", type_=Tuple[str]), {"set"}),
-        (BaseVar(name="lst", type_=Tuple[str]), BaseVar(name="string_var", type_=str)),
-        (BaseVar(name="lst", type_=Tuple[str]), BaseVar(name="float_var", type_=float)),
     ],
 )
 def test_var_unsupported_indexing_lists(var, index):
@@ -417,9 +442,9 @@ def test_var_unsupported_indexing_lists(var, index):
 @pytest.mark.parametrize(
     "var",
     [
-        BaseVar(name="lst", type_=List[int]),
-        BaseVar(name="tuple", type_=Tuple[int, int]),
-        BaseVar(name="str", type_=str),
+        BaseVar(_var_name="lst", _var_type=List[int]),
+        BaseVar(_var_name="tuple", _var_type=Tuple[int, int]),
+        BaseVar(_var_name="str", _var_type=str),
     ],
 )
 def test_var_list_slicing(var):
@@ -428,14 +453,14 @@ def test_var_list_slicing(var):
     Args:
         var : The str, list or tuple base var.
     """
-    assert str(var[:1]) == f"{{{var.name}.slice(0, 1)}}"
-    assert str(var[:1]) == f"{{{var.name}.slice(0, 1)}}"
-    assert str(var[:]) == f"{{{var.name}.slice(0, undefined)}}"
+    assert str(var[:1]) == f"{{{var._var_name}.slice(0, 1)}}"
+    assert str(var[:1]) == f"{{{var._var_name}.slice(0, 1)}}"
+    assert str(var[:]) == f"{{{var._var_name}.slice(0, undefined)}}"
 
 
 def test_dict_indexing():
     """Test that we can index into dict vars."""
-    dct = BaseVar(name="dct", type_=Dict[str, int])
+    dct = BaseVar(_var_name="dct", _var_type=Dict[str, int])
 
     # Check correct indexing.
     assert str(dct["a"]) == '{dct["a"]}'
@@ -446,66 +471,66 @@ def test_dict_indexing():
     "var, index",
     [
         (
-            BaseVar(name="dict", type_=Dict[str, str]),
+            BaseVar(_var_name="dict", _var_type=Dict[str, str]),
             [1, 2],
         ),
         (
-            BaseVar(name="dict", type_=Dict[str, str]),
+            BaseVar(_var_name="dict", _var_type=Dict[str, str]),
             {"name": "dict"},
         ),
         (
-            BaseVar(name="dict", type_=Dict[str, str]),
+            BaseVar(_var_name="dict", _var_type=Dict[str, str]),
             {"set"},
         ),
         (
-            BaseVar(name="dict", type_=Dict[str, str]),
+            BaseVar(_var_name="dict", _var_type=Dict[str, str]),
             (
                 1,
                 2,
             ),
         ),
         (
-            BaseVar(name="lst", type_=Dict[str, str]),
-            BaseVar(name="list_var", type_=List[int]),
+            BaseVar(_var_name="lst", _var_type=Dict[str, str]),
+            BaseVar(_var_name="list_var", _var_type=List[int]),
         ),
         (
-            BaseVar(name="lst", type_=Dict[str, str]),
-            BaseVar(name="set_var", type_=Set[str]),
+            BaseVar(_var_name="lst", _var_type=Dict[str, str]),
+            BaseVar(_var_name="set_var", _var_type=Set[str]),
         ),
         (
-            BaseVar(name="lst", type_=Dict[str, str]),
-            BaseVar(name="dict_var", type_=Dict[str, str]),
+            BaseVar(_var_name="lst", _var_type=Dict[str, str]),
+            BaseVar(_var_name="dict_var", _var_type=Dict[str, str]),
         ),
         (
-            BaseVar(name="df", type_=DataFrame),
+            BaseVar(_var_name="df", _var_type=DataFrame),
             [1, 2],
         ),
         (
-            BaseVar(name="df", type_=DataFrame),
+            BaseVar(_var_name="df", _var_type=DataFrame),
             {"name": "dict"},
         ),
         (
-            BaseVar(name="df", type_=DataFrame),
+            BaseVar(_var_name="df", _var_type=DataFrame),
             {"set"},
         ),
         (
-            BaseVar(name="df", type_=DataFrame),
+            BaseVar(_var_name="df", _var_type=DataFrame),
             (
                 1,
                 2,
             ),
         ),
         (
-            BaseVar(name="df", type_=DataFrame),
-            BaseVar(name="list_var", type_=List[int]),
+            BaseVar(_var_name="df", _var_type=DataFrame),
+            BaseVar(_var_name="list_var", _var_type=List[int]),
         ),
         (
-            BaseVar(name="df", type_=DataFrame),
-            BaseVar(name="set_var", type_=Set[str]),
+            BaseVar(_var_name="df", _var_type=DataFrame),
+            BaseVar(_var_name="set_var", _var_type=Set[str]),
         ),
         (
-            BaseVar(name="df", type_=DataFrame),
-            BaseVar(name="dict_var", type_=Dict[str, str]),
+            BaseVar(_var_name="df", _var_type=DataFrame),
+            BaseVar(_var_name="dict_var", _var_type=Dict[str, str]),
         ),
     ],
 )
@@ -577,8 +602,7 @@ def test_computed_var_with_annotation_error(request, fixture, full_name):
         state.var_with_annotation.foo
     assert (
         err.value.args[0]
-        == f"The State var `{full_name}` has no attribute 'foo' or may have been annotated wrongly.\n"
-        f"original message: 'ComputedVar' object has no attribute 'foo'"
+        == f"The State var `{full_name}` has no attribute 'foo' or may have been annotated wrongly."
     )
 
 
@@ -605,16 +629,19 @@ def test_import_var(import_var, expected):
 @pytest.mark.parametrize(
     "key, expected",
     [
-        ("test_key", BaseVar(name="localStorage.getItem('test_key')", type_=str)),
         (
-            BaseVar(name="key_var", type_=str),
-            BaseVar(name="localStorage.getItem(key_var)", type_=str),
+            "test_key",
+            BaseVar(_var_name="localStorage.getItem('test_key')", _var_type=str),
+        ),
+        (
+            BaseVar(_var_name="key_var", _var_type=str),
+            BaseVar(_var_name="localStorage.getItem(key_var)", _var_type=str),
         ),
         (
             BaseState.val,
-            BaseVar(name="localStorage.getItem(base_state.val)", type_=str),
+            BaseVar(_var_name="localStorage.getItem(base_state.val)", _var_type=str),
         ),
-        (None, BaseVar(name="getAllLocalStorageItems()", type_=Dict)),
+        (None, BaseVar(_var_name="getAllLocalStorageItems()", _var_type=Dict)),
     ],
 )
 def test_get_local_storage(key, expected):
@@ -626,8 +653,8 @@ def test_get_local_storage(key, expected):
 
     """
     local_storage = get_local_storage(key)
-    assert local_storage.name == expected.name
-    assert local_storage.type_ == expected.type_
+    assert local_storage._var_name == expected._var_name
+    assert local_storage._var_type == expected._var_type
 
 
 @pytest.mark.parametrize(
@@ -636,8 +663,8 @@ def test_get_local_storage(key, expected):
         ["list", "values"],
         {"name": "dict"},
         10,
-        BaseVar(name="key_var", type_=List),
-        BaseVar(name="key_var", type_=Dict[str, str]),
+        BaseVar(_var_name="key_var", _var_type=List),
+        BaseVar(_var_name="key_var", _var_type=Dict[str, str]),
     ],
 )
 def test_get_local_storage_raise_error(key):
@@ -648,7 +675,7 @@ def test_get_local_storage_raise_error(key):
     """
     with pytest.raises(TypeError) as err:
         get_local_storage(key)
-    type_ = type(key) if not isinstance(key, Var) else key.type_
+    type_ = type(key) if not isinstance(key, Var) else key._var_type
     assert (
         err.value.args[0]
         == f"Local storage keys can only be of type `str` or `var` of type `str`. Got `{type_}` instead."
@@ -658,13 +685,13 @@ def test_get_local_storage_raise_error(key):
 @pytest.mark.parametrize(
     "out, expected",
     [
-        (f"{BaseVar(name='var', type_=str)}", "${var}"),
+        (f"{BaseVar(_var_name='var', _var_type=str)}", "${var}"),
         (
-            f"testing f-string with {BaseVar(name='myvar', state='state', type_=int)}",
+            f"testing f-string with {BaseVar(_var_name='myvar', _var_state='state', _var_type=int)}",
             "testing f-string with ${state.myvar}",
         ),
         (
-            f"testing local f-string {BaseVar(name='x', is_local=True, type_=str)}",
+            f"testing local f-string {BaseVar(_var_name='x', _var_is_local=True, _var_type=str)}",
             "testing local f-string x",
         ),
     ],
@@ -676,14 +703,14 @@ def test_fstrings(out, expected):
 @pytest.mark.parametrize(
     "var",
     [
-        BaseVar(name="var", type_=int),
-        BaseVar(name="var", type_=float),
-        BaseVar(name="var", type_=str),
-        BaseVar(name="var", type_=bool),
-        BaseVar(name="var", type_=dict),
-        BaseVar(name="var", type_=tuple),
-        BaseVar(name="var", type_=set),
-        BaseVar(name="var", type_=None),
+        BaseVar(_var_name="var", _var_type=int),
+        BaseVar(_var_name="var", _var_type=float),
+        BaseVar(_var_name="var", _var_type=str),
+        BaseVar(_var_name="var", _var_type=bool),
+        BaseVar(_var_name="var", _var_type=dict),
+        BaseVar(_var_name="var", _var_type=tuple),
+        BaseVar(_var_name="var", _var_type=set),
+        BaseVar(_var_name="var", _var_type=None),
     ],
 )
 def test_unsupported_types_for_reverse(var):
@@ -700,11 +727,11 @@ def test_unsupported_types_for_reverse(var):
 @pytest.mark.parametrize(
     "var",
     [
-        BaseVar(name="var", type_=int),
-        BaseVar(name="var", type_=float),
-        BaseVar(name="var", type_=bool),
-        BaseVar(name="var", type_=set),
-        BaseVar(name="var", type_=None),
+        BaseVar(_var_name="var", _var_type=int),
+        BaseVar(_var_name="var", _var_type=float),
+        BaseVar(_var_name="var", _var_type=bool),
+        BaseVar(_var_name="var", _var_type=set),
+        BaseVar(_var_name="var", _var_type=None),
     ],
 )
 def test_unsupported_types_for_contains(var):
@@ -717,34 +744,34 @@ def test_unsupported_types_for_contains(var):
         assert var.contains(1)
     assert (
         err.value.args[0]
-        == f"Var var of type {var.type_} does not support contains check."
+        == f"Var var of type {var._var_type} does not support contains check."
     )
 
 
 @pytest.mark.parametrize(
     "other",
     [
-        BaseVar(name="other", type_=int),
-        BaseVar(name="other", type_=float),
-        BaseVar(name="other", type_=bool),
-        BaseVar(name="other", type_=list),
-        BaseVar(name="other", type_=dict),
-        BaseVar(name="other", type_=tuple),
-        BaseVar(name="other", type_=set),
+        BaseVar(_var_name="other", _var_type=int),
+        BaseVar(_var_name="other", _var_type=float),
+        BaseVar(_var_name="other", _var_type=bool),
+        BaseVar(_var_name="other", _var_type=list),
+        BaseVar(_var_name="other", _var_type=dict),
+        BaseVar(_var_name="other", _var_type=tuple),
+        BaseVar(_var_name="other", _var_type=set),
     ],
 )
 def test_unsupported_types_for_string_contains(other):
     with pytest.raises(TypeError) as err:
-        assert BaseVar(name="var", type_=str).contains(other)
+        assert BaseVar(_var_name="var", _var_type=str).contains(other)
     assert (
         err.value.args[0]
-        == f"'in <string>' requires string as left operand, not {other.type_}"
+        == f"'in <string>' requires string as left operand, not {other._var_type}"
     )
 
 
 def test_unsupported_default_contains():
     with pytest.raises(TypeError) as err:
-        assert 1 in BaseVar(name="var", type_=str)
+        assert 1 in BaseVar(_var_name="var", _var_type=str)
     assert (
         err.value.args[0]
         == "'in' operator not supported for Var types, use Var.contains() instead."

+ 19 - 16
tests/utils/test_format.py

@@ -211,11 +211,11 @@ def test_format_string(input: str, output: str):
     "input,output",
     [
         (Var.create(value="test"), "{`test`}"),
-        (Var.create(value="test", is_local=True), "{`test`}"),
-        (Var.create(value="test", is_local=False), "{test}"),
-        (Var.create(value="test", is_string=True), "{`test`}"),
-        (Var.create(value="test", is_string=False), "{`test`}"),
-        (Var.create(value="test", is_local=False, is_string=False), "{test}"),
+        (Var.create(value="test", _var_is_local=True), "{`test`}"),
+        (Var.create(value="test", _var_is_local=False), "{test}"),
+        (Var.create(value="test", _var_is_string=True), "{`test`}"),
+        (Var.create(value="test", _var_is_string=False), "{`test`}"),
+        (Var.create(value="test", _var_is_local=False, _var_is_string=False), "{test}"),
     ],
 )
 def test_format_var(input: Var, output: str):
@@ -285,7 +285,7 @@ def test_format_cond(condition: str, true_value: str, false_value: str, expected
         (
             {
                 "a": 'foo "{ "bar" }" baz',
-                "b": BaseVar(name="val", type_="str"),
+                "b": BaseVar(_var_name="val", _var_type="str"),
             },
             r'{{"a": "foo \"{ \"bar\" }\" baz", "b": val}}',
         ),
@@ -308,22 +308,25 @@ def test_format_cond(condition: str, true_value: str, false_value: str, expected
             '{_e => addEvents([Event("mock_event", {arg:_e.target.value})], _e)}',
         ),
         ({"a": "red", "b": "blue"}, '{{"a": "red", "b": "blue"}}'),
-        (BaseVar(name="var", type_="int"), "{var}"),
+        (BaseVar(_var_name="var", _var_type="int"), "{var}"),
         (
             BaseVar(
-                name="_",
-                type_=Any,
-                state="",
-                is_local=True,
-                is_string=False,
+                _var_name="_",
+                _var_type=Any,
+                _var_state="",
+                _var_is_local=True,
+                _var_is_string=False,
             ),
             "{_}",
         ),
-        (BaseVar(name='state.colors["a"]', type_="str"), '{state.colors["a"]}'),
-        ({"a": BaseVar(name="val", type_="str")}, '{{"a": val}}'),
-        ({"a": BaseVar(name='"val"', type_="str")}, '{{"a": "val"}}'),
         (
-            {"a": BaseVar(name='state.colors["val"]', type_="str")},
+            BaseVar(_var_name='state.colors["a"]', _var_type="str"),
+            '{state.colors["a"]}',
+        ),
+        ({"a": BaseVar(_var_name="val", _var_type="str")}, '{{"a": val}}'),
+        ({"a": BaseVar(_var_name='"val"', _var_type="str")}, '{{"a": "val"}}'),
+        (
+            {"a": BaseVar(_var_name='state.colors["val"]', _var_type="str")},
             '{{"a": state.colors["val"]}}',
         ),
         # tricky real-world case from markdown component

+ 3 - 3
tests/utils/test_serializers.py

@@ -105,16 +105,16 @@ def test_add_serializer():
         ([1, 2, 3], "[1, 2, 3]"),
         ([1, "2", 3.0], '[1, "2", 3.0]'),
         (
-            [1, Var.create_safe("hi"), Var.create_safe("bye", is_local=False)],
+            [1, Var.create_safe("hi"), Var.create_safe("bye", _var_is_local=False)],
             '[1, "hi", bye]',
         ),
         (
-            (1, Var.create_safe("hi"), Var.create_safe("bye", is_local=False)),
+            (1, Var.create_safe("hi"), Var.create_safe("bye", _var_is_local=False)),
             '[1, "hi", bye]',
         ),
         ({1: 2, 3: 4}, '{"1": 2, "3": 4}'),
         (
-            {1: Var.create_safe("hi"), 3: Var.create_safe("bye", is_local=False)},
+            {1: Var.create_safe("hi"), 3: Var.create_safe("bye", _var_is_local=False)},
             '{"1": "hi", "3": bye}',
         ),
         (datetime.datetime(2021, 1, 1, 1, 1, 1, 1), "2021-01-01 01:01:01.000001"),