Skip to content

Commit

Permalink
Track backend-only vars that are declared without a default value (#4016
Browse files Browse the repository at this point in the history
)

* Track backend-only vars that are declared without a default value

Without this provision, declared backend vars can be accidentally shared among
all states if a mutable value is assigned to the class attribute.

* add test case for no default backend var
  • Loading branch information
masenf authored Sep 27, 2024
1 parent eea5dc1 commit 9ca5d4a
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 1 deletion.
10 changes: 10 additions & 0 deletions reflex/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
Type,
Union,
cast,
get_type_hints,
)

import dill
Expand Down Expand Up @@ -573,6 +574,15 @@ def __init_subclass__(cls, mixin: bool = False, **kwargs):
for name, value in cls.__dict__.items()
if types.is_backend_base_variable(name, cls)
}
# Add annotated backend vars that do not have a default value.
new_backend_vars.update(
{
name: Var("", _var_type=annotation_value).get_default_value()
for name, annotation_value in get_type_hints(cls).items()
if name not in new_backend_vars
and types.is_backend_base_variable(name, cls)
}
)

cls.backend_vars = {
**cls.inherited_backend_vars,
Expand Down
8 changes: 7 additions & 1 deletion tests/units/test_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -3216,6 +3216,7 @@ class MixinState(State, mixin=True):

num: int = 0
_backend: int = 0
_backend_no_default: dict

@rx.var(cache=True)
def computed(self) -> str:
Expand Down Expand Up @@ -3243,11 +3244,16 @@ def test_mixin_state() -> None:
"""Test that a mixin state works correctly."""
assert "num" in UsesMixinState.base_vars
assert "num" in UsesMixinState.vars
assert UsesMixinState.backend_vars == {"_backend": 0}
assert UsesMixinState.backend_vars == {"_backend": 0, "_backend_no_default": {}}

assert "computed" in UsesMixinState.computed_vars
assert "computed" in UsesMixinState.vars

assert (
UsesMixinState(_reflex_internal_init=True)._backend_no_default # type: ignore
is not UsesMixinState.backend_vars["_backend_no_default"]
)


def test_child_mixin_state() -> None:
"""Test that mixin vars are only applied to the highest state in the hierarchy."""
Expand Down

0 comments on commit 9ca5d4a

Please sign in to comment.