Fixes .change() in Video, Audio, Image (#4793)

This commit is contained in:
Abubakar Abid 2023-07-11 10:56:46 -05:00 committed by GitHub
parent a82eee5733
commit abd0ced3db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 231 additions and 49 deletions

View File

@ -5,7 +5,8 @@
## Bug Fixes:
No changes to highlight.
* The `.change()` event is fixed in `Video` and `Image` so that it only fires once by [@abidlabs](https://github.com/abidlabs) in [PR 4793](https://github.com/gradio-app/gradio/pull/4793)
* The `.change()` event is fixed in `Audio` so that fires when the component value is programmatically updated by [@abidlabs](https://github.com/abidlabs) in [PR 4793](https://github.com/gradio-app/gradio/pull/4793)
## Other Changes:

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -1,9 +1,10 @@
import os
import gradio as gr
with gr.Blocks() as demo:
set_button = gr.Button("Set Values")
with gr.Row():
with gr.Column():
with gr.Column(min_width=200):
gr.Markdown("# Enter Here")
text = gr.Textbox()
num = gr.Number()
@ -15,9 +16,12 @@ with gr.Blocks() as demo:
colorpicker = gr.ColorPicker()
code = gr.Code()
dataframe = gr.Dataframe()
image = gr.Image(elem_id="image-original")
audio = gr.Audio(elem_id="audio-original")
video = gr.Video(elem_id="video-original")
with gr.Column():
gr.Markdown("# ON:INPUT")
with gr.Column(min_width=200):
gr.Markdown("# ON:INPUT/UPLOAD")
text_in = gr.Textbox()
num_in = gr.Number()
slider_in = gr.Slider()
@ -28,8 +32,11 @@ with gr.Blocks() as demo:
colorpicker_in = gr.ColorPicker()
code_in = gr.Code()
dataframe_in = gr.Dataframe()
image_up = gr.Image(elem_id="image-upload")
audio_up = gr.Audio(elem_id="audio-upload")
video_up = gr.Video(elem_id="video-upload")
with gr.Column():
with gr.Column(min_width=200):
gr.Markdown("# ON:CHANGE")
text_ch = gr.Textbox()
num_ch = gr.Number()
@ -41,33 +48,79 @@ with gr.Blocks() as demo:
colorpicker_ch = gr.ColorPicker()
code_ch = gr.Code()
dataframe_ch = gr.Dataframe()
image_ch = gr.Image(elem_id="image-change")
audio_ch = gr.Audio(elem_id="audio-change")
video_ch = gr.Video(elem_id="video-change")
set_button.click(
lambda: ["asdf", 555, 12, True, ["a", "c"], "b", "b", "#FF0000", "import gradio as gr", [["a", "b", "c", "d"], ["1", "2", "3", "4"]]],
None,
[text, num, slider, checkbox, checkbox_group, radio, dropdown, colorpicker, code, dataframe])
with gr.Column(min_width=200):
gr.Markdown("# ON:CHANGE x2")
text_ch2 = gr.Textbox()
num_ch2 = gr.Number()
slider_ch2 = gr.Slider()
checkbox_ch2 = gr.Checkbox()
checkbox_group_ch2 = gr.CheckboxGroup(["a", "b", "c"])
radio_ch2 = gr.Radio(["a", "b", "c"])
dropdown_ch2 = gr.Dropdown(["a", "b", "c"])
colorpicker_ch2 = gr.ColorPicker()
code_ch2 = gr.Code()
dataframe_ch2 = gr.Dataframe()
image_ch2 = gr.Image(elem_id="image-change-2")
audio_ch2 = gr.Audio(elem_id="audio-change-2")
video_ch2 = gr.Video(elem_id="video-change-2")
text.input(lambda x:x, text, text_in)
num.input(lambda x:x, num, num_in)
slider.input(lambda x:x, slider, slider_in)
checkbox.input(lambda x:x, checkbox, checkbox_in)
checkbox_group.input(lambda x:x, checkbox_group, checkbox_group_in)
radio.input(lambda x:x, radio, radio_in)
dropdown.input(lambda x:x, dropdown, dropdown_in)
colorpicker.input(lambda x:x, colorpicker, colorpicker_in)
code.input(lambda x:x, code, code_in)
dataframe.input(lambda x:x, dataframe, dataframe_in)
counter = gr.Number(label="Change counter")
text.change(lambda x:x, text, text_ch)
num.change(lambda x:x, num, num_ch)
slider.change(lambda x:x, slider, slider_ch)
checkbox.change(lambda x:x, checkbox, checkbox_ch)
checkbox_group.change(lambda x:x, checkbox_group, checkbox_group_ch)
radio.change(lambda x:x, radio, radio_ch)
dropdown.change(lambda x:x, dropdown, dropdown_ch)
colorpicker.change(lambda x:x, colorpicker, colorpicker_ch)
code.change(lambda x:x, code, code_ch)
dataframe.change(lambda x:x, dataframe, dataframe_ch)
lion = os.path.join(os.path.dirname(__file__), "files/lion.jpg")
cantina = os.path.join(os.path.dirname(__file__), "files/cantina.wav")
world = os.path.join(os.path.dirname(__file__), "files/world.mp4")
set_button.click(
lambda: ["asdf", 555, 12, True, ["a", "c"], "b", "b", "#FF0000", "import gradio as gr", [["a", "b", "c", "d"], ["1", "2", "3", "4"]], lion, cantina, world],
None,
[text, num, slider, checkbox, checkbox_group, radio, dropdown, colorpicker, code, dataframe, image, audio, video])
text.input(lambda x:x, text, text_in)
num.input(lambda x:x, num, num_in)
slider.input(lambda x:x, slider, slider_in)
checkbox.input(lambda x:x, checkbox, checkbox_in)
checkbox_group.input(lambda x:x, checkbox_group, checkbox_group_in)
radio.input(lambda x:x, radio, radio_in)
dropdown.input(lambda x:x, dropdown, dropdown_in)
colorpicker.input(lambda x:x, colorpicker, colorpicker_in)
code.input(lambda x:x, code, code_in)
dataframe.input(lambda x:x, dataframe, dataframe_in)
image.upload(lambda x:x, image, image_up)
audio.upload(lambda x:x, audio, audio_up)
video.upload(lambda x:x, video, video_up)
text.change(lambda x,y:(x,y+1), [text, counter], [text_ch, counter])
num.change(lambda x,y:(x, y+1), [num, counter], [num_ch, counter])
slider.change(lambda x,y:(x, y+1), [slider, counter], [slider_ch, counter])
checkbox.change(lambda x,y:(x, y+1), [checkbox, counter], [checkbox_ch, counter])
checkbox_group.change(lambda x,y:(x, y+1), [checkbox_group, counter], [checkbox_group_ch, counter])
radio.change(lambda x,y:(x, y+1), [radio, counter], [radio_ch, counter])
dropdown.change(lambda x,y:(x, y+1), [dropdown, counter], [dropdown_ch, counter])
colorpicker.change(lambda x,y:(x, y+1), [colorpicker, counter], [colorpicker_ch, counter])
code.change(lambda x,y:(x, y+1), [code, counter], [code_ch, counter])
dataframe.change(lambda x,y:(x, y+1), [dataframe, counter], [dataframe_ch, counter])
image.change(lambda x,y:(x, y+1), [image, counter], [image_ch, counter])
audio.change(lambda x,y:(x, y+1), [audio, counter], [audio_ch, counter])
video.change(lambda x,y:(x, y+1), [video, counter], [video_ch, counter])
text_ch.change(lambda x:x, text_ch, text_ch2)
num_ch.change(lambda x:x, num_ch, num_ch2)
slider_ch.change(lambda x:x, slider_ch, slider_ch2)
checkbox_ch.change(lambda x:x, checkbox_ch, checkbox_ch2)
checkbox_group_ch.change(lambda x:x, checkbox_group_ch, checkbox_group_ch2)
radio_ch.change(lambda x:x, radio_ch, radio_ch2)
dropdown_ch.change(lambda x:x, dropdown_ch, dropdown_ch2)
colorpicker_ch.change(lambda x:x, colorpicker_ch, colorpicker_ch2)
code_ch.change(lambda x:x, code_ch, code_ch2)
dataframe_ch.change(lambda x:x, dataframe_ch, dataframe_ch2)
image_ch.change(lambda x:x, image_ch, image_ch2)
audio_ch.change(lambda x:x, audio_ch, audio_ch2)
video_ch.change(lambda x:x, video_ch, video_ch2)
if __name__ == "__main__":
demo.launch()

View File

@ -1,3 +1,5 @@
<svelte:options accessors={true} />
<script lang="ts">
import { createEventDispatcher } from "svelte";
import { _ } from "svelte-i18n";
@ -23,6 +25,7 @@
export let visible = true;
export let mode: "static" | "dynamic";
export let value: null | FileData | string = null;
let old_value: null | FileData | string = null;
export let name: string;
export let source: "microphone" | "upload";
export let label: string;
@ -41,6 +44,13 @@
let _value: null | FileData;
$: _value = normalise_file(value, root, root_url);
$: {
if (JSON.stringify(value) !== JSON.stringify(old_value)) {
old_value = value;
dispatch("change");
}
}
let dragging: boolean;
</script>
@ -64,10 +74,7 @@
{label}
{show_label}
value={_value}
on:change={({ detail }) => {
value = detail;
dispatch("change", value);
}}
on:change={({ detail }) => (value = detail)}
on:stream={({ detail }) => {
value = detail;
dispatch("stream", value);

View File

@ -317,4 +317,36 @@ describe("Audio", () => {
assert.equal(fn.callCount, 2);
});
test("audio change event trigger fires when value is changed and only fires once", async () => {
const { component } = await render(Audio, {
show_label: true,
loading_status,
mode: "static",
value: {
name: "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample.wav",
data: null,
is_file: true
},
label: "static",
root: "foo",
root_url: null,
streaming: false,
pending: false,
source: "microphone",
autoplay: true
});
const mock = spy();
component.$on("change", mock);
(component.value = [
{
name: "https://gradio-builds.s3.amazonaws.com/demo-files/audio_sample2.wav",
data: null,
is_file: true
}
]),
assert.equal(mock.callCount, 1);
});
});

View File

@ -1,3 +1,5 @@
<svelte:options accessors={true} />
<script lang="ts">
import { createEventDispatcher } from "svelte";
import { Image, StaticImage } from "@gradio/image";
@ -81,7 +83,6 @@
{selectable}
on:edit
on:clear
on:change
on:stream
on:drag={({ detail }) => (dragging = detail)}
on:upload

View File

@ -0,0 +1,57 @@
import {
test,
describe,
assert,
afterEach,
vi,
beforeAll,
beforeEach
} from "vitest";
import { spy } from "tinyspy";
import { cleanup, render } from "@gradio/tootils";
import { setupi18n } from "../../i18n";
import Image from "./Image.svelte";
import type { LoadingStatus } from "../StatusTracker/types";
const loading_status = {
eta: 0,
queue_position: 1,
queue_size: 1,
status: "complete" as LoadingStatus["status"],
scroll_to_output: false,
visible: true,
fn_index: 0,
show_progress: "full" as LoadingStatus["show_progress"]
};
describe("Image", () => {
beforeAll(() => {
window.HTMLMediaElement.prototype.play = vi.fn();
window.HTMLMediaElement.prototype.pause = vi.fn();
});
beforeEach(setupi18n);
afterEach(() => cleanup());
test("image change event trigger fires when value is changed and only fires once", async () => {
const { component } = await render(Image, {
show_label: true,
loading_status,
mode: "dynamic",
value:
"https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png",
root: "foo",
root_url: null,
streaming: false,
pending: false,
source: "upload"
});
const mock = spy();
component.$on("change", mock);
component.value =
"https://github.com/gradio-app/gradio/blob/main/test/test_files/cheetah1.jpg";
assert.equal(mock.callCount, 1);
});
});

View File

@ -1,3 +1,5 @@
<svelte:options accessors={true} />
<script lang="ts">
import { createEventDispatcher } from "svelte";
import type { FileData } from "@gradio/upload";
@ -17,7 +19,7 @@
let old_value: [FileData, FileData | null] | null = null;
export let label: string;
export let source: string;
export let source: "upload" | "webcam";
export let root: string;
export let root_url: null | string;
export let show_label: boolean;
@ -31,7 +33,7 @@
export let min_width: number | undefined = undefined;
export let mode: "static" | "dynamic";
export let autoplay = false;
export let show_share_button: boolean = true;
export let show_share_button = true;
let _video: FileData | null = null;
let _subtitle: FileData | null = null;
@ -58,8 +60,6 @@
} else {
value = null;
}
dispatch("change");
}
$: {

View File

@ -8,7 +8,7 @@ import {
beforeEach,
expect
} from "vitest";
import { spyOn } from "tinyspy";
import { spy, spyOn } from "tinyspy";
import { cleanup, render } from "@gradio/tootils";
import { setupi18n } from "../../i18n";
@ -125,7 +125,7 @@ describe("Video", () => {
root_url: null,
streaming: false,
pending: false,
source: "microphone",
source: "upload",
autoplay: true
});
const startButton = getByTestId<HTMLAudioElement>("test-player");
@ -150,7 +150,7 @@ describe("Video", () => {
root_url: null,
streaming: false,
pending: false,
source: "microphone",
source: "upload",
autoplay: true
});
const startButton = getByTestId<HTMLAudioElement>("test-player");
@ -175,7 +175,7 @@ describe("Video", () => {
root_url: null,
streaming: false,
pending: false,
source: "microphone",
source: "upload",
autoplay: true
});
const startButton = getByTestId<HTMLAudioElement>("test-player");
@ -208,7 +208,7 @@ describe("Video", () => {
root_url: null,
streaming: false,
pending: false,
source: "microphone",
source: "upload",
autoplay: true
});
const startButton = getByTestId<HTMLAudioElement>("test-player");
@ -248,4 +248,37 @@ describe("Video", () => {
downloadButton.getElementsByTagName("button").length
).toBeGreaterThan(0);
});
test("video change event trigger fires when value is changed and only fires once", async () => {
const { component } = await render(Video, {
show_label: true,
loading_status,
mode: "dynamic",
value: [
{
name: "https://raw.githubusercontent.com/gradio-app/gradio/main/gradio/demo/video_component/files/a.mp4",
data: null,
is_file: true
}
],
root: "foo",
root_url: null,
streaming: false,
pending: false,
source: "upload",
autoplay: true
});
const mock = spy();
component.$on("change", mock);
(component.value = [
{
name: "https://raw.githubusercontent.com/gradio-app/gradio/main/gradio/demo/video_component/files/b.mp4",
data: null,
is_file: true
}
]),
assert.equal(mock.callCount, 1);
});
});

View File

@ -96,8 +96,6 @@
select: SelectData;
}>();
$: dispatch("change", value as string);
let dragging = false;
$: dispatch("drag", dragging);

4
pnpm-lock.yaml generated
View File

@ -1,4 +1,4 @@
lockfileVersion: '6.0'
lockfileVersion: '6.1'
settings:
autoInstallPeers: true
@ -5766,7 +5766,7 @@ packages:
peerDependencies:
'@sveltejs/kit': ^1.0.0
dependencies:
'@sveltejs/kit': 1.16.3(svelte@3.57.0)(vite@4.3.5)
'@sveltejs/kit': 1.16.3(svelte@3.59.2)(vite@4.3.9)
import-meta-resolve: 3.0.0
dev: true

View File

@ -1,2 +1,2 @@
# Reference: https://github.com/sweepai/sweep/blob/main/sweep.yaml
branch: dev
branch: dev