From 3307979868aafe2d2a67c76db6b6e50687fc434e Mon Sep 17 00:00:00 2001 From: Benedikt Bartscher Date: Sat, 1 Feb 2025 15:40:30 +0100 Subject: [PATCH] typing and usability improvements for computed var static dependencies --- reflex/vars/base.py | 70 +++++++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 21 deletions(-) diff --git a/reflex/vars/base.py b/reflex/vars/base.py index 3e28eec5f..476500d3d 100644 --- a/reflex/vars/base.py +++ b/reflex/vars/base.py @@ -1982,7 +1982,7 @@ class ComputedVar(Var[RETURN_TYPE]): _initial_value: RETURN_TYPE | types.Unset = dataclasses.field(default=types.Unset()) # Explicit var dependencies to track - _static_deps: dict[str, set[str]] = dataclasses.field(default_factory=dict) + _static_deps: dict[str | None, set[str]] = dataclasses.field(default_factory=dict) # Whether var dependencies should be auto-determined _auto_deps: bool = dataclasses.field(default=True) @@ -2062,34 +2062,62 @@ class ComputedVar(Var[RETURN_TYPE]): object.__setattr__(self, "_fget", fget) def _calculate_static_deps( - self, deps: Union[List[Union[str, Var]], dict[str, set[str]]] | None = None - ) -> dict[str, set[str]]: + self, + deps: Union[List[Union[str, Var]], dict[str | None, set[str]]] | None = None, + ) -> dict[str | None, set[str]]: + """Calculate the static dependencies of the computed var from user input or existing dependencies. + + Args: + deps: The user input dependencies or existing dependencies. + + Returns: + The static dependencies. + """ if isinstance(deps, dict): # Assume a dict is coming from _replace, so no special processing. return deps _static_deps = {} if deps is not None: for dep in deps: - if isinstance(dep, Var): - state_name = ( - all_var_data.state - if (all_var_data := dep._get_all_var_data()) - and all_var_data.state - else None - ) - if all_var_data is not None: - var_name = all_var_data.field_name - else: - var_name = dep._js_expr - _static_deps.setdefault(state_name, set()).add(var_name) - elif isinstance(dep, str) and dep != "": - _static_deps.setdefault(None, set()).add(dep) - else: - raise TypeError( - "ComputedVar dependencies must be Var instances or var names (non-empty strings)." - ) + _static_deps = self._add_static_dep(dep, _static_deps) return _static_deps + def _add_static_dep( + self, dep: Union[str, Var], deps: dict[str | None, set[str]] | None = None + ) -> dict[str | None, set[str]]: + """Add a static dependency to the computed var or existing dependency set. + + Args: + dep: The dependency to add. + deps: The existing dependency set. + + Returns: + The updated dependency set. + + Raises: + TypeError: If the computed var dependencies are not Var instances or var names. + """ + if deps is None: + deps = self._static_deps + if isinstance(dep, Var): + state_name = ( + all_var_data.state + if (all_var_data := dep._get_all_var_data()) and all_var_data.state + else None + ) + if all_var_data is not None: + var_name = all_var_data.field_name + else: + var_name = dep._js_expr + deps.setdefault(state_name, set()).add(var_name) + elif isinstance(dep, str) and dep != "": + deps.setdefault(None, set()).add(dep) + else: + raise TypeError( + "ComputedVar dependencies must be Var instances or var names (non-empty strings)." + ) + return deps + @override def _replace( self,