Spaces:
Sleeping
Sleeping
__doc__ = """ | |
This FastAPI app uses gradio components with SQL code input | |
and HTML table output. The query is executed using DuckDB. | |
The query results are shown in an iframe where the table | |
is styled and made interactive using Datatables.net scripts. | |
""" | |
import gradio as gr | |
import pandas as pd | |
from fastapi import FastAPI | |
from fastapi.responses import HTMLResponse, RedirectResponse | |
from itables import to_html_datatable | |
from sql import Q | |
app = FastAPI() | |
def query_from_request(query, request: gr.Request): | |
"""Process query from input block or from initial request. | |
https://github.com/gradio-app/gradio/issues/7464#issuecomment-1960161591 | |
""" | |
if not query: | |
query_params = request.query_params | |
base64query = dict(query_params).get("q") | |
else: | |
base64query = Q(query).base64 | |
if base64query in (None, "example"): | |
decoded = Q("""SELECT 42 AS answer, 'LU & E' AS question""") | |
base64query = decoded.base64 | |
else: | |
decoded = Q.from_base64(base64query) | |
href = format_href(base64query) | |
result = f"""<iframe src="/q/{base64query}" width="90%" height="90%"></iframe>""" | |
return (decoded, href, result) | |
def format_href(url: str): | |
href=f"localhost:7860/sql/{url}" | |
return f"""<a href="{href}">{href}</a>""" | |
def query_db(base64query: str|None = None): | |
decoded = Q.from_base64(base64query) | |
df = decoded.df() | |
html = to_html_datatable(df) | |
return f""" | |
<h3>{decoded}</h3> | |
<div>{html}</div> | |
""" | |
with gr.Blocks() as gradio_sql_interface: | |
with gr.Row(): | |
with gr.Column(): | |
header = gr.Markdown("# SQL Editor") | |
sql_code = gr.Code(language="sql", label="SQL Query", interactive=True) | |
copy_button = gr.HTML() | |
button = gr.Button("run") | |
with gr.Column(): | |
markdown = gr.Markdown("# RESULTS") | |
results = gr.HTML() | |
button.click(query_from_request, [sql_code], [sql_code, copy_button, results]) | |
gradio_sql_interface.load(query_from_request, [sql_code], [sql_code, copy_button, results], queue=True) | |
app = gr.mount_gradio_app(app, gradio_sql_interface, path="/sql") | |
def redirect_to_example(): | |
return RedirectResponse("/sql/?q=example") | |
# no need to mount/unmount dynamically | |
# just change path and app blocks? | |
# { | |
# "api.routes": [ | |
# "...", | |
# "Mount(path='/gradiosql/qq', name='', app=<gradio.routes.App object at 0x71dc7b9d6d10>)" | |
# ] | |
# } | |
# @app.get("/sql/{query}") | |
# def render_query(query: str): | |
# # unmount any previous gradio apps | |
# # for route in app.routes: | |
# # if "gradio" in route.path: | |
# # del route | |
# # global app | |
# # routes = [route for route in app.routes if 'gradio' not in route.path] | |
# # app = Starlette(routes=routes) | |
# with gr.Blocks() as gradio_sql_interface: | |
# sql_code = gr.Code(value=query, language="sql", label="SQL Query", interactive=True) | |
# button = gr.Button("run", link=f"/sql/{sql_code.value}") | |
# markdown = gr.Markdown("# RESULTS") | |
# html = gr.HTML(value=f"""<iframe src="/q/{query}" width="90%" height="90%"></iframe>""") | |
# # button.click(None, [], [], js=f"window.open('/sql/{sql_code.value}', '_top')") | |
# gradio_path = f"/gradiosql/{sql_code.value}" | |
# gr.mount_gradio_app(app, gradio_sql_interface, path=gradio_path) | |
# return RedirectResponse(gradio_path) | |
# del app.routes[index] | |
# @app.get("/redirect") | |
# async def redirect_example(): | |
# url = "/q/qqq" | |
# return Response(status_code=302, headers={"Location": url}) | |
# # return """hi<hr><iframe src="/" width="80%" height="80%"></iframe>""" | |
# @app.get("/qq/{apath}") | |
# async def build_sql_interface(apath: str): | |
# with gr.Blocks() as gradio_sql_interface: | |
# sql_code = gr.Code(value=apath, language="sql", label="SQL Query", interactive=True) | |
# html_code = gr.Code(value=html) | |
# html_html = gr.HTML(value=f"""<iframe src="/q/{apath}" width="80%" height="80%"></iframe>""") | |
# grdf = gr.DataFrame(value=df) | |
# # gradio_sql_interface.queue() | |
# gr.mount_gradio_app(app, gradio_sql_interface, path="/gradio/{apath}") | |
# # import time; time.sleep(1) | |
# return RedirectResponse("/gradio/{{apath}}") | |
# async with httpx.AsyncClient() as client: | |
# try: | |
# response = await client.get("/gradio") | |
# response.raise_for_status() | |
# return response | |
# except httpx.HTTPError as e: | |
# return {"errresponse": e} | |
# pass #raise HTTPException(status_code=exc.status_code, detail=exc.msg) | |
# return {"path":path} | |
# if __name__ == "__main__": | |
# import uvicorn | |
# uvicorn.run(app, host="0.0.0.0", port=7860) | |
# appenv/.venv/bin/uvicorn main:app --host 0.0.0.0 --port 7860 |