Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Timer component #8505

Merged
merged 54 commits into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
be480a4
chagnes
Jun 7, 2024
486c20e
add changeset
gradio-pr-bot Jun 7, 2024
9b04005
changes
Jun 7, 2024
c204ab0
changes
Jun 9, 2024
53af29d
Merge branch 'timer_event_listener' of https://github.com/gradio-app/…
Jun 9, 2024
d5dc03e
changes
Jun 10, 2024
4d0a537
Merge remote-tracking branch 'origin' into timer_event_listener
Jun 10, 2024
789fba8
Merge remote-tracking branch 'origin' into timer_event_listener
Jun 10, 2024
cb9fd09
changes
Jun 10, 2024
05924ef
Merge remote-tracking branch 'origin' into timer_event_listener
Jun 12, 2024
3a69f74
changes
Jun 12, 2024
f4f2f15
Merge remote-tracking branch 'origin' into timer_event_listener
Jun 12, 2024
3d641da
changes
Jun 12, 2024
54f025d
changes
Jun 12, 2024
0d69e96
changes
Jun 12, 2024
8b74afa
changes
Jun 12, 2024
0af8d6d
changes
Jun 13, 2024
023a246
changes
Jun 13, 2024
bde393b
changes
Jun 13, 2024
eec6f35
changes
Jun 13, 2024
742112a
Merge remote-tracking branch 'origin' into timer_event_listener
Jun 13, 2024
a2e0bdf
changes
Jun 13, 2024
e5bf2fe
Merge branch 'main' into timer_event_listener
aliabid94 Jun 14, 2024
398f92c
change
Jun 14, 2024
47b3905
add docs
aliabd Jun 15, 2024
187e717
add changeset
gradio-pr-bot Jun 15, 2024
e89ddca
remove demo
aliabd Jun 15, 2024
376db8f
Merge branch 'timer_event_listener' of https://github.com/gradio-app/…
aliabd Jun 15, 2024
eef0b53
Merge branch 'main' into timer_event_listener
pngwn Jun 15, 2024
2031e82
Merge branch 'main' into timer_event_listener
aliabd Jun 15, 2024
1404e52
Merge branch 'main' into timer_event_listener
abidlabs Jun 19, 2024
c778af5
add changeset
gradio-pr-bot Jun 20, 2024
f94b60e
changes
Jun 20, 2024
cf9d69a
add changeset
gradio-pr-bot Jun 20, 2024
cf7828a
changes
Jun 25, 2024
53b4222
changes
Jun 25, 2024
6915705
changes
Jun 25, 2024
5fa2dbb
add changeset
gradio-pr-bot Jun 25, 2024
bcf3dca
Merge remote-tracking branch 'origin' into timer_event_listener
Jun 25, 2024
d0655dd
Merge branch 'timer_event_listener' of https://github.com/gradio-app/…
Jun 25, 2024
9a7072e
changes
Jun 25, 2024
7872a20
changes
Jun 25, 2024
945806d
changes
Jun 26, 2024
be99ccb
changes
Jun 26, 2024
a4de90f
changes
Jun 26, 2024
21c3479
changes
Jun 26, 2024
1bd6546
changes
Jun 26, 2024
6a27dc3
changes
Jun 26, 2024
90173bf
changes
Jun 26, 2024
7930ee1
Update gradio/components/timer.py
aliabid94 Jun 26, 2024
115e7c7
Merge branch 'main' into timer_event_listener
abidlabs Jun 27, 2024
d8db005
changes
Jun 27, 2024
171f085
Merge remote-tracking branch 'origin' into timer_event_listener
Jun 27, 2024
de843f3
changes
Jun 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .changeset/hungry-rice-thank.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
"@gradio/app": minor
"@gradio/client": minor
"@gradio/timer": minor
"gradio": minor
"gradio_client": minor
"website": minor
---

fix:Add Timer component
2 changes: 1 addition & 1 deletion client/js/src/helpers/api_info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ export function transform_api_info(
dependencyIndex !== -1
? config.dependencies.find((dep) => dep.id == dependencyIndex)
?.types
: { continuous: false, generator: false, cancel: false };
: { generator: false, cancel: false };

if (
dependencyIndex !== -1 &&
Expand Down
8 changes: 2 additions & 6 deletions client/js/src/test/test_data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export const transformed_api_info: ApiInfo<ApiData> = {
component: "Textbox"
}
],
type: { continuous: false, generator: false, cancel: false }
type: { generator: false, cancel: false }
}
},
unnamed_endpoints: {
Expand All @@ -68,7 +68,7 @@ export const transformed_api_info: ApiInfo<ApiData> = {
component: "Textbox"
}
],
type: { continuous: false, generator: false, cancel: false }
type: { generator: false, cancel: false }
}
}
};
Expand Down Expand Up @@ -394,7 +394,6 @@ export const config_response: Config = {
max_batch_size: 4,
cancels: [],
types: {
continuous: false,
generator: false,
cancel: false
},
Expand All @@ -421,7 +420,6 @@ export const config_response: Config = {
max_batch_size: 4,
cancels: [],
types: {
continuous: false,
generator: false,
cancel: false
},
Expand All @@ -448,7 +446,6 @@ export const config_response: Config = {
max_batch_size: 4,
cancels: [],
types: {
continuous: false,
generator: false,
cancel: false
},
Expand Down Expand Up @@ -550,7 +547,6 @@ export const endpoint_info: EndpointInfo<ApiData> = {
}
],
type: {
continuous: false,
generator: false
}
};
Expand Down
1 change: 0 additions & 1 deletion client/js/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,6 @@ export interface Dependency {
}

export interface DependencyTypes {
continuous: boolean;
generator: boolean;
cancel: boolean;
}
Expand Down
6 changes: 0 additions & 6 deletions client/js/src/utils/predict.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,6 @@ export async function predict(
)!;
}

if (dependency?.types.continuous) {
throw new Error(
"Cannot call predict on this function as it may run forever. Use submit instead"
);
}

return new Promise(async (resolve, reject) => {
const app = this.submit(endpoint, data, null, null, true);
let result: unknown;
Expand Down
7 changes: 1 addition & 6 deletions client/python/gradio_client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -453,11 +453,7 @@ def predict(
client.predict(5, "add", 4, api_name="/predict")
>> 9.0
"""
inferred_fn_index = self._infer_fn_index(api_name, fn_index)
if self.endpoints[inferred_fn_index].is_continuous:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we still need this when the Client connects to Spaces running older versions of Gradio?

raise ValueError(
"Cannot call predict on this function as it may run forever. Use submit instead."
)
self._infer_fn_index(api_name, fn_index)
return self.submit(
*args, api_name=api_name, fn_index=fn_index, **kwargs
).result()
Expand Down Expand Up @@ -1061,7 +1057,6 @@ def __init__(
self.parameters_info = self._get_parameters_info()

self.root_url = client.src + "/" if not client.src.endswith("/") else client.src
self.is_continuous = dependency.get("types", {}).get("continuous", False)

# Disallow hitting endpoints that the Gradio app has disabled
self.is_valid = self.api_name is not False
Expand Down
1 change: 0 additions & 1 deletion client/python/gradio_client/compatibility.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ def __init__(self, client: Client, fn_index: int, dependency: dict, *_args):
self.input_component_types = []
self.output_component_types = []
self.root_url = client.src + "/" if not client.src.endswith("/") else client.src
self.is_continuous = dependency.get("types", {}).get("continuous", False)
try:
# Only a real API endpoint if backend_fn is True (so not just a frontend function), serializers are valid,
# and api_name is not False (meaning that the developer has explicitly disabled the API endpoint)
Expand Down
3 changes: 0 additions & 3 deletions client/python/test/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -1387,6 +1387,3 @@ def test_upstream_exceptions(count_generator_demo_exception):
match="The upstream Gradio app has raised an exception but has not enabled verbose error reporting.",
):
client.predict(7, api_name="/count")

with pytest.raises(ValueError, match="Cannot call predict on this function"):
client.predict(5, api_name="/count_forever")
1 change: 1 addition & 0 deletions demo/function_values/run.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: function_values"]}, {"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 random\n", "\n", "countries = [\n", " \"Algeria\", \"Argentina\", \"Australia\", \"Brazil\", \"Canada\", \"China\", \"Democratic Republic of the Congo\", \"Greenland (Denmark)\", \"India\", \"Kazakhstan\", \"Mexico\", \"Mongolia\", \"Peru\", \"Russia\", \"Saudi Arabia\", \"Sudan\", \"United States\"\n", "]\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Row():\n", " count = gr.Slider(1, 10, step=1, label=\"Country Count\")\n", " alpha_order = gr.Checkbox(True, label=\"Alphabetical Order\")\n", "\n", " gr.JSON(lambda count, alpha_order: countries[:count] if alpha_order else countries[-count:], inputs=[count, alpha_order])\n", " timer = gr.Timer(1)\n", " with gr.Row():\n", " gr.Textbox(lambda: random.choice(countries), label=\"Random Country\", every=timer)\n", " gr.Textbox(lambda count: \", \".join(random.sample(countries, count)), inputs=count, label=\"Random Countries\", every=timer)\n", " with gr.Row():\n", " gr.Button(\"Start\").click(lambda: gr.Timer(active=True), None, timer)\n", " gr.Button(\"Stop\").click(lambda: gr.Timer(active=False), None, timer)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
24 changes: 24 additions & 0 deletions demo/function_values/run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import gradio as gr
import random

countries = [
"Algeria", "Argentina", "Australia", "Brazil", "Canada", "China", "Democratic Republic of the Congo", "Greenland (Denmark)", "India", "Kazakhstan", "Mexico", "Mongolia", "Peru", "Russia", "Saudi Arabia", "Sudan", "United States"
]

with gr.Blocks() as demo:
with gr.Row():
count = gr.Slider(1, 10, step=1, label="Country Count")
alpha_order = gr.Checkbox(True, label="Alphabetical Order")

gr.JSON(lambda count, alpha_order: countries[:count] if alpha_order else countries[-count:], inputs=[count, alpha_order])
timer = gr.Timer(1)
with gr.Row():
gr.Textbox(lambda: random.choice(countries), label="Random Country", every=timer)
gr.Textbox(lambda count: ", ".join(random.sample(countries, count)), inputs=count, label="Random Countries", every=timer)
with gr.Row():
gr.Button("Start").click(lambda: gr.Timer(active=True), None, timer)
gr.Button("Stop").click(lambda: gr.Timer(active=False), None, timer)


if __name__ == "__main__":
demo.launch()
1 change: 1 addition & 0 deletions demo/timer/run.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: timer"]}, {"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 random\n", "import time\n", "\n", "with gr.Blocks() as demo:\n", " timer = gr.Timer(1)\n", " timestamp = gr.Number(label=\"Time\")\n", " timer.tick(lambda: round(time.time()), outputs=timestamp)\n", " gr.Number(lambda: round(time.time()), label=\"Time 2\", every=1)\n", "\n", " with gr.Row():\n", " timestamp_3 = gr.Number()\n", " start_btn = gr.Button(\"Start\")\n", " stop_btn = gr.Button(\"Stop\")\n", "\n", " time_3 = start_btn.click(lambda: round(time.time()), None, timestamp_3, every=1)\n", " stop_btn.click(fn=None, cancels=time_3)\n", "\n", " with gr.Row():\n", " min = gr.Number(1, label=\"Min\")\n", " max = gr.Number(10, label=\"Max\")\n", " timer2 = gr.Timer(1)\n", " number = gr.Number(lambda a, b: random.randint(a, b), inputs=[min, max], every=timer2, label=\"Random Number\")\n", " with gr.Row():\n", " gr.Button(\"Start\").click(lambda: gr.Timer(active=True), None, timer2)\n", " gr.Button(\"Stop\").click(lambda: gr.Timer(active=False), None, timer2)\n", " gr.Button(\"Go Fast\").click(lambda: 0.2, None, timer2)\n", " gr.Button(\"Go Slow\").click(lambda: 2, None, timer2)\n", " \n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
31 changes: 31 additions & 0 deletions demo/timer/run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import gradio as gr
import random
import time

with gr.Blocks() as demo:
timer = gr.Timer(1)
timestamp = gr.Number(label="Time")
timer.tick(lambda: round(time.time()), outputs=timestamp)
gr.Number(lambda: round(time.time()), label="Time 2", every=1)

with gr.Row():
timestamp_3 = gr.Number()
start_btn = gr.Button("Start")
stop_btn = gr.Button("Stop")

time_3 = start_btn.click(lambda: round(time.time()), None, timestamp_3, every=1)
stop_btn.click(fn=None, cancels=time_3)

with gr.Row():
min = gr.Number(1, label="Min")
max = gr.Number(10, label="Max")
timer2 = gr.Timer(1)
number = gr.Number(lambda a, b: random.randint(a, b), inputs=[min, max], every=timer2, label="Random Number")
with gr.Row():
gr.Button("Start").click(lambda: gr.Timer(active=True), None, timer2)
gr.Button("Stop").click(lambda: gr.Timer(active=False), None, timer2)
gr.Button("Go Fast").click(lambda: 0.2, None, timer2)
gr.Button("Go Slow").click(lambda: 2, None, timer2)

if __name__ == "__main__":
demo.launch()
1 change: 1 addition & 0 deletions gradio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
State,
Text,
Textbox,
Timer,
UploadButton,
Video,
component,
Expand Down
15 changes: 11 additions & 4 deletions gradio/_simple_templates/simpledropdown.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
from __future__ import annotations

import warnings
from typing import Any, Callable
from typing import TYPE_CHECKING, Any, Callable

from gradio.components.base import FormComponent
from gradio.components.base import Component, FormComponent
from gradio.events import Events

if TYPE_CHECKING:
from gradio.components import Timer


class SimpleDropdown(FormComponent):
"""
Expand All @@ -21,7 +24,8 @@ def __init__(
value: str | int | float | Callable | None = None,
label: str | None = None,
info: str | None = None,
every: float | None = None,
every: Timer | float | None = None,
inputs: Component | list[Component] | set[Component] | None = None,
show_label: bool | None = None,
scale: int | None = None,
min_width: int = 160,
Expand All @@ -38,7 +42,9 @@ def __init__(
value: default value selected in dropdown. If None, no value is selected by default. If callable, the function will be called whenever the app loads to set the initial value of the component.
label: component name in interface.
info: additional component description.
every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
every: Continously calls `value` to recalculate it if `value` is a function (has no effect otherwise). Can provide a Timer whose tick resets `value`, or a float that provides the regular interval for the reset Timer.
inputs: Components that are used as inputs to calculate `value` if `value` is a function (has no effect otherwise). `value` is recalculated any time the inputs change.
inputs: Components that are used as inputs to calculate `value` if `value` is a function (has no effect otherwise). `value` is recalculated any time the inputs change.
show_label: if True, will display label.
scale: relative size compared to adjacent Components. For example if Components A and B are in a Row, and A has scale=2, and B has scale=1, A will be twice as wide as B. Should be an integer. scale applies in Rows, and to top-level Components in Blocks where fill_height=True.
min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
Expand All @@ -58,6 +64,7 @@ def __init__(
label=label,
info=info,
every=every,
inputs=inputs,
show_label=show_label,
scale=scale,
min_width=min_width,
Expand Down
12 changes: 9 additions & 3 deletions gradio/_simple_templates/simpleimage.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from __future__ import annotations

from pathlib import Path
from typing import Any
from typing import TYPE_CHECKING, Any

from gradio_client import handle_file
from gradio_client.documentation import document
Expand All @@ -12,6 +12,9 @@
from gradio.data_classes import FileData
from gradio.events import Events

if TYPE_CHECKING:
from gradio.components import Timer


@document()
class SimpleImage(Component):
Expand All @@ -32,7 +35,8 @@ def __init__(
value: str | None = None,
*,
label: str | None = None,
every: float | None = None,
every: Timer | float | None = None,
inputs: Component | list[Component] | set[Component] | None = None,
show_label: bool | None = None,
show_download_button: bool = True,
container: bool = True,
Expand All @@ -49,7 +53,8 @@ def __init__(
Parameters:
value: A path or URL for the default value that SimpleImage component is going to take. If callable, the function will be called whenever the app loads to set the initial value of the component.
label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. Queue must be enabled. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
every: Continously calls `value` to recalculate it if `value` is a function (has no effect otherwise). Can provide a Timer whose tick resets `value`, or a float that provides the regular interval for the reset Timer.
inputs: Components that are used as inputs to calculate `value` if `value` is a function (has no effect otherwise). `value` is recalculated any time the inputs change.
show_label: if True, will display label.
show_download_button: If True, will display button to download image.
container: If True, will place the component in a container - providing some extra padding around the border.
Expand All @@ -66,6 +71,7 @@ def __init__(
super().__init__(
label=label,
every=every,
inputs=inputs,
show_label=show_label,
container=container,
scale=scale,
Expand Down
14 changes: 10 additions & 4 deletions gradio/_simple_templates/simpletextbox.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
from __future__ import annotations

from typing import Any, Callable
from typing import TYPE_CHECKING, Any, Callable

from gradio.components.base import FormComponent
from gradio.components.base import Component, FormComponent
from gradio.events import Events

if TYPE_CHECKING:
from gradio.components import Timer


class SimpleTextbox(FormComponent):
"""
Expand All @@ -23,7 +26,8 @@ def __init__(
*,
placeholder: str | None = None,
label: str | None = None,
every: float | None = None,
every: Timer | float | None = None,
inputs: Component | list[Component] | set[Component] | None = None,
show_label: bool | None = None,
scale: int | None = None,
min_width: int = 160,
Expand All @@ -40,7 +44,8 @@ def __init__(
value: default text to provide in textbox. If callable, the function will be called whenever the app loads to set the initial value of the component.
placeholder: placeholder hint to provide behind textbox.
label: component name in interface.
every: If `value` is a callable, run the function 'every' number of seconds while the client connection is open. Has no effect otherwise. The event can be accessed (e.g. to cancel it) via this component's .load_event attribute.
every: Continously calls `value` to recalculate it if `value` is a function (has no effect otherwise). Can provide a Timer whose tick resets `value`, or a float that provides the regular interval for the reset Timer.
inputs: Components that are used as inputs to calculate `value` if `value` is a function (has no effect otherwise). `value` is recalculated any time the inputs change.
show_label: if True, will display label.
scale: relative size compared to adjacent Components. For example if Components A and B are in a Row, and A has scale=2, and B has scale=1, A will be twice as wide as B. Should be an integer. scale applies in Rows, and to top-level Components in Blocks where fill_height=True.
min_width: minimum pixel width, will wrap if not sufficient screen space to satisfy this value. If a certain scale value results in this Component being narrower than min_width, the min_width parameter will be respected first.
Expand All @@ -57,6 +62,7 @@ def __init__(
super().__init__(
label=label,
every=every,
inputs=inputs,
show_label=show_label,
scale=scale,
min_width=min_width,
Expand Down
Loading