Spaces:
Sleeping
Sleeping
| import asyncio | |
| from starlette.applications import Starlette | |
| from starlette.endpoints import WebSocketEndpoint, HTTPEndpoint | |
| from starlette.responses import HTMLResponse | |
| from starlette.routing import Route, WebSocketRoute, Mount | |
| from starlette.websockets import WebSocket | |
| from starlette.types import Message, Receive, Scope, Send | |
| # -------------------- gradio ------------------------ | |
| import gradio as gr | |
| async def name_fn(name): | |
| await mbase.add_msg(f'gradio_name: {name}') | |
| return "Name: " + name + "!" | |
| io = gr.Interface(fn=name_fn, inputs=gr.Textbox(lines=2, placeholder="Name Here..."), outputs="text") | |
| # -------------------- shiny ------------------------ | |
| import shiny | |
| from shiny import App, render, ui, reactive | |
| import numpy as np | |
| import matplotlib.pyplot as plt | |
| app_ui = ui.page_fluid( | |
| ui.input_slider("n", "Number of bins", 1, 100, 20), | |
| ui.output_plot("plot", width='30%', height='120px'), | |
| ) | |
| def server(input, output, session): | |
| async def plot(): | |
| await mbase.add_msg(f'shiny_bin: {input.n()}') | |
| x = 100 + 15 * np.random.randn(120) | |
| fig, ax = plt.subplots() | |
| ax.hist(x, input.n(), density=True) | |
| return fig | |
| app_shiny = App(ui = app_ui, server = server) | |
| # -------------------- main + msg store and dispatch ------------------------ | |
| ws_list = [] | |
| class MsgBase(): | |
| """ Store and send messages to clients """ | |
| msg_history = ['start logging..',] | |
| async def add_msg(self, msg): | |
| self.msg_history.insert(0, msg) | |
| if len(self.msg_history) > 15: | |
| self.msg_history.pop() | |
| for ws in ws_list: | |
| await ws.send_text(msg) | |
| async def send_all_msg(self, ws): | |
| """ Restore all messages in new page or reloaded page""" | |
| ws_list.append(ws) | |
| for msg in reversed(self.msg_history): | |
| await ws.send_text(msg) | |
| mbase = MsgBase() | |
| html = """ | |
| <!DOCTYPE html> | |
| <html><head><title>Shiny and Gradio Test App</title> | |
| <style> | |
| .bottom_div { position:absolute; background: #E8F8E8; bottom:0; width:99%; height:100px; max-height: 30%; overflow-y: auto;} | |
| .log_msg { font-size: 0.75em; font-family: sans-serif; padding: .2em; margin: 0; line-height: 1em;} | |
| </style> | |
| </head> | |
| <body> | |
| <script type="text/javascript"> | |
| var ws = new WebSocket("wss://satcat-Shiny-Gradio-Msg-app.hf.space/ws"); | |
| ws.onmessage = function(event) { | |
| var newNode = document.createElement('li'); | |
| var content = document.createTextNode(event.data); | |
| newNode.appendChild(content); | |
| var messages = document.getElementById('log_msg'); | |
| messages.insertBefore(newNode, messages.children[0]); | |
| // remove last evement | |
| remove_idx = messages.getElementsByTagName("li").length -1; | |
| if (remove_idx > 15) { | |
| messages.children[remove_idx].remove(); | |
| } | |
| } | |
| </script> | |
| Shiny App | |
| <iframe src="/shiny/" width="100%" height="250" style="border:1px solid blue;"></iframe> | |
| Gradio App | |
| <iframe src="/gradio/" width="100%" height="250" style="border:1px solid red;"></iframe> | |
| <div class="bottom_div"><ul class="log_msg" id="log_msg"></ul></div> | |
| </body> | |
| </html>""" | |
| class Homepage(HTTPEndpoint): | |
| async def get(self, request): | |
| return HTMLResponse(html) | |
| class Echo(WebSocketEndpoint): | |
| async def on_connect(self, websocket: WebSocket) -> None: | |
| await websocket.accept() | |
| await mbase.send_all_msg(websocket) | |
| async def on_disconnect(self, websocket: WebSocket, close_code: int) -> None: | |
| ws_list.remove(websocket) | |
| routes = [ | |
| Route("/", Homepage), | |
| WebSocketRoute("/ws", Echo), | |
| Mount('/shiny', app=app_shiny) | |
| ] | |
| app = Starlette(routes=routes) | |
| app = gr.mount_gradio_app(app, io, path='/gradio') # insert gradio app this way | |
| # as a main work loop.. | |
| async def startup_event(): | |
| asyncio.create_task(dispatch_task()) | |
| async def dispatch_task(): | |
| """ background task to dispatch autonomous events """ | |
| for i in range(20): | |
| await mbase.add_msg(f'(main loop) I am work!({i})') | |
| await asyncio.sleep(8) |