Spaces:
Sleeping
Sleeping
File size: 1,316 Bytes
c509967 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | """Async helpers shared across ChemGraph CLI and UI."""
from __future__ import annotations
import asyncio
import threading
from typing import Any, Callable
def run_async_callable(fn: Callable[..., Any]) -> Any:
"""Run an async callable and return its result in a sync context.
If no event loop is running, uses ``asyncio.run`` directly.
Otherwise, spawns a daemon thread so that the call does not
conflict with an already-running loop (e.g. inside Streamlit).
Parameters
----------
fn : Callable[..., Any]
Zero-argument callable that returns an awaitable.
Returns
-------
Any
Result of the awaited callable.
"""
try:
asyncio.get_running_loop()
except RuntimeError:
return asyncio.run(fn())
result_container: dict[str, Any] = {}
error_container: dict[str, Exception] = {}
def runner() -> None:
"""Run the awaitable in a background event loop."""
try:
result_container["value"] = asyncio.run(fn())
except Exception as exc:
error_container["error"] = exc
thread = threading.Thread(target=runner, daemon=True)
thread.start()
thread.join()
if "error" in error_container:
raise error_container["error"]
return result_container.get("value")
|