diff --git a/.changeset/many-tips-create.md b/.changeset/many-tips-create.md new file mode 100644 index 0000000000000..a7032ac024f84 --- /dev/null +++ b/.changeset/many-tips-create.md @@ -0,0 +1,9 @@ +--- +"gradio": minor +--- + +feat:Cleanup of .update and .get_config per component + +get_config is removed, the config used is simply any attribute that is in the Block that shares a name with one of the constructor paramaters. + +update is not removed for backwards compatibility, but deprecated. Instead return the component itself. Created a updateable decorator that simply checks to see if we're in an update, and if so, skips the constructor and wraps the args and kwargs in an update dictionary. easy peasy. diff --git a/demo/all_demos/image.png b/demo/all_demos/image.png new file mode 100644 index 0000000000000..dc392ea954769 Binary files /dev/null and b/demo/all_demos/image.png differ diff --git a/demo/all_demos/tmp.zip b/demo/all_demos/tmp.zip index 8e6c94b1a186e..b1782ff5d98d7 100644 Binary files a/demo/all_demos/tmp.zip and b/demo/all_demos/tmp.zip differ diff --git a/demo/bar_plot/run.ipynb b/demo/bar_plot/run.ipynb index 3683f8d55714f..0b97d4dffd519 100644 --- a/demo/bar_plot/run.ipynb +++ b/demo/bar_plot/run.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: bar_plot"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio pandas"]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import pandas as pd\n", "import random\n", "\n", "simple = pd.DataFrame(\n", " {\n", " \"a\": [\"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\", \"I\"],\n", " \"b\": [28, 55, 43, 91, 81, 53, 19, 87, 52],\n", " }\n", ")\n", "\n", "fake_barley = pd.DataFrame(\n", " {\n", " \"site\": [\n", " random.choice(\n", " [\n", " \"University Farm\",\n", " \"Waseca\",\n", " \"Morris\",\n", " \"Crookston\",\n", " \"Grand Rapids\",\n", " \"Duluth\",\n", " ]\n", " )\n", " for _ in range(120)\n", " ],\n", " \"yield\": [random.randint(25, 75) for _ in range(120)],\n", " \"variety\": [\n", " random.choice(\n", " [\n", " \"Manchuria\",\n", " \"Wisconsin No. 38\",\n", " \"Glabron\",\n", " \"No. 457\",\n", " \"No. 462\",\n", " \"No. 475\",\n", " ]\n", " )\n", " for _ in range(120)\n", " ],\n", " \"year\": [\n", " random.choice(\n", " [\n", " \"1931\",\n", " \"1932\",\n", " ]\n", " )\n", " for _ in range(120)\n", " ],\n", " }\n", ")\n", "\n", "\n", "def bar_plot_fn(display):\n", " if display == \"simple\":\n", " return gr.BarPlot.update(\n", " simple,\n", " x=\"a\",\n", " y=\"b\",\n", " title=\"Simple Bar Plot with made up data\",\n", " tooltip=[\"a\", \"b\"],\n", " y_lim=[20, 100],\n", " )\n", " elif display == \"stacked\":\n", " return gr.BarPlot.update(\n", " fake_barley,\n", " x=\"variety\",\n", " y=\"yield\",\n", " color=\"site\",\n", " title=\"Barley Yield Data\",\n", " tooltip=[\"variety\", \"site\"],\n", " )\n", " elif display == \"grouped\":\n", " return gr.BarPlot.update(\n", " fake_barley.astype({\"year\": str}),\n", " x=\"year\",\n", " y=\"yield\",\n", " color=\"year\",\n", " group=\"site\",\n", " title=\"Barley Yield by Year and Site\",\n", " group_title=\"\",\n", " tooltip=[\"yield\", \"site\", \"year\"],\n", " )\n", " elif display == \"simple-horizontal\":\n", " return gr.BarPlot.update(\n", " simple,\n", " x=\"a\",\n", " y=\"b\",\n", " x_title=\"Variable A\",\n", " y_title=\"Variable B\",\n", " title=\"Simple Bar Plot with made up data\",\n", " tooltip=[\"a\", \"b\"],\n", " vertical=False,\n", " y_lim=[20, 100],\n", " )\n", " elif display == \"stacked-horizontal\":\n", " return gr.BarPlot.update(\n", " fake_barley,\n", " x=\"variety\",\n", " y=\"yield\",\n", " color=\"site\",\n", " title=\"Barley Yield Data\",\n", " vertical=False,\n", " tooltip=[\"variety\", \"site\"],\n", " )\n", " elif display == \"grouped-horizontal\":\n", " return gr.BarPlot.update(\n", " fake_barley.astype({\"year\": str}),\n", " x=\"year\",\n", " y=\"yield\",\n", " color=\"year\",\n", " group=\"site\",\n", " title=\"Barley Yield by Year and Site\",\n", " group_title=\"\",\n", " tooltip=[\"yield\", \"site\", \"year\"],\n", " vertical=False,\n", " )\n", "\n", "\n", "with gr.Blocks() as bar_plot:\n", " with gr.Row():\n", " with gr.Column():\n", " display = gr.Dropdown(\n", " choices=[\n", " \"simple\",\n", " \"stacked\",\n", " \"grouped\",\n", " \"simple-horizontal\",\n", " \"stacked-horizontal\",\n", " \"grouped-horizontal\",\n", " ],\n", " value=\"simple\",\n", " label=\"Type of Bar Plot\",\n", " )\n", " with gr.Column():\n", " plot = gr.BarPlot()\n", " display.change(bar_plot_fn, inputs=display, outputs=plot)\n", " bar_plot.load(fn=bar_plot_fn, inputs=display, outputs=plot)\n", "\n", "bar_plot.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: bar_plot"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio pandas"]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import pandas as pd\n", "import random\n", "\n", "simple = pd.DataFrame(\n", " {\n", " \"a\": [\"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\", \"I\"],\n", " \"b\": [28, 55, 43, 91, 81, 53, 19, 87, 52],\n", " }\n", ")\n", "\n", "fake_barley = pd.DataFrame(\n", " {\n", " \"site\": [\n", " random.choice(\n", " [\n", " \"University Farm\",\n", " \"Waseca\",\n", " \"Morris\",\n", " \"Crookston\",\n", " \"Grand Rapids\",\n", " \"Duluth\",\n", " ]\n", " )\n", " for _ in range(120)\n", " ],\n", " \"yield\": [random.randint(25, 75) for _ in range(120)],\n", " \"variety\": [\n", " random.choice(\n", " [\n", " \"Manchuria\",\n", " \"Wisconsin No. 38\",\n", " \"Glabron\",\n", " \"No. 457\",\n", " \"No. 462\",\n", " \"No. 475\",\n", " ]\n", " )\n", " for _ in range(120)\n", " ],\n", " \"year\": [\n", " random.choice(\n", " [\n", " \"1931\",\n", " \"1932\",\n", " ]\n", " )\n", " for _ in range(120)\n", " ],\n", " }\n", ")\n", "\n", "\n", "def bar_plot_fn(display):\n", " if display == \"simple\":\n", " return gr.BarPlot(\n", " simple,\n", " x=\"a\",\n", " y=\"b\",\n", " title=\"Simple Bar Plot with made up data\",\n", " tooltip=[\"a\", \"b\"],\n", " y_lim=[20, 100],\n", " )\n", " elif display == \"stacked\":\n", " return gr.BarPlot(\n", " fake_barley,\n", " x=\"variety\",\n", " y=\"yield\",\n", " color=\"site\",\n", " title=\"Barley Yield Data\",\n", " tooltip=[\"variety\", \"site\"],\n", " )\n", " elif display == \"grouped\":\n", " return gr.BarPlot(\n", " fake_barley.astype({\"year\": str}),\n", " x=\"year\",\n", " y=\"yield\",\n", " color=\"year\",\n", " group=\"site\",\n", " title=\"Barley Yield by Year and Site\",\n", " group_title=\"\",\n", " tooltip=[\"yield\", \"site\", \"year\"],\n", " )\n", " elif display == \"simple-horizontal\":\n", " return gr.BarPlot(\n", " simple,\n", " x=\"a\",\n", " y=\"b\",\n", " x_title=\"Variable A\",\n", " y_title=\"Variable B\",\n", " title=\"Simple Bar Plot with made up data\",\n", " tooltip=[\"a\", \"b\"],\n", " vertical=False,\n", " y_lim=[20, 100],\n", " )\n", " elif display == \"stacked-horizontal\":\n", " return gr.BarPlot(\n", " fake_barley,\n", " x=\"variety\",\n", " y=\"yield\",\n", " color=\"site\",\n", " title=\"Barley Yield Data\",\n", " vertical=False,\n", " tooltip=[\"variety\", \"site\"],\n", " )\n", " elif display == \"grouped-horizontal\":\n", " return gr.BarPlot(\n", " fake_barley.astype({\"year\": str}),\n", " x=\"year\",\n", " y=\"yield\",\n", " color=\"year\",\n", " group=\"site\",\n", " title=\"Barley Yield by Year and Site\",\n", " group_title=\"\",\n", " tooltip=[\"yield\", \"site\", \"year\"],\n", " vertical=False,\n", " )\n", "\n", "\n", "with gr.Blocks() as bar_plot:\n", " with gr.Row():\n", " with gr.Column():\n", " display = gr.Dropdown(\n", " choices=[\n", " \"simple\",\n", " \"stacked\",\n", " \"grouped\",\n", " \"simple-horizontal\",\n", " \"stacked-horizontal\",\n", " \"grouped-horizontal\",\n", " ],\n", " value=\"simple\",\n", " label=\"Type of Bar Plot\",\n", " )\n", " with gr.Column():\n", " plot = gr.BarPlot()\n", " display.change(bar_plot_fn, inputs=display, outputs=plot)\n", " bar_plot.load(fn=bar_plot_fn, inputs=display, outputs=plot)\n", "\n", "bar_plot.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/bar_plot/run.py b/demo/bar_plot/run.py index d8ce94f780681..1ddf37f1d6435 100644 --- a/demo/bar_plot/run.py +++ b/demo/bar_plot/run.py @@ -53,7 +53,7 @@ def bar_plot_fn(display): if display == "simple": - return gr.BarPlot.update( + return gr.BarPlot( simple, x="a", y="b", @@ -62,7 +62,7 @@ def bar_plot_fn(display): y_lim=[20, 100], ) elif display == "stacked": - return gr.BarPlot.update( + return gr.BarPlot( fake_barley, x="variety", y="yield", @@ -71,7 +71,7 @@ def bar_plot_fn(display): tooltip=["variety", "site"], ) elif display == "grouped": - return gr.BarPlot.update( + return gr.BarPlot( fake_barley.astype({"year": str}), x="year", y="yield", @@ -82,7 +82,7 @@ def bar_plot_fn(display): tooltip=["yield", "site", "year"], ) elif display == "simple-horizontal": - return gr.BarPlot.update( + return gr.BarPlot( simple, x="a", y="b", @@ -94,7 +94,7 @@ def bar_plot_fn(display): y_lim=[20, 100], ) elif display == "stacked-horizontal": - return gr.BarPlot.update( + return gr.BarPlot( fake_barley, x="variety", y="yield", @@ -104,7 +104,7 @@ def bar_plot_fn(display): tooltip=["variety", "site"], ) elif display == "grouped-horizontal": - return gr.BarPlot.update( + return gr.BarPlot( fake_barley.astype({"year": str}), x="year", y="yield", diff --git a/demo/blocks_essay/run.ipynb b/demo/blocks_essay/run.ipynb index 480378226a2e1..2dde03ce3734e 100644 --- a/demo/blocks_essay/run.ipynb +++ b/demo/blocks_essay/run.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: blocks_essay"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "\n", "def change_textbox(choice):\n", " if choice == \"short\":\n", " return gr.Textbox.update(lines=2, visible=True)\n", " elif choice == \"long\":\n", " return gr.Textbox.update(lines=8, visible=True)\n", " else:\n", " return gr.Textbox.update(visible=False)\n", "\n", "\n", "with gr.Blocks() as demo:\n", " radio = gr.Radio(\n", " [\"short\", \"long\", \"none\"], label=\"What kind of essay would you like to write?\"\n", " )\n", " text = gr.Textbox(lines=2, interactive=True, show_copy_button=True)\n", "\n", " radio.change(fn=change_textbox, inputs=radio, outputs=text)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: blocks_essay"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "\n", "def change_textbox(choice):\n", " if choice == \"short\":\n", " return gr.Textbox(lines=2, visible=True)\n", " elif choice == \"long\":\n", " return gr.Textbox(lines=8, visible=True, value=\"Lorem ipsum dolor sit amet\")\n", " else:\n", " return gr.Textbox(visible=False)\n", "\n", "\n", "with gr.Blocks() as demo:\n", " radio = gr.Radio(\n", " [\"short\", \"long\", \"none\"], label=\"What kind of essay would you like to write?\"\n", " )\n", " text = gr.Textbox(lines=2, interactive=True, show_copy_button=True)\n", " radio.change(fn=change_textbox, inputs=radio, outputs=text)\n", "\n", " with gr.Row():\n", " num = gr.Number(minimum=0, maximum=100, label=\"input\")\n", " out = gr.Number(label=\"output\")\n", " min = gr.Slider(0, 100, 0, label=\"min\")\n", " max = gr.Slider(0, 100, 100, label=\"max\")\n", "\n", " def reset_bounds(min, max):\n", " return gr.Number(minimum=min, maximum=max)\n", " \n", " min.change(reset_bounds, [min, max], outputs=num)\n", " max.change(reset_bounds, [min, max], outputs=num)\n", " num.submit(lambda x:x, num, out)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/blocks_essay/run.py b/demo/blocks_essay/run.py index 127ca62e0f015..1711eb70d0ff5 100644 --- a/demo/blocks_essay/run.py +++ b/demo/blocks_essay/run.py @@ -3,11 +3,11 @@ def change_textbox(choice): if choice == "short": - return gr.Textbox.update(lines=2, visible=True) + return gr.Textbox(lines=2, visible=True) elif choice == "long": - return gr.Textbox.update(lines=8, visible=True) + return gr.Textbox(lines=8, visible=True, value="Lorem ipsum dolor sit amet") else: - return gr.Textbox.update(visible=False) + return gr.Textbox(visible=False) with gr.Blocks() as demo: @@ -15,9 +15,21 @@ def change_textbox(choice): ["short", "long", "none"], label="What kind of essay would you like to write?" ) text = gr.Textbox(lines=2, interactive=True, show_copy_button=True) - radio.change(fn=change_textbox, inputs=radio, outputs=text) + with gr.Row(): + num = gr.Number(minimum=0, maximum=100, label="input") + out = gr.Number(label="output") + min = gr.Slider(0, 100, 0, label="min") + max = gr.Slider(0, 100, 100, label="max") + + def reset_bounds(min, max): + return gr.Number(minimum=min, maximum=max) + + min.change(reset_bounds, [min, max], outputs=num) + max.change(reset_bounds, [min, max], outputs=num) + num.submit(lambda x:x, num, out) + if __name__ == "__main__": demo.launch() diff --git a/demo/blocks_essay_simple/run.ipynb b/demo/blocks_essay_simple/run.ipynb new file mode 100644 index 0000000000000..a378968e215ac --- /dev/null +++ b/demo/blocks_essay_simple/run.ipynb @@ -0,0 +1 @@ +{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: blocks_essay_simple"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "\n", "def change_textbox(choice):\n", " if choice == \"short\":\n", " return gr.Textbox(lines=2, visible=True)\n", " elif choice == \"long\":\n", " return gr.Textbox(lines=8, visible=True, value=\"Lorem ipsum dolor sit amet\")\n", " else:\n", " return gr.Textbox(visible=False)\n", "\n", "\n", "with gr.Blocks() as demo:\n", " radio = gr.Radio(\n", " [\"short\", \"long\", \"none\"], label=\"What kind of essay would you like to write?\"\n", " )\n", " text = gr.Textbox(lines=2, interactive=True, show_copy_button=True)\n", " radio.change(fn=change_textbox, inputs=radio, outputs=text)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/blocks_essay_simple/run.py b/demo/blocks_essay_simple/run.py new file mode 100644 index 0000000000000..215268766535c --- /dev/null +++ b/demo/blocks_essay_simple/run.py @@ -0,0 +1,22 @@ +import gradio as gr + + +def change_textbox(choice): + if choice == "short": + return gr.Textbox(lines=2, visible=True) + elif choice == "long": + return gr.Textbox(lines=8, visible=True, value="Lorem ipsum dolor sit amet") + else: + return gr.Textbox(visible=False) + + +with gr.Blocks() as demo: + radio = gr.Radio( + ["short", "long", "none"], label="What kind of essay would you like to write?" + ) + text = gr.Textbox(lines=2, interactive=True, show_copy_button=True) + radio.change(fn=change_textbox, inputs=radio, outputs=text) + + +if __name__ == "__main__": + demo.launch() diff --git a/demo/blocks_essay_update/run.ipynb b/demo/blocks_essay_update/run.ipynb deleted file mode 100644 index 0fc70cbe02b2d..0000000000000 --- a/demo/blocks_essay_update/run.ipynb +++ /dev/null @@ -1 +0,0 @@ -{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: blocks_essay_update"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "def change_textbox(choice):\n", " if choice == \"short\":\n", " return gr.update(lines=2, visible=True, value=\"Short story: \")\n", " elif choice == \"long\":\n", " return gr.update(lines=8, visible=True, value=\"Long story...\")\n", " else:\n", " return gr.update(visible=False)\n", "\n", "with gr.Blocks() as demo:\n", " radio = gr.Radio(\n", " [\"short\", \"long\", \"none\"], label=\"Essay Length to Write?\"\n", " )\n", " text = gr.Textbox(lines=2, interactive=True)\n", " radio.change(fn=change_textbox, inputs=radio, outputs=text)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/blocks_essay_update/run.py b/demo/blocks_essay_update/run.py deleted file mode 100644 index 625da12f3cfad..0000000000000 --- a/demo/blocks_essay_update/run.py +++ /dev/null @@ -1,19 +0,0 @@ -import gradio as gr - -def change_textbox(choice): - if choice == "short": - return gr.update(lines=2, visible=True, value="Short story: ") - elif choice == "long": - return gr.update(lines=8, visible=True, value="Long story...") - else: - return gr.update(visible=False) - -with gr.Blocks() as demo: - radio = gr.Radio( - ["short", "long", "none"], label="Essay Length to Write?" - ) - text = gr.Textbox(lines=2, interactive=True) - radio.change(fn=change_textbox, inputs=radio, outputs=text) - -if __name__ == "__main__": - demo.launch() \ No newline at end of file diff --git a/demo/blocks_flashcards/run.ipynb b/demo/blocks_flashcards/run.ipynb index 7508d8039227e..96dd33e5d89c0 100644 --- a/demo/blocks_flashcards/run.ipynb +++ b/demo/blocks_flashcards/run.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: blocks_flashcards"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import random\n", "\n", "import gradio as gr\n", "\n", "demo = gr.Blocks()\n", "\n", "with demo:\n", " gr.Markdown(\n", " \"Load the flashcards in the table below, then use the Practice tab to practice.\"\n", " )\n", "\n", " with gr.Tab(\"Word Bank\"):\n", " flashcards_table = gr.Dataframe(headers=[\"front\", \"back\"], type=\"array\")\n", " with gr.Tab(\"Practice\"):\n", " with gr.Row():\n", " with gr.Column():\n", " front = gr.Textbox(label=\"Prompt\")\n", " with gr.Row():\n", " new_btn = gr.Button(\"New Card\")\n", " flip_btn = gr.Button(\"Flip Card\")\n", " with gr.Column(visible=False) as answer_col:\n", " back = gr.Textbox(label=\"Answer\")\n", " selected_card = gr.State()\n", " with gr.Row():\n", " correct_btn = gr.Button(\"Correct\")\n", " incorrect_btn = gr.Button(\"Incorrect\")\n", "\n", " with gr.Tab(\"Results\"):\n", " results = gr.State(value={})\n", " correct_field = gr.Markdown(\"# Correct: 0\")\n", " incorrect_field = gr.Markdown(\"# Incorrect: 0\")\n", " gr.Markdown(\"Card Statistics: \")\n", " results_table = gr.Dataframe(headers=[\"Card\", \"Correct\", \"Incorrect\"])\n", "\n", " def load_new_card(flashcards):\n", " card = random.choice(flashcards)\n", " return (\n", " card,\n", " card[0],\n", " gr.Column.update(visible=False),\n", " )\n", "\n", " new_btn.click(\n", " load_new_card,\n", " [flashcards_table],\n", " [selected_card, front, answer_col],\n", " )\n", "\n", " def flip_card(card):\n", " return card[1], gr.Column.update(visible=True)\n", "\n", " flip_btn.click(flip_card, [selected_card], [back, answer_col])\n", "\n", " def mark_correct(card, results):\n", " if card[0] not in results:\n", " results[card[0]] = [0, 0]\n", " results[card[0]][0] += 1\n", " correct_count = sum(result[0] for result in results.values())\n", " return (\n", " results,\n", " f\"# Correct: {correct_count}\",\n", " [[front, scores[0], scores[1]] for front, scores in results.items()],\n", " )\n", "\n", " def mark_incorrect(card, results):\n", " if card[0] not in results:\n", " results[card[0]] = [0, 0]\n", " results[card[0]][1] += 1\n", " incorrect_count = sum(result[1] for result in results.values())\n", " return (\n", " results,\n", " f\"# Inorrect: {incorrect_count}\",\n", " [[front, scores[0], scores[1]] for front, scores in results.items()],\n", " )\n", "\n", " correct_btn.click(\n", " mark_correct,\n", " [selected_card, results],\n", " [results, correct_field, results_table],\n", " )\n", "\n", " incorrect_btn.click(\n", " mark_incorrect,\n", " [selected_card, results],\n", " [results, incorrect_field, results_table],\n", " )\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: blocks_flashcards"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import random\n", "\n", "import gradio as gr\n", "\n", "demo = gr.Blocks()\n", "\n", "with demo:\n", " gr.Markdown(\n", " \"Load the flashcards in the table below, then use the Practice tab to practice.\"\n", " )\n", "\n", " with gr.Tab(\"Word Bank\"):\n", " flashcards_table = gr.Dataframe(headers=[\"front\", \"back\"], type=\"array\")\n", " with gr.Tab(\"Practice\"):\n", " with gr.Row():\n", " with gr.Column():\n", " front = gr.Textbox(label=\"Prompt\")\n", " with gr.Row():\n", " new_btn = gr.Button(\"New Card\")\n", " flip_btn = gr.Button(\"Flip Card\")\n", " with gr.Column(visible=False) as answer_col:\n", " back = gr.Textbox(label=\"Answer\")\n", " selected_card = gr.State()\n", " with gr.Row():\n", " correct_btn = gr.Button(\"Correct\")\n", " incorrect_btn = gr.Button(\"Incorrect\")\n", "\n", " with gr.Tab(\"Results\"):\n", " results = gr.State(value={})\n", " correct_field = gr.Markdown(\"# Correct: 0\")\n", " incorrect_field = gr.Markdown(\"# Incorrect: 0\")\n", " gr.Markdown(\"Card Statistics: \")\n", " results_table = gr.Dataframe(headers=[\"Card\", \"Correct\", \"Incorrect\"])\n", "\n", " def load_new_card(flashcards):\n", " card = random.choice(flashcards)\n", " return (\n", " card,\n", " card[0],\n", " gr.Column(visible=False),\n", " )\n", "\n", " new_btn.click(\n", " load_new_card,\n", " [flashcards_table],\n", " [selected_card, front, answer_col],\n", " )\n", "\n", " def flip_card(card):\n", " return card[1], gr.Column(visible=True)\n", "\n", " flip_btn.click(flip_card, [selected_card], [back, answer_col])\n", "\n", " def mark_correct(card, results):\n", " if card[0] not in results:\n", " results[card[0]] = [0, 0]\n", " results[card[0]][0] += 1\n", " correct_count = sum(result[0] for result in results.values())\n", " return (\n", " results,\n", " f\"# Correct: {correct_count}\",\n", " [[front, scores[0], scores[1]] for front, scores in results.items()],\n", " )\n", "\n", " def mark_incorrect(card, results):\n", " if card[0] not in results:\n", " results[card[0]] = [0, 0]\n", " results[card[0]][1] += 1\n", " incorrect_count = sum(result[1] for result in results.values())\n", " return (\n", " results,\n", " f\"# Inorrect: {incorrect_count}\",\n", " [[front, scores[0], scores[1]] for front, scores in results.items()],\n", " )\n", "\n", " correct_btn.click(\n", " mark_correct,\n", " [selected_card, results],\n", " [results, correct_field, results_table],\n", " )\n", "\n", " incorrect_btn.click(\n", " mark_incorrect,\n", " [selected_card, results],\n", " [results, incorrect_field, results_table],\n", " )\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/blocks_flashcards/run.py b/demo/blocks_flashcards/run.py index c7dc0ee9f52a4..9e8c606bfdba0 100644 --- a/demo/blocks_flashcards/run.py +++ b/demo/blocks_flashcards/run.py @@ -37,7 +37,7 @@ def load_new_card(flashcards): return ( card, card[0], - gr.Column.update(visible=False), + gr.Column(visible=False), ) new_btn.click( @@ -47,7 +47,7 @@ def load_new_card(flashcards): ) def flip_card(card): - return card[1], gr.Column.update(visible=True) + return card[1], gr.Column(visible=True) flip_btn.click(flip_card, [selected_card], [back, answer_col]) diff --git a/demo/blocks_form/run.ipynb b/demo/blocks_form/run.ipynb index 04d0cc6467489..ee6a47e2e0ff1 100644 --- a/demo/blocks_form/run.ipynb +++ b/demo/blocks_form/run.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: blocks_form"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " error_box = gr.Textbox(label=\"Error\", visible=False)\n", "\n", " name_box = gr.Textbox(label=\"Name\")\n", " age_box = gr.Number(label=\"Age\", minimum=0, maximum=100)\n", " symptoms_box = gr.CheckboxGroup([\"Cough\", \"Fever\", \"Runny Nose\"])\n", " submit_btn = gr.Button(\"Submit\")\n", "\n", " with gr.Column(visible=False) as output_col:\n", " diagnosis_box = gr.Textbox(label=\"Diagnosis\")\n", " patient_summary_box = gr.Textbox(label=\"Patient Summary\")\n", "\n", " def submit(name, age, symptoms):\n", " if len(name) == 0:\n", " return {error_box: gr.update(value=\"Enter name\", visible=True)}\n", " return {\n", " output_col: gr.update(visible=True),\n", " diagnosis_box: \"covid\" if \"Cough\" in symptoms else \"flu\",\n", " patient_summary_box: f\"{name}, {age} y/o\",\n", " }\n", "\n", " submit_btn.click(\n", " submit,\n", " [name_box, age_box, symptoms_box],\n", " [error_box, diagnosis_box, patient_summary_box, output_col],\n", " )\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: blocks_form"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " error_box = gr.Textbox(label=\"Error\", visible=False)\n", "\n", " name_box = gr.Textbox(label=\"Name\")\n", " age_box = gr.Number(label=\"Age\", minimum=0, maximum=100)\n", " symptoms_box = gr.CheckboxGroup([\"Cough\", \"Fever\", \"Runny Nose\"])\n", " submit_btn = gr.Button(\"Submit\")\n", "\n", " with gr.Column(visible=False) as output_col:\n", " diagnosis_box = gr.Textbox(label=\"Diagnosis\")\n", " patient_summary_box = gr.Textbox(label=\"Patient Summary\")\n", "\n", " def submit(name, age, symptoms):\n", " if len(name) == 0:\n", " return {error_box: gr.Textbox(value=\"Enter name\", visible=True)}\n", " return {\n", " output_col: gr.Column(visible=True),\n", " diagnosis_box: \"covid\" if \"Cough\" in symptoms else \"flu\",\n", " patient_summary_box: f\"{name}, {age} y/o\",\n", " }\n", "\n", " submit_btn.click(\n", " submit,\n", " [name_box, age_box, symptoms_box],\n", " [error_box, diagnosis_box, patient_summary_box, output_col],\n", " )\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/blocks_form/run.py b/demo/blocks_form/run.py index a154d1fa23579..956083cb08409 100644 --- a/demo/blocks_form/run.py +++ b/demo/blocks_form/run.py @@ -14,9 +14,9 @@ def submit(name, age, symptoms): if len(name) == 0: - return {error_box: gr.update(value="Enter name", visible=True)} + return {error_box: gr.Textbox(value="Enter name", visible=True)} return { - output_col: gr.update(visible=True), + output_col: gr.Column(visible=True), diagnosis_box: "covid" if "Cough" in symptoms else "flu", patient_summary_box: f"{name}, {age} y/o", } diff --git a/demo/blocks_multiple_event_triggers/run.ipynb b/demo/blocks_multiple_event_triggers/run.ipynb index 5f55239e0e9b6..52d3052d5c4d4 100644 --- a/demo/blocks_multiple_event_triggers/run.ipynb +++ b/demo/blocks_multiple_event_triggers/run.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: blocks_multiple_event_triggers"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio plotly pypistats"]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import pypistats\n", "from datetime import date\n", "from dateutil.relativedelta import relativedelta\n", "import pandas as pd\n", "\n", "def get_plot(lib, time):\n", " data = pypistats.overall(lib, total=True, format=\"pandas\")\n", " data = data.groupby(\"category\").get_group(\"with_mirrors\").sort_values(\"date\")\n", " start_date = date.today() - relativedelta(months=int(time.split(\" \")[0]))\n", " data = data[(data['date'] > str(start_date))]\n", " data.date = pd.to_datetime(pd.to_datetime(data.date))\n", " return gr.LinePlot.update(value=data, x=\"date\", y=\"downloads\",\n", " tooltip=['date', 'downloads'],\n", " title=f\"Pypi downloads of {lib} over last {time}\",\n", " overlay_point=True,\n", " height=400,\n", " width=900)\n", "\n", "\n", "with gr.Blocks() as demo:\n", " gr.Markdown(\n", " \"\"\"\n", " ## Pypi Download Stats \ud83d\udcc8\n", " See live download stats for all of Hugging Face's open-source libraries \ud83e\udd17\n", " \"\"\")\n", " with gr.Row():\n", " lib = gr.Dropdown([\"transformers\", \"datasets\", \"huggingface-hub\", \"gradio\", \"accelerate\"],\n", " value=\"gradio\", label=\"Library\")\n", " time = gr.Dropdown([\"3 months\", \"6 months\", \"9 months\", \"12 months\"],\n", " value=\"3 months\", label=\"Downloads over the last...\")\n", "\n", " plt = gr.LinePlot()\n", " # You can add multiple event triggers in 2 lines like this\n", " for event in [lib.change, time.change, demo.load]:\n", " event(get_plot, [lib, time], [plt])\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: blocks_multiple_event_triggers"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio plotly pypistats"]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import pypistats\n", "from datetime import date\n", "from dateutil.relativedelta import relativedelta\n", "import pandas as pd\n", "\n", "def get_plot(lib, time):\n", " data = pypistats.overall(lib, total=True, format=\"pandas\")\n", " data = data.groupby(\"category\").get_group(\"with_mirrors\").sort_values(\"date\")\n", " start_date = date.today() - relativedelta(months=int(time.split(\" \")[0]))\n", " data = data[(data['date'] > str(start_date))]\n", " data.date = pd.to_datetime(pd.to_datetime(data.date))\n", " return gr.LinePlot(value=data, x=\"date\", y=\"downloads\",\n", " tooltip=['date', 'downloads'],\n", " title=f\"Pypi downloads of {lib} over last {time}\",\n", " overlay_point=True,\n", " height=400,\n", " width=900)\n", "\n", "\n", "with gr.Blocks() as demo:\n", " gr.Markdown(\n", " \"\"\"\n", " ## Pypi Download Stats \ud83d\udcc8\n", " See live download stats for all of Hugging Face's open-source libraries \ud83e\udd17\n", " \"\"\")\n", " with gr.Row():\n", " lib = gr.Dropdown([\"transformers\", \"datasets\", \"huggingface-hub\", \"gradio\", \"accelerate\"],\n", " value=\"gradio\", label=\"Library\")\n", " time = gr.Dropdown([\"3 months\", \"6 months\", \"9 months\", \"12 months\"],\n", " value=\"3 months\", label=\"Downloads over the last...\")\n", "\n", " plt = gr.LinePlot()\n", " # You can add multiple event triggers in 2 lines like this\n", " for event in [lib.change, time.change, demo.load]:\n", " event(get_plot, [lib, time], [plt])\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/blocks_multiple_event_triggers/run.py b/demo/blocks_multiple_event_triggers/run.py index 598fbee371b77..a8340d8f760e9 100644 --- a/demo/blocks_multiple_event_triggers/run.py +++ b/demo/blocks_multiple_event_triggers/run.py @@ -10,7 +10,7 @@ def get_plot(lib, time): start_date = date.today() - relativedelta(months=int(time.split(" ")[0])) data = data[(data['date'] > str(start_date))] data.date = pd.to_datetime(pd.to_datetime(data.date)) - return gr.LinePlot.update(value=data, x="date", y="downloads", + return gr.LinePlot(value=data, x="date", y="downloads", tooltip=['date', 'downloads'], title=f"Pypi downloads of {lib} over last {time}", overlay_point=True, diff --git a/demo/blocks_plug/run.ipynb b/demo/blocks_plug/run.ipynb index 9e9b4215cdd48..c005fbae9abb9 100644 --- a/demo/blocks_plug/run.ipynb +++ b/demo/blocks_plug/run.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: blocks_plug"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "\n", "def change_tab():\n", " return gr.Tabs.update(selected=2)\n", "\n", "\n", "identity_demo, input_demo, output_demo = gr.Blocks(), gr.Blocks(), gr.Blocks()\n", "\n", "with identity_demo:\n", " gr.Interface(lambda x: x, \"text\", \"text\")\n", "\n", "with input_demo:\n", " t = gr.Textbox(label=\"Enter your text here\")\n", " with gr.Row():\n", " btn = gr.Button(\"Submit\")\n", " clr = gr.ClearButton(t)\n", "\n", "with output_demo:\n", " gr.Textbox(\"This is a static output\")\n", "\n", "with gr.Blocks() as demo:\n", " gr.Markdown(\"Three demos in one!\")\n", " with gr.Tabs(selected=1) as tabs:\n", " with gr.TabItem(\"Text Identity\", id=0) as tab0:\n", " tab0.select(lambda: gr.Tabs.update(selected=0), None, tabs)\n", " identity_demo.render()\n", " with gr.TabItem(\"Text Input\", id=1) as tab1:\n", " tab1.select(lambda: gr.Tabs.update(selected=1), None, tabs)\n", " input_demo.render()\n", " with gr.TabItem(\"Text Static\", id=2) as tab2:\n", " tab2.select(lambda: gr.Tabs.update(selected=2), None, tabs)\n", " output_demo.render()\n", " btn = gr.Button(\"Change tab\")\n", " btn.click(inputs=None, outputs=tabs, fn=change_tab)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: blocks_plug"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "\n", "def change_tab():\n", " return gr.Tabs(selected=2)\n", "\n", "\n", "identity_demo, input_demo, output_demo = gr.Blocks(), gr.Blocks(), gr.Blocks()\n", "\n", "with identity_demo:\n", " gr.Interface(lambda x: x, \"text\", \"text\")\n", "\n", "with input_demo:\n", " t = gr.Textbox(label=\"Enter your text here\")\n", " with gr.Row():\n", " btn = gr.Button(\"Submit\")\n", " clr = gr.ClearButton(t)\n", "\n", "with output_demo:\n", " gr.Textbox(\"This is a static output\")\n", "\n", "with gr.Blocks() as demo:\n", " gr.Markdown(\"Three demos in one!\")\n", " with gr.Tabs(selected=1) as tabs:\n", " with gr.TabItem(\"Text Identity\", id=0) as tab0:\n", " tab0.select(lambda: gr.Tabs(selected=0), None, tabs)\n", " identity_demo.render()\n", " with gr.TabItem(\"Text Input\", id=1) as tab1:\n", " tab1.select(lambda: gr.Tabs(selected=1), None, tabs)\n", " input_demo.render()\n", " with gr.TabItem(\"Text Static\", id=2) as tab2:\n", " tab2.select(lambda: gr.Tabs(selected=2), None, tabs)\n", " output_demo.render()\n", " btn = gr.Button(\"Change tab\")\n", " btn.click(inputs=None, outputs=tabs, fn=change_tab)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/blocks_plug/run.py b/demo/blocks_plug/run.py index 49c9fc09fa153..c2b49423298d3 100644 --- a/demo/blocks_plug/run.py +++ b/demo/blocks_plug/run.py @@ -2,7 +2,7 @@ def change_tab(): - return gr.Tabs.update(selected=2) + return gr.Tabs(selected=2) identity_demo, input_demo, output_demo = gr.Blocks(), gr.Blocks(), gr.Blocks() @@ -23,13 +23,13 @@ def change_tab(): gr.Markdown("Three demos in one!") with gr.Tabs(selected=1) as tabs: with gr.TabItem("Text Identity", id=0) as tab0: - tab0.select(lambda: gr.Tabs.update(selected=0), None, tabs) + tab0.select(lambda: gr.Tabs(selected=0), None, tabs) identity_demo.render() with gr.TabItem("Text Input", id=1) as tab1: - tab1.select(lambda: gr.Tabs.update(selected=1), None, tabs) + tab1.select(lambda: gr.Tabs(selected=1), None, tabs) input_demo.render() with gr.TabItem("Text Static", id=2) as tab2: - tab2.select(lambda: gr.Tabs.update(selected=2), None, tabs) + tab2.select(lambda: gr.Tabs(selected=2), None, tabs) output_demo.render() btn = gr.Button("Change tab") btn.click(inputs=None, outputs=tabs, fn=change_tab) diff --git a/demo/blocks_update/run.ipynb b/demo/blocks_update/run.ipynb index 6a04326ca097b..285db671e5497 100644 --- a/demo/blocks_update/run.ipynb +++ b/demo/blocks_update/run.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: blocks_update"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " gr.Markdown(\n", " \"\"\"\n", " # Animal Generator\n", " Once you select a species, the detail panel should be visible.\n", " \"\"\"\n", " )\n", "\n", " species = gr.Radio(label=\"Animal Class\", choices=[\"Mammal\", \"Fish\", \"Bird\"])\n", " animal = gr.Dropdown(label=\"Animal\", choices=[])\n", "\n", " with gr.Column(visible=False) as details_col:\n", " weight = gr.Slider(0, 20)\n", " details = gr.Textbox(label=\"Extra Details\")\n", " generate_btn = gr.Button(\"Generate\")\n", " output = gr.Textbox(label=\"Output\")\n", "\n", " species_map = {\n", " \"Mammal\": [\"Elephant\", \"Giraffe\", \"Hamster\"],\n", " \"Fish\": [\"Shark\", \"Salmon\", \"Tuna\"],\n", " \"Bird\": [\"Chicken\", \"Eagle\", \"Hawk\"],\n", " }\n", "\n", " def filter_species(species):\n", " return gr.Dropdown.update(\n", " choices=species_map[species], value=species_map[species][1]\n", " ), gr.update(visible=True)\n", "\n", " species.change(filter_species, species, [animal, details_col])\n", "\n", " def filter_weight(animal):\n", " if animal in (\"Elephant\", \"Shark\", \"Giraffe\"):\n", " return gr.update(maximum=100)\n", " else:\n", " return gr.update(maximum=20)\n", "\n", " animal.change(filter_weight, animal, weight)\n", " weight.change(lambda w: gr.update(lines=int(w / 10) + 1), weight, details)\n", "\n", " generate_btn.click(lambda x: x, details, output)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: blocks_update"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " gr.Markdown(\n", " \"\"\"\n", " # Animal Generator\n", " Once you select a species, the detail panel should be visible.\n", " \"\"\"\n", " )\n", "\n", " species = gr.Radio(label=\"Animal Class\", choices=[\"Mammal\", \"Fish\", \"Bird\"])\n", " animal = gr.Dropdown(label=\"Animal\", choices=[])\n", "\n", " with gr.Column(visible=False) as details_col:\n", " weight = gr.Slider(0, 20)\n", " details = gr.Textbox(label=\"Extra Details\")\n", " generate_btn = gr.Button(\"Generate\")\n", " output = gr.Textbox(label=\"Output\")\n", "\n", " species_map = {\n", " \"Mammal\": [\"Elephant\", \"Giraffe\", \"Hamster\"],\n", " \"Fish\": [\"Shark\", \"Salmon\", \"Tuna\"],\n", " \"Bird\": [\"Chicken\", \"Eagle\", \"Hawk\"],\n", " }\n", "\n", " def filter_species(species):\n", " return gr.Dropdown(\n", " choices=species_map[species], value=species_map[species][1]\n", " ), gr.Column(visible=True)\n", "\n", " species.change(filter_species, species, [animal, details_col])\n", "\n", " def filter_weight(animal):\n", " if animal in (\"Elephant\", \"Shark\", \"Giraffe\"):\n", " return gr.Slider(maximum=100)\n", " else:\n", " return gr.Slider(maximum=20)\n", "\n", " animal.change(filter_weight, animal, weight)\n", " weight.change(lambda w: gr.Textbox(lines=int(w / 10) + 1), weight, details)\n", "\n", " generate_btn.click(lambda x: x, details, output)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/blocks_update/run.py b/demo/blocks_update/run.py index 35576951d117a..423a8d3dce275 100644 --- a/demo/blocks_update/run.py +++ b/demo/blocks_update/run.py @@ -24,20 +24,20 @@ } def filter_species(species): - return gr.Dropdown.update( + return gr.Dropdown( choices=species_map[species], value=species_map[species][1] - ), gr.update(visible=True) + ), gr.Column(visible=True) species.change(filter_species, species, [animal, details_col]) def filter_weight(animal): if animal in ("Elephant", "Shark", "Giraffe"): - return gr.update(maximum=100) + return gr.Slider(maximum=100) else: - return gr.update(maximum=20) + return gr.Slider(maximum=20) animal.change(filter_weight, animal, weight) - weight.change(lambda w: gr.update(lines=int(w / 10) + 1), weight, details) + weight.change(lambda w: gr.Textbox(lines=int(w / 10) + 1), weight, details) generate_btn.click(lambda x: x, details, output) diff --git a/demo/chatbot_multimodal/run.ipynb b/demo/chatbot_multimodal/run.ipynb index e978080af308d..e3f6e1b3095f4 100644 --- a/demo/chatbot_multimodal/run.ipynb +++ b/demo/chatbot_multimodal/run.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: chatbot_multimodal"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/chatbot_multimodal/avatar.png"]}, {"cell_type": "code", "execution_count": null, "id": 44380577570523278879349135829904343037, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import os\n", "import time\n", "\n", "# Chatbot demo with multimodal input (text, markdown, LaTeX, code blocks, image, audio, & video). Plus shows support for streaming text.\n", "\n", "\n", "def add_text(history, text):\n", " history = history + [(text, None)]\n", " return history, gr.update(value=\"\", interactive=False)\n", "\n", "\n", "def add_file(history, file):\n", " history = history + [((file.name,), None)]\n", " return history\n", "\n", "\n", "def bot(history):\n", " response = \"**That's cool!**\"\n", " history[-1][1] = \"\"\n", " for character in response:\n", " history[-1][1] += character\n", " time.sleep(0.05)\n", " yield history\n", "\n", "\n", "with gr.Blocks() as demo:\n", " chatbot = gr.Chatbot(\n", " [],\n", " elem_id=\"chatbot\",\n", " bubble_full_width=False,\n", " avatar_images=(None, (os.path.join(os.path.abspath(''), \"avatar.png\"))),\n", " )\n", "\n", " with gr.Row():\n", " txt = gr.Textbox(\n", " scale=4,\n", " show_label=False,\n", " placeholder=\"Enter text and press enter, or upload an image\",\n", " container=False,\n", " )\n", " btn = gr.UploadButton(\"\ud83d\udcc1\", file_types=[\"image\", \"video\", \"audio\"])\n", "\n", " txt_msg = txt.submit(add_text, [chatbot, txt], [chatbot, txt], queue=False).then(\n", " bot, chatbot, chatbot\n", " )\n", " txt_msg.then(lambda: gr.update(interactive=True), None, [txt], queue=False)\n", " file_msg = btn.upload(add_file, [chatbot, btn], [chatbot], queue=False).then(\n", " bot, chatbot, chatbot\n", " )\n", "\n", "demo.queue()\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: chatbot_multimodal"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/chatbot_multimodal/avatar.png"]}, {"cell_type": "code", "execution_count": null, "id": 44380577570523278879349135829904343037, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import os\n", "import time\n", "\n", "# Chatbot demo with multimodal input (text, markdown, LaTeX, code blocks, image, audio, & video). Plus shows support for streaming text.\n", "\n", "\n", "def add_text(history, text):\n", " history = history + [(text, None)]\n", " return history, gr.Textbox(value=\"\", interactive=False)\n", "\n", "\n", "def add_file(history, file):\n", " history = history + [((file.name,), None)]\n", " return history\n", "\n", "\n", "def bot(history):\n", " response = \"**That's cool!**\"\n", " history[-1][1] = \"\"\n", " for character in response:\n", " history[-1][1] += character\n", " time.sleep(0.05)\n", " yield history\n", "\n", "\n", "with gr.Blocks() as demo:\n", " chatbot = gr.Chatbot(\n", " [],\n", " elem_id=\"chatbot\",\n", " bubble_full_width=False,\n", " avatar_images=(None, (os.path.join(os.path.abspath(''), \"avatar.png\"))),\n", " )\n", "\n", " with gr.Row():\n", " txt = gr.Textbox(\n", " scale=4,\n", " show_label=False,\n", " placeholder=\"Enter text and press enter, or upload an image\",\n", " container=False,\n", " )\n", " btn = gr.UploadButton(\"\ud83d\udcc1\", file_types=[\"image\", \"video\", \"audio\"])\n", "\n", " txt_msg = txt.submit(add_text, [chatbot, txt], [chatbot, txt], queue=False).then(\n", " bot, chatbot, chatbot\n", " )\n", " txt_msg.then(lambda: gr.Textbox(interactive=True), None, [txt], queue=False)\n", " file_msg = btn.upload(add_file, [chatbot, btn], [chatbot], queue=False).then(\n", " bot, chatbot, chatbot\n", " )\n", "\n", "demo.queue()\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/chatbot_multimodal/run.py b/demo/chatbot_multimodal/run.py index 9c0d84a16d0ef..5d831d71fb4a3 100644 --- a/demo/chatbot_multimodal/run.py +++ b/demo/chatbot_multimodal/run.py @@ -7,7 +7,7 @@ def add_text(history, text): history = history + [(text, None)] - return history, gr.update(value="", interactive=False) + return history, gr.Textbox(value="", interactive=False) def add_file(history, file): @@ -44,7 +44,7 @@ def bot(history): txt_msg = txt.submit(add_text, [chatbot, txt], [chatbot, txt], queue=False).then( bot, chatbot, chatbot ) - txt_msg.then(lambda: gr.update(interactive=True), None, [txt], queue=False) + txt_msg.then(lambda: gr.Textbox(interactive=True), None, [txt], queue=False) file_msg = btn.upload(add_file, [chatbot, btn], [chatbot], queue=False).then( bot, chatbot, chatbot ) diff --git a/demo/clear_components/run.ipynb b/demo/clear_components/run.ipynb index 6bd14142dd2a5..0d09b5df8f8e6 100644 --- a/demo/clear_components/run.ipynb +++ b/demo/clear_components/run.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: clear_components"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/clear_components/__init__.py"]}, {"cell_type": "code", "execution_count": null, "id": 44380577570523278879349135829904343037, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from datetime import datetime\n", "import os\n", "import random\n", "import string\n", "import pandas as pd\n", "\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "\n", "\n", "\n", "def random_plot():\n", " start_year = 2020\n", " x = np.arange(start_year, start_year + 5)\n", " year_count = x.shape[0]\n", " plt_format = \"-\"\n", " fig = plt.figure()\n", " ax = fig.add_subplot(111)\n", " series = np.arange(0, year_count, dtype=float)\n", " series = series**2\n", " series += np.random.rand(year_count)\n", " ax.plot(x, series, plt_format)\n", " return fig\n", "\n", "\n", "images = [\n", " \"https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80\",\n", " \"https://images.unsplash.com/photo-1554151228-14d9def656e4?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=386&q=80\",\n", " \"https://images.unsplash.com/photo-1542909168-82c3e7fdca5c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8aHVtYW4lMjBmYWNlfGVufDB8fDB8fA%3D%3D&w=1000&q=80\",\n", "]\n", "file_dir = os.path.join(os.path.abspath(''), \"..\", \"kitchen_sink\", \"files\")\n", "model3d_dir = os.path.join(os.path.abspath(''), \"..\", \"model3D\", \"files\")\n", "highlighted_text_output_1 = [\n", " {\n", " \"entity\": \"I-LOC\",\n", " \"score\": 0.9988978,\n", " \"index\": 2,\n", " \"word\": \"Chicago\",\n", " \"start\": 5,\n", " \"end\": 12,\n", " },\n", " {\n", " \"entity\": \"I-MISC\",\n", " \"score\": 0.9958592,\n", " \"index\": 5,\n", " \"word\": \"Pakistani\",\n", " \"start\": 22,\n", " \"end\": 31,\n", " },\n", "]\n", "highlighted_text_output_2 = [\n", " {\n", " \"entity\": \"I-LOC\",\n", " \"score\": 0.9988978,\n", " \"index\": 2,\n", " \"word\": \"Chicago\",\n", " \"start\": 5,\n", " \"end\": 12,\n", " },\n", " {\n", " \"entity\": \"I-LOC\",\n", " \"score\": 0.9958592,\n", " \"index\": 5,\n", " \"word\": \"Pakistan\",\n", " \"start\": 22,\n", " \"end\": 30,\n", " },\n", "]\n", "\n", "highlighted_text = \"Does Chicago have any Pakistani restaurants\"\n", "\n", "\n", "def random_model3d():\n", " model_3d = random.choice(\n", " [os.path.join(model3d_dir, model) for model in os.listdir(model3d_dir) if model != \"source.txt\"]\n", " )\n", " return model_3d\n", "\n", "\n", "\n", "components = [\n", " gr.Textbox(value=lambda: datetime.now(), label=\"Current Time\"),\n", " gr.Number(value=lambda: random.random(), label=\"Random Percentage\"),\n", " gr.Slider(minimum=0, maximum=100, randomize=True, label=\"Slider with randomize\"),\n", " gr.Slider(\n", " minimum=0,\n", " maximum=1,\n", " value=lambda: random.random(),\n", " label=\"Slider with value func\",\n", " ),\n", " gr.Checkbox(value=lambda: random.random() > 0.5, label=\"Random Checkbox\"),\n", " gr.CheckboxGroup(\n", " choices=[\"a\", \"b\", \"c\", \"d\"],\n", " value=lambda: random.choice([\"a\", \"b\", \"c\", \"d\"]),\n", " label=\"Random CheckboxGroup\",\n", " ),\n", " gr.Radio(\n", " choices=list(string.ascii_lowercase),\n", " value=lambda: random.choice(string.ascii_lowercase),\n", " ),\n", " gr.Dropdown(\n", " choices=[\"a\", \"b\", \"c\", \"d\", \"e\"],\n", " value=lambda: random.choice([\"a\", \"b\", \"c\"]),\n", " ),\n", " gr.Image(\n", " value=lambda: random.choice(images)\n", " ),\n", " gr.Video(value=lambda: os.path.join(file_dir, \"world.mp4\")),\n", " gr.Audio(value=lambda: os.path.join(file_dir, \"cantina.wav\")),\n", " gr.File(\n", " value=lambda: random.choice(\n", " [os.path.join(file_dir, img) for img in os.listdir(file_dir)]\n", " )\n", " ),\n", " gr.Dataframe(\n", " value=lambda: pd.DataFrame({\"random_number_rows\": range(5)}, columns=[\"one\", \"two\", \"three\"])\n", " ),\n", " gr.Timeseries(value=lambda: os.path.join(file_dir, \"time.csv\")),\n", " gr.ColorPicker(value=lambda: random.choice([\"#000000\", \"#ff0000\", \"#0000FF\"])),\n", " gr.Label(value=lambda: random.choice([\"Pedestrian\", \"Car\", \"Cyclist\"])),\n", " gr.HighlightedText(\n", " value=lambda: random.choice(\n", " [\n", " {\"text\": highlighted_text, \"entities\": highlighted_text_output_1},\n", " {\"text\": highlighted_text, \"entities\": highlighted_text_output_2},\n", " ]\n", " ),\n", " ),\n", " gr.JSON(value=lambda: random.choice([{\"a\": 1}, {\"b\": 2}])),\n", " gr.HTML(\n", " value=lambda: random.choice(\n", " [\n", " '

I am red

',\n", " '

I am blue

',\n", " ]\n", " )\n", " ),\n", " gr.Gallery(\n", " value=lambda: images\n", " ),\n", " gr.Model3D(value=random_model3d),\n", " gr.Plot(value=random_plot),\n", " gr.Markdown(value=lambda: f\"### {random.choice(['Hello', 'Hi', 'Goodbye!'])}\"),\n", "]\n", "\n", "\n", "def evaluate_values(*args):\n", " are_false = []\n", " for a in args:\n", " if isinstance(a, (pd.DataFrame, np.ndarray)):\n", " are_false.append(not a.any().any())\n", " elif isinstance(a, str) and a.startswith(\"#\"):\n", " are_false.append(a == \"#000000\")\n", " else:\n", " are_false.append(not a)\n", " return all(are_false)\n", "\n", "\n", "with gr.Blocks() as demo:\n", " for i, component in enumerate(components):\n", " component.label = f\"component_{str(i).zfill(2)}\"\n", " component.render()\n", " clear = gr.ClearButton(value=\"Clear\", components=components)\n", " result = gr.Textbox(label=\"Are all cleared?\")\n", " hide = gr.Button(value=\"Hide\")\n", " reveal = gr.Button(value=\"Reveal\")\n", " hide.click(\n", " lambda: [c.update(visible=False) for c in components],\n", " inputs=[],\n", " outputs=components\n", " )\n", " reveal.click(\n", " lambda: [c.update(visible=True) for c in components],\n", " inputs=[],\n", " outputs=components\n", " )\n", " get_value = gr.Button(value=\"Get Values\")\n", " get_value.click(evaluate_values, components, result)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: clear_components"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/clear_components/__init__.py"]}, {"cell_type": "code", "execution_count": null, "id": 44380577570523278879349135829904343037, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from datetime import datetime\n", "import os\n", "import random\n", "import string\n", "import pandas as pd\n", "\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "\n", "\n", "\n", "def random_plot():\n", " start_year = 2020\n", " x = np.arange(start_year, start_year + 5)\n", " year_count = x.shape[0]\n", " plt_format = \"-\"\n", " fig = plt.figure()\n", " ax = fig.add_subplot(111)\n", " series = np.arange(0, year_count, dtype=float)\n", " series = series**2\n", " series += np.random.rand(year_count)\n", " ax.plot(x, series, plt_format)\n", " return fig\n", "\n", "\n", "images = [\n", " \"https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80\",\n", " \"https://images.unsplash.com/photo-1554151228-14d9def656e4?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=386&q=80\",\n", " \"https://images.unsplash.com/photo-1542909168-82c3e7fdca5c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8aHVtYW4lMjBmYWNlfGVufDB8fDB8fA%3D%3D&w=1000&q=80\",\n", "]\n", "file_dir = os.path.join(os.path.abspath(''), \"..\", \"kitchen_sink\", \"files\")\n", "model3d_dir = os.path.join(os.path.abspath(''), \"..\", \"model3D\", \"files\")\n", "highlighted_text_output_1 = [\n", " {\n", " \"entity\": \"I-LOC\",\n", " \"score\": 0.9988978,\n", " \"index\": 2,\n", " \"word\": \"Chicago\",\n", " \"start\": 5,\n", " \"end\": 12,\n", " },\n", " {\n", " \"entity\": \"I-MISC\",\n", " \"score\": 0.9958592,\n", " \"index\": 5,\n", " \"word\": \"Pakistani\",\n", " \"start\": 22,\n", " \"end\": 31,\n", " },\n", "]\n", "highlighted_text_output_2 = [\n", " {\n", " \"entity\": \"I-LOC\",\n", " \"score\": 0.9988978,\n", " \"index\": 2,\n", " \"word\": \"Chicago\",\n", " \"start\": 5,\n", " \"end\": 12,\n", " },\n", " {\n", " \"entity\": \"I-LOC\",\n", " \"score\": 0.9958592,\n", " \"index\": 5,\n", " \"word\": \"Pakistan\",\n", " \"start\": 22,\n", " \"end\": 30,\n", " },\n", "]\n", "\n", "highlighted_text = \"Does Chicago have any Pakistani restaurants\"\n", "\n", "\n", "def random_model3d():\n", " model_3d = random.choice(\n", " [os.path.join(model3d_dir, model) for model in os.listdir(model3d_dir) if model != \"source.txt\"]\n", " )\n", " return model_3d\n", "\n", "\n", "\n", "components = [\n", " gr.Textbox(value=lambda: datetime.now(), label=\"Current Time\"),\n", " gr.Number(value=lambda: random.random(), label=\"Random Percentage\"),\n", " gr.Slider(minimum=0, maximum=100, randomize=True, label=\"Slider with randomize\"),\n", " gr.Slider(\n", " minimum=0,\n", " maximum=1,\n", " value=lambda: random.random(),\n", " label=\"Slider with value func\",\n", " ),\n", " gr.Checkbox(value=lambda: random.random() > 0.5, label=\"Random Checkbox\"),\n", " gr.CheckboxGroup(\n", " choices=[\"a\", \"b\", \"c\", \"d\"],\n", " value=lambda: random.choice([\"a\", \"b\", \"c\", \"d\"]),\n", " label=\"Random CheckboxGroup\",\n", " ),\n", " gr.Radio(\n", " choices=list(string.ascii_lowercase),\n", " value=lambda: random.choice(string.ascii_lowercase),\n", " ),\n", " gr.Dropdown(\n", " choices=[\"a\", \"b\", \"c\", \"d\", \"e\"],\n", " value=lambda: random.choice([\"a\", \"b\", \"c\"]),\n", " ),\n", " gr.Image(\n", " value=lambda: random.choice(images)\n", " ),\n", " gr.Video(value=lambda: os.path.join(file_dir, \"world.mp4\")),\n", " gr.Audio(value=lambda: os.path.join(file_dir, \"cantina.wav\")),\n", " gr.File(\n", " value=lambda: random.choice(\n", " [os.path.join(file_dir, img) for img in os.listdir(file_dir)]\n", " )\n", " ),\n", " gr.Dataframe(\n", " value=lambda: pd.DataFrame({\"random_number_rows\": range(5)}, columns=[\"one\", \"two\", \"three\"])\n", " ),\n", " gr.Timeseries(value=lambda: os.path.join(file_dir, \"time.csv\")),\n", " gr.ColorPicker(value=lambda: random.choice([\"#000000\", \"#ff0000\", \"#0000FF\"])),\n", " gr.Label(value=lambda: random.choice([\"Pedestrian\", \"Car\", \"Cyclist\"])),\n", " gr.HighlightedText(\n", " value=lambda: random.choice(\n", " [\n", " {\"text\": highlighted_text, \"entities\": highlighted_text_output_1},\n", " {\"text\": highlighted_text, \"entities\": highlighted_text_output_2},\n", " ]\n", " ),\n", " ),\n", " gr.JSON(value=lambda: random.choice([{\"a\": 1}, {\"b\": 2}])),\n", " gr.HTML(\n", " value=lambda: random.choice(\n", " [\n", " '

I am red

',\n", " '

I am blue

',\n", " ]\n", " )\n", " ),\n", " gr.Gallery(\n", " value=lambda: images\n", " ),\n", " gr.Model3D(value=random_model3d),\n", " gr.Plot(value=random_plot),\n", " gr.Markdown(value=lambda: f\"### {random.choice(['Hello', 'Hi', 'Goodbye!'])}\"),\n", "]\n", "\n", "\n", "def evaluate_values(*args):\n", " are_false = []\n", " for a in args:\n", " if isinstance(a, (pd.DataFrame, np.ndarray)):\n", " are_false.append(not a.any().any())\n", " elif isinstance(a, str) and a.startswith(\"#\"):\n", " are_false.append(a == \"#000000\")\n", " else:\n", " are_false.append(not a)\n", " return all(are_false)\n", "\n", "\n", "with gr.Blocks() as demo:\n", " for i, component in enumerate(components):\n", " component.label = f\"component_{str(i).zfill(2)}\"\n", " component.render()\n", " clear = gr.ClearButton(value=\"Clear\", components=components)\n", " result = gr.Textbox(label=\"Are all cleared?\")\n", " hide = gr.Button(value=\"Hide\")\n", " reveal = gr.Button(value=\"Reveal\")\n", " hide.click(\n", " lambda: [c.__class__(visible=False) for c in components],\n", " inputs=[],\n", " outputs=components\n", " )\n", " reveal.click(\n", " lambda: [c.__class__(visible=True) for c in components],\n", " inputs=[],\n", " outputs=components\n", " )\n", " get_value = gr.Button(value=\"Get Values\")\n", " get_value.click(evaluate_values, components, result)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/clear_components/run.py b/demo/clear_components/run.py index f5a5794cae847..d3eb8361fec2d 100644 --- a/demo/clear_components/run.py +++ b/demo/clear_components/run.py @@ -166,12 +166,12 @@ def evaluate_values(*args): hide = gr.Button(value="Hide") reveal = gr.Button(value="Reveal") hide.click( - lambda: [c.update(visible=False) for c in components], + lambda: [c.__class__(visible=False) for c in components], inputs=[], outputs=components ) reveal.click( - lambda: [c.update(visible=True) for c in components], + lambda: [c.__class__(visible=True) for c in components], inputs=[], outputs=components ) diff --git a/demo/code/run.ipynb b/demo/code/run.ipynb index 71f3e7349bbea..bd0bb5efe2fe4 100644 --- a/demo/code/run.ipynb +++ b/demo/code/run.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: code"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/code/file.css"]}, {"cell_type": "code", "execution_count": null, "id": 44380577570523278879349135829904343037, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import os\n", "from time import sleep\n", "\n", "\n", "css_file = os.path.join(os.path.abspath(''), \"file.css\")\n", "\n", "\n", "def set_lang(language):\n", " print(language)\n", " return gr.Code.update(language=language)\n", "\n", "\n", "def set_lang_from_path():\n", " sleep(1)\n", " return gr.Code.update((css_file,), language=\"css\")\n", "\n", "\n", "def code(language, code):\n", " return gr.Code.update(code, language=language)\n", "\n", "\n", "io = gr.Interface(lambda x: x, \"code\", \"code\")\n", "\n", "with gr.Blocks() as demo:\n", " lang = gr.Dropdown(value=\"python\", choices=gr.Code.languages)\n", " with gr.Row():\n", " code_in = gr.Code(\n", " language=\"python\",\n", " label=\"Input\",\n", " value='def all_odd_elements(sequence):\\n \"\"\"Returns every odd element of the sequence.\"\"\"',\n", " )\n", " code_out = gr.Code(label=\"Output\")\n", " btn = gr.Button(\"Run\")\n", " btn_two = gr.Button(\"Load File\")\n", "\n", " lang.change(set_lang, inputs=lang, outputs=code_in)\n", " btn.click(code, inputs=[lang, code_in], outputs=code_out)\n", " btn_two.click(set_lang_from_path, inputs=None, outputs=code_out)\n", " io.render()\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: code"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/code/file.css"]}, {"cell_type": "code", "execution_count": null, "id": 44380577570523278879349135829904343037, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import os\n", "from time import sleep\n", "\n", "\n", "css_file = os.path.join(os.path.abspath(''), \"file.css\")\n", "\n", "\n", "def set_lang(language):\n", " print(language)\n", " return gr.Code(language=language)\n", "\n", "\n", "def set_lang_from_path():\n", " sleep(1)\n", " return gr.Code((css_file,), language=\"css\")\n", "\n", "\n", "def code(language, code):\n", " return gr.Code(code, language=language)\n", "\n", "\n", "io = gr.Interface(lambda x: x, \"code\", \"code\")\n", "\n", "with gr.Blocks() as demo:\n", " lang = gr.Dropdown(value=\"python\", choices=gr.Code.languages)\n", " with gr.Row():\n", " code_in = gr.Code(\n", " language=\"python\",\n", " label=\"Input\",\n", " value='def all_odd_elements(sequence):\\n \"\"\"Returns every odd element of the sequence.\"\"\"',\n", " )\n", " code_out = gr.Code(label=\"Output\")\n", " btn = gr.Button(\"Run\")\n", " btn_two = gr.Button(\"Load File\")\n", "\n", " lang.change(set_lang, inputs=lang, outputs=code_in)\n", " btn.click(code, inputs=[lang, code_in], outputs=code_out)\n", " btn_two.click(set_lang_from_path, inputs=None, outputs=code_out)\n", " io.render()\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/code/run.py b/demo/code/run.py index 01cfb314a84eb..7a2aa6f1ee9ba 100644 --- a/demo/code/run.py +++ b/demo/code/run.py @@ -8,16 +8,16 @@ def set_lang(language): print(language) - return gr.Code.update(language=language) + return gr.Code(language=language) def set_lang_from_path(): sleep(1) - return gr.Code.update((css_file,), language="css") + return gr.Code((css_file,), language="css") def code(language, code): - return gr.Code.update(code, language=language) + return gr.Code(code, language=language) io = gr.Interface(lambda x: x, "code", "code") diff --git a/demo/dashboard/run.ipynb b/demo/dashboard/run.ipynb index 06abbaf396cf5..a331555fa570e 100644 --- a/demo/dashboard/run.ipynb +++ b/demo/dashboard/run.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: dashboard\n", "### This demo shows how you can build an interactive dashboard with gradio. Click on a python library on the left hand side and then on the right hand side click on the metric you'd like to see plot over time. Data is pulled from HuggingFace Hub datasets.\n", " "]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio plotly"]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/dashboard/helpers.py"]}, {"cell_type": "code", "execution_count": null, "id": 44380577570523278879349135829904343037, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import pandas as pd\n", "import plotly.express as px\n", "from helpers import *\n", "\n", "\n", "LIBRARIES = [\"accelerate\", \"datasets\", \"diffusers\", \"evaluate\", \"gradio\", \"hub_docs\",\n", " \"huggingface_hub\", \"optimum\", \"pytorch_image_models\", \"tokenizers\", \"transformers\"]\n", "\n", "\n", "def create_pip_plot(libraries, pip_choices):\n", " if \"Pip\" not in pip_choices:\n", " return gr.update(visible=False)\n", " output = retrieve_pip_installs(libraries, \"Cumulated\" in pip_choices)\n", " df = pd.DataFrame(output).melt(id_vars=\"day\")\n", " plot = px.line(df, x=\"day\", y=\"value\", color=\"variable\",\n", " title=\"Pip installs\")\n", " plot.update_layout(legend=dict(x=0.5, y=0.99), title_x=0.5, legend_title_text=\"\")\n", " return gr.update(value=plot, visible=True)\n", "\n", "\n", "def create_star_plot(libraries, star_choices):\n", " if \"Stars\" not in star_choices:\n", " return gr.update(visible=False)\n", " output = retrieve_stars(libraries, \"Week over Week\" in star_choices)\n", " df = pd.DataFrame(output).melt(id_vars=\"day\")\n", " plot = px.line(df, x=\"day\", y=\"value\", color=\"variable\",\n", " title=\"Number of stargazers\")\n", " plot.update_layout(legend=dict(x=0.5, y=0.99), title_x=0.5, legend_title_text=\"\")\n", " return gr.update(value=plot, visible=True)\n", "\n", "\n", "def create_issue_plot(libraries, issue_choices):\n", " if \"Issue\" not in issue_choices:\n", " return gr.update(visible=False)\n", " output = retrieve_issues(libraries,\n", " exclude_org_members=\"Exclude org members\" in issue_choices,\n", " week_over_week=\"Week over Week\" in issue_choices)\n", " df = pd.DataFrame(output).melt(id_vars=\"day\")\n", " plot = px.line(df, x=\"day\", y=\"value\", color=\"variable\",\n", " title=\"Cumulated number of issues, PRs, and comments\",\n", " )\n", " plot.update_layout(legend=dict(x=0.5, y=0.99), title_x=0.5, legend_title_text=\"\")\n", " return gr.update(value=plot, visible=True)\n", "\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " with gr.Column():\n", " gr.Markdown(\"## Select libraries to display\")\n", " libraries = gr.CheckboxGroup(choices=LIBRARIES, label=\"\")\n", " with gr.Column():\n", " gr.Markdown(\"## Select graphs to display\")\n", " pip = gr.CheckboxGroup(choices=[\"Pip\", \"Cumulated\"], label=\"\")\n", " stars = gr.CheckboxGroup(choices=[\"Stars\", \"Week over Week\"], label=\"\")\n", " issues = gr.CheckboxGroup(choices=[\"Issue\", \"Exclude org members\", \"week over week\"], label=\"\")\n", " with gr.Row():\n", " fetch = gr.Button(value=\"Fetch\")\n", " with gr.Row():\n", " with gr.Column():\n", " pip_plot = gr.Plot(visible=False)\n", " star_plot = gr.Plot(visible=False)\n", " issue_plot = gr.Plot(visible=False)\n", "\n", " fetch.click(create_pip_plot, inputs=[libraries, pip], outputs=pip_plot)\n", " fetch.click(create_star_plot, inputs=[libraries, stars], outputs=star_plot)\n", " fetch.click(create_issue_plot, inputs=[libraries, issues], outputs=issue_plot)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: dashboard\n", "### This demo shows how you can build an interactive dashboard with gradio. Click on a python library on the left hand side and then on the right hand side click on the metric you'd like to see plot over time. Data is pulled from HuggingFace Hub datasets.\n", " "]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio plotly"]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/dashboard/helpers.py"]}, {"cell_type": "code", "execution_count": null, "id": 44380577570523278879349135829904343037, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import pandas as pd\n", "import plotly.express as px\n", "from helpers import *\n", "\n", "\n", "LIBRARIES = [\"accelerate\", \"datasets\", \"diffusers\", \"evaluate\", \"gradio\", \"hub_docs\",\n", " \"huggingface_hub\", \"optimum\", \"pytorch_image_models\", \"tokenizers\", \"transformers\"]\n", "\n", "\n", "def create_pip_plot(libraries, pip_choices):\n", " if \"Pip\" not in pip_choices:\n", " return gr.Plot(visible=False)\n", " output = retrieve_pip_installs(libraries, \"Cumulated\" in pip_choices)\n", " df = pd.DataFrame(output).melt(id_vars=\"day\")\n", " plot = px.line(df, x=\"day\", y=\"value\", color=\"variable\",\n", " title=\"Pip installs\")\n", " plot.update_layout(legend=dict(x=0.5, y=0.99), title_x=0.5, legend_title_text=\"\")\n", " return gr.Plot(value=plot, visible=True)\n", "\n", "\n", "def create_star_plot(libraries, star_choices):\n", " if \"Stars\" not in star_choices:\n", " return gr.Plot(visible=False)\n", " output = retrieve_stars(libraries, \"Week over Week\" in star_choices)\n", " df = pd.DataFrame(output).melt(id_vars=\"day\")\n", " plot = px.line(df, x=\"day\", y=\"value\", color=\"variable\",\n", " title=\"Number of stargazers\")\n", " plot.update_layout(legend=dict(x=0.5, y=0.99), title_x=0.5, legend_title_text=\"\")\n", " return gr.Plot(value=plot, visible=True)\n", "\n", "\n", "def create_issue_plot(libraries, issue_choices):\n", " if \"Issue\" not in issue_choices:\n", " return gr.Plot(visible=False)\n", " output = retrieve_issues(libraries,\n", " exclude_org_members=\"Exclude org members\" in issue_choices,\n", " week_over_week=\"Week over Week\" in issue_choices)\n", " df = pd.DataFrame(output).melt(id_vars=\"day\")\n", " plot = px.line(df, x=\"day\", y=\"value\", color=\"variable\",\n", " title=\"Cumulated number of issues, PRs, and comments\",\n", " )\n", " plot.update_layout(legend=dict(x=0.5, y=0.99), title_x=0.5, legend_title_text=\"\")\n", " return gr.Plot(value=plot, visible=True)\n", "\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " with gr.Column():\n", " gr.Markdown(\"## Select libraries to display\")\n", " libraries = gr.CheckboxGroup(choices=LIBRARIES, label=\"\")\n", " with gr.Column():\n", " gr.Markdown(\"## Select graphs to display\")\n", " pip = gr.CheckboxGroup(choices=[\"Pip\", \"Cumulated\"], label=\"\")\n", " stars = gr.CheckboxGroup(choices=[\"Stars\", \"Week over Week\"], label=\"\")\n", " issues = gr.CheckboxGroup(choices=[\"Issue\", \"Exclude org members\", \"week over week\"], label=\"\")\n", " with gr.Row():\n", " fetch = gr.Button(value=\"Fetch\")\n", " with gr.Row():\n", " with gr.Column():\n", " pip_plot = gr.Plot(visible=False)\n", " star_plot = gr.Plot(visible=False)\n", " issue_plot = gr.Plot(visible=False)\n", "\n", " fetch.click(create_pip_plot, inputs=[libraries, pip], outputs=pip_plot)\n", " fetch.click(create_star_plot, inputs=[libraries, stars], outputs=star_plot)\n", " fetch.click(create_issue_plot, inputs=[libraries, issues], outputs=issue_plot)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/dashboard/run.py b/demo/dashboard/run.py index 8f14689c3cc30..5cd6446b4622b 100644 --- a/demo/dashboard/run.py +++ b/demo/dashboard/run.py @@ -10,29 +10,29 @@ def create_pip_plot(libraries, pip_choices): if "Pip" not in pip_choices: - return gr.update(visible=False) + return gr.Plot(visible=False) output = retrieve_pip_installs(libraries, "Cumulated" in pip_choices) df = pd.DataFrame(output).melt(id_vars="day") plot = px.line(df, x="day", y="value", color="variable", title="Pip installs") plot.update_layout(legend=dict(x=0.5, y=0.99), title_x=0.5, legend_title_text="") - return gr.update(value=plot, visible=True) + return gr.Plot(value=plot, visible=True) def create_star_plot(libraries, star_choices): if "Stars" not in star_choices: - return gr.update(visible=False) + return gr.Plot(visible=False) output = retrieve_stars(libraries, "Week over Week" in star_choices) df = pd.DataFrame(output).melt(id_vars="day") plot = px.line(df, x="day", y="value", color="variable", title="Number of stargazers") plot.update_layout(legend=dict(x=0.5, y=0.99), title_x=0.5, legend_title_text="") - return gr.update(value=plot, visible=True) + return gr.Plot(value=plot, visible=True) def create_issue_plot(libraries, issue_choices): if "Issue" not in issue_choices: - return gr.update(visible=False) + return gr.Plot(visible=False) output = retrieve_issues(libraries, exclude_org_members="Exclude org members" in issue_choices, week_over_week="Week over Week" in issue_choices) @@ -41,7 +41,7 @@ def create_issue_plot(libraries, issue_choices): title="Cumulated number of issues, PRs, and comments", ) plot.update_layout(legend=dict(x=0.5, y=0.99), title_x=0.5, legend_title_text="") - return gr.update(value=plot, visible=True) + return gr.Plot(value=plot, visible=True) with gr.Blocks() as demo: diff --git a/demo/event_trigger/run.ipynb b/demo/event_trigger/run.ipynb index cda9ee87d8dc1..66ed05b489ada 100644 --- a/demo/event_trigger/run.ipynb +++ b/demo/event_trigger/run.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: event_trigger"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('img')\n", "!wget -q -O img/a.jpg https://github.com/gradio-app/gradio/raw/main/demo/event_trigger/img/a.jpg\n", "!wget -q -O img/b.jpg https://github.com/gradio-app/gradio/raw/main/demo/event_trigger/img/b.jpg\n", "os.mkdir('mp4')\n", "!wget -q -O mp4/a.mp4 https://github.com/gradio-app/gradio/raw/main/demo/event_trigger/mp4/a.mp4\n", "!wget -q -O mp4/b.mp4 https://github.com/gradio-app/gradio/raw/main/demo/event_trigger/mp4/b.mp4"]}, {"cell_type": "code", "execution_count": null, "id": 44380577570523278879349135829904343037, "metadata": {}, "outputs": [], "source": ["# %%\n", "import gradio as gr\n", "\n", "\n", "TEST_VIDEO_A = \"mp4/a.mp4\"\n", "TEST_VIDEO_B = \"mp4/b.mp4\"\n", "\n", "TEST_IMAGE_A = \"img/a.jpg\"\n", "TEST_IMAGE_B = \"img/b.jpg\"\n", "\n", "\n", "def alert_change(component, value):\n", " print(f\"Detected {component} change, {type(value)}\")\n", "\n", " if type(value) == list or type(value) == str:\n", " print(value)\n", "\n", "\n", "def change_interactive(state):\n", " return gr.update(interactive=not state), not state\n", "\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Tab(label=\"Text change\"):\n", " with gr.Row():\n", " with gr.Column():\n", " textbox1 = gr.Textbox()\n", " textbox2 = gr.Textbox(interactive=True)\n", "\n", " with gr.Column():\n", " btn = gr.Button()\n", "\n", " def btn_click(state):\n", " return state\n", "\n", " def text_change(value):\n", " print(\"text_change\", value)\n", "\n", " btn.click(fn=btn_click, inputs=textbox1, outputs=textbox2)\n", " textbox2.change(fn=alert_change, inputs=[gr.State(\"Text\"), textbox2])\n", "\n", " with gr.Tab(label=\"Video change, play, pause\"):\n", " with gr.Row():\n", " with gr.Column():\n", " radio1 = gr.Radio(\n", " choices=[TEST_VIDEO_A, TEST_VIDEO_B],\n", " interactive=True,\n", " type=\"index\",\n", " )\n", "\n", " video_btn = gr.Button(\"Change interactive\")\n", "\n", " with gr.Column():\n", " video1 = gr.Video(value=TEST_VIDEO_A, interactive=False)\n", " video1_interactive = gr.State(value=False)\n", "\n", " def change_video(index):\n", " if index == 0:\n", " return TEST_VIDEO_A\n", " elif index == 1:\n", " return TEST_VIDEO_B\n", "\n", " def video_play():\n", " print(\"video_play\")\n", "\n", " def video_pause():\n", " print(\"video_pause\")\n", "\n", " def video_stop():\n", " print(\"video_stop\")\n", "\n", " def video_end():\n", " print(\"video_end\")\n", "\n", " video1.play(fn=video_play)\n", " video1.pause(fn=video_pause)\n", " video1.stop(fn=video_stop)\n", " video1.end(fn=video_end)\n", "\n", " radio1.change(fn=change_video, inputs=radio1, outputs=video1)\n", " video1.change(fn=alert_change, inputs=[gr.State(\"Video\"), video1])\n", "\n", " video_btn.click(\n", " fn=change_interactive,\n", " inputs=video1_interactive,\n", " outputs=[video1, video1_interactive],\n", " )\n", "\n", " with gr.Tab(label=\"Image change\"):\n", " with gr.Row():\n", " with gr.Column():\n", " radio2 = gr.Radio(\n", " choices=[TEST_IMAGE_A, TEST_IMAGE_B],\n", " interactive=True,\n", " type=\"index\",\n", " )\n", "\n", " with gr.Column():\n", " image1 = gr.Image(value=TEST_IMAGE_A, interactive=True)\n", "\n", " def change_image(index):\n", " if index == 0:\n", " return TEST_IMAGE_A\n", " elif index == 1:\n", " return TEST_IMAGE_B\n", "\n", " radio2.change(fn=change_image, inputs=radio2, outputs=image1)\n", " image1.change(fn=alert_change, inputs=[gr.State(\"Image\"), image1])\n", "\n", " with gr.Tab(label=\"File\"):\n", " with gr.Row():\n", " with gr.Column():\n", " radio3 = gr.Radio(\n", " choices=[\"A\", \"B\", \"AB\"],\n", " interactive=True,\n", " type=\"index\",\n", " )\n", "\n", " file_btn = gr.Button(\"Change interactive\")\n", "\n", " with gr.Column():\n", " file1 = gr.File(\n", " value=[TEST_IMAGE_A, TEST_IMAGE_B],\n", " interactive=False,\n", " file_count=\"multiple\",\n", " )\n", " file1_interactive = gr.State(value=False)\n", "\n", " def change_file(index):\n", " if index == 0:\n", " return [TEST_IMAGE_A]\n", " elif index == 1:\n", " return [TEST_IMAGE_A]\n", " elif index == 2:\n", " return [TEST_IMAGE_A, TEST_IMAGE_B]\n", "\n", " radio3.change(fn=change_file, inputs=radio3, outputs=file1)\n", " file1.change(fn=alert_change, inputs=[gr.State(\"File\"), file1])\n", "\n", " file_btn.click(\n", " fn=change_interactive,\n", " inputs=file1_interactive,\n", " outputs=[file1, file1_interactive],\n", " )\n", "\n", "demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: event_trigger"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('img')\n", "!wget -q -O img/a.jpg https://github.com/gradio-app/gradio/raw/main/demo/event_trigger/img/a.jpg\n", "!wget -q -O img/b.jpg https://github.com/gradio-app/gradio/raw/main/demo/event_trigger/img/b.jpg\n", "os.mkdir('mp4')\n", "!wget -q -O mp4/a.mp4 https://github.com/gradio-app/gradio/raw/main/demo/event_trigger/mp4/a.mp4\n", "!wget -q -O mp4/b.mp4 https://github.com/gradio-app/gradio/raw/main/demo/event_trigger/mp4/b.mp4"]}, {"cell_type": "code", "execution_count": null, "id": 44380577570523278879349135829904343037, "metadata": {}, "outputs": [], "source": ["# %%\n", "import gradio as gr\n", "\n", "\n", "TEST_VIDEO_A = \"mp4/a.mp4\"\n", "TEST_VIDEO_B = \"mp4/b.mp4\"\n", "\n", "TEST_IMAGE_A = \"img/a.jpg\"\n", "TEST_IMAGE_B = \"img/b.jpg\"\n", "\n", "\n", "def alert_change(component, value):\n", " print(f\"Detected {component} change, {type(value)}\")\n", "\n", " if type(value) == list or type(value) == str:\n", " print(value)\n", "\n", "\n", "def change_interactive(state):\n", " return gr.Video(interactive=not state), not state\n", "\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Tab(label=\"Text change\"):\n", " with gr.Row():\n", " with gr.Column():\n", " textbox1 = gr.Textbox()\n", " textbox2 = gr.Textbox(interactive=True)\n", "\n", " with gr.Column():\n", " btn = gr.Button()\n", "\n", " def btn_click(state):\n", " return state\n", "\n", " def text_change(value):\n", " print(\"text_change\", value)\n", "\n", " btn.click(fn=btn_click, inputs=textbox1, outputs=textbox2)\n", " textbox2.change(fn=alert_change, inputs=[gr.State(\"Text\"), textbox2])\n", "\n", " with gr.Tab(label=\"Video change, play, pause\"):\n", " with gr.Row():\n", " with gr.Column():\n", " radio1 = gr.Radio(\n", " choices=[TEST_VIDEO_A, TEST_VIDEO_B],\n", " interactive=True,\n", " type=\"index\",\n", " )\n", "\n", " video_btn = gr.Button(\"Change interactive\")\n", "\n", " with gr.Column():\n", " video1 = gr.Video(value=TEST_VIDEO_A, interactive=False)\n", " video1_interactive = gr.State(value=False)\n", "\n", " def change_video(index):\n", " if index == 0:\n", " return TEST_VIDEO_A\n", " elif index == 1:\n", " return TEST_VIDEO_B\n", "\n", " def video_play():\n", " print(\"video_play\")\n", "\n", " def video_pause():\n", " print(\"video_pause\")\n", "\n", " def video_stop():\n", " print(\"video_stop\")\n", "\n", " def video_end():\n", " print(\"video_end\")\n", "\n", " video1.play(fn=video_play)\n", " video1.pause(fn=video_pause)\n", " video1.stop(fn=video_stop)\n", " video1.end(fn=video_end)\n", "\n", " radio1.change(fn=change_video, inputs=radio1, outputs=video1)\n", " video1.change(fn=alert_change, inputs=[gr.State(\"Video\"), video1])\n", "\n", " video_btn.click(\n", " fn=change_interactive,\n", " inputs=video1_interactive,\n", " outputs=[video1, video1_interactive],\n", " )\n", "\n", " with gr.Tab(label=\"Image change\"):\n", " with gr.Row():\n", " with gr.Column():\n", " radio2 = gr.Radio(\n", " choices=[TEST_IMAGE_A, TEST_IMAGE_B],\n", " interactive=True,\n", " type=\"index\",\n", " )\n", "\n", " with gr.Column():\n", " image1 = gr.Image(value=TEST_IMAGE_A, interactive=True)\n", "\n", " def change_image(index):\n", " if index == 0:\n", " return TEST_IMAGE_A\n", " elif index == 1:\n", " return TEST_IMAGE_B\n", "\n", " radio2.change(fn=change_image, inputs=radio2, outputs=image1)\n", " image1.change(fn=alert_change, inputs=[gr.State(\"Image\"), image1])\n", "\n", " with gr.Tab(label=\"File\"):\n", " with gr.Row():\n", " with gr.Column():\n", " radio3 = gr.Radio(\n", " choices=[\"A\", \"B\", \"AB\"],\n", " interactive=True,\n", " type=\"index\",\n", " )\n", "\n", " file_btn = gr.Button(\"Change interactive\")\n", "\n", " with gr.Column():\n", " file1 = gr.File(\n", " value=[TEST_IMAGE_A, TEST_IMAGE_B],\n", " interactive=False,\n", " file_count=\"multiple\",\n", " )\n", " file1_interactive = gr.State(value=False)\n", "\n", " def change_file(index):\n", " if index == 0:\n", " return [TEST_IMAGE_A]\n", " elif index == 1:\n", " return [TEST_IMAGE_A]\n", " elif index == 2:\n", " return [TEST_IMAGE_A, TEST_IMAGE_B]\n", "\n", " radio3.change(fn=change_file, inputs=radio3, outputs=file1)\n", " file1.change(fn=alert_change, inputs=[gr.State(\"File\"), file1])\n", "\n", " file_btn.click(\n", " fn=change_interactive,\n", " inputs=file1_interactive,\n", " outputs=[file1, file1_interactive],\n", " )\n", "\n", "demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/event_trigger/run.py b/demo/event_trigger/run.py index bc25dc47199cd..2497d750ffd9b 100644 --- a/demo/event_trigger/run.py +++ b/demo/event_trigger/run.py @@ -17,7 +17,7 @@ def alert_change(component, value): def change_interactive(state): - return gr.update(interactive=not state), not state + return gr.Video(interactive=not state), not state with gr.Blocks() as demo: diff --git a/demo/fake_diffusion_with_gif/run.ipynb b/demo/fake_diffusion_with_gif/run.ipynb index f9215d07e53f8..a6f27a41349a3 100644 --- a/demo/fake_diffusion_with_gif/run.ipynb +++ b/demo/fake_diffusion_with_gif/run.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: fake_diffusion_with_gif"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/fake_diffusion_with_gif/image.gif"]}, {"cell_type": "code", "execution_count": null, "id": 44380577570523278879349135829904343037, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import numpy as np\n", "import time\n", "import os\n", "from PIL import Image\n", "import requests\n", "from io import BytesIO\n", "\n", "\n", "def create_gif(images):\n", " pil_images = []\n", " for image in images:\n", " if isinstance(image, str):\n", " response = requests.get(image)\n", " image = Image.open(BytesIO(response.content))\n", " else:\n", " image = Image.fromarray((image * 255).astype(np.uint8))\n", " pil_images.append(image)\n", " fp_out = os.path.join(os.path.abspath(''), \"image.gif\")\n", " img = pil_images.pop(0)\n", " img.save(fp=fp_out, format='GIF', append_images=pil_images,\n", " save_all=True, duration=400, loop=0)\n", " return fp_out\n", "\n", "\n", "def fake_diffusion(steps):\n", " images = []\n", " for _ in range(steps):\n", " time.sleep(1)\n", " image = np.random.random((600, 600, 3))\n", " images.append(image)\n", " yield image, gr.Image.update(visible=False)\n", " \n", " time.sleep(1)\n", " image = \"https://gradio-builds.s3.amazonaws.com/diffusion_image/cute_dog.jpg\" \n", " images.append(image)\n", " gif_path = create_gif(images)\n", " \n", " yield image, gr.Image.update(value=gif_path, visible=True)\n", "\n", "\n", "demo = gr.Interface(fake_diffusion, \n", " inputs=gr.Slider(1, 10, 3), \n", " outputs=[\"image\", gr.Image(label=\"All Images\", visible=False)])\n", "demo.queue()\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: fake_diffusion_with_gif"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "!wget -q https://github.com/gradio-app/gradio/raw/main/demo/fake_diffusion_with_gif/image.gif"]}, {"cell_type": "code", "execution_count": null, "id": 44380577570523278879349135829904343037, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import numpy as np\n", "import time\n", "import os\n", "from PIL import Image\n", "import requests\n", "from io import BytesIO\n", "\n", "\n", "def create_gif(images):\n", " pil_images = []\n", " for image in images:\n", " if isinstance(image, str):\n", " response = requests.get(image)\n", " image = Image.open(BytesIO(response.content))\n", " else:\n", " image = Image.fromarray((image * 255).astype(np.uint8))\n", " pil_images.append(image)\n", " fp_out = os.path.join(os.path.abspath(''), \"image.gif\")\n", " img = pil_images.pop(0)\n", " img.save(fp=fp_out, format='GIF', append_images=pil_images,\n", " save_all=True, duration=400, loop=0)\n", " return fp_out\n", "\n", "\n", "def fake_diffusion(steps):\n", " images = []\n", " for _ in range(steps):\n", " time.sleep(1)\n", " image = np.random.random((600, 600, 3))\n", " images.append(image)\n", " yield image, gr.Image(visible=False)\n", " \n", " time.sleep(1)\n", " image = \"https://gradio-builds.s3.amazonaws.com/diffusion_image/cute_dog.jpg\" \n", " images.append(image)\n", " gif_path = create_gif(images)\n", " \n", " yield image, gr.Image(value=gif_path, visible=True)\n", "\n", "\n", "demo = gr.Interface(fake_diffusion, \n", " inputs=gr.Slider(1, 10, 3), \n", " outputs=[\"image\", gr.Image(label=\"All Images\", visible=False)])\n", "demo.queue()\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/fake_diffusion_with_gif/run.py b/demo/fake_diffusion_with_gif/run.py index 7fcb2123ff48e..2fa896fc8c36d 100644 --- a/demo/fake_diffusion_with_gif/run.py +++ b/demo/fake_diffusion_with_gif/run.py @@ -29,14 +29,14 @@ def fake_diffusion(steps): time.sleep(1) image = np.random.random((600, 600, 3)) images.append(image) - yield image, gr.Image.update(visible=False) + yield image, gr.Image(visible=False) time.sleep(1) image = "https://gradio-builds.s3.amazonaws.com/diffusion_image/cute_dog.jpg" images.append(image) gif_path = create_gif(images) - yield image, gr.Image.update(value=gif_path, visible=True) + yield image, gr.Image(value=gif_path, visible=True) demo = gr.Interface(fake_diffusion, diff --git a/demo/line_plot/run.ipynb b/demo/line_plot/run.ipynb index a3d22a0bcab8b..2590b0d18ba72 100644 --- a/demo/line_plot/run.ipynb +++ b/demo/line_plot/run.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: line_plot"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio vega_datasets pandas"]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from vega_datasets import data\n", "\n", "stocks = data.stocks()\n", "gapminder = data.gapminder()\n", "gapminder = gapminder.loc[\n", " gapminder.country.isin([\"Argentina\", \"Australia\", \"Afghanistan\"])\n", "]\n", "climate = data.climate()\n", "seattle_weather = data.seattle_weather()\n", "\n", "## Or generate your own fake data, here's an example for stocks:\n", "#\n", "# import pandas as pd\n", "# import random\n", "#\n", "# stocks = pd.DataFrame(\n", "# {\n", "# \"symbol\": [\n", "# random.choice(\n", "# [\n", "# \"MSFT\",\n", "# \"AAPL\",\n", "# \"AMZN\",\n", "# \"IBM\",\n", "# \"GOOG\",\n", "# ]\n", "# )\n", "# for _ in range(120)\n", "# ],\n", "# \"date\": [\n", "# pd.Timestamp(year=2000 + i, month=j, day=1)\n", "# for i in range(10)\n", "# for j in range(1, 13)\n", "# ],\n", "# \"price\": [random.randint(10, 200) for _ in range(120)],\n", "# }\n", "# )\n", "\n", "\n", "def line_plot_fn(dataset):\n", " if dataset == \"stocks\":\n", " return gr.LinePlot.update(\n", " stocks,\n", " x=\"date\",\n", " y=\"price\",\n", " color=\"symbol\",\n", " color_legend_position=\"bottom\",\n", " title=\"Stock Prices\",\n", " tooltip=[\"date\", \"price\", \"symbol\"],\n", " height=300,\n", " width=500,\n", " )\n", " elif dataset == \"climate\":\n", " return gr.LinePlot.update(\n", " climate,\n", " x=\"DATE\",\n", " y=\"HLY-TEMP-NORMAL\",\n", " y_lim=[250, 500],\n", " title=\"Climate\",\n", " tooltip=[\"DATE\", \"HLY-TEMP-NORMAL\"],\n", " height=300,\n", " width=500,\n", " )\n", " elif dataset == \"seattle_weather\":\n", " return gr.LinePlot.update(\n", " seattle_weather,\n", " x=\"date\",\n", " y=\"temp_min\",\n", " tooltip=[\"weather\", \"date\"],\n", " overlay_point=True,\n", " title=\"Seattle Weather\",\n", " height=300,\n", " width=500,\n", " )\n", " elif dataset == \"gapminder\":\n", " return gr.LinePlot.update(\n", " gapminder,\n", " x=\"year\",\n", " y=\"life_expect\",\n", " color=\"country\",\n", " title=\"Life expectancy for countries\",\n", " stroke_dash=\"cluster\",\n", " x_lim=[1950, 2010],\n", " tooltip=[\"country\", \"life_expect\"],\n", " stroke_dash_legend_title=\"Country Cluster\",\n", " height=300,\n", " width=500,\n", " )\n", "\n", "\n", "with gr.Blocks() as line_plot:\n", " with gr.Row():\n", " with gr.Column():\n", " dataset = gr.Dropdown(\n", " choices=[\"stocks\", \"climate\", \"seattle_weather\", \"gapminder\"],\n", " value=\"stocks\",\n", " )\n", " with gr.Column():\n", " plot = gr.LinePlot()\n", " dataset.change(line_plot_fn, inputs=dataset, outputs=plot)\n", " line_plot.load(fn=line_plot_fn, inputs=dataset, outputs=plot)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " line_plot.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: line_plot"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio vega_datasets pandas"]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from vega_datasets import data\n", "\n", "stocks = data.stocks()\n", "gapminder = data.gapminder()\n", "gapminder = gapminder.loc[\n", " gapminder.country.isin([\"Argentina\", \"Australia\", \"Afghanistan\"])\n", "]\n", "climate = data.climate()\n", "seattle_weather = data.seattle_weather()\n", "\n", "## Or generate your own fake data, here's an example for stocks:\n", "#\n", "# import pandas as pd\n", "# import random\n", "#\n", "# stocks = pd.DataFrame(\n", "# {\n", "# \"symbol\": [\n", "# random.choice(\n", "# [\n", "# \"MSFT\",\n", "# \"AAPL\",\n", "# \"AMZN\",\n", "# \"IBM\",\n", "# \"GOOG\",\n", "# ]\n", "# )\n", "# for _ in range(120)\n", "# ],\n", "# \"date\": [\n", "# pd.Timestamp(year=2000 + i, month=j, day=1)\n", "# for i in range(10)\n", "# for j in range(1, 13)\n", "# ],\n", "# \"price\": [random.randint(10, 200) for _ in range(120)],\n", "# }\n", "# )\n", "\n", "\n", "def line_plot_fn(dataset):\n", " if dataset == \"stocks\":\n", " return gr.LinePlot(\n", " stocks,\n", " x=\"date\",\n", " y=\"price\",\n", " color=\"symbol\",\n", " color_legend_position=\"bottom\",\n", " title=\"Stock Prices\",\n", " tooltip=[\"date\", \"price\", \"symbol\"],\n", " height=300,\n", " width=500,\n", " )\n", " elif dataset == \"climate\":\n", " return gr.LinePlot(\n", " climate,\n", " x=\"DATE\",\n", " y=\"HLY-TEMP-NORMAL\",\n", " y_lim=[250, 500],\n", " title=\"Climate\",\n", " tooltip=[\"DATE\", \"HLY-TEMP-NORMAL\"],\n", " height=300,\n", " width=500,\n", " )\n", " elif dataset == \"seattle_weather\":\n", " return gr.LinePlot(\n", " seattle_weather,\n", " x=\"date\",\n", " y=\"temp_min\",\n", " tooltip=[\"weather\", \"date\"],\n", " overlay_point=True,\n", " title=\"Seattle Weather\",\n", " height=300,\n", " width=500,\n", " )\n", " elif dataset == \"gapminder\":\n", " return gr.LinePlot(\n", " gapminder,\n", " x=\"year\",\n", " y=\"life_expect\",\n", " color=\"country\",\n", " title=\"Life expectancy for countries\",\n", " stroke_dash=\"cluster\",\n", " x_lim=[1950, 2010],\n", " tooltip=[\"country\", \"life_expect\"],\n", " stroke_dash_legend_title=\"Country Cluster\",\n", " height=300,\n", " width=500,\n", " )\n", "\n", "\n", "with gr.Blocks() as line_plot:\n", " with gr.Row():\n", " with gr.Column():\n", " dataset = gr.Dropdown(\n", " choices=[\"stocks\", \"climate\", \"seattle_weather\", \"gapminder\"],\n", " value=\"stocks\",\n", " )\n", " with gr.Column():\n", " plot = gr.LinePlot()\n", " dataset.change(line_plot_fn, inputs=dataset, outputs=plot)\n", " line_plot.load(fn=line_plot_fn, inputs=dataset, outputs=plot)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " line_plot.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/line_plot/run.py b/demo/line_plot/run.py index 9b933f2cb43db..aec886c055e43 100644 --- a/demo/line_plot/run.py +++ b/demo/line_plot/run.py @@ -40,7 +40,7 @@ def line_plot_fn(dataset): if dataset == "stocks": - return gr.LinePlot.update( + return gr.LinePlot( stocks, x="date", y="price", @@ -52,7 +52,7 @@ def line_plot_fn(dataset): width=500, ) elif dataset == "climate": - return gr.LinePlot.update( + return gr.LinePlot( climate, x="DATE", y="HLY-TEMP-NORMAL", @@ -63,7 +63,7 @@ def line_plot_fn(dataset): width=500, ) elif dataset == "seattle_weather": - return gr.LinePlot.update( + return gr.LinePlot( seattle_weather, x="date", y="temp_min", @@ -74,7 +74,7 @@ def line_plot_fn(dataset): width=500, ) elif dataset == "gapminder": - return gr.LinePlot.update( + return gr.LinePlot( gapminder, x="year", y="life_expect", diff --git a/demo/live_dashboard/run.ipynb b/demo/live_dashboard/run.ipynb index 885c3fa195386..6fa3e43432590 100644 --- a/demo/live_dashboard/run.ipynb +++ b/demo/live_dashboard/run.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: live_dashboard\n", "### This demo shows how you can build a live interactive dashboard with gradio.\n", "The current time is refreshed every second and the plot every half second by using the 'every' keyword in the event handler.\n", "Changing the value of the slider will control the period of the sine curve (the distance between peaks). \n", " "]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio plotly"]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import math\n", "\n", "import pandas as pd\n", "\n", "import gradio as gr\n", "import datetime\n", "import numpy as np\n", "\n", "\n", "def get_time():\n", " return datetime.datetime.now()\n", "\n", "\n", "plot_end = 2 * math.pi\n", "\n", "\n", "def get_plot(period=1):\n", " global plot_end\n", " x = np.arange(plot_end - 2 * math.pi, plot_end, 0.02)\n", " y = np.sin(2 * math.pi * period * x)\n", " update = gr.LinePlot.update(\n", " value=pd.DataFrame({\"x\": x, \"y\": y}),\n", " x=\"x\",\n", " y=\"y\",\n", " title=\"Plot (updates every second)\",\n", " width=600,\n", " height=350,\n", " )\n", " plot_end += 2 * math.pi\n", " if plot_end > 1000:\n", " plot_end = 2 * math.pi\n", " return update\n", "\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " with gr.Column():\n", " c_time2 = gr.Textbox(label=\"Current Time refreshed every second\")\n", " gr.Textbox(\n", " \"Change the value of the slider to automatically update the plot\",\n", " label=\"\",\n", " )\n", " period = gr.Slider(\n", " label=\"Period of plot\", value=1, minimum=0, maximum=10, step=1\n", " )\n", " plot = gr.LinePlot(show_label=False)\n", " with gr.Column():\n", " name = gr.Textbox(label=\"Enter your name\")\n", " greeting = gr.Textbox(label=\"Greeting\")\n", " button = gr.Button(value=\"Greet\")\n", " button.click(lambda s: f\"Hello {s}\", name, greeting)\n", "\n", " demo.load(lambda: datetime.datetime.now(), None, c_time2, every=1)\n", " dep = demo.load(get_plot, None, plot, every=1)\n", " period.change(get_plot, period, plot, every=1, cancels=[dep])\n", "\n", "if __name__ == \"__main__\":\n", " demo.queue().launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: live_dashboard\n", "### This demo shows how you can build a live interactive dashboard with gradio.\n", "The current time is refreshed every second and the plot every half second by using the 'every' keyword in the event handler.\n", "Changing the value of the slider will control the period of the sine curve (the distance between peaks). \n", " "]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio plotly"]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import math\n", "\n", "import pandas as pd\n", "\n", "import gradio as gr\n", "import datetime\n", "import numpy as np\n", "\n", "\n", "def get_time():\n", " return datetime.datetime.now()\n", "\n", "\n", "plot_end = 2 * math.pi\n", "\n", "\n", "def get_plot(period=1):\n", " global plot_end\n", " x = np.arange(plot_end - 2 * math.pi, plot_end, 0.02)\n", " y = np.sin(2 * math.pi * period * x)\n", " update = gr.LinePlot(\n", " value=pd.DataFrame({\"x\": x, \"y\": y}),\n", " x=\"x\",\n", " y=\"y\",\n", " title=\"Plot (updates every second)\",\n", " width=600,\n", " height=350,\n", " )\n", " plot_end += 2 * math.pi\n", " if plot_end > 1000:\n", " plot_end = 2 * math.pi\n", " return update\n", "\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " with gr.Column():\n", " c_time2 = gr.Textbox(label=\"Current Time refreshed every second\")\n", " gr.Textbox(\n", " \"Change the value of the slider to automatically update the plot\",\n", " label=\"\",\n", " )\n", " period = gr.Slider(\n", " label=\"Period of plot\", value=1, minimum=0, maximum=10, step=1\n", " )\n", " plot = gr.LinePlot(show_label=False)\n", " with gr.Column():\n", " name = gr.Textbox(label=\"Enter your name\")\n", " greeting = gr.Textbox(label=\"Greeting\")\n", " button = gr.Button(value=\"Greet\")\n", " button.click(lambda s: f\"Hello {s}\", name, greeting)\n", "\n", " demo.load(lambda: datetime.datetime.now(), None, c_time2, every=1)\n", " dep = demo.load(get_plot, None, plot, every=1)\n", " period.change(get_plot, period, plot, every=1, cancels=[dep])\n", "\n", "if __name__ == \"__main__\":\n", " demo.queue().launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/live_dashboard/run.py b/demo/live_dashboard/run.py index 8362e75dda858..90c21c50bfcef 100644 --- a/demo/live_dashboard/run.py +++ b/demo/live_dashboard/run.py @@ -18,7 +18,7 @@ def get_plot(period=1): global plot_end x = np.arange(plot_end - 2 * math.pi, plot_end, 0.02) y = np.sin(2 * math.pi * period * x) - update = gr.LinePlot.update( + update = gr.LinePlot( value=pd.DataFrame({"x": x, "y": y}), x="x", y="y", diff --git a/demo/native_plots/bar_plot_demo.py b/demo/native_plots/bar_plot_demo.py index 3b4323858e240..b4ed1981dd4ae 100644 --- a/demo/native_plots/bar_plot_demo.py +++ b/demo/native_plots/bar_plot_demo.py @@ -11,58 +11,77 @@ def bar_plot_fn(display): if display == "simple": - return gr.BarPlot.update( + return gr.BarPlot( simple, x="a", y="b", + color=None, + group=None, title="Simple Bar Plot with made up data", tooltip=['a', 'b'], - y_lim=[20, 100] + y_lim=[20, 100], + x_title=None, + y_title=None, + vertical=True, ) elif display == "stacked": - return gr.BarPlot.update( + return gr.BarPlot( barley, x="variety", y="yield", color="site", + group=None, title="Barley Yield Data", - tooltip=['variety', 'site'] + tooltip=['variety', 'site'], + y_lim=None, + x_title=None, + y_title=None, + vertical=True, ) elif display == "grouped": - return gr.BarPlot.update( + return gr.BarPlot( barley.astype({"year": str}), x="year", y="yield", color="year", group="site", title="Barley Yield by Year and Site", - group_title="", - tooltip=["yield", "site", "year"] + tooltip=["yield", "site", "year"], + y_lim=None, + x_title=None, + y_title=None, + vertical=True, ) elif display == "simple-horizontal": - return gr.BarPlot.update( + return gr.BarPlot( simple, x="a", y="b", - x_title="Variable A", - y_title="Variable B", + color=None, + group=None, title="Simple Bar Plot with made up data", tooltip=['a', 'b'], + y_lim=[20, 100], + x_title="Variable A", + y_title="Variable B", vertical=False, - y_lim=[20, 100] ) elif display == "stacked-horizontal": - return gr.BarPlot.update( + return gr.BarPlot( barley, x="variety", y="yield", color="site", + group=None, title="Barley Yield Data", + tooltip=['variety', 'site'], + y_lim=None, + x_title=None, + y_title=None, vertical=False, - tooltip=['variety', 'site'] ) elif display == "grouped-horizontal": - return gr.BarPlot.update( + return gr.BarPlot( barley.astype({"year": str}), x="year", y="yield", @@ -71,6 +90,9 @@ def bar_plot_fn(display): title="Barley Yield by Year and Site", group_title="", tooltip=["yield", "site", "year"], + y_lim=None, + x_title=None, + y_title=None, vertical=False ) diff --git a/demo/native_plots/line_plot_demo.py b/demo/native_plots/line_plot_demo.py index 423d0998d20e5..6ba86557b17b5 100644 --- a/demo/native_plots/line_plot_demo.py +++ b/demo/native_plots/line_plot_demo.py @@ -12,49 +12,65 @@ def line_plot_fn(dataset): if dataset == "stocks": - return gr.LinePlot.update( + return gr.LinePlot( stocks, x="date", y="price", color="symbol", - color_legend_position="bottom", - title="Stock Prices", + x_lim=None, + y_lim=None, + stroke_dash=None, tooltip=['date', 'price', 'symbol'], + overlay_point=False, + title="Stock Prices", + stroke_dash_legend_title=None, height=300, width=500 ) elif dataset == "climate": - return gr.LinePlot.update( + return gr.LinePlot( climate, x="DATE", y="HLY-TEMP-NORMAL", + color=None, + x_lim=None, y_lim=[250, 500], - title="Climate", + stroke_dash=None, tooltip=['DATE', 'HLY-TEMP-NORMAL'], + overlay_point=False, + title="Climate", + stroke_dash_legend_title=None, height=300, width=500 ) elif dataset == "seattle_weather": - return gr.LinePlot.update( + return gr.LinePlot( seattle_weather, x="date", y="temp_min", + color=None, + x_lim=None, + y_lim=None, + stroke_dash=None, tooltip=["weather", "date"], overlay_point=True, title="Seattle Weather", + stroke_dash_legend_title=None, height=300, width=500 ) elif dataset == "gapminder": - return gr.LinePlot.update( + return gr.LinePlot( gapminder, x="year", y="life_expect", color="country", - title="Life expectancy for countries", - stroke_dash="cluster", x_lim=[1950, 2010], + y_lim=None, + stroke_dash="cluster", tooltip=['country', 'life_expect'], + overlay_point=False, + title="Life expectancy for countries", stroke_dash_legend_title="Country Cluster", height=300, width=500 diff --git a/demo/native_plots/scatter_plot_demo.py b/demo/native_plots/scatter_plot_demo.py index 45a0ca8b5f3d9..3ae129ea9d3a7 100644 --- a/demo/native_plots/scatter_plot_demo.py +++ b/demo/native_plots/scatter_plot_demo.py @@ -8,7 +8,7 @@ def scatter_plot_fn(dataset): if dataset == "iris": - return gr.ScatterPlot.update( + return gr.ScatterPlot( value=iris, x="petalWidth", y="petalLength", @@ -21,7 +21,7 @@ def scatter_plot_fn(dataset): caption="", ) else: - return gr.ScatterPlot.update( + return gr.ScatterPlot( value=cars, x="Horsepower", y="Miles_per_Gallon", diff --git a/demo/scatter_plot/run.ipynb b/demo/scatter_plot/run.ipynb index 7f84ab0987081..d5d992f1a732f 100644 --- a/demo/scatter_plot/run.ipynb +++ b/demo/scatter_plot/run.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: scatter_plot"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio vega_datasets pandas"]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from vega_datasets import data\n", "\n", "cars = data.cars()\n", "iris = data.iris()\n", "\n", "# # Or generate your own fake data\n", "\n", "# import pandas as pd\n", "# import random\n", "\n", "# cars_data = {\n", "# \"Name\": [\"car name \" + f\" {int(i/10)}\" for i in range(400)],\n", "# \"Miles_per_Gallon\": [random.randint(10, 30) for _ in range(400)],\n", "# \"Origin\": [random.choice([\"USA\", \"Europe\", \"Japan\"]) for _ in range(400)],\n", "# \"Horsepower\": [random.randint(50, 250) for _ in range(400)],\n", "# }\n", "\n", "# iris_data = {\n", "# \"petalWidth\": [round(random.uniform(0, 2.5), 2) for _ in range(150)],\n", "# \"petalLength\": [round(random.uniform(0, 7), 2) for _ in range(150)],\n", "# \"species\": [\n", "# random.choice([\"setosa\", \"versicolor\", \"virginica\"]) for _ in range(150)\n", "# ],\n", "# }\n", "\n", "# cars = pd.DataFrame(cars_data)\n", "# iris = pd.DataFrame(iris_data)\n", "\n", "\n", "def scatter_plot_fn(dataset):\n", " if dataset == \"iris\":\n", " return gr.ScatterPlot.update(\n", " value=iris,\n", " x=\"petalWidth\",\n", " y=\"petalLength\",\n", " color=\"species\",\n", " title=\"Iris Dataset\",\n", " color_legend_title=\"Species\",\n", " x_title=\"Petal Width\",\n", " y_title=\"Petal Length\",\n", " tooltip=[\"petalWidth\", \"petalLength\", \"species\"],\n", " caption=\"\",\n", " )\n", " else:\n", " return gr.ScatterPlot.update(\n", " value=cars,\n", " x=\"Horsepower\",\n", " y=\"Miles_per_Gallon\",\n", " color=\"Origin\",\n", " tooltip=\"Name\",\n", " title=\"Car Data\",\n", " y_title=\"Miles per Gallon\",\n", " color_legend_title=\"Origin of Car\",\n", " caption=\"MPG vs Horsepower of various cars\",\n", " )\n", "\n", "\n", "with gr.Blocks() as scatter_plot:\n", " with gr.Row():\n", " with gr.Column():\n", " dataset = gr.Dropdown(choices=[\"cars\", \"iris\"], value=\"cars\")\n", " with gr.Column():\n", " plot = gr.ScatterPlot()\n", " dataset.change(scatter_plot_fn, inputs=dataset, outputs=plot)\n", " scatter_plot.load(fn=scatter_plot_fn, inputs=dataset, outputs=plot)\n", "\n", "if __name__ == \"__main__\":\n", " scatter_plot.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: scatter_plot"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio vega_datasets pandas"]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from vega_datasets import data\n", "\n", "cars = data.cars()\n", "iris = data.iris()\n", "\n", "# # Or generate your own fake data\n", "\n", "# import pandas as pd\n", "# import random\n", "\n", "# cars_data = {\n", "# \"Name\": [\"car name \" + f\" {int(i/10)}\" for i in range(400)],\n", "# \"Miles_per_Gallon\": [random.randint(10, 30) for _ in range(400)],\n", "# \"Origin\": [random.choice([\"USA\", \"Europe\", \"Japan\"]) for _ in range(400)],\n", "# \"Horsepower\": [random.randint(50, 250) for _ in range(400)],\n", "# }\n", "\n", "# iris_data = {\n", "# \"petalWidth\": [round(random.uniform(0, 2.5), 2) for _ in range(150)],\n", "# \"petalLength\": [round(random.uniform(0, 7), 2) for _ in range(150)],\n", "# \"species\": [\n", "# random.choice([\"setosa\", \"versicolor\", \"virginica\"]) for _ in range(150)\n", "# ],\n", "# }\n", "\n", "# cars = pd.DataFrame(cars_data)\n", "# iris = pd.DataFrame(iris_data)\n", "\n", "\n", "def scatter_plot_fn(dataset):\n", " if dataset == \"iris\":\n", " return gr.ScatterPlot(\n", " value=iris,\n", " x=\"petalWidth\",\n", " y=\"petalLength\",\n", " color=\"species\",\n", " title=\"Iris Dataset\",\n", " color_legend_title=\"Species\",\n", " x_title=\"Petal Width\",\n", " y_title=\"Petal Length\",\n", " tooltip=[\"petalWidth\", \"petalLength\", \"species\"],\n", " caption=\"\",\n", " )\n", " else:\n", " return gr.ScatterPlot(\n", " value=cars,\n", " x=\"Horsepower\",\n", " y=\"Miles_per_Gallon\",\n", " color=\"Origin\",\n", " tooltip=\"Name\",\n", " title=\"Car Data\",\n", " y_title=\"Miles per Gallon\",\n", " color_legend_title=\"Origin of Car\",\n", " caption=\"MPG vs Horsepower of various cars\",\n", " )\n", "\n", "\n", "with gr.Blocks() as scatter_plot:\n", " with gr.Row():\n", " with gr.Column():\n", " dataset = gr.Dropdown(choices=[\"cars\", \"iris\"], value=\"cars\")\n", " with gr.Column():\n", " plot = gr.ScatterPlot()\n", " dataset.change(scatter_plot_fn, inputs=dataset, outputs=plot)\n", " scatter_plot.load(fn=scatter_plot_fn, inputs=dataset, outputs=plot)\n", "\n", "if __name__ == \"__main__\":\n", " scatter_plot.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/scatter_plot/run.py b/demo/scatter_plot/run.py index 64cd140468e13..5cc11df2690fb 100644 --- a/demo/scatter_plot/run.py +++ b/demo/scatter_plot/run.py @@ -30,7 +30,7 @@ def scatter_plot_fn(dataset): if dataset == "iris": - return gr.ScatterPlot.update( + return gr.ScatterPlot( value=iris, x="petalWidth", y="petalLength", @@ -43,7 +43,7 @@ def scatter_plot_fn(dataset): caption="", ) else: - return gr.ScatterPlot.update( + return gr.ScatterPlot( value=cars, x="Horsepower", y="Miles_per_Gallon", diff --git a/demo/stream_audio/run.ipynb b/demo/stream_audio/run.ipynb index 801062c1c5ad2..3cb0d76c525ab 100644 --- a/demo/stream_audio/run.ipynb +++ b/demo/stream_audio/run.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: stream_audio"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import numpy as np\n", "import time\n", "\n", "def add_to_stream(audio, instream):\n", " time.sleep(1)\n", " if audio is None:\n", " return gr.update(), instream\n", " if instream is None:\n", " ret = audio\n", " else:\n", " ret = (audio[0], np.concatenate((instream[1], audio[1])))\n", " return ret, ret\n", "\n", "\n", "with gr.Blocks() as demo:\n", " inp = gr.Audio(source=\"microphone\")\n", " out = gr.Audio()\n", " stream = gr.State()\n", " clear = gr.Button(\"Clear\")\n", "\n", " inp.stream(add_to_stream, [inp, stream], [out, stream])\n", " clear.click(lambda: [None, None, None], None, [inp, out, stream])\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: stream_audio"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import numpy as np\n", "import time\n", "\n", "def add_to_stream(audio, instream):\n", " time.sleep(1)\n", " if audio is None:\n", " return gr.Audio(), instream\n", " if instream is None:\n", " ret = audio\n", " else:\n", " ret = (audio[0], np.concatenate((instream[1], audio[1])))\n", " return ret, ret\n", "\n", "\n", "with gr.Blocks() as demo:\n", " inp = gr.Audio(source=\"microphone\")\n", " out = gr.Audio()\n", " stream = gr.State()\n", " clear = gr.Button(\"Clear\")\n", "\n", " inp.stream(add_to_stream, [inp, stream], [out, stream])\n", " clear.click(lambda: [None, None, None], None, [inp, out, stream])\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/stream_audio/run.py b/demo/stream_audio/run.py index 81713cdc99eac..cfc6cfd88cdf0 100644 --- a/demo/stream_audio/run.py +++ b/demo/stream_audio/run.py @@ -5,7 +5,7 @@ def add_to_stream(audio, instream): time.sleep(1) if audio is None: - return gr.update(), instream + return gr.Audio(), instream if instream is None: ret = audio else: diff --git a/demo/variable_outputs/run.ipynb b/demo/variable_outputs/run.ipynb index 22cd6a3329c4d..578fdf9314ccf 100644 --- a/demo/variable_outputs/run.ipynb +++ b/demo/variable_outputs/run.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: variable_outputs"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "max_textboxes = 10\n", "\n", "def variable_outputs(k):\n", " k = int(k)\n", " return [gr.Textbox.update(visible=True)]*k + [gr.Textbox.update(visible=False)]*(max_textboxes-k)\n", "\n", "with gr.Blocks() as demo:\n", " s = gr.Slider(1, max_textboxes, value=max_textboxes, step=1, label=\"How many textboxes to show:\")\n", " textboxes = []\n", " for i in range(max_textboxes):\n", " t = gr.Textbox(f\"Textbox {i}\")\n", " textboxes.append(t)\n", "\n", " s.change(variable_outputs, s, textboxes)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: variable_outputs"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "max_textboxes = 10\n", "\n", "def variable_outputs(k):\n", " k = int(k)\n", " return [gr.Textbox(visible=True)]*k + [gr.Textbox(visible=False)]*(max_textboxes-k)\n", "\n", "with gr.Blocks() as demo:\n", " s = gr.Slider(1, max_textboxes, value=max_textboxes, step=1, label=\"How many textboxes to show:\")\n", " textboxes = []\n", " for i in range(max_textboxes):\n", " t = gr.Textbox(f\"Textbox {i}\")\n", " textboxes.append(t)\n", "\n", " s.change(variable_outputs, s, textboxes)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/variable_outputs/run.py b/demo/variable_outputs/run.py index 6c5360dedd919..c893faf60aa25 100644 --- a/demo/variable_outputs/run.py +++ b/demo/variable_outputs/run.py @@ -4,7 +4,7 @@ def variable_outputs(k): k = int(k) - return [gr.Textbox.update(visible=True)]*k + [gr.Textbox.update(visible=False)]*(max_textboxes-k) + return [gr.Textbox(visible=True)]*k + [gr.Textbox(visible=False)]*(max_textboxes-k) with gr.Blocks() as demo: s = gr.Slider(1, max_textboxes, value=max_textboxes, step=1, label="How many textboxes to show:") diff --git a/gradio/blocks.py b/gradio/blocks.py index 2b9c042cc61b2..eb82619594b7e 100644 --- a/gradio/blocks.py +++ b/gradio/blocks.py @@ -13,6 +13,7 @@ import webbrowser from abc import abstractmethod from collections import defaultdict +from functools import wraps from pathlib import Path from types import ModuleType from typing import TYPE_CHECKING, Any, AsyncIterator, Callable, Literal, cast @@ -45,6 +46,7 @@ InvalidBlockError, ) from gradio.helpers import EventData, create_tracker, skip, special_args +from gradio.state_holder import SessionState from gradio.themes import Default as DefaultTheme from gradio.themes import ThemeClass as Theme from gradio.tunneling import ( @@ -59,7 +61,6 @@ check_function_inputs_match, component_or_layout_class, concurrency_count_warning, - delete_none, get_cancel_function, get_continuous_fn, get_package_version, @@ -89,6 +90,42 @@ } +def in_event_listener(): + from gradio import context + + return getattr(context.thread_data, "in_event_listener", False) + + +def updateable(fn): + @wraps(fn) + def wrapper(*args, **kwargs): + fn_args = inspect.getfullargspec(fn).args + self = args[0] + for i, arg in enumerate(args): + if i == 0 or i >= len(fn_args): # skip self, *args + continue + arg_name = fn_args[i] + kwargs[arg_name] = arg + self.constructor_args = kwargs + if in_event_listener(): + return None + else: + return fn(self, **kwargs) + + return wrapper + + +updated_cls_set = set() + + +class Updateable: + def __new__(cls, *args, **kwargs): + if cls not in updated_cls_set: + cls.__init__ = updateable(cls.__init__) + updated_cls_set.add(cls) + return super().__new__(cls) + + class Block: def __init__( self, @@ -113,6 +150,8 @@ def __init__( self._skip_init_processing = _skip_init_processing self.parent: BlockContext | None = None self.is_rendered: bool = False + self.constructor_args: dict + self.state_session_capacity = 10000 if render: self.render() @@ -307,12 +346,13 @@ def set_event_trigger( return dependency, len(Context.root_block.dependencies) - 1 def get_config(self): - return { - "visible": self.visible, - "elem_id": self.elem_id, - "elem_classes": self.elem_classes, - "root_url": self.root_url, - } + config = {} + signature = inspect.signature(self.__class__.__init__) + for parameter in signature.parameters.values(): + if hasattr(self, parameter.name): + value = getattr(self, parameter.name) + config[parameter.name] = value + return {**config, "root_url": self.root_url, "name": self.get_block_name()} @staticmethod @abstractmethod @@ -324,6 +364,7 @@ def get_specific_update(cls, generic_update: dict[str, Any]) -> dict: generic_update = generic_update.copy() del generic_update["__type__"] specific_update = cls.update(**generic_update) + specific_update = utils.delete_none(specific_update, skip_value=True) return specific_update @@ -452,13 +493,20 @@ def postprocess_update_dict(block: Block, update_dict: dict, postprocess: bool = interactive = update_dict.pop("interactive", None) if interactive is not None: update_dict["mode"] = "dynamic" if interactive else "static" - prediction_value = delete_none(update_dict, skip_value=True) - if "value" in prediction_value and postprocess: + attr_dict = { + k: getattr(block, k) if hasattr(block, k) else v for k, v in update_dict.items() + } + attr_dict["__type__"] = "update" + attr_dict.pop("value", None) + if "value" in update_dict: assert isinstance( block, components.IOComponent ), f"Component {block.__class__} does not support value" - prediction_value["value"] = block.postprocess(prediction_value["value"]) - return prediction_value + if postprocess: + attr_dict["value"] = block.postprocess(update_dict["value"]) + else: + attr_dict["value"] = update_dict["value"] + return attr_dict def convert_component_dict_to_list( @@ -1068,6 +1116,7 @@ async def call_function( requests: routes.Request | list[routes.Request] | None = None, event_id: str | None = None, event_data: EventData | None = None, + in_event_listener: bool = False, ): """ Calls function with given index and preprocessed input, and measures process time. @@ -1084,7 +1133,10 @@ async def call_function( is_generating = False request = requests[0] if isinstance(requests, list) else requests start = time.time() - fn = utils.get_function_with_locals(block_fn.fn, self, event_id) + + fn = utils.get_function_with_locals( + block_fn.fn, self, event_id, in_event_listener + ) if iterator is None: # If not a generator function that has already run if block_fn.inputs_as_dict: @@ -1221,7 +1273,10 @@ def validate_inputs(self, fn_index: int, inputs: list[Any]): [{received}]""" ) - def preprocess_data(self, fn_index: int, inputs: list[Any], state: dict[int, Any]): + def preprocess_data( + self, fn_index: int, inputs: list[Any], state: SessionState | None + ): + state = state or SessionState(self) block_fn = self.fns[fn_index] dependency = self.dependencies[fn_index] @@ -1240,8 +1295,10 @@ def preprocess_data(self, fn_index: int, inputs: list[Any], state: dict[int, Any block, components.Component ), f"{block.__class__} Component with id {input_id} not a valid input component." if getattr(block, "stateful", False): - processed_input.append(state.get(input_id)) + processed_input.append(state[input_id]) else: + if input_id in state: + block = state[input_id] processed_input.append(block.preprocess(inputs[i])) else: processed_input = inputs @@ -1284,8 +1341,9 @@ def validate_outputs(self, fn_index: int, predictions: Any | list[Any]): ) def postprocess_data( - self, fn_index: int, predictions: list | dict, state: dict[int, Any] + self, fn_index: int, predictions: list | dict, state: SessionState | None ): + state = state or SessionState(self) block_fn = self.fns[fn_index] dependency = self.dependencies[fn_index] batch = dependency["batch"] @@ -1327,10 +1385,31 @@ def postprocess_data( output.append(None) else: prediction_value = predictions[i] + if utils.is_update( + prediction_value + ): # if update is passed directly (deprecated), remove Nones + prediction_value = utils.delete_none( + prediction_value, skip_value=True + ) + + if isinstance(prediction_value, Block): + prediction_value = prediction_value.constructor_args + prediction_value["__type__"] = "update" if utils.is_update(prediction_value): + if output_id in state: + args = state[output_id].constructor_args.copy() + else: + args = self.blocks[output_id].constructor_args.copy() + args.update(prediction_value) + args.pop("value", None) + args.pop("__type__") + args["render"] = False + args["_skip_init_processing"] = not block_fn.postprocess + state[output_id] = self.blocks[output_id].__class__(**args) + assert isinstance(prediction_value, dict) prediction_value = postprocess_update_dict( - block=block, + block=state[output_id], update_dict=prediction_value, postprocess=block_fn.postprocess, ) @@ -1375,12 +1454,13 @@ async def process_api( self, fn_index: int, inputs: list[Any], - state: dict[int, Any], + state: SessionState | None = None, request: routes.Request | list[routes.Request] | None = None, iterators: dict[int, Any] | None = None, session_hash: str | None = None, event_id: str | None = None, event_data: EventData | None = None, + in_event_listener: bool = True, ) -> dict[str, Any]: """ Processes API calls from the frontend. First preprocesses the data, @@ -1419,7 +1499,13 @@ async def process_api( self.preprocess_data(fn_index, list(i), state) for i in zip(*inputs) ] result = await self.call_function( - fn_index, list(zip(*inputs)), None, request, event_id, event_data + fn_index, + list(zip(*inputs)), + None, + request, + event_id, + event_data, + in_event_listener, ) preds = result["prediction"] data = [ @@ -1435,7 +1521,13 @@ async def process_api( inputs = self.preprocess_data(fn_index, inputs, state) was_generating = old_iterator is not None result = await self.call_function( - fn_index, inputs, old_iterator, request, event_id, event_data + fn_index, + inputs, + old_iterator, + request, + event_id, + event_data, + in_event_listener, ) data = self.postprocess_data(fn_index, result["prediction"], state) is_generating, iterator = result["is_generating"], result["iterator"] @@ -1750,6 +1842,7 @@ def launch( root_path: str | None = None, _frontend: bool = True, app_kwargs: dict[str, Any] | None = None, + state_session_capacity: int = 10000, ) -> tuple[FastAPI, str, str]: """ Launches a simple web server that serves the demo. Can also be used to create a @@ -1784,6 +1877,7 @@ def launch( blocked_paths: List of complete filepaths or parent directories that gradio is not allowed to serve (i.e. users of your app are not allowed to access). Must be absolute paths. Warning: takes precedence over `allowed_paths` and all other directories exposed by Gradio by default. root_path: The root path (or "mount point") of the application, if it's not served from the root ("/") of the domain. Often used when the application is behind a reverse proxy that forwards requests to the application. For example, if the application is served at "https://example.com/myapp", the `root_path` should be set to "/myapp". Can be set by environment variable GRADIO_ROOT_PATH. Defaults to "". app_kwargs: Additional keyword arguments to pass to the underlying FastAPI app as a dictionary of parameter keys and argument values. For example, `{"docs_url": "/docs"}` + state_session_capacity: The maximum number of sessions whose information to store in memory. If the number of sessions exceeds this number, the oldest sessions will be removed. Reduce capacity to reduce memory usage when using gradio.State or returning updated components from functions. Defaults to 10000. Returns: app: FastAPI app object that is running the demo local_url: Locally accessible link to the demo @@ -1826,6 +1920,7 @@ def reverse(text): self.width = width self.favicon_path = favicon_path self.ssl_verify = ssl_verify + self.state_session_capacity = state_session_capacity if root_path is None: self.root_path = os.environ.get("GRADIO_ROOT_PATH", "") else: diff --git a/gradio/components/annotated_image.py b/gradio/components/annotated_image.py index acb137566dc05..b3034c17e5f41 100644 --- a/gradio/components/annotated_image.py +++ b/gradio/components/annotated_image.py @@ -2,6 +2,7 @@ from __future__ import annotations +import warnings from typing import Literal import numpy as np @@ -97,17 +98,6 @@ def __init__( **kwargs, ) - def get_config(self): - return { - "show_legend": self.show_legend, - "value": self.value, - "height": self.height, - "width": self.width, - "color_map": self.color_map, - "selectable": self.selectable, - **IOComponent.get_config(self), - } - @staticmethod def update( value: tuple[ @@ -126,6 +116,9 @@ def update( min_width: int | None = None, visible: bool | None = None, ): + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.AnnotatedImage(...)` instead of `return gr.AnnotatedImage.update(...)`." + ) updated_config = { "show_legend": show_legend, "height": height, diff --git a/gradio/components/audio.py b/gradio/components/audio.py index 72ba6d42410e7..22436d1c6209a 100644 --- a/gradio/components/audio.py +++ b/gradio/components/audio.py @@ -3,6 +3,7 @@ from __future__ import annotations import tempfile +import warnings from pathlib import Path from typing import Any, Callable, Literal @@ -141,18 +142,6 @@ def __init__( ) TokenInterpretable.__init__(self) - def get_config(self): - return { - "source": self.source, - "value": self.value, - "streaming": self.streaming, - "autoplay": self.autoplay, - "show_download_button": self.show_download_button, - "show_share_button": self.show_share_button, - "show_edit_button": self.show_edit_button, - **IOComponent.get_config(self), - } - def example_inputs(self) -> dict[str, Any]: return { "raw": {"is_file": False, "data": media_data.BASE64_AUDIO}, @@ -175,6 +164,9 @@ def update( show_share_button: bool | None = None, show_edit_button: bool | None = None, ): + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.Audio(...)` instead of `return gr.Audio.update(...)`." + ) return { "source": source, "label": label, diff --git a/gradio/components/bar_plot.py b/gradio/components/bar_plot.py index 9d11200faa0e3..d6f54de4809e4 100644 --- a/gradio/components/bar_plot.py +++ b/gradio/components/bar_plot.py @@ -2,6 +2,7 @@ from __future__ import annotations +import warnings from typing import Callable, Literal import altair as alt @@ -69,6 +70,7 @@ def __init__( elem_id: str | None = None, elem_classes: list[str] | str | None = None, sort: Literal["x", "y", "-x", "-y"] | None = None, + **kwargs, ): """ Parameters: @@ -132,13 +134,9 @@ def __init__( elem_id=elem_id, elem_classes=elem_classes, every=every, + **kwargs, ) - def get_config(self): - config = super().get_config() - config["caption"] = self.caption - return config - def get_block_name(self) -> str: return "plot" @@ -213,6 +211,9 @@ def update( visible: Whether the plot should be visible. sort: Specifies the sorting axis as either "x", "y", "-x" or "-y". If None, no sorting is applied. """ + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.BarPlot(...)` instead of `return gr.BarPlot.update(...)`." + ) properties = [ x, y, diff --git a/gradio/components/base.py b/gradio/components/base.py index 3b923bc0a226c..9acab862e3ecb 100644 --- a/gradio/components/base.py +++ b/gradio/components/base.py @@ -26,7 +26,7 @@ from PIL import Image as _Image # using _ to minimize namespace pollution from gradio import processing_utils, utils -from gradio.blocks import Block, BlockContext +from gradio.blocks import Block, BlockContext, Updateable from gradio.deprecation import warn_deprecation, warn_style_method_deprecation from gradio.events import ( EventListener, @@ -50,7 +50,7 @@ class _Keywords(Enum): FINISHED_ITERATING = "FINISHED_ITERATING" # Used to skip processing of a component's value (needed for generators + state) -class Component(Block, Serializable): +class Component(Updateable, Block, Serializable): """ A base class for defining the methods that all gradio components should have. """ @@ -65,15 +65,6 @@ def __str__(self): def __repr__(self): return f"{self.get_block_name()}" - def get_config(self): - """ - :return: a dictionary with context variables for the javascript file associated with the context - """ - return { - "name": self.get_block_name(), - **super().get_config(), - } - def preprocess(self, x: Any) -> Any: """ Any preprocessing needed to be performed on function input. @@ -335,20 +326,6 @@ def file_bytes_to_file(self, data: bytes, file_name: str): path.write_bytes(data) return path - def get_config(self): - config = { - "label": self.label, - "show_label": self.show_label, - "container": self.container, - "scale": self.scale, - "min_width": self.min_width, - "interactive": self.interactive, - **super().get_config(), - } - if self.info: - config["info"] = self.info - return config - @staticmethod def get_load_fn_and_initial_value(value): if callable(value): diff --git a/gradio/components/button.py b/gradio/components/button.py index b350f17aab378..e64db3827b2e0 100644 --- a/gradio/components/button.py +++ b/gradio/components/button.py @@ -2,12 +2,13 @@ from __future__ import annotations +import warnings from typing import Callable, Literal from gradio_client.documentation import document, set_documentation_group from gradio_client.serializing import StringSerializable -from gradio.components.base import Component, IOComponent, _Keywords +from gradio.components.base import IOComponent, _Keywords from gradio.deprecation import warn_deprecation, warn_style_method_deprecation from gradio.events import Clickable @@ -73,19 +74,6 @@ def __init__( self.icon = icon self.link = link - def get_config(self): - return { - "value": self.value, - "variant": self.variant, - "size": self.size, - "icon": self.icon, - "link": self.link, - "interactive": self.interactive, - "scale": self.scale, - "min_width": self.min_width, - **Component.get_config(self), - } - @staticmethod def update( value: str | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE, @@ -98,6 +86,9 @@ def update( scale: int | None = None, min_width: int | None = None, ): + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.Button(...)` instead of `return gr.Button.update(...)`." + ) return { "variant": variant, "size": size, diff --git a/gradio/components/chatbot.py b/gradio/components/chatbot.py index 16fa9e67ad482..cb5d4006d7839 100644 --- a/gradio/components/chatbot.py +++ b/gradio/components/chatbot.py @@ -3,6 +3,7 @@ from __future__ import annotations import inspect +import warnings from pathlib import Path from typing import Callable, Literal @@ -125,22 +126,6 @@ def __init__( **kwargs, ) - def get_config(self): - return { - "value": self.value, - "latex_delimiters": self.latex_delimiters, - "selectable": self.selectable, - "likeable": self.likeable, - "height": self.height, - "show_share_button": self.show_share_button, - "rtl": self.rtl, - "show_copy_button": self.show_copy_button, - "avatar_images": self.avatar_images, - "sanitize_html": self.sanitize_html, - "bubble_full_width": self.bubble_full_width, - **IOComponent.get_config(self), - } - @staticmethod def update( value: list[list[str | tuple[str] | tuple[str, str] | None]] @@ -161,6 +146,9 @@ def update( sanitize_html: bool | None = None, bubble_full_width: bool | None = None, ): + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.Chatbot(...)` instead of `return gr.Chatbot.update(...)`." + ) updated_config = { "label": label, "show_label": show_label, diff --git a/gradio/components/checkbox.py b/gradio/components/checkbox.py index 08b6478f4b180..4394bb84f8fc1 100644 --- a/gradio/components/checkbox.py +++ b/gradio/components/checkbox.py @@ -2,6 +2,7 @@ from __future__ import annotations +import warnings from typing import Callable, Literal from gradio_client.documentation import document, set_documentation_group @@ -89,12 +90,6 @@ def __init__( ) NeighborInterpretable.__init__(self) - def get_config(self): - return { - "value": self.value, - **IOComponent.get_config(self), - } - @staticmethod def update( value: bool | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE, @@ -107,6 +102,9 @@ def update( interactive: bool | None = None, visible: bool | None = None, ): + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.Checkbox(...)` instead of `return gr.Checkbox.update(...)`." + ) return { "label": label, "info": info, diff --git a/gradio/components/checkboxgroup.py b/gradio/components/checkboxgroup.py index 96f4987b519db..793247853e4e9 100644 --- a/gradio/components/checkboxgroup.py +++ b/gradio/components/checkboxgroup.py @@ -2,6 +2,7 @@ from __future__ import annotations +import warnings from typing import Any, Callable, Literal from gradio_client.documentation import document, set_documentation_group @@ -104,13 +105,6 @@ def __init__( ) NeighborInterpretable.__init__(self) - def get_config(self): - return { - "choices": self.choices, - "value": self.value, - **IOComponent.get_config(self), - } - def example_inputs(self) -> dict[str, Any]: return { "raw": [self.choices[0][1]] if self.choices else None, @@ -133,6 +127,9 @@ def update( interactive: bool | None = None, visible: bool | None = None, ): + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.CheckboxGroup(...)` instead of `return gr.CheckboxGroup.update(...)`." + ) choices = ( None if choices is None diff --git a/gradio/components/code.py b/gradio/components/code.py index f12890f415e15..2b3bd170caa12 100644 --- a/gradio/components/code.py +++ b/gradio/components/code.py @@ -2,6 +2,7 @@ from __future__ import annotations +import warnings from typing import Literal from gradio_client.documentation import document, set_documentation_group @@ -98,14 +99,6 @@ def __init__( **kwargs, ) - def get_config(self): - return { - "value": self.value, - "language": self.language, - "lines": self.lines, - **IOComponent.get_config(self), - } - def postprocess(self, y): if y is None: return None @@ -143,6 +136,9 @@ def update( | None = None, interactive: bool | None = None, ): + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.Code(...)` instead of `return gr.Code.update(...)`." + ) return { "label": label, "show_label": show_label, diff --git a/gradio/components/color_picker.py b/gradio/components/color_picker.py index f88a0c8dd9acf..f8acd134f32fd 100644 --- a/gradio/components/color_picker.py +++ b/gradio/components/color_picker.py @@ -2,6 +2,7 @@ from __future__ import annotations +import warnings from typing import Any, Callable, Literal from gradio_client.documentation import document, set_documentation_group @@ -85,12 +86,6 @@ def example_inputs(self) -> dict[str, Any]: "serialized": "#000000", } - def get_config(self): - return { - "value": self.value, - **IOComponent.get_config(self), - } - @staticmethod def update( value: str | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE, @@ -103,6 +98,9 @@ def update( visible: bool | None = None, interactive: bool | None = None, ): + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.ColorPicker(...)` instead of `return gr.ColorPicker.update(...)`." + ) return { "value": value, "label": label, diff --git a/gradio/components/dataframe.py b/gradio/components/dataframe.py index 0cbde2b43b20f..0b709c7407601 100644 --- a/gradio/components/dataframe.py +++ b/gradio/components/dataframe.py @@ -2,6 +2,7 @@ from __future__ import annotations +import warnings from typing import TYPE_CHECKING, Any, Callable, Literal import numpy as np @@ -154,22 +155,6 @@ def __init__( **kwargs, ) - def get_config(self): - return { - "headers": self.headers, - "datatype": self.datatype, - "row_count": self.row_count, - "col_count": self.col_count, - "value": self.value, - "max_rows": self.max_rows, - "max_cols": self.max_cols, - "overflow_row_behaviour": self.overflow_row_behaviour, - "wrap": self.wrap, - "latex_delimiters": self.latex_delimiters, - "height": self.height, - **IOComponent.get_config(self), - } - @staticmethod def update( value: Any | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE, @@ -184,6 +169,9 @@ def update( interactive: bool | None = None, visible: bool | None = None, ): + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.Dataframe(...)` instead of `return gr.Dataframe.update(...)`." + ) return { "max_rows": max_rows, "max_cols": max_cols, diff --git a/gradio/components/dataset.py b/gradio/components/dataset.py index bd13e8582dbae..8cb422778a9a1 100644 --- a/gradio/components/dataset.py +++ b/gradio/components/dataset.py @@ -2,6 +2,7 @@ from __future__ import annotations +import warnings from typing import Any, Literal from gradio_client.documentation import document, set_documentation_group @@ -64,44 +65,30 @@ def __init__( self.container = container self.scale = scale self.min_width = min_width - self.components = [get_component_instance(c) for c in components] + self._components = [get_component_instance(c) for c in components] # Narrow type to IOComponent assert all( - isinstance(c, IOComponent) for c in self.components + isinstance(c, IOComponent) for c in self._components ), "All components in a `Dataset` must be subclasses of `IOComponent`" - self.components = [c for c in self.components if isinstance(c, IOComponent)] - for component in self.components: + self._components = [c for c in self._components if isinstance(c, IOComponent)] + for component in self._components: component.root_url = self.root_url self.samples = [[]] if samples is None else samples for example in self.samples: - for i, (component, ex) in enumerate(zip(self.components, example)): + for i, (component, ex) in enumerate(zip(self._components, example)): example[i] = component.as_example(ex) self.type = type self.label = label if headers is not None: self.headers = headers - elif all(c.label is None for c in self.components): + elif all(c.label is None for c in self._components): self.headers = [] else: - self.headers = [c.label or "" for c in self.components] + self.headers = [c.label or "" for c in self._components] self.samples_per_page = samples_per_page - def get_config(self): - return { - "components": [component.get_block_name() for component in self.components], - "headers": self.headers, - "samples": self.samples, - "type": self.type, - "label": self.label, - "samples_per_page": self.samples_per_page, - "container": self.container, - "scale": self.scale, - "min_width": self.min_width, - **Component.get_config(self), - } - @staticmethod def update( samples: Any | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE, @@ -111,6 +98,9 @@ def update( scale: int | None = None, min_width: int | None = None, ): + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.Dataset(...)` instead of `return gr.Dataset.update(...)`." + ) return { "samples": samples, "visible": visible, @@ -121,6 +111,13 @@ def update( "__type__": "update", } + def get_config(self): + config = super().get_config() + config["components"] = [ + component.get_block_name() for component in self._components + ] + return config + def preprocess(self, x: Any) -> Any: """ Any preprocessing needed to be performed on function input. diff --git a/gradio/components/dropdown.py b/gradio/components/dropdown.py index cb2796da93bd8..022a3257c37e7 100644 --- a/gradio/components/dropdown.py +++ b/gradio/components/dropdown.py @@ -156,18 +156,6 @@ def example_inputs(self) -> dict[str, Any]: "serialized": self.choices[0] if self.choices else None, } - def get_config(self): - return { - "choices": self.choices, - "value": self.value, - "multiselect": self.multiselect, - "max_choices": self.max_choices, - "allow_custom_value": self.allow_custom_value, - "container": self.container, - "filterable": self.filterable, - **IOComponent.get_config(self), - } - @staticmethod def update( value: Any | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE, @@ -183,6 +171,9 @@ def update( placeholder: str | None = None, visible: bool | None = None, ): + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.Dropdown(...)` instead of `return gr.Dropdown.update(...)`." + ) choices = ( None if choices is None diff --git a/gradio/components/file.py b/gradio/components/file.py index 6c5a41b18d9de..af9dfaf86d5fe 100644 --- a/gradio/components/file.py +++ b/gradio/components/file.py @@ -127,16 +127,6 @@ def __init__( **kwargs, ) - def get_config(self): - return { - "file_count": self.file_count, - "file_types": self.file_types, - "value": self.value, - "selectable": self.selectable, - "height": self.height, - **IOComponent.get_config(self), - } - @staticmethod def update( value: Any | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE, @@ -149,6 +139,9 @@ def update( interactive: bool | None = None, visible: bool | None = None, ): + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.File(...)` instead of `return gr.File.update(...)`." + ) return { "label": label, "show_label": show_label, diff --git a/gradio/components/gallery.py b/gradio/components/gallery.py index 316be3517eab2..782b16ac8cff9 100644 --- a/gradio/components/gallery.py +++ b/gradio/components/gallery.py @@ -2,6 +2,7 @@ from __future__ import annotations +import warnings from pathlib import Path from typing import Any, Callable, Literal @@ -135,6 +136,9 @@ def update( show_share_button: bool | None = None, show_download_button: bool | None = None, ): + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.Gallery(...)` instead of `return gr.Gallery.update(...)`." + ) updated_config = { "label": label, "show_label": show_label, @@ -155,20 +159,6 @@ def update( } return updated_config - def get_config(self): - return { - "value": self.value, - "grid_cols": self.grid_cols, - "grid_rows": self.grid_rows, - "height": self.height, - "preview": self.preview, - "object_fit": self.object_fit, - "allow_preview": self.allow_preview, - "show_share_button": self.show_share_button, - "show_download_button": self.show_download_button, - **IOComponent.get_config(self), - } - def postprocess( self, y: list[np.ndarray | _Image.Image | str] diff --git a/gradio/components/highlighted_text.py b/gradio/components/highlighted_text.py index b661fb7d650c2..85465bcf32ded 100644 --- a/gradio/components/highlighted_text.py +++ b/gradio/components/highlighted_text.py @@ -2,6 +2,7 @@ from __future__ import annotations +import warnings from typing import Callable, Literal from gradio_client.documentation import document, set_documentation_group @@ -92,16 +93,6 @@ def __init__( **kwargs, ) - def get_config(self): - return { - "color_map": self.color_map, - "show_legend": self.show_legend, - "value": self.value, - "selectable": self.selectable, - "combine_adjacent": self.combine_adjacent, - **IOComponent.get_config(self), - } - @staticmethod def update( value: list[tuple[str, str | float | None]] @@ -118,6 +109,9 @@ def update( visible: bool | None = None, interactive: bool | None = None, ): + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.HighlightedText(...)` instead of `return gr.HighlightedText.update(...)`." + ) updated_config = { "color_map": color_map, "show_legend": show_legend, diff --git a/gradio/components/html.py b/gradio/components/html.py index 4fd58cf95261f..19199abc6c9f7 100644 --- a/gradio/components/html.py +++ b/gradio/components/html.py @@ -2,6 +2,7 @@ from __future__ import annotations +import warnings from typing import Any, Callable, Literal from gradio_client.documentation import document, set_documentation_group @@ -58,12 +59,6 @@ def __init__( **kwargs, ) - def get_config(self): - return { - "value": self.value, - **IOComponent.get_config(self), - } - @staticmethod def update( value: Any | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE, @@ -71,6 +66,9 @@ def update( show_label: bool | None = None, visible: bool | None = None, ): + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.HTML(...)` instead of `return gr.HTML.update(...)`." + ) updated_config = { "label": label, "show_label": show_label, diff --git a/gradio/components/image.py b/gradio/components/image.py index 263b2e802834d..b5fd6a19cd021 100644 --- a/gradio/components/image.py +++ b/gradio/components/image.py @@ -172,26 +172,6 @@ def __init__( ) TokenInterpretable.__init__(self) - def get_config(self): - return { - "image_mode": self.image_mode, - "shape": self.shape, - "height": self.height, - "width": self.width, - "source": self.source, - "tool": self.tool, - "value": self.value, - "streaming": self.streaming, - "mirror_webcam": self.mirror_webcam, - "brush_radius": self.brush_radius, - "brush_color": self.brush_color, - "mask_opacity": self.mask_opacity, - "selectable": self.selectable, - "show_share_button": self.show_share_button, - "show_download_button": self.show_download_button, - **IOComponent.get_config(self), - } - @staticmethod def update( value: Any | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE, @@ -210,6 +190,9 @@ def update( mask_opacity: float | None = None, show_share_button: bool | None = None, ): + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.Image(...)` instead of `return gr.Image.update(...)`." + ) return { "height": height, "width": width, diff --git a/gradio/components/interpretation.py b/gradio/components/interpretation.py index fc476d99b813c..b261f4f637d20 100644 --- a/gradio/components/interpretation.py +++ b/gradio/components/interpretation.py @@ -43,12 +43,6 @@ def __init__( ) self.component = component - def get_config(self): - return { - "component": self.component.get_block_name(), - "component_props": self.component.get_config(), - } - @staticmethod def update( value: Any | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE, diff --git a/gradio/components/json_component.py b/gradio/components/json_component.py index bdd32c51febf8..46bef37ba671e 100644 --- a/gradio/components/json_component.py +++ b/gradio/components/json_component.py @@ -3,6 +3,7 @@ from __future__ import annotations import json +import warnings from typing import Any, Callable, Literal from gradio_client.documentation import document, set_documentation_group @@ -70,12 +71,6 @@ def __init__( **kwargs, ) - def get_config(self): - return { - "value": self.value, - **IOComponent.get_config(self), - } - @staticmethod def update( value: Any | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE, @@ -86,6 +81,9 @@ def update( min_width: int | None = None, visible: bool | None = None, ): + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.JSON(...)` instead of `return gr.JSON.update(...)`." + ) updated_config = { "label": label, "show_label": show_label, diff --git a/gradio/components/label.py b/gradio/components/label.py index 5a2c40fd387b7..f6e965b0a3f81 100644 --- a/gradio/components/label.py +++ b/gradio/components/label.py @@ -3,6 +3,7 @@ from __future__ import annotations import operator +import warnings from pathlib import Path from typing import Callable, Literal @@ -90,15 +91,6 @@ def __init__( **kwargs, ) - def get_config(self): - return { - "num_top_classes": self.num_top_classes, - "value": self.value, - "color": self.color, - "selectable": self.selectable, - **IOComponent.get_config(self), - } - def postprocess(self, y: dict[str, float] | str | float | None) -> dict | None: """ Parameters: @@ -146,6 +138,9 @@ def update( visible: bool | None = None, color: str | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE, ): + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.Label(...)` instead of `return gr.Label.update(...)`." + ) # If color is not specified (NO_VALUE) map it to None so that # it gets filtered out in postprocess. This will mean the color # will not be updated in the front-end diff --git a/gradio/components/line_plot.py b/gradio/components/line_plot.py index 7250ed741cd0e..02ae8999e495c 100644 --- a/gradio/components/line_plot.py +++ b/gradio/components/line_plot.py @@ -2,6 +2,7 @@ from __future__ import annotations +import warnings from typing import Callable, Literal import altair as alt @@ -81,6 +82,7 @@ def __init__( visible: bool = True, elem_id: str | None = None, elem_classes: list[str] | str | None = None, + **kwargs, ): """ Parameters: @@ -145,13 +147,9 @@ def __init__( elem_id=elem_id, elem_classes=elem_classes, every=every, + **kwargs, ) - def get_config(self): - config = super().get_config() - config["caption"] = self.caption - return config - def get_block_name(self) -> str: return "plot" @@ -239,6 +237,9 @@ def update( show_label: Whether the label should be displayed. visible: Whether the plot should be visible. """ + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.LinePlot(...)` instead of `return gr.LinePlot.update(...)`." + ) properties = [ x, y, diff --git a/gradio/components/markdown.py b/gradio/components/markdown.py index cd327957b202a..2898ee2379fbe 100644 --- a/gradio/components/markdown.py +++ b/gradio/components/markdown.py @@ -3,12 +3,13 @@ from __future__ import annotations import inspect +import warnings from typing import Any, Callable, Literal from gradio_client.documentation import document, set_documentation_group from gradio_client.serializing import StringSerializable -from gradio.components.base import Component, IOComponent, _Keywords +from gradio.components.base import IOComponent, _Keywords from gradio.events import ( Changeable, ) @@ -76,15 +77,6 @@ def postprocess(self, y: str | None) -> str | None: unindented_y = inspect.cleandoc(y) return unindented_y - def get_config(self): - return { - "value": self.value, - "rtl": self.rtl, - "latex_delimiters": self.latex_delimiters, - "sanitize_html": self.sanitize_html, - **Component.get_config(self), - } - @staticmethod def update( value: Any | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE, @@ -93,6 +85,9 @@ def update( latex_delimiters: list[dict[str, str | bool]] | None = None, sanitize_html: bool | None = None, ): + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.Markdown(...)` instead of `return gr.Markdown.update(...)`." + ) updated_config = { "visible": visible, "value": value, diff --git a/gradio/components/model3d.py b/gradio/components/model3d.py index c8f9e34f702ca..d11bef86b2c1e 100644 --- a/gradio/components/model3d.py +++ b/gradio/components/model3d.py @@ -2,6 +2,7 @@ from __future__ import annotations +import warnings from pathlib import Path from typing import Any, Callable, Literal @@ -95,16 +96,6 @@ def __init__( **kwargs, ) - def get_config(self): - return { - "clear_color": self.clear_color, - "value": self.value, - "camera_position": self.camera_position, - "height": self.height, - "zoom_speed": self.zoom_speed, - **IOComponent.get_config(self), - } - def example_inputs(self) -> dict[str, Any]: return { "raw": {"is_file": False, "data": media_data.BASE64_MODEL3D}, @@ -128,6 +119,9 @@ def update( min_width: int | None = None, visible: bool | None = None, ): + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.Model3D(...)` instead of `return gr.Model3D.update(...)`." + ) updated_config = { "camera_position": camera_position, "clear_color": clear_color, diff --git a/gradio/components/number.py b/gradio/components/number.py index 5d2b9fcccc146..6f6d0149ac50a 100644 --- a/gradio/components/number.py +++ b/gradio/components/number.py @@ -3,6 +3,7 @@ from __future__ import annotations import math +import warnings from typing import Callable, Literal import numpy as np @@ -125,16 +126,6 @@ def _round_to_precision(num: float | int, precision: int | None) -> float | int: else: return round(num, precision) - def get_config(self): - return { - "value": self.value, - "minimum": self.minimum, - "maximum": self.maximum, - "step": self.step, - "container": self.container, - **IOComponent.get_config(self), - } - @staticmethod def update( value: float | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE, @@ -150,6 +141,9 @@ def update( interactive: bool | None = None, visible: bool | None = None, ): + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.Number(...)` instead of `return gr.Number.update(...)`." + ) return { "label": label, "info": info, diff --git a/gradio/components/plot.py b/gradio/components/plot.py index 54927b8b89885..763f871c9d7b7 100644 --- a/gradio/components/plot.py +++ b/gradio/components/plot.py @@ -3,6 +3,7 @@ from __future__ import annotations import json +import warnings from types import ModuleType from typing import Any, Callable, Literal @@ -80,11 +81,10 @@ def get_config(self): bokeh_version = bokeh.__version__ except ImportError: bokeh_version = None - return { - "value": self.value, - "bokeh_version": bokeh_version, - **IOComponent.get_config(self), - } + + config = super().get_config() + config["bokeh_version"] = bokeh_version + return config @staticmethod def update( @@ -96,6 +96,9 @@ def update( min_width: int | None = None, visible: bool | None = None, ): + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.Plot(...)` instead of `return gr.Plot.update(...)`." + ) updated_config = { "label": label, "show_label": show_label, diff --git a/gradio/components/radio.py b/gradio/components/radio.py index 9316774219870..2b11cb7de77af 100644 --- a/gradio/components/radio.py +++ b/gradio/components/radio.py @@ -2,6 +2,7 @@ from __future__ import annotations +import warnings from typing import Any, Callable, Literal from gradio_client.documentation import document, set_documentation_group @@ -105,13 +106,6 @@ def __init__( ) NeighborInterpretable.__init__(self) - def get_config(self): - return { - "choices": self.choices, - "value": self.value, - **IOComponent.get_config(self), - } - def example_inputs(self) -> dict[str, Any]: return { "raw": self.choices[0][1] if self.choices else None, @@ -135,6 +129,9 @@ def update( interactive: bool | None = None, visible: bool | None = None, ): + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.Radio(...)` instead of `return gr.Radio.update(...)`." + ) choices = ( None if choices is None diff --git a/gradio/components/scatter_plot.py b/gradio/components/scatter_plot.py index b0a9bb107bafc..7527aaca68ece 100644 --- a/gradio/components/scatter_plot.py +++ b/gradio/components/scatter_plot.py @@ -2,6 +2,7 @@ from __future__ import annotations +import warnings from typing import Callable, Literal import altair as alt @@ -96,6 +97,7 @@ def __init__( visible: bool = True, elem_id: str | None = None, elem_classes: list[str] | str | None = None, + **kwargs, ): """ Parameters: @@ -164,13 +166,9 @@ def __init__( visible=visible, elem_id=elem_id, elem_classes=elem_classes, + **kwargs, ) - def get_config(self): - config = super().get_config() - config["caption"] = self.caption - return config - def get_block_name(self) -> str: return "plot" @@ -273,6 +271,9 @@ def update( show_label: Whether the label should be displayed. visible: Whether the plot should be visible. """ + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.ScatterPlot(...)` instead of `return gr.ScatterPlot.update(...)`." + ) properties = [ x, y, diff --git a/gradio/components/slider.py b/gradio/components/slider.py index c589eb675d09d..514fec178b6a5 100644 --- a/gradio/components/slider.py +++ b/gradio/components/slider.py @@ -4,6 +4,7 @@ import math import random +import warnings from typing import Any, Callable, Literal import numpy as np @@ -121,15 +122,6 @@ def example_inputs(self) -> dict[str, Any]: "serialized": self.minimum, } - def get_config(self): - return { - "minimum": self.minimum, - "maximum": self.maximum, - "step": self.step, - "value": self.value, - **IOComponent.get_config(self), - } - def get_random_value(self): n_steps = int((self.maximum - self.minimum) / self.step) step = random.randint(0, n_steps) @@ -155,6 +147,9 @@ def update( interactive: bool | None = None, visible: bool | None = None, ): + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.Slider(...)` instead of `return gr.Slider.update(...)`." + ) return { "minimum": minimum, "maximum": maximum, diff --git a/gradio/components/textbox.py b/gradio/components/textbox.py index dfd1ad85c4a6e..f228570f45959 100644 --- a/gradio/components/textbox.py +++ b/gradio/components/textbox.py @@ -2,6 +2,7 @@ from __future__ import annotations +import warnings from typing import Callable, Literal import numpy as np @@ -138,22 +139,6 @@ def __init__( self.rtl = rtl self.text_align = text_align - def get_config(self): - return { - "lines": self.lines, - "max_lines": self.max_lines, - "placeholder": self.placeholder, - "value": self.value, - "type": self.type, - "autofocus": self.autofocus, - "show_copy_button": self.show_copy_button, - "container": self.container, - "text_align": self.text_align, - "rtl": self.rtl, - "autoscroll": self.autoscroll, - **IOComponent.get_config(self), - } - @staticmethod def update( value: str | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE, @@ -175,6 +160,9 @@ def update( autofocus: bool | None = None, autoscroll: bool | None = None, ): + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.Textbox(...)` instead of `return gr.Textbox.update(...)`." + ) return { "lines": lines, "max_lines": max_lines, diff --git a/gradio/components/timeseries.py b/gradio/components/timeseries.py index 92d9086108bda..7cdd82ecb0926 100644 --- a/gradio/components/timeseries.py +++ b/gradio/components/timeseries.py @@ -2,6 +2,7 @@ from __future__ import annotations +import warnings from pathlib import Path from typing import Any, Callable, Literal @@ -82,15 +83,6 @@ def __init__( **kwargs, ) - def get_config(self): - return { - "x": self.x, - "y": self.y, - "value": self.value, - "colors": self.colors, - **IOComponent.get_config(self), - } - @staticmethod def update( value: Any | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE, @@ -103,6 +95,9 @@ def update( interactive: bool | None = None, visible: bool | None = None, ): + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.Timeseries(...)` instead of `return gr.Timeseries.update(...)`." + ) return { "colors": colors, "label": label, diff --git a/gradio/components/upload_button.py b/gradio/components/upload_button.py index fc0924bfff94b..fadf375d250dd 100644 --- a/gradio/components/upload_button.py +++ b/gradio/components/upload_button.py @@ -11,7 +11,7 @@ from gradio_client.serializing import FileSerializable from gradio import utils -from gradio.components.base import Component, IOComponent, _Keywords +from gradio.components.base import IOComponent, _Keywords from gradio.deprecation import warn_deprecation, warn_style_method_deprecation from gradio.events import Clickable, Uploadable @@ -89,20 +89,6 @@ def __init__( **kwargs, ) - def get_config(self): - return { - "label": self.label, - "value": self.value, - "size": self.size, - "file_count": self.file_count, - "file_types": self.file_types, - "scale": self.scale, - "min_width": self.min_width, - "variant": self.variant, - "interactive": self.interactive, - **Component.get_config(self), - } - @staticmethod def update( value: str @@ -117,6 +103,9 @@ def update( scale: int | None = None, min_width: int | None = None, ): + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.UploadButton(...)` instead of `return gr.UploadButton.update(...)`." + ) return { "variant": variant, "interactive": interactive, diff --git a/gradio/components/video.py b/gradio/components/video.py index f9ae9bf2f5889..684558458610f 100644 --- a/gradio/components/video.py +++ b/gradio/components/video.py @@ -131,19 +131,6 @@ def __init__( **kwargs, ) - def get_config(self): - return { - "source": self.source, - "value": self.value, - "height": self.height, - "width": self.width, - "mirror_webcam": self.mirror_webcam, - "include_audio": self.include_audio, - "autoplay": self.autoplay, - "show_share_button": self.show_share_button, - **IOComponent.get_config(self), - } - @staticmethod def update( value: str @@ -163,6 +150,9 @@ def update( autoplay: bool | None = None, show_share_button: bool | None = None, ): + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.Video(...)` instead of `return gr.Video.update(...)`." + ) return { "source": source, "height": height, diff --git a/gradio/events.py b/gradio/events.py index d56357f6473d3..257edc583a9de 100644 --- a/gradio/events.py +++ b/gradio/events.py @@ -364,6 +364,11 @@ def __init__(self): See EventData documentation on how to use this event data. """ + def get_config(self): + config = super().get_config() + config["selectable"] = self.selectable + return config + class SelectData(EventData): def __init__(self, target: Block | None, data: Any): @@ -395,6 +400,11 @@ def __init__(self): See EventData documentation on how to use this event data. """ + def get_config(self): + config = super().get_config() + config["likeable"] = self.likeable + return config + class LikeData(EventData): def __init__(self, target: Block | None, data: Any): diff --git a/gradio/helpers.py b/gradio/helpers.py index 1642c25ee7280..820f0afacf90d 100644 --- a/gradio/helpers.py +++ b/gradio/helpers.py @@ -338,7 +338,6 @@ async def get_final_item(*args): fn_index=fn_index, inputs=processed_input, request=None, - state={}, ) output = prediction["data"] if len(generated_values): @@ -783,10 +782,9 @@ def special_args( return inputs or [], progress_index, event_data_index -@document() def update(**kwargs) -> dict: """ - Updates component properties. When a function passed into a Gradio Interface or a Blocks events returns a typical value, it updates the value of the output component. But it is also possible to update the properties of an output component (such as the number of lines of a `Textbox` or the visibility of an `Image`) by returning the component's `update()` function, which takes as parameters any of the constructor parameters for that component. + DEPRECATED. Updates component properties. When a function passed into a Gradio Interface or a Blocks events returns a typical value, it updates the value of the output component. But it is also possible to update the properties of an output component (such as the number of lines of a `Textbox` or the visibility of an `Image`) by returning the component's `update()` function, which takes as parameters any of the constructor parameters for that component. This is a shorthand for using the update method on a component. For example, rather than using gr.Number.update(...) you can just use gr.update(...). Note that your editor's autocompletion will suggest proper parameters @@ -822,6 +820,9 @@ def change_textbox(choice): live=True, ).launch() """ + warnings.warn( + "Using the update method is deprecated. Simply return a new object instead, e.g. `return gr.Textbox(...)` instead of `return gr.update(...)" + ) kwargs["__type__"] = "generic_update" return kwargs diff --git a/gradio/layouts.py b/gradio/layouts.py index c370651debceb..d7007622150ae 100644 --- a/gradio/layouts.py +++ b/gradio/layouts.py @@ -5,7 +5,7 @@ from gradio_client.documentation import document, set_documentation_group -from gradio.blocks import BlockContext +from gradio.blocks import BlockContext, Updateable from gradio.deprecation import warn_deprecation, warn_style_method_deprecation from gradio.events import Changeable, Selectable @@ -16,7 +16,7 @@ @document() -class Row(BlockContext): +class Row(Updateable, BlockContext): """ Row is a layout element within Blocks that renders all children horizontally. Example: @@ -48,15 +48,7 @@ def __init__( self.equal_height = equal_height if variant == "compact": self.allow_expected_parents = False - super().__init__(visible=visible, elem_id=elem_id, **kwargs) - - def get_config(self): - return { - "type": "row", - "variant": self.variant, - "equal_height": self.equal_height, - **super().get_config(), - } + BlockContext.__init__(self, visible=visible, elem_id=elem_id, **kwargs) @staticmethod def update( @@ -85,7 +77,7 @@ def style( @document() -class Column(BlockContext): +class Column(Updateable, BlockContext): """ Column is a layout element within Blocks that renders all children vertically. The widths of columns can be set through the `scale` and `min_width` parameters. If a certain scale results in a column narrower than min_width, the min_width parameter will win. @@ -129,16 +121,7 @@ def __init__( self.variant = variant if variant == "compact": self.allow_expected_parents = False - super().__init__(visible=visible, elem_id=elem_id, **kwargs) - - def get_config(self): - return { - "type": "column", - "variant": self.variant, - "scale": self.scale, - "min_width": self.min_width, - **super().get_config(), - } + BlockContext.__init__(self, visible=visible, elem_id=elem_id, **kwargs) @staticmethod def update( @@ -176,9 +159,6 @@ def __init__( Selectable.__init__(self) self.selected = selected - def get_config(self): - return {"selected": self.selected, **super(BlockContext, self).get_config()} - @staticmethod def update( selected: int | str | None = None, @@ -223,13 +203,6 @@ def __init__( self.label = label self.id = id - def get_config(self): - return { - "label": self.label, - "id": self.id, - **super(BlockContext, self).get_config(), - } - def get_expected_parent(self) -> type[Tabs]: return Tabs @@ -241,7 +214,7 @@ def get_block_name(self): @document() -class Group(BlockContext): +class Group(Updateable, BlockContext): """ Group is a layout element within Blocks which groups together children so that they do not have any padding or margin between them. @@ -263,10 +236,7 @@ def __init__( visible: If False, group will be hidden. elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles. """ - super().__init__(visible=visible, elem_id=elem_id, **kwargs) - - def get_config(self): - return {"type": "group", **super().get_config()} + BlockContext.__init__(self, visible=visible, elem_id=elem_id, **kwargs) @staticmethod def update( @@ -278,7 +248,7 @@ def update( } -class Box(BlockContext): +class Box(Updateable, BlockContext): """ DEPRECATED. Box is a a layout element which places children in a box with rounded corners and @@ -302,10 +272,7 @@ def __init__( elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles. """ warnings.warn("gr.Box is deprecated. Use gr.Group instead.", DeprecationWarning) - super().__init__(visible=visible, elem_id=elem_id, **kwargs) - - def get_config(self): - return {"type": "box", **super().get_config()} + BlockContext.__init__(self, visible=visible, elem_id=elem_id, **kwargs) @staticmethod def update( @@ -321,7 +288,7 @@ def style(self, **kwargs): return self -class Form(BlockContext): +class Form(Updateable, BlockContext): def __init__(self, *, scale: int = 0, min_width: int = 0, **kwargs): """ Parameters: @@ -330,26 +297,18 @@ def __init__(self, *, scale: int = 0, min_width: int = 0, **kwargs): """ self.scale = scale self.min_width = min_width - super().__init__(**kwargs) + BlockContext.__init__(self, **kwargs) def add_child(self, child: Block): if isinstance(self.parent, Row): scale = getattr(child, "scale", None) self.scale += 1 if scale is None else scale self.min_width += getattr(child, "min_width", 0) or 0 - super().add_child(child) - - def get_config(self): - return { - "type": "form", - "scale": self.scale, - "min_width": self.min_width, - **super().get_config(), - } + BlockContext.add_child(self, child) @document() -class Accordion(BlockContext): +class Accordion(Updateable, BlockContext): """ Accordion is a layout element which can be toggled to show/hide the contained content. Example: @@ -374,15 +333,7 @@ def __init__( """ self.label = label self.open = open - super().__init__(visible=visible, elem_id=elem_id, **kwargs) - - def get_config(self): - return { - "type": "accordion", - "open": self.open, - "label": self.label, - **super().get_config(), - } + BlockContext.__init__(self, visible=visible, elem_id=elem_id, **kwargs) @staticmethod def update( diff --git a/gradio/queueing.py b/gradio/queueing.py index 7aea8dd59add3..a36c0668b383f 100644 --- a/gradio/queueing.py +++ b/gradio/queueing.py @@ -438,7 +438,11 @@ async def process_events(self, events: list[Event], batch: bool) -> None: event, { "msg": "process_completed", - "output": {"error": str(e)}, + "output": { + "error": None + if len(e.args) and e.args[0] is None + else str(e) + }, "success": False, }, ) diff --git a/gradio/route_utils.py b/gradio/route_utils.py index 9d77d2b6b1c2c..9cc0b69034f36 100644 --- a/gradio/route_utils.py +++ b/gradio/route_utils.py @@ -1,7 +1,6 @@ from __future__ import annotations import json -from copy import deepcopy from typing import TYPE_CHECKING, Optional, Union import fastapi @@ -11,6 +10,7 @@ from gradio.data_classes import PredictBody from gradio.exceptions import Error from gradio.helpers import EventData +from gradio.state_holder import SessionState if TYPE_CHECKING: from gradio.routes import App @@ -164,12 +164,6 @@ def restore_session_state(app: App, body: PredictBody): fn_index = body.fn_index session_hash = getattr(body, "session_hash", None) if session_hash is not None: - if session_hash not in app.state_holder: - app.state_holder[session_hash] = { - _id: deepcopy(getattr(block, "value", None)) - for _id, block in app.get_blocks().blocks.items() - if getattr(block, "stateful", False) - } session_state = app.state_holder[session_hash] # The should_reset set keeps track of the fn_indices # that have been cancelled. When a job is cancelled, @@ -182,7 +176,7 @@ def restore_session_state(app: App, body: PredictBody): else: iterators = app.iterators[session_hash] else: - session_state = {} + session_state = SessionState(app.get_blocks()) iterators = {} return session_state, iterators @@ -225,6 +219,7 @@ async def call_process_api( session_hash=session_hash, event_id=event_id, event_data=event_data, + in_event_listener=True, ) iterator = output.pop("iterator", None) if hasattr(body, "session_hash"): diff --git a/gradio/routes.py b/gradio/routes.py index be6ab745b4378..dd785e98bc292 100644 --- a/gradio/routes.py +++ b/gradio/routes.py @@ -54,6 +54,7 @@ from gradio.oauth import attach_oauth from gradio.queueing import Estimation, Event from gradio.route_utils import Request # noqa: F401 +from gradio.state_holder import StateHolder from gradio.utils import ( cancel_tasks, get_package_version, @@ -113,7 +114,7 @@ def __init__(self, **kwargs): self.tokens = {} self.auth = None self.blocks: gradio.Blocks | None = None - self.state_holder = {} + self.state_holder = StateHolder() self.iterators = defaultdict(dict) self.iterators_to_reset = defaultdict(set) self.lock = utils.safe_get_lock() @@ -145,6 +146,7 @@ def configure_app(self, blocks: gradio.Blocks) -> None: self.favicon_path = blocks.favicon_path self.tokens = {} self.root_path = blocks.root_path + self.state_holder.set_blocks(blocks) def get_blocks(self) -> gradio.Blocks: if self.blocks is None: diff --git a/gradio/state_holder.py b/gradio/state_holder.py new file mode 100644 index 0000000000000..012457f75c298 --- /dev/null +++ b/gradio/state_holder.py @@ -0,0 +1,57 @@ +from __future__ import annotations + +import threading +from collections import OrderedDict +from copy import deepcopy +from typing import TYPE_CHECKING, Any + +if TYPE_CHECKING: + from gradio.blocks import Blocks + + +class StateHolder: + def __init__(self): + self.capacity = 10000 + self.session_data = OrderedDict() + self.lock = threading.Lock() + + def set_blocks(self, blocks: Blocks): + self.blocks = blocks + self.capacity = blocks.state_session_capacity + + def __getitem__(self, session_id: int) -> SessionState: + if session_id not in self.session_data: + self.session_data[session_id] = SessionState(self.blocks) + self.update(session_id) + return self.session_data[session_id] + + def __contains__(self, session_id: int): + return session_id in self.session_data + + def update(self, session_id: int): + with self.lock: + if session_id in self.session_data: + self.session_data.move_to_end(session_id) + if len(self.session_data) > self.capacity: + self.session_data.popitem(last=False) + + +class SessionState: + def __init__(self, blocks: Blocks): + self.blocks = blocks + self._data = {} + + def __getitem__(self, key: int) -> Any: + if key not in self._data: + block = self.blocks.blocks[key] + if getattr(block, "stateful", False): + self._data[key] = deepcopy(getattr(block, "value", None)) + else: + self._data[key] = None + return self._data[key] + + def __setitem__(self, key: int, value: Any): + self._data[key] = value + + def __contains__(self, key: int): + return key in self._data diff --git a/gradio/test_data/blocks_configs.py b/gradio/test_data/blocks_configs.py new file mode 100644 index 0000000000000..e250f3b132731 --- /dev/null +++ b/gradio/test_data/blocks_configs.py @@ -0,0 +1,910 @@ +XRAY_CONFIG = { + "version": "3.40.1", + "mode": "blocks", + "dev_mode": True, + "analytics_enabled": False, + "components": [ + { + "id": 31, + "type": "markdown", + "props": { + "value": "

Detect Disease From Scan

\n

With this model you can lorem ipsum

\n\n", + "visible": True, + "rtl": False, + "name": "markdown", + }, + "serializer": "StringSerializable", + "api_info": {"info": {"type": "string"}, "serialized_info": False}, + "example_inputs": {"raw": "Howdy!", "serialized": "Howdy!"}, + }, + { + "id": 32, + "type": "checkboxgroup", + "props": { + "choices": [ + ("Covid", "Covid"), + ("Malaria", "Malaria"), + ("Lung Cancer", "Lung Cancer"), + ], + "value": [], + "type": "value", + "label": "Disease to Scan For", + "show_label": True, + "container": True, + "min_width": 160, + "visible": True, + "name": "checkboxgroup", + "selectable": False, + }, + "serializer": "ListStringSerializable", + "api_info": { + "info": {"type": "array", "items": {"type": "string"}}, + "serialized_info": False, + }, + "example_inputs": {"raw": ["Covid"], "serialized": ["Covid"]}, + }, + { + "id": 33, + "type": "tabs", + "props": {"visible": True, "name": "tabs", "selectable": False}, + }, + { + "id": 34, + "type": "tabitem", + "props": {"label": "X-ray", "name": "tabitem", "selectable": False}, + }, + { + "id": 35, + "type": "row", + "props": { + "variant": "default", + "visible": True, + "equal_height": True, + "name": "row", + }, + }, + { + "id": 36, + "type": "image", + "props": { + "image_mode": "RGB", + "invert_colors": False, + "source": "upload", + "tool": "editor", + "type": "numpy", + "show_label": True, + "show_download_button": True, + "container": True, + "min_width": 160, + "visible": True, + "streaming": False, + "mirror_webcam": True, + "brush_color": "#000000", + "mask_opacity": 0.7, + "show_share_button": False, + "name": "image", + "selectable": False, + }, + "serializer": "ImgSerializable", + "api_info": { + "info": { + "type": "string", + "description": "base64 representation of an image", + }, + "serialized_info": True, + }, + "example_inputs": { + "raw": "data:image/png;base64,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", + "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png", + }, + }, + { + "id": 37, + "type": "json", + "props": { + "show_label": True, + "container": True, + "min_width": 160, + "visible": True, + "name": "json", + }, + "serializer": "JSONSerializable", + "api_info": { + "info": {"type": {}, "description": "any valid json"}, + "serialized_info": True, + }, + "example_inputs": {"raw": {"a": 1, "b": 2}, "serialized": None}, + }, + { + "id": 38, + "type": "button", + "props": { + "value": "Run", + "variant": "secondary", + "visible": True, + "interactive": True, + "name": "button", + }, + "serializer": "StringSerializable", + "api_info": {"info": {"type": "string"}, "serialized_info": False}, + "example_inputs": {"raw": "Howdy!", "serialized": "Howdy!"}, + }, + { + "id": 39, + "type": "tabitem", + "props": {"label": "CT Scan", "name": "tabitem", "selectable": False}, + }, + { + "id": 40, + "type": "row", + "props": { + "variant": "default", + "visible": True, + "equal_height": True, + "name": "row", + }, + }, + { + "id": 41, + "type": "image", + "props": { + "image_mode": "RGB", + "invert_colors": False, + "source": "upload", + "tool": "editor", + "type": "numpy", + "show_label": True, + "show_download_button": True, + "container": True, + "min_width": 160, + "visible": True, + "streaming": False, + "mirror_webcam": True, + "brush_color": "#000000", + "mask_opacity": 0.7, + "show_share_button": False, + "name": "image", + "selectable": False, + }, + "serializer": "ImgSerializable", + "api_info": { + "info": { + "type": "string", + "description": "base64 representation of an image", + }, + "serialized_info": True, + }, + "example_inputs": { + "raw": "data:image/png;base64,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", + "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png", + }, + }, + { + "id": 42, + "type": "json", + "props": { + "show_label": True, + "container": True, + "min_width": 160, + "visible": True, + "name": "json", + }, + "serializer": "JSONSerializable", + "api_info": { + "info": {"type": {}, "description": "any valid json"}, + "serialized_info": True, + }, + "example_inputs": {"raw": {"a": 1, "b": 2}, "serialized": None}, + }, + { + "id": 43, + "type": "button", + "props": { + "value": "Run", + "variant": "secondary", + "visible": True, + "interactive": True, + "name": "button", + }, + "serializer": "StringSerializable", + "api_info": {"info": {"type": "string"}, "serialized_info": False}, + "example_inputs": {"raw": "Howdy!", "serialized": "Howdy!"}, + }, + { + "id": 44, + "type": "textbox", + "props": { + "value": "", + "lines": 1, + "max_lines": 20, + "show_label": True, + "container": True, + "min_width": 160, + "visible": True, + "autofocus": False, + "type": "text", + "rtl": False, + "show_copy_button": False, + "name": "textbox", + "selectable": False, + }, + "serializer": "StringSerializable", + "api_info": {"info": {"type": "string"}, "serialized_info": False}, + "example_inputs": {"raw": "Howdy!", "serialized": "Howdy!"}, + }, + { + "id": 45, + "type": "form", + "props": {"scale": 0, "min_width": 0, "name": "form"}, + }, + { + "id": 46, + "type": "form", + "props": {"scale": 0, "min_width": 0, "name": "form"}, + }, + ], + "css": None, + "title": "Gradio", + "space_id": None, + "enable_queue": None, + "show_error": True, + "show_api": True, + "is_colab": False, + "stylesheets": [ + "https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600&display=swap", + "https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&display=swap", + ], + "theme": "default", + "layout": { + "id": 30, + "children": [ + {"id": 31}, + {"id": 45, "children": [{"id": 32}]}, + { + "id": 33, + "children": [ + { + "id": 34, + "children": [ + {"id": 35, "children": [{"id": 36}, {"id": 37}]}, + {"id": 38}, + ], + }, + { + "id": 39, + "children": [ + {"id": 40, "children": [{"id": 41}, {"id": 42}]}, + {"id": 43}, + ], + }, + ], + }, + {"id": 46, "children": [{"id": 44}]}, + ], + }, + "dependencies": [ + { + "targets": [38], + "trigger": "click", + "inputs": [32, 36], + "outputs": [37], + "backend_fn": True, + "js": None, + "queue": None, + "api_name": None, + "scroll_to_output": False, + "show_progress": "full", + "every": None, + "batch": False, + "max_batch_size": 4, + "cancels": [], + "types": {"continuous": False, "generator": False}, + "collects_event_data": False, + "trigger_after": None, + "trigger_only_on_success": False, + }, + { + "targets": [43], + "trigger": "click", + "inputs": [32, 41], + "outputs": [42], + "backend_fn": True, + "js": None, + "queue": None, + "api_name": None, + "scroll_to_output": False, + "show_progress": "full", + "every": None, + "batch": False, + "max_batch_size": 4, + "cancels": [], + "types": {"continuous": False, "generator": False}, + "collects_event_data": False, + "trigger_after": None, + "trigger_only_on_success": False, + }, + { + "targets": [], + "trigger": "load", + "inputs": [], + "outputs": [44], + "backend_fn": True, + "js": None, + "queue": None, + "api_name": None, + "scroll_to_output": False, + "show_progress": "full", + "every": None, + "batch": False, + "max_batch_size": 4, + "cancels": [], + "types": {"continuous": False, "generator": False}, + "collects_event_data": False, + "trigger_after": None, + "trigger_only_on_success": False, + }, + ], +} + +XRAY_CONFIG_DIFF_IDS = { + "version": "3.32.0\n", + "mode": "blocks", + "dev_mode": True, + "analytics_enabled": False, + "components": [ + { + "id": 1, + "type": "markdown", + "props": { + "value": "

Detect Disease From Scan

\n

With this model you can lorem ipsum

\n\n", + "visible": True, + "rtl": False, + "name": "markdown", + }, + "serializer": "StringSerializable", + "api_info": {"info": {"type": "string"}, "serialized_info": False}, + "example_inputs": {"raw": "Howdy!", "serialized": "Howdy!"}, + }, + { + "id": 2, + "type": "checkboxgroup", + "props": { + "choices": [ + ("Covid", "Covid"), + ("Malaria", "Malaria"), + ("Lung Cancer", "Lung Cancer"), + ], + "value": [], + "type": "value", + "label": "Disease to Scan For", + "show_label": True, + "container": True, + "min_width": 160, + "visible": True, + "name": "checkboxgroup", + "selectable": False, + }, + "serializer": "ListStringSerializable", + "api_info": { + "info": {"type": "array", "items": {"type": "string"}}, + "serialized_info": False, + }, + "example_inputs": {"raw": ["Covid"], "serialized": ["Covid"]}, + }, + { + "id": 3, + "type": "tabs", + "props": {"visible": True, "name": "tabs", "selectable": False}, + }, + { + "id": 4, + "type": "tabitem", + "props": {"label": "X-ray", "name": "tabitem", "selectable": False}, + }, + { + "id": 5, + "type": "row", + "props": { + "variant": "default", + "visible": True, + "equal_height": True, + "name": "row", + }, + }, + { + "id": 6, + "type": "image", + "props": { + "image_mode": "RGB", + "invert_colors": False, + "source": "upload", + "tool": "editor", + "type": "numpy", + "show_label": True, + "show_download_button": True, + "container": True, + "min_width": 160, + "visible": True, + "streaming": False, + "mirror_webcam": True, + "brush_color": "#000000", + "mask_opacity": 0.7, + "show_share_button": False, + "name": "image", + "selectable": False, + }, + "serializer": "ImgSerializable", + "api_info": { + "info": { + "type": "string", + "description": "base64 representation of an image", + }, + "serialized_info": True, + }, + "example_inputs": { + "raw": "data:image/png;base64,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", + "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png", + }, + }, + { + "id": 7, + "type": "json", + "props": { + "show_label": True, + "container": True, + "min_width": 160, + "visible": True, + "name": "json", + }, + "serializer": "JSONSerializable", + "api_info": { + "info": {"type": {}, "description": "any valid json"}, + "serialized_info": True, + }, + "example_inputs": {"raw": {"a": 1, "b": 2}, "serialized": None}, + }, + { + "id": 8, + "type": "button", + "props": { + "value": "Run", + "variant": "secondary", + "visible": True, + "interactive": True, + "name": "button", + }, + "serializer": "StringSerializable", + "api_info": {"info": {"type": "string"}, "serialized_info": False}, + "example_inputs": {"raw": "Howdy!", "serialized": "Howdy!"}, + }, + { + "id": 9, + "type": "tabitem", + "props": {"label": "CT Scan", "name": "tabitem", "selectable": False}, + }, + { + "id": 10, + "type": "row", + "props": { + "variant": "default", + "visible": True, + "equal_height": True, + "name": "row", + }, + }, + { + "id": 11, + "type": "image", + "props": { + "image_mode": "RGB", + "invert_colors": False, + "source": "upload", + "tool": "editor", + "type": "numpy", + "show_label": True, + "show_download_button": True, + "container": True, + "min_width": 160, + "visible": True, + "streaming": False, + "mirror_webcam": True, + "brush_color": "#000000", + "mask_opacity": 0.7, + "show_share_button": False, + "name": "image", + "selectable": False, + }, + "serializer": "ImgSerializable", + "api_info": { + "info": { + "type": "string", + "description": "base64 representation of an image", + }, + "serialized_info": True, + }, + "example_inputs": { + "raw": "data:image/png;base64,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", + "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png", + }, + }, + { + "id": 12, + "type": "json", + "props": { + "show_label": True, + "container": True, + "min_width": 160, + "visible": True, + "name": "json", + }, + "serializer": "JSONSerializable", + "api_info": { + "info": {"type": {}, "description": "any valid json"}, + "serialized_info": True, + }, + "example_inputs": {"raw": {"a": 1, "b": 2}, "serialized": None}, + }, + { + "id": 13, + "type": "button", + "props": { + "value": "Run", + "variant": "secondary", + "visible": True, + "interactive": True, + "name": "button", + }, + "serializer": "StringSerializable", + "api_info": {"info": {"type": "string"}, "serialized_info": False}, + "example_inputs": {"raw": "Howdy!", "serialized": "Howdy!"}, + }, + { + "id": 14, + "type": "textbox", + "props": { + "value": "", + "lines": 1, + "max_lines": 20, + "show_label": True, + "container": True, + "min_width": 160, + "visible": True, + "autofocus": False, + "type": "text", + "rtl": False, + "show_copy_button": False, + "name": "textbox", + "selectable": False, + }, + "serializer": "StringSerializable", + "api_info": {"info": {"type": "string"}, "serialized_info": False}, + "example_inputs": {"raw": "Howdy!", "serialized": "Howdy!"}, + }, + { + "id": 15, + "type": "form", + "props": {"scale": 0, "min_width": 0, "name": "form"}, + }, + { + "id": 16, + "type": "form", + "props": {"scale": 0, "min_width": 0, "name": "form"}, + }, + ], + "css": None, + "title": "Gradio", + "space_id": None, + "enable_queue": None, + "show_error": True, + "show_api": True, + "is_colab": False, + "stylesheets": [ + "https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600&display=swap", + "https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&display=swap", + ], + "theme": "default", + "layout": { + "id": 0, + "children": [ + {"id": 1}, + {"id": 15, "children": [{"id": 2}]}, + { + "id": 3, + "children": [ + { + "id": 4, + "children": [ + {"id": 5, "children": [{"id": 6}, {"id": 7}]}, + {"id": 8}, + ], + }, + { + "id": 9, + "children": [ + {"id": 10, "children": [{"id": 11}, {"id": 12}]}, + {"id": 13}, + ], + }, + ], + }, + {"id": 16, "children": [{"id": 14}]}, + ], + }, + "dependencies": [ + { + "targets": [8], + "trigger": "click", + "inputs": [2, 6], + "outputs": [7], + "backend_fn": True, + "js": None, + "queue": None, + "api_name": None, + "scroll_to_output": False, + "show_progress": "full", + "every": None, + "batch": False, + "max_batch_size": 4, + "cancels": [], + "types": {"continuous": False, "generator": False}, + "collects_event_data": False, + "trigger_after": None, + "trigger_only_on_success": False, + }, + { + "targets": [13], + "trigger": "click", + "inputs": [2, 11], + "outputs": [12], + "backend_fn": True, + "js": None, + "queue": None, + "api_name": None, + "scroll_to_output": False, + "show_progress": "full", + "every": None, + "batch": False, + "max_batch_size": 4, + "cancels": [], + "types": {"continuous": False, "generator": False}, + "collects_event_data": False, + "trigger_after": None, + "trigger_only_on_success": False, + }, + { + "targets": [], + "trigger": "load", + "inputs": [], + "outputs": [14], + "backend_fn": True, + "js": None, + "queue": None, + "api_name": None, + "scroll_to_output": False, + "show_progress": "full", + "every": None, + "batch": False, + "max_batch_size": 4, + "cancels": [], + "types": {"continuous": False, "generator": False}, + "collects_event_data": False, + "trigger_after": None, + "trigger_only_on_success": False, + }, + ], +} + + +XRAY_CONFIG_WITH_MISTAKE = { + "mode": "blocks", + "dev_mode": True, + "analytics_enabled": False, + "theme": "default", + "components": [ + { + "id": 1, + "type": "markdown", + "props": { + "value": "

Detect Disease From Scan

\n

With this model you can lorem ipsum

\n\n", + "name": "markdown", + "rtl": False, + }, + }, + { + "id": 2, + "type": "checkboxgroup", + "props": { + "choices": [ + ("Covid", "Covid"), + ("Malaria", "Malaria"), + ("Lung Cancer", "Lung Cancer"), + ], + "value": [], + "name": "checkboxgroup", + "selectable": False, + "show_label": True, + "label": "Disease to Scan For", + "container": True, + "min_width": 160, + }, + }, + { + "id": 3, + "type": "tabs", + "props": { + "value": True, + }, + }, + { + "id": 4, + "type": "tabitem", + "props": { + "label": "X-ray", + "value": True, + }, + }, + { + "id": 5, + "type": "row", + "props": { + "type": "row", + "variant": "default", + "equal_height": True, + "value": True, + }, + }, + { + "id": 6, + "type": "image", + "props": { + "image_mode": "RGB", + "brush_color": "#000000", + "mask_opacity": 0.7, + "source": "upload", + "streaming": False, + "mirror_webcam": True, + "tool": "editor", + "name": "image", + "selectable": False, + "show_share_button": False, + }, + }, + { + "id": 7, + "type": "json", + "props": { + "name": "json", + }, + }, + { + "id": 8, + "type": "button", + "props": { + "value": "Run", + "name": "button", + "interactive": True, + "css": {"background-color": "red", "--hover-color": "orange"}, + "variant": "secondary", + }, + }, + { + "id": 9, + "type": "tabitem", + "props": { + "show_label": True, + "label": "CT Scan", + "value": True, + }, + }, + { + "id": 10, + "type": "row", + "props": { + "type": "row", + "variant": "default", + "equal_height": True, + "value": True, + }, + }, + { + "id": 11, + "type": "image", + "props": { + "image_mode": "RGB", + "brush_color": "#000000", + "mask_opacity": 0.7, + "source": "upload", + "tool": "editor", + "streaming": False, + "mirror_webcam": True, + "name": "image", + "selectable": False, + "show_share_button": False, + }, + }, + { + "id": 12, + "type": "json", + "props": { + "name": "json", + }, + }, + { + "id": 13, + "type": "button", + "props": { + "value": "Run", + "interactive": True, + "name": "button", + "variant": "secondary", + }, + }, + { + "id": 14, + "type": "textbox", + "props": { + "lines": 1, + "value": "", + "name": "textbox", + "selectable": False, + "show_copy_button": False, + "type": "text", + "rtl": False, + "autofocus": False, + }, + }, + ], + "layout": { + "id": 0, + "children": [ + {"id": 1}, + {"id": 2}, + { + "id": 3, + "children": [ + { + "id": 4, + "children": [ + {"id": 5, "children": [{"id": 6}, {"id": 7}]}, + {"id": 8}, + ], + }, + { + "id": 9, + "children": [ + {"id": 10, "children": [{"id": 12}, {"id": 11}]}, + {"id": 13}, + ], + }, + ], + }, + {"id": 14}, + ], + }, + "dependencies": [ + { + "targets": [8], + "trigger": "click", + "inputs": [2, 6], + "outputs": [7], + "api_name": None, + "scroll_to_output": False, + "cancels": [], + "trigger_after": None, + "trigger_only_on_success": False, + "show_progress": "full", + }, + { + "targets": [13], + "trigger": "click", + "inputs": [2, 11], + "outputs": [12], + "api_name": None, + "scroll_to_output": False, + "cancels": [], + "trigger_after": None, + "trigger_only_on_success": False, + "show_progress": "full", + }, + ], +} diff --git a/gradio/utils.py b/gradio/utils.py index 426742fb998ea..d5a013da7b9e6 100644 --- a/gradio/utils.py +++ b/gradio/utils.py @@ -11,7 +11,6 @@ import json.decoder import os import pkgutil -import pprint import random import re import threading @@ -335,7 +334,8 @@ def assert_configs_are_equivalent_besides_ids( """ config1 = copy.deepcopy(config1) config2 = copy.deepcopy(config2) - pp = pprint.PrettyPrinter(indent=2) + config1 = json.loads(json.dumps(config1)) # convert tuples to lists + config2 = json.loads(json.dumps(config2)) for key in root_keys: assert config1[key] == config2[key], f"Configs have different: {key}" @@ -345,15 +345,19 @@ def assert_configs_are_equivalent_besides_ids( ), "# of components are different" def assert_same_components(config1_id, config2_id): - c1 = list(filter(lambda c: c["id"] == config1_id, config1["components"]))[0] - c2 = list(filter(lambda c: c["id"] == config2_id, config2["components"]))[0] + c1 = list(filter(lambda c: c["id"] == config1_id, config1["components"])) + if len(c1) == 0: + raise ValueError(f"Could not find component with id {config1_id}") + c1 = c1[0] + c2 = list(filter(lambda c: c["id"] == config2_id, config2["components"])) + if len(c2) == 0: + raise ValueError(f"Could not find component with id {config2_id}") + c2 = c2[0] c1 = copy.deepcopy(c1) c1.pop("id") c2 = copy.deepcopy(c2) c2.pop("id") - assert json.dumps(c1) == json.dumps( - c2 - ), f"{pp.pprint(c1)} does not match {pp.pprint(c2)}" + assert c1 == c2, f"{c1} does not match {c2}" def same_children_recursive(children1, chidren2): for child1, child2 in zip(children1, chidren2): @@ -655,14 +659,24 @@ def wrapper(*args, **kwargs): return wrapper -def get_function_with_locals(fn: Callable, blocks: Blocks, event_id: str | None): +def get_function_with_locals( + fn: Callable, blocks: Blocks, event_id: str | None, in_event_listener: bool +): def before_fn(blocks, event_id): from gradio.context import thread_data thread_data.blocks = blocks + thread_data.in_event_listener = in_event_listener thread_data.event_id = event_id - return function_wrapper(fn, before_fn=before_fn, before_args=(blocks, event_id)) + def after_fn(): + from gradio.context import thread_data + + thread_data.in_event_listener = False + + return function_wrapper( + fn, before_fn=before_fn, before_args=(blocks, event_id), after_fn=after_fn + ) async def cancel_tasks(task_ids: set[str]): diff --git a/guides/03_building-with-blocks/01_blocks-and-event-listeners.md b/guides/03_building-with-blocks/01_blocks-and-event-listeners.md index 26ff31c75aef4..5d97b460c84b1 100644 --- a/guides/03_building-with-blocks/01_blocks-and-event-listeners.md +++ b/guides/03_building-with-blocks/01_blocks-and-event-listeners.md @@ -122,12 +122,12 @@ Keep in mind that with dictionary returns, we still need to specify the possible ## Updating Component Configurations -The return value of an event listener function is usually the updated value of the corresponding output Component. Sometimes we want to update the configuration of the Component as well, such as the visibility. In this case, we return a `gr.update()` object instead of just the update Component value. +The return value of an event listener function is usually the updated value of the corresponding output Component. Sometimes we want to update the configuration of the Component as well, such as the visibility. In this case, we return a new Component, setting the properties we want to change. -$code_blocks_essay_update -$demo_blocks_essay_update +$code_blocks_essay_simple +$demo_blocks_essay_simple -See how we can configure the Textbox itself through the `gr.update()` method. The `value=` argument can still be used to update the value along with Component configuration. +See how we can configure the Textbox itself through a new `gr.Textbox()` method. The `value=` argument can still be used to update the value along with Component configuration. Any arguments we do not set will use their previous values. ## Running Events Consecutively diff --git a/guides/03_building-with-blocks/02_controlling-layout.md b/guides/03_building-with-blocks/02_controlling-layout.md index a42128051f084..ac91c523e947c 100644 --- a/guides/03_building-with-blocks/02_controlling-layout.md +++ b/guides/03_building-with-blocks/02_controlling-layout.md @@ -64,7 +64,7 @@ Learn more about [Tabs](https://gradio.app/docs/#tab) and [Accordions](https://g ## Visibility -Both Components and Layout elements have a `visible` argument that can set initially and also updated using `gr.update()`. Setting `gr.update(visible=...)` on a Column can be used to show or hide a set of Components. +Both Components and Layout elements have a `visible` argument that can set initially and also updated. Setting `gr.Column(visible=...)` on a Column can be used to show or hide a set of Components. $code_blocks_form $demo_blocks_form diff --git a/guides/cn/03_building-with-blocks/01_blocks-and-event-listeners.md b/guides/cn/03_building-with-blocks/01_blocks-and-event-listeners.md index a64cb175fc588..7e60ffb91f07d 100644 --- a/guides/cn/03_building-with-blocks/01_blocks-and-event-listeners.md +++ b/guides/cn/03_building-with-blocks/01_blocks-and-event-listeners.md @@ -118,8 +118,8 @@ with gr.Blocks() as demo: 事件监听器函数的返回值通常是相应输出组件的更新值。有时我们还希望更新组件的配置,例如可见性。在这种情况下,我们返回一个 `gr.update()` 对象,而不仅仅是更新组件的值。 -$code_blocks_essay_update -$demo_blocks_essay_update +$code_blocks_essay_simple +$demo_blocks_essay_simple 请注意,我们可以通过 `gr.update()` 方法自我配置文本框。`value=` 参数仍然可以用于更新值以及组件配置。 diff --git a/js/app/index.html b/js/app/index.html index e4ee0f65d302d..6d5ef1880b5cf 100644 --- a/js/app/index.html +++ b/js/app/index.html @@ -37,8 +37,8 @@ %gradio_config% diff --git a/js/app/test/blocks_essay.spec.ts b/js/app/test/blocks_essay.spec.ts new file mode 100644 index 0000000000000..92377db03ee10 --- /dev/null +++ b/js/app/test/blocks_essay.spec.ts @@ -0,0 +1,40 @@ +import { test, expect } from "@gradio/tootils"; + +test("updates frontend correctly", async ({ page }) => { + const short_btn = await page.getByLabel("short"); + const long_btn = await page.getByLabel("long"); + const hidden_btn = await page.getByLabel("none"); + const textbox = await page.locator("textarea").first(); + + textbox.fill("hello world"); + await long_btn.check(); + await expect(textbox).toHaveValue("Lorem ipsum dolor sit amet"); + await expect(textbox).toHaveAttribute("rows", "8"); + + textbox.fill("hello world"); + await short_btn.check(); + await expect(textbox).toHaveValue("hello world"); + + await hidden_btn.check(); + await expect(textbox).toBeHidden(); +}); + +test("updates backend correctly", async ({ page }) => { + const min_slider = await page.getByLabel("min"); + const max_slider = await page.getByLabel("max"); + const num = await page.getByLabel("input"); + const output = await page.getByLabel("out"); + + await min_slider.fill("10"); + await num.fill("15"); + await num.press("Enter"); + await expect(output).toHaveValue("15"); + + await num.fill("25"); + await num.press("Enter"); + await expect(output).toHaveValue("25"); + + await num.fill("5"); + await num.press("Enter"); + await expect(output).toHaveValue("25"); +}); diff --git a/scripts/overwrite_xray_config.py b/scripts/overwrite_xray_config.py index b1296f5c6f462..0ad8e2efc15e9 100644 --- a/scripts/overwrite_xray_config.py +++ b/scripts/overwrite_xray_config.py @@ -22,7 +22,7 @@ def ct_model(diseases, img): """ ) disease = gr.CheckboxGroup( - choices=["Covid", "Malaria", "Lung Cancer"], label="Disease to Scan For" + choices=[["Covid", "Covid"], ["Malaria", "Malaria"], ["Lung Cancer", "Lung Cancer"]], label="Disease to Scan For" ) with gr.Tabs(): @@ -58,7 +58,7 @@ def ct_model(diseases, img): """ ) disease = gr.CheckboxGroup( - choices=["Covid", "Malaria", "Lung Cancer"], label="Disease to Scan For" + choices=[["Covid", "Covid"], ["Malaria", "Malaria"], ["Lung Cancer", "Lung Cancer"]], label="Disease to Scan For" ) with gr.Tabs(): diff --git a/test/conftest.py b/test/conftest.py index f2c672fbf0827..c2c8529534526 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -30,7 +30,7 @@ def io_components(): if children: classes_to_check.extend(children) - if "value" in inspect.signature(subclass).parameters: + if "value" in inspect.signature(subclass.__init__).parameters: subclasses.append(subclass) return subclasses diff --git a/test/test_blocks.py b/test/test_blocks.py index 040ad07a918a9..c223500dbd5cc 100644 --- a/test/test_blocks.py +++ b/test/test_blocks.py @@ -140,6 +140,7 @@ def ct_model(diseases, img): with open(xray_config_file) as fp: xray_config = json.load(fp) + print(json.dumps(config)) assert assert_configs_are_equivalent_besides_ids(xray_config, config) assert config["show_api"] is True _ = demo.launch(prevent_thread_lock=True, show_api=False) @@ -194,7 +195,9 @@ def greet(data): btn.click(greet, {first, last}, greeting) - result = await demo.process_api(inputs=["huggy", "face"], fn_index=0, state={}) + result = await demo.process_api( + inputs=["huggy", "face"], fn_index=0, state=None + ) assert result["data"] == ["Hello huggy face"] @pytest.mark.asyncio @@ -209,7 +212,7 @@ async def wait(x): button.click(wait, [text], [text]) start = time.time() - result = await demo.process_api(inputs=[1], fn_index=0, state={}) + result = await demo.process_api(inputs=[1], fn_index=0, state=None) end = time.time() difference = end - start assert difference >= 0.01 @@ -620,7 +623,7 @@ def test_blocks_do_not_filter_none_values_from_updates(self, io_components): ) output = demo.postprocess_data( - 0, [gr.update(value=None) for _ in io_components], state={} + 0, [gr.update(value=None) for _ in io_components], state=None ) assert all( o["value"] == c.postprocess(None) for o, c in zip(output, io_components) @@ -636,7 +639,7 @@ def test_blocks_does_not_replace_keyword_literal(self): outputs=text, ) - output = demo.postprocess_data(0, gr.update(value="NO_VALUE"), state={}) + output = demo.postprocess_data(0, gr.update(value="NO_VALUE"), state=None) assert output[0]["value"] == "NO_VALUE" def test_blocks_does_not_del_dict_keys_inplace(self): @@ -649,7 +652,7 @@ def change_visibility(value): checkbox = gr.Checkbox(value=True, label="Show image") checkbox.change(change_visibility, inputs=checkbox, outputs=im_list) - output = demo.postprocess_data(0, [gr.update(visible=False)] * 2, state={}) + output = demo.postprocess_data(0, [gr.update(visible=False)] * 2, state=None) assert output == [ {"visible": False, "__type__": "update"}, {"visible": False, "__type__": "update"}, @@ -662,14 +665,14 @@ def test_blocks_returns_correct_output_dict_single_key(self): update = gr.Button(value="update") def update_values(val): - return {num2: gr.Number.update(value=42)} + return {num2: gr.Number(value=42)} update.click(update_values, inputs=[num], outputs=[num2]) - output = demo.postprocess_data(0, {num2: gr.Number.update(value=42)}, state={}) + output = demo.postprocess_data(0, {num2: gr.Number(value=42)}, state=None) assert output[0]["value"] == 42 - output = demo.postprocess_data(0, {num2: 23}, state={}) + output = demo.postprocess_data(0, {num2: 23}, state=None) assert output[0] == 23 @pytest.mark.asyncio @@ -684,7 +687,7 @@ def infer(x): share_button = gr.Button("share", visible=False) run_button.click(infer, prompt, [image, share_button], postprocess=False) - output = await demo.process_api(0, ["test"], state={}) + output = await demo.process_api(0, ["test"], state=None) assert output["data"][0] == media_data.BASE64_IMAGE assert output["data"][1] == {"__type__": "update", "visible": True} @@ -693,7 +696,7 @@ async def test_blocks_update_dict_does_not_postprocess_value_if_postprocessing_f self, ): def infer(x): - return gr.Image.update(value=media_data.BASE64_IMAGE) + return gr.Image(value=media_data.BASE64_IMAGE) with gr.Blocks() as demo: prompt = gr.Textbox() @@ -701,7 +704,7 @@ def infer(x): run_button = gr.Button() run_button.click(infer, [prompt], [image], postprocess=False) - output = await demo.process_api(0, ["test"], state={}) + output = await demo.process_api(0, ["test"], state=None) assert output["data"][0] == { "__type__": "update", "value": media_data.BASE64_IMAGE, @@ -713,8 +716,8 @@ async def test_blocks_update_interactive( ): def specific_update(): return [ - gr.Image.update(interactive=True), - gr.Textbox.update(interactive=True), + gr.Image(interactive=True), + gr.Textbox(interactive=True), ] def generic_update(): @@ -728,7 +731,7 @@ def generic_update(): run.click(generic_update, None, [image, textbox]) for fn_index in range(2): - output = await demo.process_api(fn_index, [], state={}) + output = await demo.process_api(fn_index, [], state=None) assert output["data"][0] == { "__type__": "update", "mode": "dynamic", @@ -745,7 +748,7 @@ def test_error_raised_if_num_outputs_mismatch(self): ValueError, match=r'An event handler didn\'t receive enough output values \(needed: 2, received: 1\)\.\nWanted outputs:\n \[textbox, textbox\]\nReceived outputs:\n \["test"\]', ): - demo.postprocess_data(fn_index=0, predictions=["test"], state={}) + demo.postprocess_data(fn_index=0, predictions=["test"], state=None) def test_error_raised_if_num_outputs_mismatch_with_function_name(self): def infer(x): @@ -760,7 +763,7 @@ def infer(x): ValueError, match=r'An event handler \(infer\) didn\'t receive enough output values \(needed: 2, received: 1\)\.\nWanted outputs:\n \[textbox, textbox\]\nReceived outputs:\n \["test"\]', ): - demo.postprocess_data(fn_index=0, predictions=["test"], state={}) + demo.postprocess_data(fn_index=0, predictions=["test"], state=None) def test_error_raised_if_num_outputs_mismatch_single_output(self): with gr.Blocks() as demo: @@ -772,7 +775,7 @@ def test_error_raised_if_num_outputs_mismatch_single_output(self): ValueError, match=r"An event handler didn\'t receive enough output values \(needed: 2, received: 1\)\.\nWanted outputs:\n \[number, number\]\nReceived outputs:\n \[1\]", ): - demo.postprocess_data(fn_index=0, predictions=1, state={}) + demo.postprocess_data(fn_index=0, predictions=1, state=None) def test_error_raised_if_num_outputs_mismatch_tuple_output(self): def infer(a, b): @@ -788,7 +791,104 @@ def infer(a, b): ValueError, match=r"An event handler \(infer\) didn\'t receive enough output values \(needed: 3, received: 2\)\.\nWanted outputs:\n \[number, number, number\]\nReceived outputs:\n \[1, 2\]", ): - demo.postprocess_data(fn_index=0, predictions=(1, 2), state={}) + demo.postprocess_data(fn_index=0, predictions=(1, 2), state=None) + + +class TestStateHolder: + @pytest.mark.asyncio + async def test_state_stored_up_to_capacity(self): + with gr.Blocks() as demo: + num = gr.Number() + state = gr.State(value=0) + + def run(x, s): + return s, s + 1 + + num.submit( + run, + inputs=[num, state], + outputs=[num, state], + ) + app, _, _ = demo.launch(prevent_thread_lock=True, state_session_capacity=2) + client = TestClient(app) + + session_1 = client.post( + "/api/predict/", + json={"data": [1, None], "session_hash": "1", "fn_index": 0}, + ) + assert session_1.json()["data"][0] == 0 + session_2 = client.post( + "/api/predict/", + json={"data": [1, None], "session_hash": "2", "fn_index": 0}, + ) + assert session_2.json()["data"][0] == 0 + session_1 = client.post( + "/api/predict/", + json={"data": [1, None], "session_hash": "1", "fn_index": 0}, + ) + assert session_1.json()["data"][0] == 1 + session_2 = client.post( + "/api/predict/", + json={"data": [1, None], "session_hash": "2", "fn_index": 0}, + ) + assert session_2.json()["data"][0] == 1 + session_3 = client.post( + "/api/predict/", + json={"data": [1, None], "session_hash": "3", "fn_index": 0}, + ) + assert session_3.json()["data"][0] == 0 + session_2 = client.post( + "/api/predict/", + json={"data": [1, None], "session_hash": "2", "fn_index": 0}, + ) + assert session_2.json()["data"][0] == 2 + session_1 = client.post( + "/api/predict/", + json={"data": [1, None], "session_hash": "1", "fn_index": 0}, + ) + assert ( + session_1.json()["data"][0] == 0 + ) # state was lost for session 1 when session 3 was added, since state_session_capacity=2 + + @pytest.mark.asyncio + async def test_updates_stored_up_to_capacity(self): + with gr.Blocks() as demo: + min = gr.Number() + num = gr.Number() + + def run(min, num): + return min, gr.Number(value=num, minimum=min) + + num.submit( + run, + inputs=[min, num], + outputs=[min, num], + ) + app, _, _ = demo.launch(prevent_thread_lock=True, state_session_capacity=2) + client = TestClient(app) + + session_1 = client.post( + "/api/predict/", json={"data": [5, 5], "session_hash": "1", "fn_index": 0} + ) + assert session_1.json()["data"][0] == 5 + session_1 = client.post( + "/api/predict/", json={"data": [2, 2], "session_hash": "1", "fn_index": 0} + ) + assert "error" in session_1.json() # error because min is 5 and num is 2 + session_2 = client.post( + "/api/predict/", json={"data": [5, 5], "session_hash": "2", "fn_index": 0} + ) + assert session_2.json()["data"][0] == 5 + session_3 = client.post( + "/api/predict/", json={"data": [5, 5], "session_hash": "3", "fn_index": 0} + ) + assert session_3.json()["data"][0] == 5 + session_1 = client.post( + "/api/predict/", json={"data": [2, 2], "session_hash": "1", "fn_index": 0} + ) + assert ( + "error" not in session_1.json() + ) # no error because sesssion 1 block config was lost when session 3 was added class TestCallFunction: @@ -1026,7 +1126,7 @@ def batch_fn(x): btn = gr.Button() btn.click(batch_fn, inputs=text, outputs=text, batch=True) - await demo.process_api(0, [["Adam", "Yahya"]], state={}) + await demo.process_api(0, [["Adam", "Yahya"]], state=None) @pytest.mark.asyncio async def test_exceeds_max_batch_size(self): @@ -1045,7 +1145,7 @@ def batch_fn(x): batch_fn, inputs=text, outputs=text, batch=True, max_batch_size=2 ) - await demo.process_api(0, [["A", "B", "C"]], state={}) + await demo.process_api(0, [["A", "B", "C"]], state=None) @pytest.mark.asyncio async def test_unequal_batch_sizes(self): @@ -1063,7 +1163,7 @@ def batch_fn(x, y): btn = gr.Button() btn.click(batch_fn, inputs=[t1, t2], outputs=t1, batch=True) - await demo.process_api(0, [["A", "B", "C"], ["D", "E"]], state={}) + await demo.process_api(0, [["A", "B", "C"], ["D", "E"]], state=None) class TestSpecificUpdate: @@ -1077,23 +1177,8 @@ def test_with_update(self): ) assert specific_update == { "lines": 4, - "info": None, - "max_lines": None, - "autofocus": None, - "placeholder": None, - "label": None, - "show_label": None, - "container": None, - "scale": None, - "min_width": None, - "visible": None, "value": gr.components._Keywords.NO_VALUE, - "type": None, "interactive": False, - "show_copy_button": None, - "rtl": None, - "text_align": None, - "autoscroll": None, "__type__": "update", } @@ -1102,23 +1187,8 @@ def test_with_update(self): ) assert specific_update == { "lines": 4, - "max_lines": None, - "info": None, - "placeholder": None, - "label": None, - "show_label": None, - "container": None, - "scale": None, - "autofocus": None, - "min_width": None, - "visible": None, "value": gr.components._Keywords.NO_VALUE, - "type": None, "interactive": True, - "show_copy_button": None, - "rtl": None, - "text_align": None, - "autoscroll": None, "__type__": "update", } @@ -1138,19 +1208,9 @@ def test_with_generic_update(self): } ) assert specific_update == { - "autoplay": None, - "source": None, - "label": None, - "show_label": None, "visible": True, "value": "test.mp4", "interactive": True, - "container": None, - "height": None, - "min_width": None, - "scale": None, - "width": None, - "show_share_button": None, "__type__": "update", } @@ -1162,17 +1222,17 @@ async def test_accordion_update(self): open_btn = gr.Button(label="Open Accordion") close_btn = gr.Button(label="Close Accordion") open_btn.click( - lambda: gr.Accordion.update(open=True, label="Open Accordion"), + lambda: gr.Accordion(open=True, label="Open Accordion"), inputs=None, outputs=[accordion], ) close_btn.click( - lambda: gr.Accordion.update(open=False, label="Closed Accordion"), + lambda: gr.Accordion(open=False, label="Closed Accordion"), inputs=None, outputs=[accordion], ) result = await demo.process_api( - fn_index=0, inputs=[None], request=None, state={} + fn_index=0, inputs=[None], request=None, state=None ) assert result["data"][0] == { "open": True, @@ -1180,7 +1240,7 @@ async def test_accordion_update(self): "__type__": "update", } result = await demo.process_api( - fn_index=1, inputs=[None], request=None, state={} + fn_index=1, inputs=[None], request=None, state=None ) assert result["data"][0] == { "open": False, diff --git a/test/test_components.py b/test/test_components.py index e39a7785ffbe4..4001dcd63fe01 100644 --- a/test/test_components.py +++ b/test/test_components.py @@ -106,6 +106,8 @@ def test_component_functions(self): "rtl": False, "text_align": None, "autofocus": False, + "selectable": False, + "info": None, "autoscroll": True, } @@ -229,6 +231,8 @@ def test_component_functions(self): "visible": True, "interactive": None, "root_url": None, + "info": None, + "precision": None, } def test_component_functions_integer(self): @@ -279,6 +283,8 @@ def test_component_functions_integer(self): "visible": True, "interactive": None, "root_url": None, + "info": None, + "precision": 0, } def test_component_functions_precision(self): @@ -397,6 +403,7 @@ def test_component_functions(self): "visible": True, "interactive": None, "root_url": None, + "info": None, } @pytest.mark.asyncio @@ -470,6 +477,8 @@ def test_component_functions(self): "visible": True, "interactive": None, "root_url": None, + "selectable": False, + "info": None, } @pytest.mark.asyncio @@ -522,6 +531,9 @@ def test_component_functions(self): "visible": True, "interactive": None, "root_url": None, + "selectable": False, + "type": "value", + "info": None, } with pytest.raises(ValueError): gr.CheckboxGroup(["a"], type="unknown") @@ -570,6 +582,9 @@ def test_component_functions(self): "visible": True, "interactive": None, "root_url": None, + "selectable": False, + "type": "value", + "info": None, } radio = gr.Radio(choices=["a", "b"], type="index") @@ -660,6 +675,9 @@ def test_component_functions(self): "multiselect": True, "filterable": True, "max_choices": 2, + "selectable": False, + "type": "value", + "info": None, } with pytest.raises(ValueError): gr.Dropdown(["a"], type="unknown") @@ -737,6 +755,8 @@ def test_component_functions(self): "root_url": None, "mirror_webcam": True, "selectable": False, + "invert_colors": False, + "type": "pil", } assert image_input.preprocess(None) is None image_input = gr.Image(invert_colors=True) @@ -911,6 +931,8 @@ def test_component_functions(self): "value": None, "interactive": None, "root_url": None, + "type": "numpy", + "format": "wav", } assert audio_input.preprocess(None) is None x_wav["is_example"] = True @@ -952,6 +974,8 @@ def test_component_functions(self): "value": None, "interactive": None, "root_url": None, + "type": "filepath", + "format": "wav", } assert audio_output.deserialize( { @@ -1070,6 +1094,7 @@ def test_component_functions(self): "root_url": None, "selectable": False, "height": None, + "type": "file", } assert file_input.preprocess(None) is None x_file["is_example"] = True @@ -1160,31 +1185,27 @@ def test_component_functions(self): headers=["Name", "Age", "Member"], label="Dataframe Input" ) assert dataframe_input.get_config() == { + "value": {"headers": ["Name", "Age", "Member"], "data": [["", "", ""]]}, + "selectable": False, "headers": ["Name", "Age", "Member"], - "datatype": ["str", "str", "str"], "row_count": (1, "dynamic"), "col_count": (3, "dynamic"), - "value": { - "data": [ - ["", "", ""], - ], - "headers": ["Name", "Age", "Member"], - }, - "name": "dataframe", - "show_label": True, - "label": "Dataframe Input", + "datatype": ["str", "str", "str"], + "type": "pandas", "max_rows": 20, "max_cols": None, "overflow_row_behaviour": "paginate", - "container": True, - "min_width": 160, + "label": "Dataframe Input", + "show_label": True, "scale": None, + "min_width": 160, + "interactive": None, + "visible": True, "elem_id": None, "elem_classes": None, - "visible": True, - "interactive": None, - "root_url": None, "wrap": False, + "root_url": None, + "name": "dataframe", "height": None, "latex_delimiters": [{"display": False, "left": "$", "right": "$"}], } @@ -1196,31 +1217,27 @@ def test_component_functions(self): dataframe_output = gr.Dataframe() assert dataframe_output.get_config() == { + "value": {"headers": [1, 2, 3], "data": [["", "", ""]]}, + "selectable": False, "headers": [1, 2, 3], + "row_count": (1, "dynamic"), + "col_count": (3, "dynamic"), + "datatype": ["str", "str", "str"], + "type": "pandas", "max_rows": 20, "max_cols": None, "overflow_row_behaviour": "paginate", - "name": "dataframe", - "show_label": True, "label": None, - "container": True, - "min_width": 160, + "show_label": True, "scale": None, + "min_width": 160, + "interactive": None, + "visible": True, "elem_id": None, "elem_classes": None, - "visible": True, - "datatype": ["str", "str", "str"], - "row_count": (1, "dynamic"), - "col_count": (3, "dynamic"), - "value": { - "data": [ - ["", "", ""], - ], - "headers": [1, 2, 3], - }, - "interactive": None, - "root_url": None, "wrap": False, + "root_url": None, + "name": "dataframe", "height": None, "latex_delimiters": [{"display": False, "left": "$", "right": "$"}], } @@ -1417,6 +1434,7 @@ def test_component_functions(self): "root_url": None, "mirror_webcam": True, "include_audio": True, + "format": None, } assert video_input.preprocess(None) is None x_video["is_example"] = True @@ -1721,7 +1739,6 @@ def test_component_functions(self): "elem_id": None, "elem_classes": None, "visible": True, - "interactive": None, "root_url": None, "color": None, "selectable": False, @@ -1871,10 +1888,11 @@ def test_component_functions(self): "elem_classes": None, "visible": True, "value": None, - "interactive": None, "root_url": None, "selectable": False, "combine_adjacent": False, + "adjacent_separator": "", + "interactive": None, } def test_in_interface(self): @@ -1953,7 +1971,6 @@ def test_component_functions(self): "value": None, "root_url": None, "selectable": False, - "interactive": None, } def test_in_interface(self): @@ -2048,7 +2065,6 @@ def test_component_functions(self): "value": [], "label": None, "show_label": True, - "interactive": None, "name": "chatbot", "show_share_button": False, "visible": True, @@ -2088,7 +2104,6 @@ def test_component_functions(self): "show_label": True, "label": None, "name": "json", - "interactive": None, "root_url": None, } @@ -2134,20 +2149,16 @@ def test_component_functions(self): get_config """ html_component = gr.components.HTML("#Welcome onboard", label="HTML Input") - assert { - "container": True, - "min_width": None, - "scale": None, - "elem_id": None, - "elem_classes": None, - "visible": True, + assert html_component.get_config() == { "value": "#Welcome onboard", - "show_label": True, "label": "HTML Input", - "name": "html", - "interactive": None, + "show_label": True, + "visible": True, + "elem_id": None, + "elem_classes": None, "root_url": None, - } == html_component.get_config() + "name": "html", + } def test_in_interface(self): """ @@ -2181,29 +2192,28 @@ def test_component_functions(self): """ get_config """ - component = gr.components.Model3D(None, label="Model") - assert { - "clear_color": [0, 0, 0, 0], + model_component = gr.components.Model3D(None, label="Model") + assert model_component.get_config() == { "value": None, + "clear_color": [0, 0, 0, 0], "label": "Model", "show_label": True, - "interactive": None, - "root_url": None, - "name": "model3d", + "container": True, + "scale": None, + "min_width": 160, "visible": True, "elem_id": None, "elem_classes": None, - "container": True, - "min_width": 160, - "scale": None, + "root_url": None, + "name": "model3d", "camera_position": (None, None, None), "height": None, "zoom_speed": 1, - } == component.get_config() + } file = "test/test_files/Box.gltf" - output1 = component.postprocess(file) - output2 = component.postprocess(Path(file)) + output1 = model_component.postprocess(file) + output2 = model_component.postprocess(Path(file)) assert output1 == output2 def test_in_interface(self): @@ -2243,6 +2253,7 @@ def test_component_functions(self): "interactive": None, "root_url": None, "name": "colorpicker", + "info": None, } def test_in_interface_as_input(self): @@ -2406,6 +2417,7 @@ def test_dataset_calls_as_example(*mocks): class TestScatterPlot: @patch.dict("sys.modules", {"bokeh": MagicMock(__version__="3.0.3")}) def test_get_config(self): + print(gr.ScatterPlot().get_config()) assert gr.ScatterPlot().get_config() == { "caption": None, "elem_id": None, @@ -2413,6 +2425,7 @@ def test_get_config(self): "interactive": None, "label": None, "name": "plot", + "bokeh_version": "3.0.3", "root_url": None, "show_label": True, "container": True, @@ -2420,7 +2433,27 @@ def test_get_config(self): "scale": None, "value": None, "visible": True, - "bokeh_version": "3.0.3", + "x": None, + "y": None, + "color": None, + "size": None, + "shape": None, + "title": None, + "tooltip": None, + "x_title": None, + "y_title": None, + "color_legend_title": None, + "size_legend_title": None, + "shape_legend_title": None, + "color_legend_position": None, + "size_legend_position": None, + "shape_legend_position": None, + "height": None, + "width": None, + "x_lim": None, + "y_lim": None, + "x_label_angle": None, + "y_label_angle": None, } def test_no_color(self): @@ -2593,6 +2626,7 @@ def test_get_config(self): "interactive": None, "label": None, "name": "plot", + "bokeh_version": "3.0.3", "root_url": None, "show_label": True, "container": True, @@ -2600,7 +2634,25 @@ def test_get_config(self): "scale": None, "value": None, "visible": True, - "bokeh_version": "3.0.3", + "x": None, + "y": None, + "color": None, + "stroke_dash": None, + "overlay_point": None, + "title": None, + "tooltip": None, + "x_title": None, + "y_title": None, + "color_legend_title": None, + "stroke_dash_legend_title": None, + "color_legend_position": None, + "stroke_dash_legend_position": None, + "height": None, + "width": None, + "x_lim": None, + "y_lim": None, + "x_label_angle": None, + "y_label_angle": None, } def test_no_color(self): @@ -2759,6 +2811,7 @@ def test_get_config(self): "interactive": None, "label": None, "name": "plot", + "bokeh_version": "3.0.3", "root_url": None, "show_label": True, "container": True, @@ -2766,7 +2819,24 @@ def test_get_config(self): "scale": None, "value": None, "visible": True, - "bokeh_version": "3.0.3", + "x": None, + "y": None, + "color": None, + "vertical": True, + "group": None, + "title": None, + "tooltip": None, + "x_title": None, + "y_title": None, + "color_legend_title": None, + "group_title": None, + "color_legend_position": None, + "height": None, + "width": None, + "y_lim": None, + "x_label_angle": None, + "y_label_angle": None, + "sort": None, } def test_update_defaults_none(self): diff --git a/test/test_external.py b/test/test_external.py index 26a82385b8338..0e0dadf642ece 100644 --- a/test/test_external.py +++ b/test/test_external.py @@ -241,7 +241,6 @@ def test_conversational_in_blocks(self): gr.load("models/microsoft/DialoGPT-medium") app, _, _ = io.launch(prevent_thread_lock=True) client = TestClient(app) - assert app.state_holder == {} response = client.post( "/api/predict/", json={"session_hash": "foo", "data": ["Hi!", None], "fn_index": 0}, @@ -249,7 +248,7 @@ def test_conversational_in_blocks(self): output = response.json() assert isinstance(output["data"], list) assert isinstance(output["data"][0], list) - assert isinstance(app.state_holder["foo"], dict) + assert "foo" in app.state_holder def test_speech_recognition_model(self): io = gr.load("models/facebook/wav2vec2-base-960h") diff --git a/test/test_files/xray_config.json b/test/test_files/xray_config.json index 21c8ec6436778..01caf59a3ff4e 100644 --- a/test/test_files/xray_config.json +++ b/test/test_files/xray_config.json @@ -1,479 +1,513 @@ { - "version": "3.43.2", - "mode": "blocks", - "app_id": 13795391484029587257, - "dev_mode": false, - "analytics_enabled": true, - "components": [ - { - "id": 1, - "type": "markdown", - "props": { - "value": "# Detect Disease From Scan\nWith this model you can lorem ipsum\n- ipsum 1\n- ipsum 2", - "rtl": false, - "latex_delimiters": [ - { - "left": "$", - "right": "$", - "display": false - } - ], - "sanitize_html": true, - "name": "markdown", - "visible": true - }, - "serializer": "StringSerializable", - "api_info": { - "info": { - "type": "string" - }, - "serialized_info": false - }, - "example_inputs": { - "raw": "Howdy!", - "serialized": "Howdy!" - } - }, - { - "id": 2, - "type": "checkboxgroup", - "props": { - "choices": [ - [ - "Covid", - "Covid" - ], - [ - "Malaria", - "Malaria" - ], - [ - "Lung Cancer", - "Lung Cancer" - ] - ], - "value": [], - "label": "Disease to Scan For", - "show_label": true, - "container": true, - "min_width": 160, - "name": "checkboxgroup", - "visible": true - }, - "serializer": "ListStringSerializable", - "api_info": { - "info": { - "type": "array", - "items": { - "type": "string" - } - }, - "serialized_info": false - }, - "example_inputs": { - "raw": [ - "Covid" - ], - "serialized": [ - "Covid" - ] - } - }, - { - "id": 3, - "type": "tabs", - "props": { - "visible": true - } - }, - { - "id": 4, - "type": "tabitem", - "props": { - "label": "X-ray", - "visible": true - } - }, - { - "id": 5, - "type": "row", - "props": { - "type": "row", - "variant": "default", - "equal_height": true, - "visible": true - } - }, - { - "id": 6, - "type": "image", - "props": { - "image_mode": "RGB", - "source": "upload", - "tool": "editor", - "streaming": false, - "mirror_webcam": true, - "brush_color": "#000000", - "mask_opacity": 0.7, - "selectable": false, - "show_share_button": false, - "show_download_button": true, - "show_label": true, - "container": true, - "min_width": 160, - "name": "image", - "visible": true - }, - "serializer": "ImgSerializable", - "api_info": { - "info": { - "type": "string", - "description": "base64 representation of an image" - }, - "serialized_info": true - }, - "example_inputs": { - "raw": "data:image/png;base64,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", - "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png" - } - }, - { - "id": 7, - "type": "json", - "props": { - "show_label": true, - "container": true, - "min_width": 160, - "name": "json", - "visible": true - }, - "serializer": "JSONSerializable", - "api_info": { - "info": { - "type": {}, - "description": "any valid json" - }, - "serialized_info": true - }, - "example_inputs": { - "raw": { - "a": 1, - "b": 2 - }, - "serialized": null - } - }, - { - "id": 8, - "type": "button", - "props": { - "value": "Run", - "variant": "secondary", - "interactive": true, - "name": "button", - "visible": true - }, - "serializer": "StringSerializable", - "api_info": { - "info": { - "type": "string" - }, - "serialized_info": false - }, - "example_inputs": { - "raw": "Howdy!", - "serialized": "Howdy!" - } - }, - { - "id": 9, - "type": "tabitem", - "props": { - "label": "CT Scan", - "visible": true - } - }, - { - "id": 10, - "type": "row", - "props": { - "type": "row", - "variant": "default", - "equal_height": true, - "visible": true - } - }, - { - "id": 11, - "type": "image", - "props": { - "image_mode": "RGB", - "source": "upload", - "tool": "editor", - "streaming": false, - "mirror_webcam": true, - "brush_color": "#000000", - "mask_opacity": 0.7, - "selectable": false, - "show_share_button": false, - "show_download_button": true, - "show_label": true, - "container": true, - "min_width": 160, - "name": "image", - "visible": true - }, - "serializer": "ImgSerializable", - "api_info": { - "info": { - "type": "string", - "description": "base64 representation of an image" - }, - "serialized_info": true - }, - "example_inputs": { - "raw": "data:image/png;base64,R0lGODlhPQBEAPeoAJosM//AwO/AwHVYZ/z595kzAP/s7P+goOXMv8+fhw/v739/f+8PD98fH/8mJl+fn/9ZWb8/PzWlwv///6wWGbImAPgTEMImIN9gUFCEm/gDALULDN8PAD6atYdCTX9gUNKlj8wZAKUsAOzZz+UMAOsJAP/Z2ccMDA8PD/95eX5NWvsJCOVNQPtfX/8zM8+QePLl38MGBr8JCP+zs9myn/8GBqwpAP/GxgwJCPny78lzYLgjAJ8vAP9fX/+MjMUcAN8zM/9wcM8ZGcATEL+QePdZWf/29uc/P9cmJu9MTDImIN+/r7+/vz8/P8VNQGNugV8AAF9fX8swMNgTAFlDOICAgPNSUnNWSMQ5MBAQEJE3QPIGAM9AQMqGcG9vb6MhJsEdGM8vLx8fH98AANIWAMuQeL8fABkTEPPQ0OM5OSYdGFl5jo+Pj/+pqcsTE78wMFNGQLYmID4dGPvd3UBAQJmTkP+8vH9QUK+vr8ZWSHpzcJMmILdwcLOGcHRQUHxwcK9PT9DQ0O/v70w5MLypoG8wKOuwsP/g4P/Q0IcwKEswKMl8aJ9fX2xjdOtGRs/Pz+Dg4GImIP8gIH0sKEAwKKmTiKZ8aB/f39Wsl+LFt8dgUE9PT5x5aHBwcP+AgP+WltdgYMyZfyywz78AAAAAAAD///8AAP9mZv///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAKgALAAAAAA9AEQAAAj/AFEJHEiwoMGDCBMqXMiwocAbBww4nEhxoYkUpzJGrMixogkfGUNqlNixJEIDB0SqHGmyJSojM1bKZOmyop0gM3Oe2liTISKMOoPy7GnwY9CjIYcSRYm0aVKSLmE6nfq05QycVLPuhDrxBlCtYJUqNAq2bNWEBj6ZXRuyxZyDRtqwnXvkhACDV+euTeJm1Ki7A73qNWtFiF+/gA95Gly2CJLDhwEHMOUAAuOpLYDEgBxZ4GRTlC1fDnpkM+fOqD6DDj1aZpITp0dtGCDhr+fVuCu3zlg49ijaokTZTo27uG7Gjn2P+hI8+PDPERoUB318bWbfAJ5sUNFcuGRTYUqV/3ogfXp1rWlMc6awJjiAAd2fm4ogXjz56aypOoIde4OE5u/F9x199dlXnnGiHZWEYbGpsAEA3QXYnHwEFliKAgswgJ8LPeiUXGwedCAKABACCN+EA1pYIIYaFlcDhytd51sGAJbo3onOpajiihlO92KHGaUXGwWjUBChjSPiWJuOO/LYIm4v1tXfE6J4gCSJEZ7YgRYUNrkji9P55sF/ogxw5ZkSqIDaZBV6aSGYq/lGZplndkckZ98xoICbTcIJGQAZcNmdmUc210hs35nCyJ58fgmIKX5RQGOZowxaZwYA+JaoKQwswGijBV4C6SiTUmpphMspJx9unX4KaimjDv9aaXOEBteBqmuuxgEHoLX6Kqx+yXqqBANsgCtit4FWQAEkrNbpq7HSOmtwag5w57GrmlJBASEU18ADjUYb3ADTinIttsgSB1oJFfA63bduimuqKB1keqwUhoCSK374wbujvOSu4QG6UvxBRydcpKsav++Ca6G8A6Pr1x2kVMyHwsVxUALDq/krnrhPSOzXG1lUTIoffqGR7Goi2MAxbv6O2kEG56I7CSlRsEFKFVyovDJoIRTg7sugNRDGqCJzJgcKE0ywc0ELm6KBCCJo8DIPFeCWNGcyqNFE06ToAfV0HBRgxsvLThHn1oddQMrXj5DyAQgjEHSAJMWZwS3HPxT/QMbabI/iBCliMLEJKX2EEkomBAUCxRi42VDADxyTYDVogV+wSChqmKxEKCDAYFDFj4OmwbY7bDGdBhtrnTQYOigeChUmc1K3QTnAUfEgGFgAWt88hKA6aCRIXhxnQ1yg3BCayK44EWdkUQcBByEQChFXfCB776aQsG0BIlQgQgE8qO26X1h8cEUep8ngRBnOy74E9QgRgEAC8SvOfQkh7FDBDmS43PmGoIiKUUEGkMEC/PJHgxw0xH74yx/3XnaYRJgMB8obxQW6kL9QYEJ0FIFgByfIL7/IQAlvQwEpnAC7DtLNJCKUoO/w45c44GwCXiAFB/OXAATQryUxdN4LfFiwgjCNYg+kYMIEFkCKDs6PKAIJouyGWMS1FSKJOMRB/BoIxYJIUXFUxNwoIkEKPAgCBZSQHQ1A2EWDfDEUVLyADj5AChSIQW6gu10bE/JG2VnCZGfo4R4d0sdQoBAHhPjhIB94v/wRoRKQWGRHgrhGSQJxCS+0pCZbEhAAOw==", - "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png" - } - }, - { - "id": 12, - "type": "json", - "props": { - "show_label": true, - "container": true, - "min_width": 160, - "name": "json", - "visible": true - }, - "serializer": "JSONSerializable", - "api_info": { - "info": { - "type": {}, - "description": "any valid json" - }, - "serialized_info": true - }, - "example_inputs": { - "raw": { - "a": 1, - "b": 2 - }, - "serialized": null - } - }, - { - "id": 13, - "type": "button", - "props": { - "value": "Run", - "variant": "secondary", - "interactive": true, - "name": "button", - "visible": true - }, - "serializer": "StringSerializable", - "api_info": { - "info": { - "type": "string" - }, - "serialized_info": false - }, - "example_inputs": { - "raw": "Howdy!", - "serialized": "Howdy!" - } - }, - { - "id": 14, - "type": "textbox", - "props": { - "lines": 1, - "max_lines": 20, - "value": "", - "type": "text", - "autofocus": false, - "show_copy_button": false, - "container": true, - "rtl": false, - "autoscroll": true, - "show_label": true, - "min_width": 160, - "name": "textbox", - "visible": true - }, - "serializer": "StringSerializable", - "api_info": { - "info": { - "type": "string" - }, - "serialized_info": false - }, - "example_inputs": { - "raw": "Howdy!", - "serialized": "Howdy!" - } - }, - { - "id": 15, - "type": "form", - "props": { - "type": "form", - "scale": 0, - "min_width": 0, - "visible": true - } - }, - { - "id": 16, - "type": "form", - "props": { - "type": "form", - "scale": 0, - "min_width": 0, - "visible": true - } - } - ], - "css": null, - "title": "Gradio", - "space_id": null, - "enable_queue": null, - "show_error": true, - "show_api": true, - "is_colab": false, - "stylesheets": [ - "https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600&display=swap", - "https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&display=swap" - ], - "theme": "default", - "layout": { - "id": 0, - "children": [ - { - "id": 1 - }, - { - "id": 15, - "children": [ - { - "id": 2 - } - ] - }, - { - "id": 3, - "children": [ - { - "id": 4, - "children": [ - { - "id": 5, - "children": [ - { - "id": 6 - }, - { - "id": 7 - } - ] - }, - { - "id": 8 - } - ] - }, - { - "id": 9, - "children": [ - { - "id": 10, - "children": [ - { - "id": 11 - }, - { - "id": 12 - } - ] - }, - { - "id": 13 - } - ] - } - ] - }, - { - "id": 16, - "children": [ - { - "id": 14 - } - ] - } - ] - }, - "dependencies": [ - { - "targets": [ - 8 - ], - "trigger": "click", - "inputs": [ - 2, - 6 - ], - "outputs": [ - 7 - ], - "backend_fn": true, - "js": null, - "queue": null, - "api_name": null, - "scroll_to_output": false, - "show_progress": "full", - "every": null, - "batch": false, - "max_batch_size": 4, - "cancels": [], - "types": { - "continuous": false, - "generator": false - }, - "collects_event_data": false, - "trigger_after": null, - "trigger_only_on_success": false - }, - { - "targets": [ - 13 - ], - "trigger": "click", - "inputs": [ - 2, - 11 - ], - "outputs": [ - 12 - ], - "backend_fn": true, - "js": null, - "queue": null, - "api_name": null, - "scroll_to_output": false, - "show_progress": "full", - "every": null, - "batch": false, - "max_batch_size": 4, - "cancels": [], - "types": { - "continuous": false, - "generator": false - }, - "collects_event_data": false, - "trigger_after": null, - "trigger_only_on_success": false - } - ] + "version": "3.44.1", + "mode": "blocks", + "app_id": 3299865391549106311, + "dev_mode": false, + "analytics_enabled": false, + "components": [ + { + "id": 31, + "type": "markdown", + "props": { + "value": "# Detect Disease From Scan\nWith this model you can lorem ipsum\n- ipsum 1\n- ipsum 2", + "rtl": false, + "latex_delimiters": [ + { + "left": "$", + "right": "$", + "display": false + } + ], + "visible": true, + "sanitize_html": true, + "name": "markdown" + }, + "serializer": "StringSerializable", + "api_info": { + "info": { + "type": "string" + }, + "serialized_info": false + }, + "example_inputs": { + "raw": "Howdy!", + "serialized": "Howdy!" + } + }, + { + "id": 32, + "type": "checkboxgroup", + "props": { + "choices": [ + [ + "Covid", + "Covid" + ], + [ + "Malaria", + "Malaria" + ], + [ + "Lung Cancer", + "Lung Cancer" + ] + ], + "value": [], + "type": "value", + "label": "Disease to Scan For", + "show_label": true, + "container": true, + "min_width": 160, + "visible": true, + "name": "checkboxgroup", + "selectable": false + }, + "serializer": "ListStringSerializable", + "api_info": { + "info": { + "type": "array", + "items": { + "type": "string" + } + }, + "serialized_info": false + }, + "example_inputs": { + "raw": [ + "Covid" + ], + "serialized": [ + "Covid" + ] + } + }, + { + "id": 33, + "type": "tabs", + "props": { + "visible": true, + "name": "tabs", + "selectable": false + } + }, + { + "id": 34, + "type": "tabitem", + "props": { + "label": "X-ray", + "name": "tabitem", + "selectable": false + } + }, + { + "id": 35, + "type": "row", + "props": { + "variant": "default", + "visible": true, + "equal_height": true, + "name": "row" + } + }, + { + "id": 36, + "type": "image", + "props": { + "image_mode": "RGB", + "invert_colors": false, + "source": "upload", + "tool": "editor", + "type": "numpy", + "show_label": true, + "show_download_button": true, + "container": true, + "min_width": 160, + "visible": true, + "streaming": false, + "mirror_webcam": true, + "brush_color": "#000000", + "mask_opacity": 0.7, + "show_share_button": false, + "name": "image", + "selectable": false + }, + "serializer": "ImgSerializable", + "api_info": { + "info": { + "type": "string", + "description": "base64 representation of an image" + }, + "serialized_info": true + }, + "example_inputs": { + "raw": "data:image/png;base64,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", + "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png" + } + }, + { + "id": 37, + "type": "json", + "props": { + "show_label": true, + "container": true, + "min_width": 160, + "visible": true, + "name": "json" + }, + "serializer": "JSONSerializable", + "api_info": { + "info": { + "type": {}, + "description": "any valid json" + }, + "serialized_info": true + }, + "example_inputs": { + "raw": { + "a": 1, + "b": 2 + }, + "serialized": null + } + }, + { + "id": 38, + "type": "button", + "props": { + "value": "Run", + "variant": "secondary", + "visible": true, + "interactive": true, + "name": "button" + }, + "serializer": "StringSerializable", + "api_info": { + "info": { + "type": "string" + }, + "serialized_info": false + }, + "example_inputs": { + "raw": "Howdy!", + "serialized": "Howdy!" + } + }, + { + "id": 39, + "type": "tabitem", + "props": { + "label": "CT Scan", + "name": "tabitem", + "selectable": false + } + }, + { + "id": 40, + "type": "row", + "props": { + "variant": "default", + "visible": true, + "equal_height": true, + "name": "row" + } + }, + { + "id": 41, + "type": "image", + "props": { + "image_mode": "RGB", + "invert_colors": false, + "source": "upload", + "tool": "editor", + "type": "numpy", + "show_label": true, + "show_download_button": true, + "container": true, + "min_width": 160, + "visible": true, + "streaming": false, + "mirror_webcam": true, + "brush_color": "#000000", + "mask_opacity": 0.7, + "show_share_button": false, + "name": "image", + "selectable": false + }, + "serializer": "ImgSerializable", + "api_info": { + "info": { + "type": "string", + "description": "base64 representation of an image" + }, + "serialized_info": true + }, + "example_inputs": { + "raw": "data:image/png;base64,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", + "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png" + } + }, + { + "id": 42, + "type": "json", + "props": { + "show_label": true, + "container": true, + "min_width": 160, + "visible": true, + "name": "json" + }, + "serializer": "JSONSerializable", + "api_info": { + "info": { + "type": {}, + "description": "any valid json" + }, + "serialized_info": true + }, + "example_inputs": { + "raw": { + "a": 1, + "b": 2 + }, + "serialized": null + } + }, + { + "id": 43, + "type": "button", + "props": { + "value": "Run", + "variant": "secondary", + "visible": true, + "interactive": true, + "name": "button" + }, + "serializer": "StringSerializable", + "api_info": { + "info": { + "type": "string" + }, + "serialized_info": false + }, + "example_inputs": { + "raw": "Howdy!", + "serialized": "Howdy!" + } + }, + { + "id": 44, + "type": "textbox", + "props": { + "value": "", + "lines": 1, + "max_lines": 20, + "show_label": true, + "container": true, + "min_width": 160, + "visible": true, + "autofocus": false, + "autoscroll": true, + "type": "text", + "rtl": false, + "show_copy_button": false, + "name": "textbox", + "selectable": false + }, + "serializer": "StringSerializable", + "api_info": { + "info": { + "type": "string" + }, + "serialized_info": false + }, + "example_inputs": { + "raw": "Howdy!", + "serialized": "Howdy!" + } + }, + { + "id": 45, + "type": "form", + "props": { + "scale": 0, + "min_width": 0, + "name": "form" + } + }, + { + "id": 46, + "type": "form", + "props": { + "scale": 0, + "min_width": 0, + "name": "form" + } + } + ], + "css": null, + "title": "Gradio", + "space_id": null, + "enable_queue": null, + "show_error": true, + "show_api": true, + "is_colab": false, + "stylesheets": [ + "https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600&display=swap", + "https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&display=swap" + ], + "theme": "default", + "layout": { + "id": 30, + "children": [ + { + "id": 31 + }, + { + "id": 45, + "children": [ + { + "id": 32 + } + ] + }, + { + "id": 33, + "children": [ + { + "id": 34, + "children": [ + { + "id": 35, + "children": [ + { + "id": 36 + }, + { + "id": 37 + } + ] + }, + { + "id": 38 + } + ] + }, + { + "id": 39, + "children": [ + { + "id": 40, + "children": [ + { + "id": 41 + }, + { + "id": 42 + } + ] + }, + { + "id": 43 + } + ] + } + ] + }, + { + "id": 46, + "children": [ + { + "id": 44 + } + ] + } + ] + }, + "dependencies": [ + { + "targets": [ + 38 + ], + "trigger": "click", + "inputs": [ + 32, + 36 + ], + "outputs": [ + 37 + ], + "backend_fn": true, + "js": null, + "queue": null, + "api_name": null, + "scroll_to_output": false, + "show_progress": "full", + "every": null, + "batch": false, + "max_batch_size": 4, + "cancels": [], + "types": { + "continuous": false, + "generator": false + }, + "collects_event_data": false, + "trigger_after": null, + "trigger_only_on_success": false + }, + { + "targets": [ + 43 + ], + "trigger": "click", + "inputs": [ + 32, + 41 + ], + "outputs": [ + 42 + ], + "backend_fn": true, + "js": null, + "queue": null, + "api_name": null, + "scroll_to_output": false, + "show_progress": "full", + "every": null, + "batch": false, + "max_batch_size": 4, + "cancels": [], + "types": { + "continuous": false, + "generator": false + }, + "collects_event_data": false, + "trigger_after": null, + "trigger_only_on_success": false + }, + { + "targets": [], + "trigger": "load", + "inputs": [], + "outputs": [ + 44 + ], + "backend_fn": true, + "js": null, + "queue": null, + "api_name": null, + "scroll_to_output": false, + "show_progress": "full", + "every": null, + "batch": false, + "max_batch_size": 4, + "cancels": [], + "types": { + "continuous": false, + "generator": false + }, + "collects_event_data": false, + "trigger_after": null, + "trigger_only_on_success": false + } + ] } \ No newline at end of file diff --git a/test/test_files/xray_config_diff_ids.json b/test/test_files/xray_config_diff_ids.json index 991b757980aa1..c5c15ac9debcb 100644 --- a/test/test_files/xray_config_diff_ids.json +++ b/test/test_files/xray_config_diff_ids.json @@ -1,479 +1,513 @@ { - "version": "3.43.2", - "mode": "blocks", - "app_id": 1168406096942204620, - "dev_mode": false, - "analytics_enabled": true, - "components": [ - { - "id": 101, - "type": "markdown", - "props": { - "value": "# Detect Disease From Scan\nWith this model you can lorem ipsum\n- ipsum 1\n- ipsum 2", - "rtl": false, - "latex_delimiters": [ - { - "left": "$", - "right": "$", - "display": false - } - ], - "sanitize_html": true, - "name": "markdown", - "visible": true - }, - "serializer": "StringSerializable", - "api_info": { - "info": { - "type": "string" - }, - "serialized_info": false - }, - "example_inputs": { - "raw": "Howdy!", - "serialized": "Howdy!" - } - }, - { - "id": 102, - "type": "checkboxgroup", - "props": { - "choices": [ - [ - "Covid", - "Covid" - ], - [ - "Malaria", - "Malaria" - ], - [ - "Lung Cancer", - "Lung Cancer" - ] - ], - "value": [], - "label": "Disease to Scan For", - "show_label": true, - "container": true, - "min_width": 160, - "name": "checkboxgroup", - "visible": true - }, - "serializer": "ListStringSerializable", - "api_info": { - "info": { - "type": "array", - "items": { - "type": "string" - } - }, - "serialized_info": false - }, - "example_inputs": { - "raw": [ - "Covid" - ], - "serialized": [ - "Covid" - ] - } - }, - { - "id": 103, - "type": "tabs", - "props": { - "visible": true - } - }, - { - "id": 104, - "type": "tabitem", - "props": { - "label": "X-ray", - "visible": true - } - }, - { - "id": 105, - "type": "row", - "props": { - "type": "row", - "variant": "default", - "equal_height": true, - "visible": true - } - }, - { - "id": 106, - "type": "image", - "props": { - "image_mode": "RGB", - "source": "upload", - "tool": "editor", - "streaming": false, - "mirror_webcam": true, - "brush_color": "#000000", - "mask_opacity": 0.7, - "selectable": false, - "show_share_button": false, - "show_download_button": true, - "show_label": true, - "container": true, - "min_width": 160, - "name": "image", - "visible": true - }, - "serializer": "ImgSerializable", - "api_info": { - "info": { - "type": "string", - "description": "base64 representation of an image" - }, - "serialized_info": true - }, - "example_inputs": { - "raw": "data:image/png;base64,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", - "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png" - } - }, - { - "id": 107, - "type": "json", - "props": { - "show_label": true, - "container": true, - "min_width": 160, - "name": "json", - "visible": true - }, - "serializer": "JSONSerializable", - "api_info": { - "info": { - "type": {}, - "description": "any valid json" - }, - "serialized_info": true - }, - "example_inputs": { - "raw": { - "a": 1, - "b": 2 - }, - "serialized": null - } - }, - { - "id": 108, - "type": "button", - "props": { - "value": "Run", - "variant": "secondary", - "interactive": true, - "name": "button", - "visible": true - }, - "serializer": "StringSerializable", - "api_info": { - "info": { - "type": "string" - }, - "serialized_info": false - }, - "example_inputs": { - "raw": "Howdy!", - "serialized": "Howdy!" - } - }, - { - "id": 109, - "type": "tabitem", - "props": { - "label": "CT Scan", - "visible": true - } - }, - { - "id": 110, - "type": "row", - "props": { - "type": "row", - "variant": "default", - "equal_height": true, - "visible": true - } - }, - { - "id": 111, - "type": "image", - "props": { - "image_mode": "RGB", - "source": "upload", - "tool": "editor", - "streaming": false, - "mirror_webcam": true, - "brush_color": "#000000", - "mask_opacity": 0.7, - "selectable": false, - "show_share_button": false, - "show_download_button": true, - "show_label": true, - "container": true, - "min_width": 160, - "name": "image", - "visible": true - }, - "serializer": "ImgSerializable", - "api_info": { - "info": { - "type": "string", - "description": "base64 representation of an image" - }, - "serialized_info": true - }, - "example_inputs": { - "raw": "data:image/png;base64,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", - "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png" - } - }, - { - "id": 112, - "type": "json", - "props": { - "show_label": true, - "container": true, - "min_width": 160, - "name": "json", - "visible": true - }, - "serializer": "JSONSerializable", - "api_info": { - "info": { - "type": {}, - "description": "any valid json" - }, - "serialized_info": true - }, - "example_inputs": { - "raw": { - "a": 1, - "b": 2 - }, - "serialized": null - } - }, - { - "id": 113, - "type": "button", - "props": { - "value": "Run", - "variant": "secondary", - "interactive": true, - "name": "button", - "visible": true - }, - "serializer": "StringSerializable", - "api_info": { - "info": { - "type": "string" - }, - "serialized_info": false - }, - "example_inputs": { - "raw": "Howdy!", - "serialized": "Howdy!" - } - }, - { - "id": 114, - "type": "textbox", - "props": { - "lines": 1, - "max_lines": 20, - "value": "", - "type": "text", - "autofocus": false, - "show_copy_button": false, - "container": true, - "rtl": false, - "autoscroll": true, - "show_label": true, - "min_width": 160, - "name": "textbox", - "visible": true - }, - "serializer": "StringSerializable", - "api_info": { - "info": { - "type": "string" - }, - "serialized_info": false - }, - "example_inputs": { - "raw": "Howdy!", - "serialized": "Howdy!" - } - }, - { - "id": 115, - "type": "form", - "props": { - "type": "form", - "scale": 0, - "min_width": 0, - "visible": true - } - }, - { - "id": 116, - "type": "form", - "props": { - "type": "form", - "scale": 0, - "min_width": 0, - "visible": true - } - } - ], - "css": null, - "title": "Gradio", - "space_id": null, - "enable_queue": null, - "show_error": true, - "show_api": true, - "is_colab": false, - "stylesheets": [ - "https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600&display=swap", - "https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&display=swap" - ], - "theme": "default", - "layout": { - "id": 100, - "children": [ - { - "id": 101 - }, - { - "id": 115, - "children": [ - { - "id": 102 - } - ] - }, - { - "id": 103, - "children": [ - { - "id": 104, - "children": [ - { - "id": 105, - "children": [ - { - "id": 106 - }, - { - "id": 107 - } - ] - }, - { - "id": 108 - } - ] - }, - { - "id": 109, - "children": [ - { - "id": 110, - "children": [ - { - "id": 111 - }, - { - "id": 112 - } - ] - }, - { - "id": 113 - } - ] - } - ] - }, - { - "id": 116, - "children": [ - { - "id": 114 - } - ] - } - ] - }, - "dependencies": [ - { - "targets": [ - 108 - ], - "trigger": "click", - "inputs": [ - 102, - 106 - ], - "outputs": [ - 107 - ], - "backend_fn": true, - "js": null, - "queue": null, - "api_name": null, - "scroll_to_output": false, - "show_progress": "full", - "every": null, - "batch": false, - "max_batch_size": 4, - "cancels": [], - "types": { - "continuous": false, - "generator": false - }, - "collects_event_data": false, - "trigger_after": null, - "trigger_only_on_success": false - }, - { - "targets": [ - 113 - ], - "trigger": "click", - "inputs": [ - 102, - 111 - ], - "outputs": [ - 112 - ], - "backend_fn": true, - "js": null, - "queue": null, - "api_name": null, - "scroll_to_output": false, - "show_progress": "full", - "every": null, - "batch": false, - "max_batch_size": 4, - "cancels": [], - "types": { - "continuous": false, - "generator": false - }, - "collects_event_data": false, - "trigger_after": null, - "trigger_only_on_success": false - } - ] + "version": "3.44.1", + "mode": "blocks", + "app_id": 3299865391549106311, + "dev_mode": false, + "analytics_enabled": false, + "components": [ + { + "id": 1031, + "type": "markdown", + "props": { + "value": "# Detect Disease From Scan\nWith this model you can lorem ipsum\n- ipsum 1\n- ipsum 2", + "rtl": false, + "latex_delimiters": [ + { + "left": "$", + "right": "$", + "display": false + } + ], + "visible": true, + "sanitize_html": true, + "name": "markdown" + }, + "serializer": "StringSerializable", + "api_info": { + "info": { + "type": "string" + }, + "serialized_info": false + }, + "example_inputs": { + "raw": "Howdy!", + "serialized": "Howdy!" + } + }, + { + "id": 1032, + "type": "checkboxgroup", + "props": { + "choices": [ + [ + "Covid", + "Covid" + ], + [ + "Malaria", + "Malaria" + ], + [ + "Lung Cancer", + "Lung Cancer" + ] + ], + "value": [], + "type": "value", + "label": "Disease to Scan For", + "show_label": true, + "container": true, + "min_width": 160, + "visible": true, + "name": "checkboxgroup", + "selectable": false + }, + "serializer": "ListStringSerializable", + "api_info": { + "info": { + "type": "array", + "items": { + "type": "string" + } + }, + "serialized_info": false + }, + "example_inputs": { + "raw": [ + "Covid" + ], + "serialized": [ + "Covid" + ] + } + }, + { + "id": 1033, + "type": "tabs", + "props": { + "visible": true, + "name": "tabs", + "selectable": false + } + }, + { + "id": 1034, + "type": "tabitem", + "props": { + "label": "X-ray", + "name": "tabitem", + "selectable": false + } + }, + { + "id": 1035, + "type": "row", + "props": { + "variant": "default", + "visible": true, + "equal_height": true, + "name": "row" + } + }, + { + "id": 1036, + "type": "image", + "props": { + "image_mode": "RGB", + "invert_colors": false, + "source": "upload", + "tool": "editor", + "type": "numpy", + "show_label": true, + "show_download_button": true, + "container": true, + "min_width": 160, + "visible": true, + "streaming": false, + "mirror_webcam": true, + "brush_color": "#000000", + "mask_opacity": 0.7, + "show_share_button": false, + "name": "image", + "selectable": false + }, + "serializer": "ImgSerializable", + "api_info": { + "info": { + "type": "string", + "description": "base64 representation of an image" + }, + "serialized_info": true + }, + "example_inputs": { + "raw": "data:image/png;base64,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", + "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png" + } + }, + { + "id": 1037, + "type": "json", + "props": { + "show_label": true, + "container": true, + "min_width": 160, + "visible": true, + "name": "json" + }, + "serializer": "JSONSerializable", + "api_info": { + "info": { + "type": {}, + "description": "any valid json" + }, + "serialized_info": true + }, + "example_inputs": { + "raw": { + "a": 1, + "b": 2 + }, + "serialized": null + } + }, + { + "id": 1038, + "type": "button", + "props": { + "value": "Run", + "variant": "secondary", + "visible": true, + "interactive": true, + "name": "button" + }, + "serializer": "StringSerializable", + "api_info": { + "info": { + "type": "string" + }, + "serialized_info": false + }, + "example_inputs": { + "raw": "Howdy!", + "serialized": "Howdy!" + } + }, + { + "id": 1039, + "type": "tabitem", + "props": { + "label": "CT Scan", + "name": "tabitem", + "selectable": false + } + }, + { + "id": 1040, + "type": "row", + "props": { + "variant": "default", + "visible": true, + "equal_height": true, + "name": "row" + } + }, + { + "id": 1041, + "type": "image", + "props": { + "image_mode": "RGB", + "invert_colors": false, + "source": "upload", + "tool": "editor", + "type": "numpy", + "show_label": true, + "show_download_button": true, + "container": true, + "min_width": 160, + "visible": true, + "streaming": false, + "mirror_webcam": true, + "brush_color": "#000000", + "mask_opacity": 0.7, + "show_share_button": false, + "name": "image", + "selectable": false + }, + "serializer": "ImgSerializable", + "api_info": { + "info": { + "type": "string", + "description": "base64 representation of an image" + }, + "serialized_info": true + }, + "example_inputs": { + "raw": "data:image/png;base64,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", + "serialized": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png" + } + }, + { + "id": 1042, + "type": "json", + "props": { + "show_label": true, + "container": true, + "min_width": 160, + "visible": true, + "name": "json" + }, + "serializer": "JSONSerializable", + "api_info": { + "info": { + "type": {}, + "description": "any valid json" + }, + "serialized_info": true + }, + "example_inputs": { + "raw": { + "a": 1, + "b": 2 + }, + "serialized": null + } + }, + { + "id": 1043, + "type": "button", + "props": { + "value": "Run", + "variant": "secondary", + "visible": true, + "interactive": true, + "name": "button" + }, + "serializer": "StringSerializable", + "api_info": { + "info": { + "type": "string" + }, + "serialized_info": false + }, + "example_inputs": { + "raw": "Howdy!", + "serialized": "Howdy!" + } + }, + { + "id": 1044, + "type": "textbox", + "props": { + "value": "", + "lines": 1, + "max_lines": 20, + "show_label": true, + "container": true, + "min_width": 160, + "visible": true, + "autofocus": false, + "autoscroll": true, + "type": "text", + "rtl": false, + "show_copy_button": false, + "name": "textbox", + "selectable": false + }, + "serializer": "StringSerializable", + "api_info": { + "info": { + "type": "string" + }, + "serialized_info": false + }, + "example_inputs": { + "raw": "Howdy!", + "serialized": "Howdy!" + } + }, + { + "id": 1045, + "type": "form", + "props": { + "scale": 0, + "min_width": 0, + "name": "form" + } + }, + { + "id": 1046, + "type": "form", + "props": { + "scale": 0, + "min_width": 0, + "name": "form" + } + } + ], + "css": null, + "title": "Gradio", + "space_id": null, + "enable_queue": null, + "show_error": true, + "show_api": true, + "is_colab": false, + "stylesheets": [ + "https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600&display=swap", + "https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&display=swap" + ], + "theme": "default", + "layout": { + "id": 1030, + "children": [ + { + "id": 1031 + }, + { + "id": 1045, + "children": [ + { + "id": 1032 + } + ] + }, + { + "id": 1033, + "children": [ + { + "id": 1034, + "children": [ + { + "id": 1035, + "children": [ + { + "id": 1036 + }, + { + "id": 1037 + } + ] + }, + { + "id": 1038 + } + ] + }, + { + "id": 1039, + "children": [ + { + "id": 1040, + "children": [ + { + "id": 1041 + }, + { + "id": 1042 + } + ] + }, + { + "id": 1043 + } + ] + } + ] + }, + { + "id": 1046, + "children": [ + { + "id": 1044 + } + ] + } + ] + }, + "dependencies": [ + { + "targets": [ + 1038 + ], + "trigger": "click", + "inputs": [ + 1032, + 1036 + ], + "outputs": [ + 1037 + ], + "backend_fn": true, + "js": null, + "queue": null, + "api_name": null, + "scroll_to_output": false, + "show_progress": "full", + "every": null, + "batch": false, + "max_batch_size": 4, + "cancels": [], + "types": { + "continuous": false, + "generator": false + }, + "collects_event_data": false, + "trigger_after": null, + "trigger_only_on_success": false + }, + { + "targets": [ + 1043 + ], + "trigger": "click", + "inputs": [ + 1032, + 1041 + ], + "outputs": [ + 1042 + ], + "backend_fn": true, + "js": null, + "queue": null, + "api_name": null, + "scroll_to_output": false, + "show_progress": "full", + "every": null, + "batch": false, + "max_batch_size": 4, + "cancels": [], + "types": { + "continuous": false, + "generator": false + }, + "collects_event_data": false, + "trigger_after": null, + "trigger_only_on_success": false + }, + { + "targets": [], + "trigger": "load", + "inputs": [], + "outputs": [ + 1044 + ], + "backend_fn": true, + "js": null, + "queue": null, + "api_name": null, + "scroll_to_output": false, + "show_progress": "full", + "every": null, + "batch": false, + "max_batch_size": 4, + "cancels": [], + "types": { + "continuous": false, + "generator": false + }, + "collects_event_data": false, + "trigger_after": null, + "trigger_only_on_success": false + } + ] } \ No newline at end of file