Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow bound method as event handler #4348

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions reflex/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -1345,6 +1345,10 @@ def check_fn_match_arg_spec(
EventFnArgMismatch: Raised if the number of mandatory arguments do not match
"""
user_args = inspect.getfullargspec(user_func).args
# Drop the first argument if it's a bound method
if inspect.ismethod(user_func) and user_func.__self__ is not None:
user_args = user_args[1:]

user_default_args = inspect.getfullargspec(user_func).defaults
number_of_user_args = len(user_args) - number_of_bound_args
number_of_user_default_args = len(user_default_args) if user_default_args else 0
Expand Down
15 changes: 15 additions & 0 deletions tests/units/test_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import pytest

import reflex as rx
from reflex.event import (
Event,
EventChain,
Expand Down Expand Up @@ -439,3 +440,17 @@ def _args_spec(value: Var[int]) -> tuple[Var[int]]:
# Ensure chain carries _var_data
chain_var = Var.create(EventChain(events=[S.s(S.x)], args_spec=_args_spec))
assert chain_var._get_all_var_data() == S.x._get_all_var_data()


def test_event_bound_method() -> None:
class S(BaseState):
@event
def e(self, arg: str):
print(arg)

class Wrapper:
def get_handler(self, arg: str):
return S.e(arg)

w = Wrapper()
_ = rx.input(on_change=w.get_handler)
Loading