Make argument optional for event handlers (#950)
This commit is contained in:
parent
b4e534cc97
commit
893c0b132e
@ -220,7 +220,9 @@ class Component(Base, ABC):
|
|||||||
event = call_event_handler(v, arg)
|
event = call_event_handler(v, arg)
|
||||||
|
|
||||||
# Check that the event handler takes no args if it's uncontrolled.
|
# Check that the event handler takes no args if it's uncontrolled.
|
||||||
if not is_controlled_event and len(event.args) > 0:
|
if not is_controlled_event and (
|
||||||
|
event.args is not None and len(event.args) > 0
|
||||||
|
):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Event handler: {v.fn} for uncontrolled event {event_trigger} should not take any args."
|
f"Event handler: {v.fn} for uncontrolled event {event_trigger} should not take any args."
|
||||||
)
|
)
|
||||||
|
@ -90,7 +90,7 @@ class EventSpec(Base):
|
|||||||
local_args: Tuple[Var, ...] = ()
|
local_args: Tuple[Var, ...] = ()
|
||||||
|
|
||||||
# The arguments to pass to the function.
|
# The arguments to pass to the function.
|
||||||
args: Tuple[Tuple[Var, Var], ...] = ()
|
args: Optional[Tuple[Tuple[Var, Var], ...]] = ()
|
||||||
|
|
||||||
# Whether to upload files.
|
# Whether to upload files.
|
||||||
upload: bool = False
|
upload: bool = False
|
||||||
@ -318,7 +318,9 @@ def call_event_fn(fn: Callable, arg: Var) -> List[EventSpec]:
|
|||||||
return events
|
return events
|
||||||
|
|
||||||
|
|
||||||
def get_handler_args(event_spec: EventSpec, arg: Var) -> Tuple[Tuple[Var, Var], ...]:
|
def get_handler_args(
|
||||||
|
event_spec: EventSpec, arg: Var
|
||||||
|
) -> Optional[Tuple[Tuple[Var, Var], ...]]:
|
||||||
"""Get the handler args for the given event spec.
|
"""Get the handler args for the given event spec.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -327,16 +329,14 @@ def get_handler_args(event_spec: EventSpec, arg: Var) -> Tuple[Tuple[Var, Var],
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The handler args.
|
The handler args.
|
||||||
|
|
||||||
Raises:
|
|
||||||
ValueError: If the event handler has an invalid signature.
|
|
||||||
"""
|
"""
|
||||||
args = inspect.getfullargspec(event_spec.handler.fn).args
|
args = inspect.getfullargspec(event_spec.handler.fn).args
|
||||||
if len(args) < 2:
|
|
||||||
raise ValueError(
|
return (
|
||||||
f"Event handler has an invalid signature, needed a method with a parameter, got {event_spec.handler}."
|
event_spec.args
|
||||||
)
|
if len(args) > 2
|
||||||
return event_spec.args if len(args) > 2 else ((Var.create_safe(args[1]), arg),)
|
else (((Var.create_safe(args[1]), arg),) if len(args) == 2 else None)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def fix_events(
|
def fix_events(
|
||||||
@ -369,7 +369,7 @@ def fix_events(
|
|||||||
e = e()
|
e = e()
|
||||||
assert isinstance(e, EventSpec), f"Unexpected event type, {type(e)}."
|
assert isinstance(e, EventSpec), f"Unexpected event type, {type(e)}."
|
||||||
name = format.format_event_handler(e.handler)
|
name = format.format_event_handler(e.handler)
|
||||||
payload = {k.name: v.name for k, v in e.args}
|
payload = {k.name: v.name for k, v in e.args} if e.args else {}
|
||||||
|
|
||||||
# Create an event and append it to the list.
|
# Create an event and append it to the list.
|
||||||
out.append(
|
out.append(
|
||||||
|
@ -286,11 +286,17 @@ def format_event(event_spec: EventSpec) -> str:
|
|||||||
Returns:
|
Returns:
|
||||||
The compiled event.
|
The compiled event.
|
||||||
"""
|
"""
|
||||||
args = ",".join(
|
args = (
|
||||||
[
|
",".join(
|
||||||
":".join((name.name, json.dumps(val.name) if val.is_string else val.name))
|
[
|
||||||
for name, val in event_spec.args
|
":".join(
|
||||||
]
|
(name.name, json.dumps(val.name) if val.is_string else val.name)
|
||||||
|
)
|
||||||
|
for name, val in event_spec.args
|
||||||
|
]
|
||||||
|
)
|
||||||
|
if event_spec.args is not None
|
||||||
|
else ""
|
||||||
)
|
)
|
||||||
return f"E(\"{format_event_handler(event_spec.handler)}\", {wrap(args, '{')})"
|
return f"E(\"{format_event_handler(event_spec.handler)}\", {wrap(args, '{')})"
|
||||||
|
|
||||||
@ -323,7 +329,7 @@ def format_full_control_event(event_chain: EventChain) -> str:
|
|||||||
from pynecone.compiler import templates
|
from pynecone.compiler import templates
|
||||||
|
|
||||||
event_spec = event_chain.events[0]
|
event_spec = event_chain.events[0]
|
||||||
arg = event_spec.args[0][1]
|
arg = event_spec.args[0][1] if event_spec.args else None
|
||||||
state_name = event_chain.state_name
|
state_name = event_chain.state_name
|
||||||
chain = ",".join([format_event(event) for event in event_chain.events])
|
chain = ",".join([format_event(event) for event in event_chain.events])
|
||||||
event = templates.FULL_CONTROL(state_name=state_name, arg=arg, chain=chain)
|
event = templates.FULL_CONTROL(state_name=state_name, arg=arg, chain=chain)
|
||||||
|
@ -391,13 +391,10 @@ def test_invalid_event_handler_args(component2, test_state):
|
|||||||
# Controlled event handlers should take args.
|
# Controlled event handlers should take args.
|
||||||
# This is okay.
|
# This is okay.
|
||||||
component2.create(on_open=test_state.do_something_arg)
|
component2.create(on_open=test_state.do_something_arg)
|
||||||
# This is not okay.
|
|
||||||
with pytest.raises(ValueError):
|
# do_something is allowed and will simply run while ignoring the arg
|
||||||
component2.create(on_open=test_state.do_something)
|
component2.create(on_open=test_state.do_something)
|
||||||
with pytest.raises(ValueError):
|
component2.create(on_open=[test_state.do_something_arg, test_state.do_something])
|
||||||
component2.create(
|
|
||||||
on_open=[test_state.do_something_arg, test_state.do_something]
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_hooks_nested(component1, component2, component3):
|
def test_get_hooks_nested(component1, component2, component3):
|
||||||
|
Loading…
Reference in New Issue
Block a user