Download agent/async_utils.py from SaylorTwift/hermes-agent: direct link, hf CLI and curl.
- Browser
- Download file 2.05 kB
-
https://huggingface.co/SaylorTwift/hermes-agent/resolve/main/agent/async_utils.py
- Command line
-
hf download hf://SaylorTwift/hermes-agent/agent/async_utils.py
-
curl -L -o async_utils.py https://huggingface.co/SaylorTwift/hermes-agent/resolve/main/agent/async_utils.py
2.05 kB
| """Async/sync bridging helpers. | |
| ``asyncio.run_coroutine_threadsafe`` can raise ``RuntimeError`` (loop closed during a | |
| shutdown race); the coroutine is then never awaited or closed, which triggers a | |
| "coroutine was never awaited" RuntimeWarning and leaks its frame. The helpers here | |
| close the coroutine on scheduling failure. ``future.result()`` failures are deliberately | |
| NOT handled: once the loop accepts the coroutine its lifecycle belongs to the loop. | |
| """ | |
| from __future__ import annotations | |
| import asyncio | |
| import logging | |
| from concurrent.futures import Future | |
| from typing import Any, Coroutine, Optional | |
| _DEFAULT_LOGGER = logging.getLogger(__name__) | |
| def safe_schedule_threadsafe( | |
| coro: Coroutine[Any, Any, Any], loop: Optional[asyncio.AbstractEventLoop], *, | |
| logger: Optional[logging.Logger] = None, | |
| log_message: str = "Failed to schedule coroutine on loop", log_level: int = logging.DEBUG, | |
| ) -> Optional[Future]: | |
| """Schedule ``coro`` on ``loop`` from a sync context, leak-safe. | |
| Returns the Future on success, or ``None`` if the loop is missing or scheduling | |
| raised; in every failure path the coroutine is closed. Callers keep full control | |
| over the returned future (``.result(timeout=...)``, callbacks, fire-and-forget). | |
| """ | |
| log = logger if logger is not None else _DEFAULT_LOGGER | |
| try: | |
| if loop is None: | |
| raise RuntimeError("loop is None") | |
| return asyncio.run_coroutine_threadsafe(coro, loop) | |
| except Exception as exc: | |
| if asyncio.iscoroutine(coro): | |
| coro.close() | |
| log.log(log_level, "%s: %s", log_message, exc) | |
| return None | |
| def consume_detached_task_result(task: "asyncio.Future[Any]") -> None: | |
| """``add_done_callback`` for cancelled-and-detached tasks: observe the exception so the | |
| loop does not log "exception was never retrieved"; cancellation and terminal errors | |
| are swallowed because the task's owner already gave up on it.""" | |
| try: | |
| task.exception() | |
| except (asyncio.CancelledError, Exception): | |
| pass | |