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:
Masen Furer 2024-09-27 12:04:43 -07:00 committed by GitHub
parent eea5dc1918
commit 9ca5d4a095
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 17 additions and 1 deletions

View File

@ -30,6 +30,7 @@ from typing import (
Type,
Union,
cast,
get_type_hints,
)
import dill
@ -573,6 +574,15 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
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,

View File

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