Переглянути джерело

[REF-3160] fix rx.Var._replace raise TypeError on invalid kwargs (#3625)

* fix: unexpected kwargs raise type error, on _replace

* add: docstring for _replace, test for invalid kwargs replace

* add: parametrize var for replace test

* fix: computed_var _replace with invalid kwargs
Jishnu N 10 місяців тому
батько
коміт
690b719437
2 змінених файлів з 54 додано та 14 видалено
  1. 31 14
      reflex/vars.py
  2. 23 0
      tests/test_var.py

+ 31 - 14
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.

+ 23 - 0
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",
     [