Skip to content
Draft
1 change: 1 addition & 0 deletions packages/reflex-base/news/7397.misc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
`LambdaEventCallback.__code__` is now declared read-only, matching bound methods such as `ClientStateVar.set_value`, whose `__code__` cannot be assigned.
12 changes: 11 additions & 1 deletion packages/reflex-base/src/reflex_base/event/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3054,7 +3054,17 @@ def __get__(self, instance: Any, owner: Any) -> Callable:
class LambdaEventCallback(Protocol[*P]):
"""A protocol for a lambda event callback."""

__code__: types.CodeType
@property
def __code__(self) -> types.CodeType:
Comment thread
benedikt-bartscher marked this conversation as resolved.
Resolved
Comment thread
greptile-apps[bot] marked this conversation as resolved.
Resolved
"""The code object of the callback.

Read-only, so a bound method, whose ``__code__`` is a read-only view of
its function's, satisfies the protocol as well as a function or lambda.

Returns:
The code object.
"""
...

@overload
def __call__(self: "LambdaEventCallback[()]") -> Any: ...
Expand Down
14 changes: 14 additions & 0 deletions tests/units/test_event.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import inspect
import json
import logging
import shutil
Expand Down Expand Up @@ -1293,6 +1294,19 @@ def return_plain_callable_var(_v: Var[Any]) -> Any:
)


def test_lambda_event_callback_only_requires_a_readable_code_object():
"""Bound methods expose a read-only ``__code__``, so the protocol must not need a settable one."""

class Handlers:
def on_value(self, value: str) -> None: ...

assert Handlers().on_value.__code__ is Handlers.on_value.__code__

code = inspect.getattr_static(LambdaEventCallback, "__code__")
assert isinstance(code, property)
assert code.fset is None


def test_event_chain_create_accepts_a_tuple_of_events():
"""A tuple of events binds into the same chain as a list of them."""
events = (_handler_with_arg()(1), rx.console_log("logged"))
Expand Down
Loading