diff --git a/src/python/app.py b/src/python/app.py index 80635a05..7d6a445e 100644 --- a/src/python/app.py +++ b/src/python/app.py @@ -61,9 +61,17 @@ class App: def _call_coro(self, coro: Coroutine, uuid: str) -> None: - self.run_in_loop(coro).add_done_callback( - lambda future: CoroutineDone(uuid=uuid, result=future.result()), - ) + def on_done(future: Future) -> None: + try: + result = future.result() + exception = None + except Exception as err: + result = None + exception = err + + CoroutineDone(uuid, result, exception) + + self.run_in_loop(coro).add_done_callback(on_done) def call_backend_coro(self, name: str, uuid: str, args: Sequence[str] = (), diff --git a/src/python/pyotherside_events.py b/src/python/pyotherside_events.py index ba3a7999..3a7e88b3 100644 --- a/src/python/pyotherside_events.py +++ b/src/python/pyotherside_events.py @@ -1,6 +1,6 @@ from dataclasses import dataclass, field from enum import Enum -from typing import Any, Dict, List, Union +from typing import Any, Dict, List, Optional, Union import pyotherside @@ -47,8 +47,9 @@ class AlertRequested(PyOtherSideEvent): class CoroutineDone(PyOtherSideEvent): """Indicate that an asyncio coroutine finished.""" - uuid: str = field() - result: Any = None + uuid: str = field() + result: Any = None + exception: Optional[Exception] = None @dataclass diff --git a/src/qml/Python.qml b/src/qml/Python.qml index 39f7f855..525e613e 100644 --- a/src/qml/Python.qml +++ b/src/qml/Python.qml @@ -14,18 +14,20 @@ Python { return call_sync("APP.backend." + name, args) } - function callCoro(name, args=[], callback=null) { + function callCoro(name, args=[], onSuccess=null, onError=null) { let uuid = Math.random() + "." + name - pendingCoroutines[uuid] = callback || function() {} + pendingCoroutines[uuid] = {onSuccess, onError} call("APP.call_backend_coro", [name, uuid, args]) } - function callClientCoro(accountId, name, args=[], callback=null) { + function callClientCoro( + accountId, name, args=[], onSuccess=null, onError=null + ) { callCoro("wait_until_client_exists", [accountId], () => { let uuid = Math.random() + "." + name - pendingCoroutines[uuid] = callback || function() {} + pendingCoroutines[uuid] = {onSuccess, onError} call("APP.call_client_coro", [accountId, name, uuid, args]) }) } diff --git a/src/qml/event_handlers.js b/src/qml/event_handlers.js index e0465b92..2d2f2a57 100644 --- a/src/qml/event_handlers.js +++ b/src/qml/event_handlers.js @@ -13,8 +13,20 @@ function onAlertRequested() { } -function onCoroutineDone(uuid, result) { - py.pendingCoroutines[uuid](result) +function onCoroutineDone(uuid, result, error) { + let onSuccess = py.pendingCoroutines[uuid].onSuccess + let onError = py.pendingCoroutines[uuid].onError + + if (error) { + let type = py.getattr(py.getattr(error, "__class__"), "__name__") + let args = py.getattr(error, "args") + + onError ? + onError(type, args, error) : + console.error(uuid + ": " + type + ": " + args) + + } else if (onSuccess) { onSuccess(result) } + delete pendingCoroutines[uuid] }