diff --git a/.changeset/many-tips-create.md b/.changeset/many-tips-create.md new file mode 100644 index 000000000000..a7032ac024f8 --- /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 000000000000..dc392ea95476 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 8e6c94b1a186..b1782ff5d98d 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 3683f8d55714..0b97d4dffd51 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 d8ce94f78068..1ddf37f1d643 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 480378226a2e..2dde03ce3734 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 127ca62e0f01..1711eb70d0ff 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 000000000000..a378968e215a --- /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 000000000000..215268766535 --- /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 0fc70cbe02b2..000000000000 --- 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 625da12f3cfa..000000000000 --- 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 7508d8039227..96dd33e5d89c 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 c7dc0ee9f52a..9e8c606bfdba 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 04d0cc646748..ee6a47e2e0ff 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 a154d1fa2357..956083cb0840 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 5f55239e0e9b..52d3052d5c4d 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 598fbee371b7..a8340d8f760e 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 9e9b4215cdd4..c005fbae9abb 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 49c9fc09fa15..c2b49423298d 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 6a04326ca097..285db671e549 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 35576951d117..423a8d3dce27 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 e978080af308..e3f6e1b3095f 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 9c0d84a16d0e..5d831d71fb4a 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 6bd14142dd2a..0d09b5df8f8e 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 f5a5794cae84..d3eb8361fec2 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 71f3e7349bbe..bd0bb5efe2fe 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 01cfb314a84e..7a2aa6f1ee9b 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 06abbaf396cf..a331555fa570 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 8f14689c3cc3..5cd6446b4622 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 cda9ee87d8dc..66ed05b489ad 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 bc25dc47199c..2497d750ffd9 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 f9215d07e53f..a6f27a41349a 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 7fcb2123ff48..2fa896fc8c36 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 a3d22a0bcab8..2590b0d18ba7 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 9b933f2cb43d..aec886c055e4 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 885c3fa19538..6fa3e4343259 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 8362e75dda85..90c21c50bfce 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 3b4323858e24..b4ed1981dd4a 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 423d0998d20e..6ba86557b17b 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 45a0ca8b5f3d..3ae129ea9d3a 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 7f84ab098708..d5d992f1a732 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 64cd140468e1..5cc11df2690f 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 801062c1c5ad..3cb0d76c525a 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 81713cdc99ea..cfc6cfd88cdf 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 22cd6a3329c4..578fdf9314cc 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 6c5360dedd91..c893faf60aa2 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 2b9c042cc61b..eb82619594b7 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 acb137566dc0..b3034c17e5f4 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 72ba6d42410e..22436d1c6209 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 9d11200faa0e..d6f54de4809e 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 3b923bc0a226..9acab862e3ec 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 b350f17aab37..e64db3827b2e 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 16fa9e67ad48..cb5d4006d783 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 08b6478f4b18..4394bb84f8fc 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 96f4987b519d..793247853e4e 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 f12890f415e1..2b3bd170caa1 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 f88a0c8dd9ac..f8acd134f32f 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 0cbde2b43b20..0b709c740760 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 bd13e8582dba..8cb422778a9a 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 cb2796da93bd..022a3257c37e 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 6c5a41b18d9d..af9dfaf86d5f 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 316be3517eab..782b16ac8cff 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 b661fb7d650c..85465bcf32de 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 4fd58cf95261..19199abc6c9f 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 263b2e802834..b5fd6a19cd02 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 fc476d99b813..b261f4f637d2 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 bdd32c51febf..46bef37ba671 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 5a2c40fd387b..f6e965b0a3f8 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 7250ed741cd0..02ae8999e495 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 cd327957b202..2898ee2379fb 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 c8f9e34f702c..d11bef86b2c1 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 5d2b9fcccc14..6f6d0149ac50 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 54927b8b8988..763f871c9d7b 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 931677421987..2b11cb7de77a 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 b0a9bb107baf..7527aaca68ec 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 c589eb675d09..514fec178b6a 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 dfd1ad85c4a6..f228570f4595 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 92d9086108bd..7cdd82ecb092 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 fc0924bfff94..fadf375d250d 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 f9ae9bf2f588..684558458610 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 d56357f6473d..257edc583a9d 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 1642c25ee728..820f0afacf90 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 c370651debce..d7007622150a 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 7aea8dd59add..a36c0668b383 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 9d77d2b6b1c2..9cc0b69034f3 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 be6ab745b437..dd785e98bc29 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 000000000000..012457f75c29 --- /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 000000000000..e250f3b13273 --- /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 426742fb998e..d5a013da7b9e 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 26ff31c75aef..5d97b460c84b 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 a42128051f08..ac91c523e947 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 a64cb175fc58..7e60ffb91f07 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 e4ee0f65d302..6d5ef1880b5c 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 000000000000..92377db03ee1 --- /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 b1296f5c6f46..0ad8e2efc15e 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 f2c672fbf082..c2c852953452 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 040ad07a918a..c223500dbd5c 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 e39a7785ffbe..4001dcd63fe0 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 26a82385b833..0e0dadf642ec 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 21c8ec643677..01caf59a3ff4 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,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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, - "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 991b757980aa..c5c15ac9debc 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