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(
|
def _create_event_chain(
|
||||||
self,
|
self,
|
||||||
event_trigger: str,
|
event_trigger: str,
|
||||||
value: Union[Var, EventHandler, List[EventHandler], Callable],
|
value: Union[
|
||||||
|
Var, EventHandler, EventSpec, List[Union[EventHandler, EventSpec]], Callable
|
||||||
|
],
|
||||||
) -> Union[EventChain, Var]:
|
) -> Union[EventChain, Var]:
|
||||||
"""Create an event chain from a variety of input types.
|
"""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)
|
arg = controlled_triggers.get(event_trigger, EVENT_ARG)
|
||||||
|
|
||||||
# If the input is a single event handler, wrap it in a list.
|
# If the input is a single event handler, wrap it in a list.
|
||||||
if isinstance(value, EventHandler):
|
if isinstance(value, (EventHandler, EventSpec)):
|
||||||
value = [value]
|
value = [value]
|
||||||
|
|
||||||
# If the input is a list of event handlers, create an event chain.
|
# 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.
|
# Add the event to the chain.
|
||||||
events.append(event)
|
events.append(event)
|
||||||
|
elif isinstance(v, EventSpec):
|
||||||
|
# Add the event to the chain.
|
||||||
|
events.append(v)
|
||||||
elif isinstance(v, Callable):
|
elif isinstance(v, Callable):
|
||||||
# Call the lambda to get the event chain.
|
# Call the lambda to get the event chain.
|
||||||
events.extend(utils.call_event_fn(v, arg))
|
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.
|
# Special server-side events.
|
||||||
def redirect(path: str) -> Event:
|
def redirect(path: str) -> EventSpec:
|
||||||
"""Redirect to a new path.
|
"""Redirect to a new path.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -132,14 +132,18 @@ def redirect(path: str) -> Event:
|
|||||||
Returns:
|
Returns:
|
||||||
An event to redirect to the path.
|
An event to redirect to the path.
|
||||||
"""
|
"""
|
||||||
return Event(
|
|
||||||
token="",
|
def fn():
|
||||||
name="_redirect",
|
return None
|
||||||
payload={"path": path},
|
|
||||||
|
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.
|
"""Do a console.log on the browser.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -148,14 +152,18 @@ def console_log(message: str) -> Event:
|
|||||||
Returns:
|
Returns:
|
||||||
An event to log the message.
|
An event to log the message.
|
||||||
"""
|
"""
|
||||||
return Event(
|
|
||||||
token="",
|
def fn():
|
||||||
name="_console",
|
return None
|
||||||
payload={"message": message},
|
|
||||||
|
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.
|
"""Create a window alert on the browser.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -164,10 +172,14 @@ def window_alert(message: str) -> Event:
|
|||||||
Returns:
|
Returns:
|
||||||
An event to alert the message.
|
An event to alert the message.
|
||||||
"""
|
"""
|
||||||
return Event(
|
|
||||||
token="",
|
def fn():
|
||||||
name="_alert",
|
return None
|
||||||
payload={"message": message},
|
|
||||||
|
fn.__qualname__ = "_alert"
|
||||||
|
return EventSpec(
|
||||||
|
handler=EventHandler(fn=fn),
|
||||||
|
args=(("message", message),),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -545,9 +545,10 @@ class State(Base, ABC):
|
|||||||
except Exception:
|
except Exception:
|
||||||
error = traceback.format_exc()
|
error = traceback.format_exc()
|
||||||
print(error)
|
print(error)
|
||||||
return StateUpdate(
|
events = utils.fix_events(
|
||||||
events=[window_alert("An error occurred. See logs for details.")]
|
[window_alert("An error occurred. See logs for details.")], event.token
|
||||||
)
|
)
|
||||||
|
return StateUpdate(events=events)
|
||||||
|
|
||||||
# Fix the returned events.
|
# Fix the returned events.
|
||||||
events = utils.fix_events(events, event.token)
|
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),)
|
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.
|
"""Fix a list of events returned by an event handler.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -1444,13 +1446,7 @@ def fix_events(events: Optional[List[Event]], token: str) -> List[Event]:
|
|||||||
# Fix the events created by the handler.
|
# Fix the events created by the handler.
|
||||||
out = []
|
out = []
|
||||||
for e in events:
|
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.
|
# Otherwise, create an event from the event spec.
|
||||||
else:
|
|
||||||
if isinstance(e, EventHandler):
|
if isinstance(e, EventHandler):
|
||||||
e = e()
|
e = e()
|
||||||
assert isinstance(e, EventSpec), f"Unexpected event type, {type(e)}."
|
assert isinstance(e, EventSpec), f"Unexpected event type, {type(e)}."
|
||||||
|
@ -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
|
from pynecone.var import Var
|
||||||
|
|
||||||
|
|
||||||
@ -46,3 +47,27 @@ def test_call_event_handler():
|
|||||||
assert event_spec.handler == handler
|
assert event_spec.handler == handler
|
||||||
assert event_spec.local_args == ()
|
assert event_spec.local_args == ()
|
||||||
assert event_spec.args == (("arg1", "first"), ("arg2", "second"))
|
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