fix: async default setters break setvar (#4169)

* fix: async default setters break setvar

* fix unit test
This commit is contained in:
benedikt-bartscher 2024-10-24 23:27:35 +02:00 committed by GitHub
parent d0c1eb7488
commit c0ed8b7d91
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 30 additions and 1 deletions

View File

@ -220,6 +220,7 @@ class EventHandlerSetVar(EventHandler):
Raises:
AttributeError: If the given Var name does not exist on the state.
EventHandlerValueError: If the given Var name is not a str
NotImplementedError: If the setter for the given Var is async
"""
from reflex.utils.exceptions import EventHandlerValueError
@ -228,11 +229,20 @@ class EventHandlerSetVar(EventHandler):
raise EventHandlerValueError(
f"Var name must be passed as a string, got {args[0]!r}"
)
handler = getattr(self.state_cls, constants.SETTER_PREFIX + args[0], None)
# Check that the requested Var setter exists on the State at compile time.
if getattr(self.state_cls, constants.SETTER_PREFIX + args[0], None) is None:
if handler is None:
raise AttributeError(
f"Variable `{args[0]}` cannot be set on `{self.state_cls.get_full_name()}`"
)
if asyncio.iscoroutinefunction(handler.fn):
raise NotImplementedError(
f"Setter for {args[0]} is async, which is not supported."
)
return super().__call__(*args)

View File

@ -106,6 +106,7 @@ class TestState(BaseState):
fig: Figure = Figure()
dt: datetime.datetime = datetime.datetime.fromisoformat("1989-11-09T18:53:00+01:00")
_backend: int = 0
asynctest: int = 0
@ComputedVar
def sum(self) -> float:
@ -129,6 +130,14 @@ class TestState(BaseState):
"""Do something."""
pass
async def set_asynctest(self, value: int):
"""Set the asynctest value. Intentionally overwrite the default setter with an async one.
Args:
value: The new value.
"""
self.asynctest = value
class ChildState(TestState):
"""A child state fixture."""
@ -313,6 +322,7 @@ def test_class_vars(test_state):
"upper",
"fig",
"dt",
"asynctest",
}
@ -733,6 +743,7 @@ def test_reset(test_state, child_state):
"mapping",
"dt",
"_backend",
"asynctest",
}
# The dirty vars should be reset.
@ -3179,6 +3190,13 @@ async def test_setvar(mock_app: rx.App, token: str):
TestState.setvar(42, 42)
@pytest.mark.asyncio
async def test_setvar_async_setter():
"""Test that overridden async setters raise Exception when used with setvar."""
with pytest.raises(NotImplementedError):
TestState.setvar("asynctest", 42)
@pytest.mark.skipif("REDIS_URL" not in os.environ, reason="Test requires redis")
@pytest.mark.parametrize(
"expiration_kwargs, expected_values",

View File

@ -601,6 +601,7 @@ formatted_router = {
"sum": 3.14,
"upper": "",
"router": formatted_router,
"asynctest": 0,
},
ChildState.get_full_name(): {
"count": 23,