import asyncio from typing import Callable, TypeVar from wandb.sdk import wandb_setup from wandb.sdk.lib import asyncio_compat, printer _T = TypeVar("_T") def run_async_with_spinner( spinner_printer: printer.Printer, text: str, func: Callable[[], _T], ) -> _T: """Run a slow function while displaying a loading icon. Args: spinner_printer: The printer to use to display text. text: The text to display next to the spinner while the function runs. func: The function to run. Returns: The result of func. """ async def loop_run_with_spinner() -> _T: async def update_spinner() -> None: tick = 0 with spinner_printer.dynamic_text() as text_area: if not text_area: spinner_printer.display(text) return while True: spinner = spinner_printer.loading_symbol(tick) text_area.set_text(f"{spinner} {text}") tick += 1 await asyncio.sleep(0.1) async with asyncio_compat.cancel_on_exit(update_spinner()): return await asyncio.get_running_loop().run_in_executor(None, func) asyncer = wandb_setup.singleton().asyncer return asyncer.run(loop_run_with_spinner)