Skip to content

Commit

Permalink
Fix event triggers and recent regressions related to gr.DataFrame (#…
Browse files Browse the repository at this point in the history
…10403)

* fixes

* add changeset

* fix

* add changeset

* cleanup

* notebooks

* changes

* fix

---------

Co-authored-by: gradio-pr-bot <[email protected]>
  • Loading branch information
abidlabs and gradio-pr-bot authored Jan 22, 2025
1 parent 9dc5d15 commit 3219382
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 32 deletions.
6 changes: 6 additions & 0 deletions .changeset/sixty-impalas-bathe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@gradio/dataframe": patch
"gradio": patch
---

fix:Fix event triggers and recent regressions related to `gr.DataFrame`
2 changes: 1 addition & 1 deletion demo/dataframe_streaming/run.ipynb
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: dataframe_streaming"]}, {"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 pandas as pd\n", "import time\n", "\n", "def update_dataframe(df):\n", " df.iloc[:, :] = 1\n", " yield df, 1\n", " time.sleep(0.1)\n", " df.iloc[:, :] = 2\n", " yield df, 2\n", "\n", "initial_df = pd.DataFrame(0, index=range(5), columns=range(5))\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " button = gr.Button(\"Update DataFrame\")\n", " number = gr.Number(value=0, label=\"Number\")\n", " dataframe = gr.Dataframe(value=initial_df, label=\"Dataframe\")\n", " button.click(fn=update_dataframe, inputs=dataframe, outputs=[dataframe, number])\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: dataframe_streaming"]}, {"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 pandas as pd\n", "import time\n", "\n", "def update_dataframe(df):\n", " df.iloc[:, :] = 1\n", " yield df, 1\n", " time.sleep(0.1)\n", " df.iloc[:, :] = 2\n", " yield df, 2\n", "\n", "initial_df = pd.DataFrame(0, index=range(5), columns=range(5))\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " button = gr.Button(\"Update DataFrame\")\n", " number = gr.Number(value=0, label=\"Number\")\n", " dataframe = gr.Dataframe(value=initial_df, label=\"Dataframe\")\n", " button.click(fn=update_dataframe, inputs=dataframe, outputs=[dataframe, number])\n", " with gr.Row():\n", " change_events = gr.Number(label=\"Change events\")\n", " input_events = gr.Number(label=\"Input events\")\n", "\n", " dataframe.change(lambda x:x+1, inputs=change_events, outputs=change_events)\n", " dataframe.input(lambda x:x+1, inputs=input_events, outputs=input_events)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
6 changes: 6 additions & 0 deletions demo/dataframe_streaming/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ def update_dataframe(df):
number = gr.Number(value=0, label="Number")
dataframe = gr.Dataframe(value=initial_df, label="Dataframe")
button.click(fn=update_dataframe, inputs=dataframe, outputs=[dataframe, number])
with gr.Row():
change_events = gr.Number(label="Change events")
input_events = gr.Number(label="Input events")

dataframe.change(lambda x:x+1, inputs=change_events, outputs=change_events)
dataframe.input(lambda x:x+1, inputs=input_events, outputs=input_events)

if __name__ == "__main__":
demo.launch()
1 change: 1 addition & 0 deletions js/dataframe/Index.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
{styling}
headers={_headers}
on:change={(e) => gradio.dispatch("change")}
on:input={(e) => gradio.dispatch("input")}
on:select={(e) => gradio.dispatch("select", e.detail)}
{wrap}
{datatype}
Expand Down
69 changes: 39 additions & 30 deletions js/dataframe/shared/Table.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import { afterUpdate, createEventDispatcher, tick, onMount } from "svelte";
import { dsvFormat } from "d3-dsv";
import { dequal } from "dequal/lite";
import { copy } from "@gradio/utils";
import { Upload } from "@gradio/upload";
import EditableCell from "./EditableCell.svelte";
Expand Down Expand Up @@ -144,34 +143,44 @@
}
let _headers = make_headers(headers);
let old_headers: string[] | undefined;
let old_headers: string[] = headers;
$: {
if (!dequal(headers, old_headers)) {
trigger_headers();
_headers = make_headers(headers);
old_headers = JSON.parse(JSON.stringify(headers));
}
}
function trigger_headers(): void {
_headers = make_headers(headers);
old_headers = headers.slice();
trigger_change();
}
let data: { id: string; value: string | number }[][] = [[]];
let old_val: undefined | (string | number)[][] = undefined;
$: if (!dequal(values, old_val)) {
data = process_data(values as (string | number)[][]);
old_val = JSON.parse(JSON.stringify(values)) as (string | number)[][];
}
let data: { id: string; value: string | number }[][] = [[]];
let old_val: undefined | (string | number)[][] = undefined;
let previous_headers_string = JSON.stringify(_headers.map((h) => h.value));
let previous_data_string = JSON.stringify(
data.map((row) => row.map((cell) => String(cell.value)))
);
async function trigger_change(): Promise<void> {
dispatch("change");
if (!value_is_output) {
dispatch("input");
const current_headers_string = JSON.stringify(_headers.map((h) => h.value));
const current_data_string = JSON.stringify(
data.map((row) => row.map((cell) => String(cell.value)))
);
if (
current_data_string !== previous_data_string ||
current_headers_string !== previous_headers_string
) {
dispatch("change");
if (!value_is_output) {
dispatch("input");
}
previous_data_string = current_data_string;
previous_headers_string = current_headers_string;
}
}
Expand Down Expand Up @@ -414,7 +423,7 @@
selected = [index !== undefined ? index : data.length - 1, 0];
}
$: (data || selected_header) && trigger_change();
$: (data || _headers) && trigger_change();
async function add_col(index?: number): Promise<void> {
parent.focus();
Expand Down Expand Up @@ -639,8 +648,18 @@
observer.observe(parent);
document.addEventListener("click", handle_click_outside);
window.addEventListener("resize", handle_resize);
document.addEventListener("fullscreenchange", handle_fullscreen_change);
return () => {
observer.disconnect();
document.removeEventListener("click", handle_click_outside);
window.removeEventListener("resize", handle_resize);
document.removeEventListener(
"fullscreenchange",
handle_fullscreen_change
);
};
});
Expand Down Expand Up @@ -695,20 +714,6 @@
set_cell_widths();
}
onMount(() => {
document.addEventListener("click", handle_click_outside);
window.addEventListener("resize", handle_resize);
document.addEventListener("fullscreenchange", handle_fullscreen_change);
return () => {
document.removeEventListener("click", handle_click_outside);
window.removeEventListener("resize", handle_resize);
document.removeEventListener(
"fullscreenchange",
handle_fullscreen_change
);
};
});
let active_button: {
type: "header" | "cell";
row?: number;
Expand Down Expand Up @@ -969,6 +974,8 @@
clear_on_focus = false;
clicked_cell = { row: index, col: j };
selected = [index, j];
selected_header = false;
header_edit = false;
if (editable) {
editing = [index, j];
}
Expand All @@ -986,6 +993,8 @@
active_header_menu = null;
clicked_cell = { row: index, col: j };
selected = [index, j];
selected_header = false;
header_edit = false;
if (editable) {
editing = [index, j];
}
Expand Down
8 changes: 7 additions & 1 deletion js/spa/test/dataframe_streaming.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import { test, expect } from "@self/tootils";

test("DataFrame updates correctly when button is clicked", async ({ page }) => {
test("DataFrame updates and events are tracked correctly", async ({ page }) => {
await expect(page.getByLabel("Change events")).toHaveValue("0");
await expect(page.getByLabel("Input events")).toHaveValue("0");

await page.getByRole("button", { name: "Update DataFrame" }).click();
await expect(
page.getByRole("table", { name: "Dataframe" }).locator("td").first()
).toHaveText("2");

await expect(page.getByLabel("Change events")).toHaveValue("2");
await expect(page.getByLabel("Input events")).toHaveValue("0");
});

0 comments on commit 3219382

Please sign in to comment.