diff --git a/reflex/vars.py b/reflex/vars.py index afe3e60c3..f226d88bd 100644 --- a/reflex/vars.py +++ b/reflex/vars.py @@ -496,6 +496,9 @@ class Var: Returns: A new BaseVar with the updated fields overwriting the corresponding fields in this Var. + + Raises: + TypeError: If kwargs contains keys that are not allowed. """ field_values = dict( _var_name=kwargs.pop("_var_name", self._var_name), @@ -507,9 +510,14 @@ class Var: self._var_full_name_needs_state_prefix, ), _var_data=VarData.merge( - kwargs.get("_var_data", self._var_data), merge_var_data + kwargs.pop("_var_data", self._var_data), merge_var_data ), ) + + if kwargs: + unexpected_kwargs = ", ".join(kwargs.keys()) + raise TypeError(f"Unexpected keyword arguments: {unexpected_kwargs}") + return BaseVar(**field_values) def _decode(self) -> Any: @@ -2024,26 +2032,35 @@ class ComputedVar(Var, property): Returns: The new ComputedVar instance. + + Raises: + TypeError: If kwargs contains keys that are not allowed. """ - return ComputedVar( - fget=kwargs.get("fget", self.fget), - initial_value=kwargs.get("initial_value", self._initial_value), - cache=kwargs.get("cache", self._cache), - deps=kwargs.get("deps", self._static_deps), - auto_deps=kwargs.get("auto_deps", self._auto_deps), - interval=kwargs.get("interval", self._update_interval), - backend=kwargs.get("backend", self._backend), - _var_name=kwargs.get("_var_name", self._var_name), - _var_type=kwargs.get("_var_type", self._var_type), - _var_is_local=kwargs.get("_var_is_local", self._var_is_local), - _var_is_string=kwargs.get("_var_is_string", self._var_is_string), - _var_full_name_needs_state_prefix=kwargs.get( + field_values = dict( + fget=kwargs.pop("fget", self.fget), + initial_value=kwargs.pop("initial_value", self._initial_value), + cache=kwargs.pop("cache", self._cache), + deps=kwargs.pop("deps", self._static_deps), + auto_deps=kwargs.pop("auto_deps", self._auto_deps), + interval=kwargs.pop("interval", self._update_interval), + backend=kwargs.pop("backend", self._backend), + _var_name=kwargs.pop("_var_name", self._var_name), + _var_type=kwargs.pop("_var_type", self._var_type), + _var_is_local=kwargs.pop("_var_is_local", self._var_is_local), + _var_is_string=kwargs.pop("_var_is_string", self._var_is_string), + _var_full_name_needs_state_prefix=kwargs.pop( "_var_full_name_needs_state_prefix", self._var_full_name_needs_state_prefix, ), _var_data=VarData.merge(self._var_data, merge_var_data), ) + if kwargs: + unexpected_kwargs = ", ".join(kwargs.keys()) + raise TypeError(f"Unexpected keyword arguments: {unexpected_kwargs}") + + return ComputedVar(**field_values) + @property def _cache_attr(self) -> str: """Get the attribute used to cache the value on the instance. diff --git a/tests/test_var.py b/tests/test_var.py index e58daaa03..918d3a177 100644 --- a/tests/test_var.py +++ b/tests/test_var.py @@ -539,6 +539,29 @@ def test_var_indexing_str(): assert str(str_var[-1]) == "{str.at(-1)}" +@pytest.mark.parametrize( + "var", + [ + (BaseVar(_var_name="foo", _var_type=int)), + (BaseVar(_var_name="bar", _var_type=float)), + ], +) +def test_var_replace_with_invalid_kwargs(var): + with pytest.raises(TypeError) as excinfo: + var._replace(_this_should_fail=True) + assert "Unexpected keyword arguments" in str(excinfo.value) + + +def test_computed_var_replace_with_invalid_kwargs(): + @computed_var(initial_value=1) + def test_var(state) -> int: + return 1 + + with pytest.raises(TypeError) as excinfo: + test_var._replace(_random_kwarg=True) + assert "Unexpected keyword arguments" in str(excinfo.value) + + @pytest.mark.parametrize( "var, index", [