Call special events from event triggers (#601)
This commit is contained in:
parent
f76acb2d9c
commit
6c8ce67b8b
@ -159,7 +159,9 @@ class Component(Base, ABC):
|
||||
def _create_event_chain(
|
||||
self,
|
||||
event_trigger: str,
|
||||
value: Union[Var, EventHandler, List[EventHandler], Callable],
|
||||
value: Union[
|
||||
Var, EventHandler, EventSpec, List[Union[EventHandler, EventSpec]], Callable
|
||||
],
|
||||
) -> Union[EventChain, Var]:
|
||||
"""Create an event chain from a variety of input types.
|
||||
|
||||
@ -186,7 +188,7 @@ class Component(Base, ABC):
|
||||
arg = controlled_triggers.get(event_trigger, EVENT_ARG)
|
||||
|
||||
# If the input is a single event handler, wrap it in a list.
|
||||
if isinstance(value, EventHandler):
|
||||
if isinstance(value, (EventHandler, EventSpec)):
|
||||
value = [value]
|
||||
|
||||
# If the input is a list of event handlers, create an event chain.
|
||||
@ -205,6 +207,9 @@ class Component(Base, ABC):
|
||||
|
||||
# Add the event to the chain.
|
||||
events.append(event)
|
||||
elif isinstance(v, EventSpec):
|
||||
# Add the event to the chain.
|
||||
events.append(v)
|
||||
elif isinstance(v, Callable):
|
||||
# Call the lambda to get the event chain.
|
||||
events.extend(utils.call_event_fn(v, arg))
|
||||
|
@ -123,7 +123,7 @@ EVENT_ARG = BaseVar(name="_e", type_=FrontendEvent, is_local=True)
|
||||
|
||||
|
||||
# Special server-side events.
|
||||
def redirect(path: str) -> Event:
|
||||
def redirect(path: str) -> EventSpec:
|
||||
"""Redirect to a new path.
|
||||
|
||||
Args:
|
||||
@ -132,14 +132,18 @@ def redirect(path: str) -> Event:
|
||||
Returns:
|
||||
An event to redirect to the path.
|
||||
"""
|
||||
return Event(
|
||||
token="",
|
||||
name="_redirect",
|
||||
payload={"path": path},
|
||||
|
||||
def fn():
|
||||
return None
|
||||
|
||||
fn.__qualname__ = "_redirect"
|
||||
return EventSpec(
|
||||
handler=EventHandler(fn=fn),
|
||||
args=(("path", path),),
|
||||
)
|
||||
|
||||
|
||||
def console_log(message: str) -> Event:
|
||||
def console_log(message: str) -> EventSpec:
|
||||
"""Do a console.log on the browser.
|
||||
|
||||
Args:
|
||||
@ -148,14 +152,18 @@ def console_log(message: str) -> Event:
|
||||
Returns:
|
||||
An event to log the message.
|
||||
"""
|
||||
return Event(
|
||||
token="",
|
||||
name="_console",
|
||||
payload={"message": message},
|
||||
|
||||
def fn():
|
||||
return None
|
||||
|
||||
fn.__qualname__ = "_console"
|
||||
return EventSpec(
|
||||
handler=EventHandler(fn=fn),
|
||||
args=(("message", message),),
|
||||
)
|
||||
|
||||
|
||||
def window_alert(message: str) -> Event:
|
||||
def window_alert(message: str) -> EventSpec:
|
||||
"""Create a window alert on the browser.
|
||||
|
||||
Args:
|
||||
@ -164,10 +172,14 @@ def window_alert(message: str) -> Event:
|
||||
Returns:
|
||||
An event to alert the message.
|
||||
"""
|
||||
return Event(
|
||||
token="",
|
||||
name="_alert",
|
||||
payload={"message": message},
|
||||
|
||||
def fn():
|
||||
return None
|
||||
|
||||
fn.__qualname__ = "_alert"
|
||||
return EventSpec(
|
||||
handler=EventHandler(fn=fn),
|
||||
args=(("message", message),),
|
||||
)
|
||||
|
||||
|
||||
|
@ -545,9 +545,10 @@ class State(Base, ABC):
|
||||
except Exception:
|
||||
error = traceback.format_exc()
|
||||
print(error)
|
||||
return StateUpdate(
|
||||
events=[window_alert("An error occurred. See logs for details.")]
|
||||
events = utils.fix_events(
|
||||
[window_alert("An error occurred. See logs for details.")], event.token
|
||||
)
|
||||
return StateUpdate(events=events)
|
||||
|
||||
# Fix the returned events.
|
||||
events = utils.fix_events(events, event.token)
|
||||
|
@ -1421,7 +1421,9 @@ def get_handler_args(event_spec: EventSpec, arg: Var) -> Tuple[Tuple[str, str],
|
||||
return event_spec.args if len(args) > 2 else ((args[1], arg.name),)
|
||||
|
||||
|
||||
def fix_events(events: Optional[List[Event]], token: str) -> List[Event]:
|
||||
def fix_events(
|
||||
events: Optional[List[Union[EventHandler, EventSpec]]], token: str
|
||||
) -> List[Event]:
|
||||
"""Fix a list of events returned by an event handler.
|
||||
|
||||
Args:
|
||||
@ -1444,18 +1446,12 @@ def fix_events(events: Optional[List[Event]], token: str) -> List[Event]:
|
||||
# Fix the events created by the handler.
|
||||
out = []
|
||||
for e in events:
|
||||
# If it is already an event, don't modify it.
|
||||
if isinstance(e, Event):
|
||||
name = e.name
|
||||
payload = e.payload
|
||||
|
||||
# Otherwise, create an event from the event spec.
|
||||
else:
|
||||
if isinstance(e, EventHandler):
|
||||
e = e()
|
||||
assert isinstance(e, EventSpec), f"Unexpected event type, {type(e)}."
|
||||
name = format_event_handler(e.handler)
|
||||
payload = dict(e.args)
|
||||
if isinstance(e, EventHandler):
|
||||
e = e()
|
||||
assert isinstance(e, EventSpec), f"Unexpected event type, {type(e)}."
|
||||
name = format_event_handler(e.handler)
|
||||
payload = dict(e.args)
|
||||
|
||||
# Create an event and append it to the list.
|
||||
out.append(
|
||||
|
@ -1,4 +1,5 @@
|
||||
from pynecone.event import Event, EventHandler
|
||||
from pynecone import event
|
||||
from pynecone.event import Event, EventHandler, EventSpec
|
||||
from pynecone.var import Var
|
||||
|
||||
|
||||
@ -46,3 +47,27 @@ def test_call_event_handler():
|
||||
assert event_spec.handler == handler
|
||||
assert event_spec.local_args == ()
|
||||
assert event_spec.args == (("arg1", "first"), ("arg2", "second"))
|
||||
|
||||
|
||||
def test_event_redirect():
|
||||
"""Test the event redirect function."""
|
||||
spec = event.redirect("/path")
|
||||
assert isinstance(spec, EventSpec)
|
||||
assert spec.handler.fn.__qualname__ == "_redirect"
|
||||
assert spec.args == (("path", "/path"),)
|
||||
|
||||
|
||||
def test_event_console_log():
|
||||
"""Test the event console log function."""
|
||||
spec = event.console_log("message")
|
||||
assert isinstance(spec, EventSpec)
|
||||
assert spec.handler.fn.__qualname__ == "_console"
|
||||
assert spec.args == (("message", "message"),)
|
||||
|
||||
|
||||
def test_event_window_alert():
|
||||
"""Test the event window alert function."""
|
||||
spec = event.window_alert("message")
|
||||
assert isinstance(spec, EventSpec)
|
||||
assert spec.handler.fn.__qualname__ == "_alert"
|
||||
assert spec.args == (("message", "message"),)
|
||||
|
Loading…
Reference in New Issue
Block a user