Skip to content

Commit

Permalink
Refactor example_inputs(), separating its logic into two separate m…
Browse files Browse the repository at this point in the history
…ethods: `example_payload()` and `example_value()` (#7620)

* fix

* lint

* add changeset

* add changeset

* example

* checkbox

* fix, add test

* fixes

* changes

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
  • Loading branch information
abidlabs and gradio-pr-bot committed Mar 6, 2024
1 parent d8636bb commit 1a4b089
Show file tree
Hide file tree
Showing 49 changed files with 329 additions and 78 deletions.
5 changes: 5 additions & 0 deletions .changeset/itchy-wombats-end.md
@@ -0,0 +1,5 @@
---
"gradio": patch
---

feat:Refactor `example_inputs()`, separating its logic into two separate methods: `example_payload()` and `example_value()`
5 changes: 4 additions & 1 deletion gradio/_simple_templates/simpledropdown.py
Expand Up @@ -73,7 +73,10 @@ def api_info(self) -> dict[str, Any]:
"enum": [c[1] for c in self.choices],
}

def example_inputs(self) -> Any:
def example_payload(self) -> Any:
return self.choices[0][1] if self.choices else None

def example_value(self) -> Any:
return self.choices[0][1] if self.choices else None

def preprocess(self, payload: str | int | float | None) -> str | int | float | None:
Expand Down
5 changes: 4 additions & 1 deletion gradio/_simple_templates/simpleimage.py
Expand Up @@ -97,5 +97,8 @@ def postprocess(self, value: str | Path | None) -> FileData | None:
return None
return FileData(path=str(value), orig_name=Path(value).name)

def example_inputs(self) -> Any:
def example_payload(self) -> Any:
return "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png"

def example_value(self) -> Any:
return "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png"
5 changes: 4 additions & 1 deletion gradio/_simple_templates/simpletextbox.py
Expand Up @@ -87,5 +87,8 @@ def postprocess(self, value: str | None) -> str | None:
def api_info(self) -> dict[str, Any]:
return {"type": "string"}

def example_inputs(self) -> Any:
def example_payload(self) -> Any:
return "Hello!!"

def example_value(self) -> Any:
return "Hello!!"
3 changes: 3 additions & 0 deletions gradio/blocks.py
Expand Up @@ -1776,6 +1776,9 @@ def get_layout(block):

if not block.skip_api:
block_config["api_info"] = block.api_info() # type: ignore
# .example_inputs() has been renamed .example_payload() but
# we use the old name for backwards compatibility with custom components
# created on Gradio 4.20.0 or earlier
block_config["example_inputs"] = block.example_inputs() # type: ignore
config["components"].append(block_config)
config["dependencies"] = self.dependencies
Expand Down
4 changes: 2 additions & 2 deletions gradio/cli/commands/components/_create_utils.py
Expand Up @@ -18,7 +18,7 @@ def _in_test_dir():


default_demo_code = """
example = {name}().example_inputs()
example = {name}().example_value()
demo = gr.Interface(
lambda x:x,
Expand All @@ -29,7 +29,7 @@ def _in_test_dir():
"""

static_only_demo_code = """
example = {name}().example_inputs()
example = {name}().example_value()
with gr.Blocks() as demo:
with gr.Row():
Expand Down
20 changes: 17 additions & 3 deletions gradio/components/annotated_image.py
Expand Up @@ -4,6 +4,7 @@

from typing import Any, List

import gradio_client.utils as client_utils
import numpy as np
import PIL.Image
from gradio_client.documentation import document
Expand Down Expand Up @@ -103,7 +104,7 @@ def preprocess(
) -> tuple[str, list[tuple[str, str]]] | None:
"""
Parameters:
payload: Tuple of base image and list of annotations.
payload: Dict of base image and list of annotations.
Returns:
Passes its value as a `tuple` consisting of a `str` filepath to a base image and `list` of annotations. Each annotation itself is `tuple` of a mask (as a `str` filepath to image) and a `str` label.
"""
Expand Down Expand Up @@ -131,6 +132,10 @@ def postprocess(
return None
base_img = value[0]
if isinstance(base_img, str):
if client_utils.is_http_url_like(base_img):
base_img = processing_utils.save_url_to_cache(
base_img, cache_dir=self.GRADIO_CACHE
)
base_img_path = base_img
base_img = np.array(PIL.Image.open(base_img))
elif isinstance(base_img, np.ndarray):
Expand Down Expand Up @@ -198,5 +203,14 @@ def hex_to_rgb(value):
annotations=sections,
)

def example_inputs(self) -> Any:
return {}
def example_payload(self) -> Any:
return {
"image": "https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png",
"annotations": [],
}

def example_value(self) -> Any:
return (
"https://raw.githubusercontent.com/gradio-app/gradio/main/test/test_files/bus.png",
[([0, 0, 100, 100], "bus")],
)
5 changes: 4 additions & 1 deletion gradio/components/audio.py
Expand Up @@ -181,7 +181,10 @@ def __init__(
value=value,
)

def example_inputs(self) -> Any:
def example_payload(self) -> Any:
return "https://github.com/gradio-app/gradio/raw/main/test/test_files/audio_sample.wav"

def example_value(self) -> Any:
return "https://github.com/gradio-app/gradio/raw/main/test/test_files/audio_sample.wav"

def preprocess(
Expand Down
7 changes: 5 additions & 2 deletions gradio/components/bar_plot.py
Expand Up @@ -299,5 +299,8 @@ def postprocess(self, value: pd.DataFrame | None) -> AltairPlotData | None:

return AltairPlotData(type="altair", plot=chart.to_json(), chart="bar")

def example_inputs(self) -> dict[str, Any]:
return {}
def example_payload(self) -> Any:
return None

def example_value(self) -> Any:
return pd.DataFrame({self.x: [1, 2, 3], self.y: [4, 5, 6]})
21 changes: 19 additions & 2 deletions gradio/components/base.py
Expand Up @@ -83,8 +83,7 @@ def api_info(self) -> dict[str, list[str]]:
@abstractmethod
def example_inputs(self) -> Any:
"""
The example inputs for this component as a dictionary whose values are example inputs compatible with this component.
Keys of the dictionary are: raw, serialized
Deprecated and replaced by `example_payload()` and `example_value()`.
"""
pass

Expand Down Expand Up @@ -267,6 +266,24 @@ def as_example(self, value):
"""Deprecated and replaced by `process_example()`."""
return self.process_example(value)

def example_inputs(self) -> Any:
"""Deprecated and replaced by `example_payload()` and `example_value()`."""
return self.example_payload()

def example_payload(self) -> Any:
"""
An example input data for this component, e.g. what is passed to this component's preprocess() method.
This is used to generate the docs for the View API page for Gradio apps using this component.
"""
raise NotImplementedError()

def example_value(self) -> Any:
"""
An example output data for this component, e.g. what is passed to this component's postprocess() method.
This is used to generate an example value if this component is used as a template for a custom component.
"""
raise NotImplementedError()

def api_info(self) -> dict[str, Any]:
"""
The typing information for this component as a dictionary whose values are a list of 2 strings: [Python type, language-agnostic description].
Expand Down
7 changes: 5 additions & 2 deletions gradio/components/button.py
Expand Up @@ -89,5 +89,8 @@ def postprocess(self, value: str | None) -> str | None:
"""
return value

def example_inputs(self) -> Any:
return None
def example_payload(self) -> Any:
return "Run"

def example_value(self) -> Any:
return "Run"
5 changes: 4 additions & 1 deletion gradio/components/chatbot.py
Expand Up @@ -226,5 +226,8 @@ def postprocess(
)
return ChatbotData(root=processed_messages)

def example_inputs(self) -> Any:
def example_payload(self) -> Any:
return [["Hello!", None]]

def example_value(self) -> Any:
return [["Hello!", None]]
5 changes: 4 additions & 1 deletion gradio/components/checkbox.py
Expand Up @@ -73,7 +73,10 @@ def __init__(
def api_info(self) -> dict[str, Any]:
return {"type": "boolean"}

def example_inputs(self) -> bool:
def example_payload(self) -> bool:
return True

def example_value(self) -> bool:
return True

def preprocess(self, payload: bool | None) -> bool | None:
Expand Down
5 changes: 4 additions & 1 deletion gradio/components/checkboxgroup.py
Expand Up @@ -85,7 +85,10 @@ def __init__(
value=value,
)

def example_inputs(self) -> Any:
def example_payload(self) -> Any:
return [self.choices[0][1]] if self.choices else None

def example_value(self) -> Any:
return [self.choices[0][1]] if self.choices else None

def api_info(self) -> dict[str, Any]:
Expand Down
7 changes: 5 additions & 2 deletions gradio/components/clear_button.py
Expand Up @@ -127,5 +127,8 @@ def postprocess(self, value: str | None) -> str | None:
"""
return value

def example_inputs(self) -> Any:
return None
def example_payload(self) -> Any:
return "Clear"

def example_value(self) -> Any:
return "Clear"
5 changes: 4 additions & 1 deletion gradio/components/code.py
Expand Up @@ -162,5 +162,8 @@ def flag(self, payload: Any, flag_dir: str | Path = "") -> str:
def api_info(self) -> dict[str, Any]:
return {"type": "string"}

def example_inputs(self) -> Any:
def example_payload(self) -> Any:
return "print('Hello World')"

def example_value(self) -> Any:
return "print('Hello World')"
5 changes: 4 additions & 1 deletion gradio/components/color_picker.py
Expand Up @@ -68,7 +68,10 @@ def __init__(
value=value,
)

def example_inputs(self) -> str:
def example_payload(self) -> str:
return "#000000"

def example_value(self) -> str:
return "#000000"

def api_info(self) -> dict[str, Any]:
Expand Down
5 changes: 4 additions & 1 deletion gradio/components/dataframe.py
Expand Up @@ -371,5 +371,8 @@ def process_example(
value_df = pd.DataFrame(value_df_data.data, columns=value_df_data.headers)
return value_df.head(n=5).to_dict(orient="split")["data"]

def example_inputs(self) -> Any:
def example_payload(self) -> Any:
return {"headers": ["a", "b"], "data": [["foo", "bar"]]}

def example_value(self) -> Any:
return {"headers": ["a", "b"], "data": [["foo", "bar"]]}
5 changes: 4 additions & 1 deletion gradio/components/dataset.py
Expand Up @@ -152,5 +152,8 @@ def postprocess(self, samples: list[list]) -> dict:
"__type__": "update",
}

def example_inputs(self) -> Any:
def example_payload(self) -> Any:
return 0

def example_value(self) -> Any:
return []
5 changes: 4 additions & 1 deletion gradio/components/download_button.py
Expand Up @@ -99,7 +99,10 @@ def postprocess(self, value: str | Path | None) -> FileData | None:
return None
return FileData(path=str(value))

def example_inputs(self) -> str:
def example_payload(self) -> str:
return "https://github.com/gradio-app/gradio/raw/main/test/test_files/sample_file.pdf"

def example_value(self) -> str:
return "https://github.com/gradio-app/gradio/raw/main/test/test_files/sample_file.pdf"

@property
Expand Down
8 changes: 7 additions & 1 deletion gradio/components/dropdown.py
Expand Up @@ -130,7 +130,13 @@ def api_info(self) -> dict[str, Any]:
}
return json_type

def example_inputs(self) -> Any:
def example_payload(self) -> Any:
if self.multiselect:
return [self.choices[0][1]] if self.choices else []
else:
return self.choices[0][1] if self.choices else None

def example_value(self) -> Any:
if self.multiselect:
return [self.choices[0][1]] if self.choices else []
else:
Expand Down
5 changes: 4 additions & 1 deletion gradio/components/fallback.py
Expand Up @@ -22,7 +22,10 @@ def postprocess(self, value):
"""
return value

def example_inputs(self):
def example_payload(self):
return {"foo": "bar"}

def example_value(self):
return {"foo": "bar"}

def api_info(self):
Expand Down
39 changes: 35 additions & 4 deletions gradio/components/file.py
Expand Up @@ -7,8 +7,10 @@
from pathlib import Path
from typing import Any, Callable, Literal

import gradio_client.utils as client_utils
from gradio_client.documentation import document

from gradio import processing_utils
from gradio.components.base import Component
from gradio.data_classes import FileData, ListFiles
from gradio.events import Events
Expand All @@ -18,7 +20,7 @@
@document()
class File(Component):
"""
Creates a file component that allows uploading one or more generic files (when used as an input) or displaying generic files (as output).
Creates a file component that allows uploading one or more generic files (when used as an input) or displaying generic files or URLs for download (as output).
Demo: zip_files, zip_to_json
"""
Expand Down Expand Up @@ -47,7 +49,7 @@ def __init__(
):
"""
Parameters:
value: Default file to display, given as str file path. If callable, the function will be called whenever the app loads to set the initial value of the component.
value: Default file(s) to display, given as a str file path or URL, or a list of str file paths / URLs. If callable, the function will be called whenever the app loads to set the initial value of the component.
file_count: if single, allows user to upload one file. If "multiple", user uploads multiple files. If "directory", user uploads all files in selected directory. Return type will be list for each file in case of "multiple" or "directory".
file_types: List of file extensions or types of files to be uploaded (e.g. ['image', '.json', '.mp4']). "file" allows any file to be uploaded, "image" allows only image files to be uploaded, "audio" allows only audio files to be uploaded, "video" allows only video files to be uploaded, "text" allows only text files to be uploaded.
type: Type of value to be returned by component. "file" returns a temporary file object with the same base name as the uploaded file, whose full path can be retrieved by file_obj.name, "binary" returns an bytes object.
Expand Down Expand Up @@ -139,15 +141,36 @@ def preprocess(
return [self._process_single_file(f) for f in payload] # type: ignore
return [self._process_single_file(payload)] # type: ignore

def _download_files(self, value: str | list[str]) -> str | list[str]:
downloaded_files = []
if isinstance(value, list):
for file in value:
if client_utils.is_http_url_like(file):
downloaded_file = processing_utils.save_url_to_cache(
file, self.GRADIO_CACHE
)
downloaded_files.append(downloaded_file)
else:
downloaded_files.append(file)
return downloaded_files
if client_utils.is_http_url_like(value):
downloaded_file = processing_utils.save_url_to_cache(
value, self.GRADIO_CACHE
)
return downloaded_file
else:
return value

def postprocess(self, value: str | list[str] | None) -> ListFiles | FileData | None:
"""
Parameters:
value: Expects a `str` filepath, or a `list[str]` of filepaths.
value: Expects a `str` filepath or URL, or a `list[str]` of filepaths/URLs.
Returns:
File information as a FileData object, or a list of FileData objects.
"""
if value is None:
return None
value = self._download_files(value)
if isinstance(value, list):
return ListFiles(
root=[
Expand All @@ -174,7 +197,15 @@ def process_example(self, input_data: str | list | None) -> str:
else:
return Path(input_data).name

def example_inputs(self) -> Any:
def example_payload(self) -> Any:
if self.file_count == "single":
return "https://github.com/gradio-app/gradio/raw/main/test/test_files/sample_file.pdf"
else:
return [
"https://github.com/gradio-app/gradio/raw/main/test/test_files/sample_file.pdf"
]

def example_value(self) -> Any:
if self.file_count == "single":
return "https://github.com/gradio-app/gradio/raw/main/test/test_files/sample_file.pdf"
else:
Expand Down

0 comments on commit 1a4b089

Please sign in to comment.