Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions reflex/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ def _get_computed_vars(cls) -> list[tuple[str, ComputedVar]]:
"""
return [
(name, v)
for mixin in [*cls._mixins(), cls]
for mixin in (*cls._mixins(), cls)
for name, v in mixin.__dict__.items()
if is_computed_var(v) and name not in cls.inherited_vars
]
Expand Down Expand Up @@ -569,14 +569,14 @@ def __init_subclass__(cls, mixin: bool = False, **kwargs):

new_backend_vars = {
name: value if not isinstance(value, Field) else value.default_value()
for mixin_cls in [*cls._mixins(), cls]
for mixin_cls in (*cls._mixins(), cls)
for name, value in list(mixin_cls.__dict__.items())
if types.is_backend_base_variable(name, mixin_cls)
}
# Add annotated backend vars that may not have a default value.
new_backend_vars.update({
name: cls._get_var_default(name, annotation_value)
for mixin_cls in [*cls._mixins(), cls]
for mixin_cls in (*cls._mixins(), cls)
for name, annotation_value in mixin_cls._get_type_hints().items()
if name not in new_backend_vars
and types.is_backend_base_variable(name, mixin_cls)
Expand Down Expand Up @@ -764,21 +764,21 @@ def computed_var_func(state: Self):
return getattr(cls, unique_var_name)

@classmethod
def _mixins(cls) -> list[type]:
def _mixins(cls) -> tuple[type[BaseState], ...]:
"""Get the mixin classes of the state.

Returns:
The mixin classes of the state.
"""
return [
return tuple(
mixin
for mixin in cls.__mro__
if (
mixin is not cls
and issubclass(mixin, BaseState)
and mixin._mixin is True
)
]
)

@classmethod
def _handle_local_def(cls):
Expand All @@ -796,6 +796,7 @@ def _handle_local_def(cls):
cls.__module__ = reflex.istate.dynamic.__name__

@classmethod
@functools.cache
def _get_type_hints(cls) -> dict[str, Any]:
"""Get the type hints for this class.

Expand Down Expand Up @@ -898,8 +899,9 @@ def _check_overridden_basevars(cls):
Raises:
ComputedVarShadowsBaseVarsError: When a computed var shadows a base var.
"""
hints = cls._get_type_hints()
for name, computed_var_ in cls._get_computed_vars():
if name in get_type_hints(cls):
if name in hints:
msg = f"The computed var name `{computed_var_._js_expr}` shadows a base var in {cls.__module__}.{cls.__name__}; use a different name instead"
raise ComputedVarShadowsBaseVarsError(msg)

Expand Down
11 changes: 4 additions & 7 deletions reflex/utils/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
StateVarTypes = (*PrimitiveTypes, Base, type(None))

if TYPE_CHECKING:
from reflex.state import BaseState
from reflex.vars.base import Var

VAR1 = TypeVar("VAR1", bound="Var")
Expand Down Expand Up @@ -902,12 +903,12 @@ def is_valid_var_type(type_: type) -> bool:
)


def is_backend_base_variable(name: str, cls: type) -> bool:
def is_backend_base_variable(name: str, cls: type[BaseState]) -> bool:
"""Check if this variable name correspond to a backend variable.

Args:
name: The name of the variable to check
cls: The class of the variable to check
cls: The class of the variable to check (must be a BaseState subclass)

Returns:
bool: The result of the check
Expand All @@ -924,11 +925,7 @@ def is_backend_base_variable(name: str, cls: type) -> bool:
if name.startswith(f"_{cls.__name__}__"):
return False

# Extract the namespace of the original module if defined (dynamic substates).
if callable(getattr(cls, "_get_type_hints", None)):
hints = cls._get_type_hints()
else:
hints = get_type_hints(cls)
hints = cls._get_type_hints()
if name in hints:
hint = get_origin(hints[name])
if hint == ClassVar:
Expand Down
Loading