Skip to content

Commit d393a4a

Browse files
Fix type hints for render and on (#8429)
* type hint * add changeset * Use union * type check * lint * add changeset --------- Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
1 parent 341844f commit d393a4a

3 files changed

Lines changed: 67 additions & 17 deletions

File tree

.changeset/breezy-bottles-hide.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"gradio": patch
3+
---
4+
5+
feat:Fix type hints for render and on

gradio/events.py

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,17 @@
55

66
import dataclasses
77
from functools import partial, wraps
8-
from typing import TYPE_CHECKING, Any, Callable, Literal, Sequence
8+
from typing import (
9+
TYPE_CHECKING,
10+
Any,
11+
Callable,
12+
Dict,
13+
List,
14+
Literal,
15+
Sequence,
16+
Union,
17+
cast,
18+
)
919

1020
from gradio_client.documentation import document
1121
from jinja2 import Template
@@ -145,6 +155,32 @@ class EventListenerMethod:
145155
event_name: str
146156

147157

158+
if TYPE_CHECKING:
159+
EventListenerCallable = Callable[
160+
[
161+
Union[Callable, None],
162+
Union[Component, Sequence[Component], None],
163+
Union[Block, Sequence[Block], Sequence[Component], Component, None],
164+
Union[str, None, Literal[False]],
165+
bool,
166+
Literal["full", "minimal", "hidden"],
167+
Union[bool, None],
168+
bool,
169+
int,
170+
bool,
171+
bool,
172+
Union[Dict[str, Any], List[Dict[str, Any]], None],
173+
Union[float, None],
174+
Union[Literal["once", "multiple", "always_last"], None],
175+
Union[str, None],
176+
Union[int, None, Literal["default"]],
177+
Union[str, None],
178+
bool,
179+
],
180+
Dependency,
181+
]
182+
183+
148184
class EventListener(str):
149185
def __new__(cls, event_name, *_args, **_kwargs):
150186
return super().__new__(cls, event_name)
@@ -331,7 +367,7 @@ def inner(*args, **kwargs):
331367

332368

333369
def on(
334-
triggers: Sequence[Any] | Any | None = None,
370+
triggers: Sequence[EventListenerCallable] | EventListenerCallable | None = None,
335371
fn: Callable | None | Literal["decorator"] = "decorator",
336372
inputs: Component | list[Component] | set[Component] | None = None,
337373
outputs: Block | list[Block] | list[Component] | None = None,
@@ -376,8 +412,10 @@ def on(
376412
"""
377413
from gradio.components.base import Component
378414

379-
if isinstance(triggers, EventListener):
380-
triggers = [triggers]
415+
triggers_typed = cast(EventListener, triggers)
416+
417+
if isinstance(triggers_typed, EventListener):
418+
triggers_typed = [triggers_typed]
381419
if isinstance(inputs, Component):
382420
inputs = [inputs]
383421

@@ -418,18 +456,18 @@ def inner(*args, **kwargs):
418456
if root_block is None:
419457
raise Exception("Cannot call on() outside of a gradio.Blocks context.")
420458
if triggers is None:
421-
triggers = (
459+
methods = (
422460
[EventListenerMethod(input, "change") for input in inputs]
423461
if inputs is not None
424462
else []
425463
) # type: ignore
426464
else:
427-
triggers = [
428-
EventListenerMethod(t.__self__ if t.has_trigger else None, t.event_name)
429-
for t in triggers
430-
] # type: ignore
465+
methods = [
466+
EventListenerMethod(t.__self__ if t.has_trigger else None, t.event_name) # type: ignore
467+
for t in triggers_typed
468+
]
431469
dep, dep_index = root_block.set_event_trigger(
432-
triggers,
470+
methods,
433471
fn,
434472
inputs,
435473
outputs,
@@ -448,7 +486,7 @@ def inner(*args, **kwargs):
448486
show_api=show_api,
449487
trigger_mode=trigger_mode,
450488
)
451-
set_cancel_events(triggers, cancels)
489+
set_cancel_events(methods, cancels)
452490
return Dependency(None, dep.get_config(), dep_index, fn)
453491

454492

gradio/renderable.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from __future__ import annotations
22

3-
from typing import Callable, Literal
3+
from typing import TYPE_CHECKING, Callable, List, Literal, Sequence, Union, cast
44

55
from gradio_client.documentation import document
66

@@ -10,6 +10,9 @@
1010
from gradio.events import EventListener, EventListenerMethod
1111
from gradio.layouts import Column, Row
1212

13+
if TYPE_CHECKING:
14+
from gradio.events import EventListenerCallable
15+
1316

1417
class Renderable:
1518
def __init__(
@@ -76,8 +79,8 @@ def apply(self, *args, **kwargs):
7679

7780
@document()
7881
def render(
79-
inputs: list[Component] | None = None,
80-
triggers: list[EventListener] | EventListener | None = None,
82+
inputs: list[Component] | Component | None = None,
83+
triggers: Sequence[EventListenerCallable] | EventListenerCallable | None = None,
8184
*,
8285
queue: bool = True,
8386
trigger_mode: Literal["once", "multiple", "always_last"] | None = "always_last",
@@ -116,23 +119,27 @@ def show_split(text):
116119
btn = gr.Button("Clear")
117120
btn.click(lambda: gr.Textbox(value=""), None, text)
118121
"""
122+
new_triggers = cast(Union[List[EventListener], EventListener, None], triggers)
123+
119124
if Context.root_block is None:
120125
raise ValueError("Reactive render must be inside a Blocks context.")
121126

122127
inputs = (
123128
[inputs] if isinstance(inputs, Component) else [] if inputs is None else inputs
124129
)
125130
_triggers: list[tuple[Block | None, str]] = []
126-
if triggers is None:
131+
if new_triggers is None:
127132
_triggers = [(Context.root_block, "load")]
128133
for input in inputs:
129134
if hasattr(input, "change"):
130135
_triggers.append((input, "change"))
131136
else:
132-
triggers = [triggers] if isinstance(triggers, EventListener) else triggers
137+
new_triggers = (
138+
[new_triggers] if isinstance(new_triggers, EventListener) else new_triggers
139+
)
133140
_triggers = [
134141
(getattr(t, "__self__", None) if t.has_trigger else None, t.event_name)
135-
for t in triggers
142+
for t in new_triggers
136143
]
137144

138145
def wrapper_function(fn):

0 commit comments

Comments
 (0)