mirror of
https://github.com/gradio-app/gradio.git
synced 2025-02-17 11:29:58 +08:00
Fix bugs with gr.update (#2157)
* Use void to reset to original state * Cosmetic fixes to comments * Use keyword * Set default value to no value * Fix test * Make private * Improve comment on _Keywords.NO_VALUE Improve comment Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Use NO_VALUE in `test_blocks` Co-authored-by: Abubakar Abid <abubakar@huggingface.co> * Update test/test_blocks.py Use NO_VALUE in tests Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: Abubakar Abid <abubakar@huggingface.co>
This commit is contained in:
parent
3464673064
commit
6c1bfbb42c
@ -18,7 +18,7 @@ from demos.kitchen_sink_random.constants import (
|
||||
|
||||
components = [
|
||||
gr.Textbox(value=lambda: datetime.now(), label="Current Time"),
|
||||
gr.Number(value=lambda: random.random(), label="Ranom Percentage"),
|
||||
gr.Number(value=lambda: random.random(), label="Random Percentage"),
|
||||
gr.Slider(minimum=-1, maximum=1, randomize=True, label="Slider with randomize"),
|
||||
gr.Slider(
|
||||
minimum=0,
|
||||
@ -88,11 +88,23 @@ with gr.Blocks() as demo:
|
||||
for component in components:
|
||||
component.render()
|
||||
reset = gr.Button(value="Reset")
|
||||
hide = gr.Button(value="Hide")
|
||||
reveal = gr.Button(value="Reveal")
|
||||
reset.click(
|
||||
lambda: [c.update(value=None) for c in components],
|
||||
inputs=[],
|
||||
outputs=components,
|
||||
)
|
||||
hide.click(
|
||||
lambda: [c.update(visible=False) for c in components],
|
||||
inputs=[],
|
||||
outputs=components
|
||||
)
|
||||
reveal.click(
|
||||
lambda: [c.update(visible=True) for c in components],
|
||||
inputs=[],
|
||||
outputs=components
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -7,7 +7,6 @@ import os
|
||||
import pkgutil
|
||||
import random
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
import warnings
|
||||
import webbrowser
|
||||
@ -35,7 +34,6 @@ from gradio.documentation import (
|
||||
document_component_api,
|
||||
set_documentation_group,
|
||||
)
|
||||
from gradio.exceptions import Error
|
||||
from gradio.utils import component_or_layout_class, delete_none
|
||||
|
||||
set_documentation_group("blocks")
|
||||
@ -669,6 +667,13 @@ class Blocks(BlockContext):
|
||||
prediction_value = block.__class__.update(
|
||||
**prediction_value
|
||||
)
|
||||
# If the prediction is the default (NO_VALUE) enum then the user did
|
||||
# not specify a value for the 'value' key and we can get rid of it
|
||||
if (
|
||||
prediction_value.get("value")
|
||||
== components._Keywords.NO_VALUE
|
||||
):
|
||||
prediction_value.pop("value")
|
||||
prediction_value = delete_none(prediction_value)
|
||||
if "value" in prediction_value:
|
||||
prediction_value["value"] = block.postprocess(
|
||||
|
@ -15,6 +15,7 @@ import tempfile
|
||||
import uuid
|
||||
import warnings
|
||||
from copy import deepcopy
|
||||
from enum import Enum
|
||||
from pathlib import Path
|
||||
from types import ModuleType
|
||||
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple
|
||||
@ -59,6 +60,10 @@ from gradio.utils import component_or_layout_class
|
||||
set_documentation_group("component")
|
||||
|
||||
|
||||
class _Keywords(Enum):
|
||||
NO_VALUE = "NO_VALUE" # Used as a sentinel to determine if nothing is provided as a argument for `value` in `Component.update()`
|
||||
|
||||
|
||||
class Component(Block):
|
||||
"""
|
||||
A base class for defining the methods that all gradio components should have.
|
||||
@ -286,7 +291,7 @@ class Textbox(Changeable, Submittable, IOComponent, SimpleSerializable, FormComp
|
||||
|
||||
@staticmethod
|
||||
def update(
|
||||
value: Optional[str] = None,
|
||||
value: Optional[str] = _Keywords.NO_VALUE,
|
||||
lines: Optional[int] = None,
|
||||
max_lines: Optional[int] = None,
|
||||
placeholder: Optional[str] = None,
|
||||
@ -465,7 +470,7 @@ class Number(Changeable, Submittable, IOComponent, SimpleSerializable, FormCompo
|
||||
|
||||
@staticmethod
|
||||
def update(
|
||||
value: Optional[float] = None,
|
||||
value: Optional[float] = _Keywords.NO_VALUE,
|
||||
label: Optional[str] = None,
|
||||
show_label: Optional[bool] = None,
|
||||
interactive: Optional[bool] = None,
|
||||
@ -637,7 +642,7 @@ class Slider(Changeable, IOComponent, SimpleSerializable, FormComponent):
|
||||
|
||||
@staticmethod
|
||||
def update(
|
||||
value: Optional[float] = None,
|
||||
value: Optional[float] = _Keywords.NO_VALUE,
|
||||
minimum: Optional[float] = None,
|
||||
maximum: Optional[float] = None,
|
||||
step: Optional[float] = None,
|
||||
@ -763,7 +768,7 @@ class Checkbox(Changeable, IOComponent, SimpleSerializable, FormComponent):
|
||||
|
||||
@staticmethod
|
||||
def update(
|
||||
value: Optional[bool] = None,
|
||||
value: Optional[bool] = _Keywords.NO_VALUE,
|
||||
label: Optional[str] = None,
|
||||
show_label: Optional[bool] = None,
|
||||
interactive: Optional[bool] = None,
|
||||
@ -861,7 +866,7 @@ class CheckboxGroup(Changeable, IOComponent, SimpleSerializable, FormComponent):
|
||||
|
||||
@staticmethod
|
||||
def update(
|
||||
value: Optional[List[str]] = None,
|
||||
value: Optional[List[str]] = _Keywords.NO_VALUE,
|
||||
choices: Optional[List[str]] = None,
|
||||
label: Optional[str] = None,
|
||||
show_label: Optional[bool] = None,
|
||||
@ -1024,7 +1029,7 @@ class Radio(Changeable, IOComponent, SimpleSerializable, FormComponent):
|
||||
|
||||
@staticmethod
|
||||
def update(
|
||||
value: Optional[Any] = None,
|
||||
value: Optional[Any] = _Keywords.NO_VALUE,
|
||||
choices: Optional[List[str]] = None,
|
||||
label: Optional[str] = None,
|
||||
show_label: Optional[bool] = None,
|
||||
@ -1257,7 +1262,7 @@ class Image(Editable, Clearable, Changeable, Streamable, IOComponent, ImgSeriali
|
||||
|
||||
@staticmethod
|
||||
def update(
|
||||
value: Optional[Any] = None,
|
||||
value: Optional[Any] = _Keywords.NO_VALUE,
|
||||
label: Optional[str] = None,
|
||||
show_label: Optional[bool] = None,
|
||||
interactive: Optional[bool] = None,
|
||||
@ -1581,7 +1586,7 @@ class Video(Changeable, Clearable, Playable, IOComponent, FileSerializable):
|
||||
|
||||
@staticmethod
|
||||
def update(
|
||||
value: Optional[Any] = None,
|
||||
value: Optional[Any] = _Keywords.NO_VALUE,
|
||||
source: Optional[str] = None,
|
||||
label: Optional[str] = None,
|
||||
show_label: Optional[bool] = None,
|
||||
@ -1768,7 +1773,7 @@ class Audio(Changeable, Clearable, Playable, Streamable, IOComponent, FileSerial
|
||||
|
||||
@staticmethod
|
||||
def update(
|
||||
value: Optional[Any] = None,
|
||||
value: Optional[Any] = _Keywords.NO_VALUE,
|
||||
source: Optional[str] = None,
|
||||
label: Optional[str] = None,
|
||||
show_label: Optional[bool] = None,
|
||||
@ -2046,7 +2051,7 @@ class File(Changeable, Clearable, IOComponent, FileSerializable):
|
||||
|
||||
@staticmethod
|
||||
def update(
|
||||
value: Optional[Any] = None,
|
||||
value: Optional[Any] = _Keywords.NO_VALUE,
|
||||
label: Optional[str] = None,
|
||||
show_label: Optional[bool] = None,
|
||||
interactive: Optional[bool] = None,
|
||||
@ -2282,7 +2287,7 @@ class Dataframe(Changeable, IOComponent, JSONSerializable):
|
||||
|
||||
@staticmethod
|
||||
def update(
|
||||
value: Optional[Any] = None,
|
||||
value: Optional[Any] = _Keywords.NO_VALUE,
|
||||
max_rows: Optional[int] = None,
|
||||
max_cols: Optional[str] = None,
|
||||
label: Optional[str] = None,
|
||||
@ -2494,7 +2499,7 @@ class Timeseries(Changeable, IOComponent, JSONSerializable):
|
||||
|
||||
@staticmethod
|
||||
def update(
|
||||
value: Optional[Any] = None,
|
||||
value: Optional[Any] = _Keywords.NO_VALUE,
|
||||
colors: Optional[List[str]] = None,
|
||||
label: Optional[str] = None,
|
||||
show_label: Optional[bool] = None,
|
||||
@ -2644,7 +2649,7 @@ class Button(Clickable, IOComponent, SimpleSerializable):
|
||||
|
||||
@staticmethod
|
||||
def update(
|
||||
value: Optional[str] = None,
|
||||
value: Optional[str] = _Keywords.NO_VALUE,
|
||||
variant: Optional[str] = None,
|
||||
visible: Optional[bool] = None,
|
||||
):
|
||||
@ -2732,7 +2737,7 @@ class ColorPicker(Changeable, Submittable, IOComponent, SimpleSerializable):
|
||||
|
||||
@staticmethod
|
||||
def update(
|
||||
value: Optional[str] = None,
|
||||
value: Optional[str] = _Keywords.NO_VALUE,
|
||||
label: Optional[str] = None,
|
||||
show_label: Optional[bool] = None,
|
||||
visible: Optional[bool] = None,
|
||||
@ -2867,7 +2872,7 @@ class Label(Changeable, IOComponent, JSONSerializable):
|
||||
|
||||
@staticmethod
|
||||
def update(
|
||||
value: Optional[Dict[str, float] | str | float] = None,
|
||||
value: Optional[Dict[str, float] | str | float] = _Keywords.NO_VALUE,
|
||||
label: Optional[str] = None,
|
||||
show_label: Optional[bool] = None,
|
||||
visible: Optional[bool] = None,
|
||||
@ -2957,7 +2962,9 @@ class HighlightedText(Changeable, IOComponent, JSONSerializable):
|
||||
|
||||
@staticmethod
|
||||
def update(
|
||||
value: Optional[List[Tuple[str, str | float | None]] | Dict] = None,
|
||||
value: Optional[
|
||||
List[Tuple[str, str | float | None]] | Dict
|
||||
] = _Keywords.NO_VALUE,
|
||||
color_map: Optional[Dict[str, str]] = None,
|
||||
show_legend: Optional[bool] = None,
|
||||
label: Optional[str] = None,
|
||||
@ -3086,7 +3093,7 @@ class JSON(Changeable, IOComponent, JSONSerializable):
|
||||
|
||||
@staticmethod
|
||||
def update(
|
||||
value: Optional[Any] = None,
|
||||
value: Optional[Any] = _Keywords.NO_VALUE,
|
||||
label: Optional[str] = None,
|
||||
show_label: Optional[bool] = None,
|
||||
visible: Optional[bool] = None,
|
||||
@ -3171,7 +3178,7 @@ class HTML(Changeable, IOComponent, SimpleSerializable):
|
||||
|
||||
@staticmethod
|
||||
def update(
|
||||
value: Optional[Any] = None,
|
||||
value: Optional[Any] = _Keywords.NO_VALUE,
|
||||
label: Optional[str] = None,
|
||||
show_label: Optional[bool] = None,
|
||||
visible: Optional[bool] = None,
|
||||
@ -3228,7 +3235,7 @@ class Gallery(IOComponent):
|
||||
|
||||
@staticmethod
|
||||
def update(
|
||||
value: Optional[Any] = None,
|
||||
value: Optional[Any] = _Keywords.NO_VALUE,
|
||||
label: Optional[str] = None,
|
||||
show_label: Optional[bool] = None,
|
||||
visible: Optional[bool] = None,
|
||||
@ -3361,7 +3368,7 @@ class Carousel(IOComponent, Changeable):
|
||||
|
||||
@staticmethod
|
||||
def update(
|
||||
value: Optional[Any] = None,
|
||||
value: Optional[Any] = _Keywords.NO_VALUE,
|
||||
label: Optional[str] = None,
|
||||
show_label: Optional[bool] = None,
|
||||
visible: Optional[bool] = None,
|
||||
@ -3452,7 +3459,7 @@ class Chatbot(Changeable, IOComponent, JSONSerializable):
|
||||
|
||||
@staticmethod
|
||||
def update(
|
||||
value: Optional[Any] = None,
|
||||
value: Optional[Any] = _Keywords.NO_VALUE,
|
||||
color_map: Optional[Tuple[str, str]] = None,
|
||||
label: Optional[str] = None,
|
||||
show_label: Optional[bool] = None,
|
||||
@ -3551,7 +3558,7 @@ class Model3D(Changeable, Editable, Clearable, IOComponent, FileSerializable):
|
||||
|
||||
@staticmethod
|
||||
def update(
|
||||
value: Optional[Any] = None,
|
||||
value: Optional[Any] = _Keywords.NO_VALUE,
|
||||
label: Optional[str] = None,
|
||||
show_label: Optional[bool] = None,
|
||||
visible: Optional[bool] = None,
|
||||
@ -3668,7 +3675,7 @@ class Plot(Changeable, Clearable, IOComponent, JSONSerializable):
|
||||
|
||||
@staticmethod
|
||||
def update(
|
||||
value: Optional[Any] = None,
|
||||
value: Optional[Any] = _Keywords.NO_VALUE,
|
||||
label: Optional[str] = None,
|
||||
show_label: Optional[bool] = None,
|
||||
visible: Optional[bool] = None,
|
||||
@ -3756,7 +3763,7 @@ class Markdown(IOComponent, Changeable, SimpleSerializable):
|
||||
|
||||
@staticmethod
|
||||
def update(
|
||||
value: Optional[Any] = None,
|
||||
value: Optional[Any] = _Keywords.NO_VALUE,
|
||||
visible: Optional[bool] = None,
|
||||
):
|
||||
updated_config = {
|
||||
@ -3832,7 +3839,7 @@ class Dataset(Clickable, Component):
|
||||
|
||||
@staticmethod
|
||||
def update(
|
||||
samples: Optional[Any] = None,
|
||||
samples: Optional[Any] = _Keywords.NO_VALUE,
|
||||
visible: Optional[bool] = None,
|
||||
label: Optional[str] = None,
|
||||
):
|
||||
@ -3905,7 +3912,7 @@ class Interpretation(Component):
|
||||
|
||||
@staticmethod
|
||||
def update(
|
||||
value: Optional[Any] = None,
|
||||
value: Optional[Any] = _Keywords.NO_VALUE,
|
||||
visible: Optional[bool] = None,
|
||||
):
|
||||
return {
|
||||
@ -3949,7 +3956,7 @@ class StatusTracker(Component):
|
||||
|
||||
@staticmethod
|
||||
def update(
|
||||
value: Optional[Any] = None,
|
||||
value: Optional[Any] = _Keywords.NO_VALUE,
|
||||
visible: Optional[bool] = None,
|
||||
):
|
||||
return {
|
||||
|
@ -46,12 +46,12 @@ XRAY_CONFIG = {
|
||||
"image_mode": "RGB",
|
||||
"source": "upload",
|
||||
"tool": "editor",
|
||||
"value": None,
|
||||
"streaming": False,
|
||||
"mirror_webcam": True,
|
||||
"show_label": True,
|
||||
"name": "image",
|
||||
"visible": True,
|
||||
"value": None,
|
||||
"style": {},
|
||||
},
|
||||
},
|
||||
@ -59,10 +59,10 @@ XRAY_CONFIG = {
|
||||
"id": 29,
|
||||
"type": "json",
|
||||
"props": {
|
||||
"value": None,
|
||||
"show_label": True,
|
||||
"name": "json",
|
||||
"visible": True,
|
||||
"value": None,
|
||||
"style": {},
|
||||
},
|
||||
},
|
||||
@ -94,24 +94,24 @@ XRAY_CONFIG = {
|
||||
"image_mode": "RGB",
|
||||
"source": "upload",
|
||||
"tool": "editor",
|
||||
"value": None,
|
||||
"streaming": False,
|
||||
"mirror_webcam": True,
|
||||
"show_label": True,
|
||||
"name": "image",
|
||||
"visible": True,
|
||||
"style": {},
|
||||
"value": None,
|
||||
},
|
||||
},
|
||||
{
|
||||
"id": 34,
|
||||
"type": "json",
|
||||
"props": {
|
||||
"value": None,
|
||||
"show_label": True,
|
||||
"name": "json",
|
||||
"visible": True,
|
||||
"style": {},
|
||||
"value": None,
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -279,6 +279,7 @@ XRAY_CONFIG_DIFF_IDS = {
|
||||
"type": "image",
|
||||
"props": {
|
||||
"image_mode": "RGB",
|
||||
"value": None,
|
||||
"source": "upload",
|
||||
"tool": "editor",
|
||||
"streaming": False,
|
||||
@ -286,7 +287,6 @@ XRAY_CONFIG_DIFF_IDS = {
|
||||
"show_label": True,
|
||||
"name": "image",
|
||||
"visible": True,
|
||||
"value": None,
|
||||
"style": {},
|
||||
},
|
||||
},
|
||||
@ -295,10 +295,10 @@ XRAY_CONFIG_DIFF_IDS = {
|
||||
"type": "json",
|
||||
"props": {
|
||||
"show_label": True,
|
||||
"value": None,
|
||||
"name": "json",
|
||||
"visible": True,
|
||||
"style": {},
|
||||
"value": None,
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -349,8 +349,8 @@ XRAY_CONFIG_DIFF_IDS = {
|
||||
"show_label": True,
|
||||
"name": "json",
|
||||
"visible": True,
|
||||
"value": None,
|
||||
"style": {},
|
||||
"value": None,
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -525,7 +525,6 @@ XRAY_CONFIG_WITH_MISTAKE = {
|
||||
"id": 7,
|
||||
"type": "json",
|
||||
"props": {
|
||||
"value": None,
|
||||
"name": "json",
|
||||
"style": {},
|
||||
},
|
||||
@ -572,7 +571,6 @@ XRAY_CONFIG_WITH_MISTAKE = {
|
||||
"id": 12,
|
||||
"type": "json",
|
||||
"props": {
|
||||
"value": None,
|
||||
"name": "json",
|
||||
"style": {},
|
||||
},
|
||||
|
@ -13,6 +13,7 @@ def copy_all_demos(source_dir: str, dest_dir: str):
|
||||
"blocks_layout",
|
||||
"blocks_mask",
|
||||
"blocks_multiple_event_triggers",
|
||||
"blocks_update",
|
||||
"calculator",
|
||||
"fake_gan",
|
||||
"gender_sentence_default_interpretation",
|
||||
|
@ -266,5 +266,20 @@ def test_blocks_do_not_filter_none_values_from_updates(io_components):
|
||||
)
|
||||
|
||||
|
||||
def test_blocks_does_not_replace_keyword_literal():
|
||||
|
||||
with gr.Blocks() as demo:
|
||||
text = gr.Textbox()
|
||||
btn = gr.Button(value="Reset")
|
||||
btn.click(
|
||||
lambda: gr.update(value="NO_VALUE"),
|
||||
inputs=[],
|
||||
outputs=text,
|
||||
)
|
||||
|
||||
output = demo.postprocess_data(0, gr.update(value="NO_VALUE"), state=None)
|
||||
assert output[0]["value"] == "NO_VALUE"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
Loading…
Reference in New Issue
Block a user