Track backend-only vars that are declared without a default value (#4016)
* 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
This commit is contained in:
parent
eea5dc1918
commit
9ca5d4a095
@ -30,6 +30,7 @@ from typing import (
|
|||||||
Type,
|
Type,
|
||||||
Union,
|
Union,
|
||||||
cast,
|
cast,
|
||||||
|
get_type_hints,
|
||||||
)
|
)
|
||||||
|
|
||||||
import dill
|
import dill
|
||||||
@ -573,6 +574,15 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|||||||
for name, value in cls.__dict__.items()
|
for name, value in cls.__dict__.items()
|
||||||
if types.is_backend_base_variable(name, cls)
|
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.backend_vars = {
|
||||||
**cls.inherited_backend_vars,
|
**cls.inherited_backend_vars,
|
||||||
|
@ -3216,6 +3216,7 @@ class MixinState(State, mixin=True):
|
|||||||
|
|
||||||
num: int = 0
|
num: int = 0
|
||||||
_backend: int = 0
|
_backend: int = 0
|
||||||
|
_backend_no_default: dict
|
||||||
|
|
||||||
@rx.var(cache=True)
|
@rx.var(cache=True)
|
||||||
def computed(self) -> str:
|
def computed(self) -> str:
|
||||||
@ -3243,11 +3244,16 @@ def test_mixin_state() -> None:
|
|||||||
"""Test that a mixin state works correctly."""
|
"""Test that a mixin state works correctly."""
|
||||||
assert "num" in UsesMixinState.base_vars
|
assert "num" in UsesMixinState.base_vars
|
||||||
assert "num" in UsesMixinState.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.computed_vars
|
||||||
assert "computed" in UsesMixinState.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:
|
def test_child_mixin_state() -> None:
|
||||||
"""Test that mixin vars are only applied to the highest state in the hierarchy."""
|
"""Test that mixin vars are only applied to the highest state in the hierarchy."""
|
||||||
|
Loading…
Reference in New Issue
Block a user