import os import sys from pathlib import Path # Force client-side rendering before Gradio is imported/launched. HF Spaces sets # GRADIO_SSR_MODE=True, which runs a Node SSR proxy that server-renders the bare # app and bypasses our critical-head loader/middleware (flash of bare elements). # Overriding the env here keeps rendering client-side so the loader covers startup. os.environ["GRADIO_SSR_MODE"] = "False" sys.path.insert(0, str(Path(__file__).parent / "src")) from dota2tuned.ui.runtime_hooks import ( # noqa: E402 close_idle_main_event_loop, gradio_launch_runtime_kwargs, install_quiet_unraisablehook, ) # Install before importing Gradio. Gradio 6 on HF Spaces can create orphaned # asyncio loops during import/startup; Python 3.12 reports those as noisy # unraisable "Invalid file descriptor: -1" tracebacks. install_quiet_unraisablehook() import gradio as gr # noqa: E402 from dota2tuned.ui.gradio_app import ( # noqa: E402 APP_CSS, APP_HEAD, build_app, launch_app_kwargs, ) demo = build_app() close_idle_main_event_loop() if __name__ == "__main__": # NOTE: the load JS is attached inside build_app via demo.load(); launch(js=) # is a no-op on page load in Gradio 6.18, so it is intentionally not passed. # app_kwargs wires the critical-head middleware that prevents the bare-element # flash (Gradio injects head= only after mount; see launch_app_kwargs). # ssr_mode=False: HF Spaces auto-enables SSR (Node proxy), which server-renders # the bare app and bypasses both our head= loader and the Python middleware. # Client-side rendering lets the critical-head middleware hide the app until ready. demo.launch( css=APP_CSS, head=APP_HEAD, theme=gr.themes.Soft(), ssr_mode=False, **gradio_launch_runtime_kwargs(), app_kwargs=launch_app_kwargs(), )