added better default labels to form components (#1040)

* added better default labels to form components

* updated default labels

* formatting

* fixed tests
This commit is contained in:
Abubakar Abid 2022-04-20 10:54:44 -07:00 committed by GitHub
parent 20847c51d5
commit 5c34d91865
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 150 additions and 173 deletions

View File

@ -307,7 +307,7 @@ class Blocks(BlockContext):
{
"id": _id,
"type": (block.get_block_name()),
"props": block.get_template_context()
"props": utils.delete_none(block.get_template_context())
if hasattr(block, "get_template_context")
else None,
}

View File

@ -132,9 +132,7 @@ class Component(Block):
Creates a component, where class name equals to str_shortcut.
@param str_shortcut: string shortcut of a component
@return:
True, found_class or
False, None
@return: the insantiated component object, or None if no such component exists
"""
# If we do not import templates Python cannot recognize grandchild classes names.
import gradio.templates
@ -2371,7 +2369,11 @@ class Variable(Component):
return {"default_value": self.default_value, **super().get_template_context()}
############################
# Only Output Components
############################
class Label(Component):
"""
Component outputs a classification label, along with confidence scores of top categories if provided. Confidence scores are represented as a dictionary mapping labels to scores between 0 and 1.
@ -2998,7 +3000,97 @@ class Model3D(Component):
self.set_event_trigger("clear", fn, inputs, outputs)
class Plot(Component):
"""
Used for plot output.
Output type: matplotlib plt, plotly figure, or Bokeh fig (json_item format)
Demos: outbreak_forecast
"""
def __init__(
self,
type: str = None,
label: str = None,
css: Optional[Dict] = None,
**kwargs,
):
"""
Parameters:
type (str): type of plot (matplotlib, plotly)
label (str): component name in interface.
"""
self.type = type
super().__init__(label=label, css=css, **kwargs)
def get_template_context(self):
return {**super().get_template_context()}
def postprocess(self, y):
"""
Parameters:
y (str): plot data
Returns:
(str): plot type
(str): plot base64 or json
"""
dtype = self.type
if self.type == "plotly":
out_y = y.to_json()
elif self.type == "matplotlib":
out_y = processing_utils.encode_plot_to_base64(y)
elif self.type == "bokeh":
out_y = json.dumps(y)
elif self.type == "auto":
if isinstance(y, (ModuleType, matplotlib.pyplot.Figure)):
dtype = "matplotlib"
out_y = processing_utils.encode_plot_to_base64(y)
elif isinstance(y, dict):
dtype = "bokeh"
out_y = json.dumps(y)
else:
dtype = "plotly"
out_y = y.to_json()
else:
raise ValueError(
"Unknown type. Please choose from: 'plotly', 'matplotlib', 'bokeh'."
)
return {"type": dtype, "plot": out_y}
def change(
self,
fn: Callable,
inputs: List[Component],
outputs: List[Component],
status_tracker: Optional[StatusTracker] = None,
):
"""
Parameters:
fn: Callable function
inputs: List of inputs
outputs: List of outputs
status: StatusTracker to visualize function progress
Returns: None
"""
self.set_event_trigger(
"change", fn, inputs, outputs, status_tracker=status_tracker
)
def clear(self, fn: Callable, inputs: List[Component], outputs: List[Component]):
"""
Parameters:
fn: Callable function
inputs: List of inputs
outputs: List of outputs
Returns: None
"""
self.set_event_trigger("clear", fn, inputs, outputs)
############################
# Static Components
############################
class Markdown(Component):
"""
Used for Markdown output. Expects a valid string that is rendered into Markdown.
@ -3186,92 +3278,6 @@ class Dataset(Component):
)
class Plot(Component):
"""
Used for plot output.
Output type: matplotlib plt, plotly figure, or Bokeh fig (json_item format)
Demos: outbreak_forecast
"""
def __init__(
self,
type: str = None,
label: str = None,
css: Optional[Dict] = None,
**kwargs,
):
"""
Parameters:
type (str): type of plot (matplotlib, plotly)
label (str): component name in interface.
"""
self.type = type
super().__init__(label=label, css=css, **kwargs)
def get_template_context(self):
return {**super().get_template_context()}
def postprocess(self, y):
"""
Parameters:
y (str): plot data
Returns:
(str): plot type
(str): plot base64 or json
"""
dtype = self.type
if self.type == "plotly":
out_y = y.to_json()
elif self.type == "matplotlib":
out_y = processing_utils.encode_plot_to_base64(y)
elif self.type == "bokeh":
out_y = json.dumps(y)
elif self.type == "auto":
if isinstance(y, (ModuleType, matplotlib.pyplot.Figure)):
dtype = "matplotlib"
out_y = processing_utils.encode_plot_to_base64(y)
elif isinstance(y, dict):
dtype = "bokeh"
out_y = json.dumps(y)
else:
dtype = "plotly"
out_y = y.to_json()
else:
raise ValueError(
"Unknown type. Please choose from: 'plotly', 'matplotlib', 'bokeh'."
)
return {"type": dtype, "plot": out_y}
def change(
self,
fn: Callable,
inputs: List[Component],
outputs: List[Component],
status_tracker: Optional[StatusTracker] = None,
):
"""
Parameters:
fn: Callable function
inputs: List of inputs
outputs: List of outputs
status: StatusTracker to visualize function progress
Returns: None
"""
self.set_event_trigger(
"change", fn, inputs, outputs, status_tracker=status_tracker
)
def clear(self, fn: Callable, inputs: List[Component], outputs: List[Component]):
"""
Parameters:
fn: Callable function
inputs: List of inputs
outputs: List of outputs
Returns: None
"""
self.set_event_trigger("clear", fn, inputs, outputs)
class Interpretation(Component):
"""
Used to create an interpretation widget for a component.
@ -3295,14 +3301,12 @@ class Interpretation(Component):
}
def component(str_shortcut: str) -> (bool, Optional[Component]):
def component(str_shortcut: str) -> Optional[Component]:
"""
Creates a component, where class name equals to str_shortcut.
@param str_shortcut: string shortcut of a component
@return:
True, found_class or
False, None
@return component: the component object
"""
component = Component.get_component_shortcut(str_shortcut)
if component is None:

View File

@ -18,7 +18,7 @@ from typing import TYPE_CHECKING, Any, Callable, List, Optional, Tuple
from markdown_it import MarkdownIt
from mdit_py_plugins.footnote import footnote_plugin
from gradio import context, interpretation, utils
from gradio import interpretation, utils
from gradio.blocks import Blocks, Column, Row, TabItem, Tabs
from gradio.components import (
Button,
@ -32,8 +32,6 @@ from gradio.components import (
)
from gradio.external import load_from_pipeline, load_interface # type: ignore
from gradio.flagging import CSVLogger, FlaggingCallback # type: ignore
from gradio.inputs import State as i_State # type: ignore
from gradio.outputs import State as o_State # type: ignore
from gradio.process_examples import cache_interface_examples, load_from_cache
if TYPE_CHECKING: # Only import for type checking (is False at runtime).
@ -487,7 +485,10 @@ class Interface(Blocks):
component.label = param_name
for i, component in enumerate(self.output_components):
if component.label is None:
component.label = "output_" + str(i)
if len(self.output_components) == 1:
component.label = "output"
else:
component.label = "output " + str(i)
self.cache_examples = cache_examples
if cache_examples:

View File

@ -55,7 +55,7 @@
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.3.1/iframeResizer.contentWindow.min.js"></script>
<title>Gradio</title>
<script type="module" crossorigin src="./assets/index.49d6d26d.js"></script>
<script type="module" crossorigin src="./assets/index.2f71b643.js"></script>
<link rel="stylesheet" href="./assets/index.39bf42f9.css">
</head>

View File

@ -7,9 +7,7 @@ XRAY_CONFIG = {
"props": {
"default_value": "<h1>Detect Disease From Scan</h1>\n<p>With this model you can lorem ipsum</p>\n<ul>\n<li>ipsum 1</li>\n<li>ipsum 2</li>\n</ul>\n",
"name": "markdown",
"label": None,
"css": {},
"interactive": None,
},
},
{
@ -21,7 +19,6 @@ XRAY_CONFIG = {
"name": "checkboxgroup",
"label": "Disease to Scan For",
"css": {},
"interactive": None,
},
},
{"id": 3, "type": "tabs", "props": {"css": {}, "default_value": True}},
@ -40,14 +37,10 @@ XRAY_CONFIG = {
"type": "image",
"props": {
"image_mode": "RGB",
"shape": None,
"source": "upload",
"tool": "editor",
"default_value": None,
"name": "image",
"label": None,
"css": {},
"interactive": None,
},
},
{
@ -56,9 +49,7 @@ XRAY_CONFIG = {
"props": {
"default_value": '""',
"name": "json",
"label": None,
"css": {},
"interactive": None,
},
},
{
@ -67,9 +58,7 @@ XRAY_CONFIG = {
"props": {
"default_value": "Run",
"name": "button",
"label": None,
"css": {"background-color": "red", "--hover-color": "orange"},
"interactive": None,
},
},
{
@ -87,14 +76,10 @@ XRAY_CONFIG = {
"type": "image",
"props": {
"image_mode": "RGB",
"shape": None,
"source": "upload",
"tool": "editor",
"default_value": None,
"name": "image",
"label": None,
"css": {},
"interactive": None,
},
},
{
@ -103,9 +88,7 @@ XRAY_CONFIG = {
"props": {
"default_value": '""',
"name": "json",
"label": None,
"css": {},
"interactive": None,
},
},
{
@ -114,9 +97,7 @@ XRAY_CONFIG = {
"props": {
"default_value": "Run",
"name": "button",
"label": None,
"css": {},
"interactive": None,
},
},
{
@ -125,12 +106,9 @@ XRAY_CONFIG = {
"props": {
"lines": 1,
"max_lines": 20,
"placeholder": None,
"default_value": "",
"name": "textbox",
"label": None,
"css": {},
"interactive": None,
},
},
],
@ -199,9 +177,7 @@ XRAY_CONFIG_DIFF_IDS = {
"props": {
"default_value": "<h1>Detect Disease From Scan</h1>\n<p>With this model you can lorem ipsum</p>\n<ul>\n<li>ipsum 1</li>\n<li>ipsum 2</li>\n</ul>\n",
"name": "markdown",
"label": None,
"css": {},
"interactive": None,
},
},
{
@ -213,7 +189,6 @@ XRAY_CONFIG_DIFF_IDS = {
"name": "checkboxgroup",
"label": "Disease to Scan For",
"css": {},
"interactive": None,
},
},
{"id": 3, "type": "tabs", "props": {"css": {}, "default_value": True}},
@ -232,14 +207,10 @@ XRAY_CONFIG_DIFF_IDS = {
"type": "image",
"props": {
"image_mode": "RGB",
"shape": None,
"source": "upload",
"tool": "editor",
"default_value": None,
"name": "image",
"label": None,
"css": {},
"interactive": None,
},
},
{
@ -248,9 +219,7 @@ XRAY_CONFIG_DIFF_IDS = {
"props": {
"default_value": '""',
"name": "json",
"label": None,
"css": {},
"interactive": None,
},
},
{
@ -259,9 +228,7 @@ XRAY_CONFIG_DIFF_IDS = {
"props": {
"default_value": "Run",
"name": "button",
"label": None,
"css": {"background-color": "red", "--hover-color": "orange"},
"interactive": None,
},
},
{
@ -279,14 +246,10 @@ XRAY_CONFIG_DIFF_IDS = {
"type": "image",
"props": {
"image_mode": "RGB",
"shape": None,
"source": "upload",
"tool": "editor",
"default_value": None,
"name": "image",
"label": None,
"css": {},
"interactive": None,
},
},
{
@ -295,9 +258,7 @@ XRAY_CONFIG_DIFF_IDS = {
"props": {
"default_value": '""',
"name": "json",
"label": None,
"css": {},
"interactive": None,
},
},
{
@ -306,9 +267,7 @@ XRAY_CONFIG_DIFF_IDS = {
"props": {
"default_value": "Run",
"name": "button",
"label": None,
"css": {},
"interactive": None,
},
},
{
@ -316,13 +275,10 @@ XRAY_CONFIG_DIFF_IDS = {
"type": "textbox",
"props": {
"lines": 1,
"placeholder": None,
"default_value": "",
"name": "textbox",
"max_lines": 20,
"label": None,
"css": {},
"interactive": None,
},
},
],
@ -383,9 +339,7 @@ XRAY_CONFIG_WITH_MISTAKE = {
"props": {
"default_value": "<h1>Detect Disease From Scan</h1>\n<p>With this model you can lorem ipsum</p>\n<ul>\n<li>ipsum 1</li>\n<li>ipsum 2</li>\n</ul>\n",
"name": "markdown",
"label": None,
"css": {},
"interactive": None,
},
},
{
@ -397,7 +351,6 @@ XRAY_CONFIG_WITH_MISTAKE = {
"name": "checkboxgroup",
"label": "Disease to Scan For",
"css": {},
"interactive": None,
},
},
{"id": 3, "type": "tabs", "props": {"css": {}, "default_value": True}},
@ -416,14 +369,10 @@ XRAY_CONFIG_WITH_MISTAKE = {
"type": "image",
"props": {
"image_mode": "RGB",
"shape": None,
"source": "upload",
"tool": "editor",
"default_value": None,
"name": "image",
"label": None,
"css": {},
"interactive": None,
},
},
{
@ -432,9 +381,7 @@ XRAY_CONFIG_WITH_MISTAKE = {
"props": {
"default_value": '""',
"name": "json",
"label": None,
"css": {},
"interactive": None,
},
},
{
@ -443,9 +390,7 @@ XRAY_CONFIG_WITH_MISTAKE = {
"props": {
"default_value": "Run",
"name": "button",
"label": None,
"css": {"background-color": "red", "--hover-color": "orange"},
"interactive": None,
},
},
{
@ -463,14 +408,10 @@ XRAY_CONFIG_WITH_MISTAKE = {
"type": "image",
"props": {
"image_mode": "RGB",
"shape": None,
"source": "upload",
"tool": "editor",
"default_value": None,
"name": "image",
"label": None,
"css": {},
"interactive": None,
},
},
{
@ -479,9 +420,7 @@ XRAY_CONFIG_WITH_MISTAKE = {
"props": {
"default_value": '""',
"name": "json",
"label": None,
"css": {},
"interactive": None,
},
},
{
@ -490,9 +429,7 @@ XRAY_CONFIG_WITH_MISTAKE = {
"props": {
"default_value": "Run",
"name": "button",
"label": None,
"css": {},
"interactive": None,
},
},
{
@ -500,12 +437,9 @@ XRAY_CONFIG_WITH_MISTAKE = {
"type": "textbox",
"props": {
"lines": 1,
"placeholder": None,
"default_value": "",
"name": "textbox",
"label": None,
"css": {},
"interactive": None,
},
},
],

View File

@ -352,3 +352,21 @@ def format_ner_list(input_string: str, ner_groups: Dict[str : str | int]):
output.append((input_string[end:], None))
return output
def delete_none(_dict):
"""
Delete None values recursively from all of the dictionaries, tuples, lists, sets.
Credit: https://stackoverflow.com/questions/33797126/proper-way-to-remove-keys-in-dictionary-with-none-values-in-python
"""
if isinstance(_dict, dict):
for key, value in list(_dict.items()):
if isinstance(value, (list, dict, tuple, set)):
_dict[key] = delete_none(value)
elif value is None or key is None:
del _dict[key]
elif isinstance(_dict, (list, set, tuple)):
_dict = type(_dict)(delete_none(item) for item in _dict if item is not None)
return _dict

View File

@ -15,6 +15,7 @@ from gradio.test_data.blocks_configs import (
from gradio.utils import (
assert_configs_are_equivalent_besides_ids,
colab_check,
delete_none,
error_analytics,
format_ner_list,
get_local_ip_address,
@ -164,5 +165,24 @@ class TestFormatNERList(unittest.TestCase):
self.assertEqual(format_ner_list(string, groups), result)
class TestDeleteNone(unittest.TestCase):
"""Credit: https://stackoverflow.com/questions/33797126/proper-way-to-remove-keys-in-dictionary-with-none-values-in-python"""
def test_delete_none(self):
input = {
"a": 12,
"b": 34,
"c": None,
"k": {
"d": 34,
"t": None,
"m": [{"k": 23, "t": None}, [None, 1, 2, 3], {1, 2, None}],
None: 123,
},
}
truth = {"a": 12, "b": 34, "k": {"d": 34, "m": [{"k": 23}, [1, 2, 3], {1, 2}]}}
self.assertEqual(delete_none(input), truth)
if __name__ == "__main__":
unittest.main()

View File

@ -19,7 +19,7 @@
props.mode = "static";
} else if (props.interactive === true) {
props.mode = "dynamic";
} else if (props.interactive === null && dynamic_ids.has(id)) {
} else if (dynamic_ids.has(id)) {
props.mode = "dynamic";
} else {
props.mode = "static";

View File

@ -4,7 +4,7 @@
export let value: boolean = false;
export let default_value: boolean = false;
export let style: string = "";
export let label: string;
export let label: string = "Checkbox";
export let mode: "static" | "dynamic";
if (default_value) value = default_value;

View File

@ -7,7 +7,7 @@
export let mode: "static" | "dynamic";
export let style: string = "";
export let label: string;
export let label: string = "Checkbox Group";
if (default_value) value = default_value;
</script>

View File

@ -1,6 +1,6 @@
<script lang="ts">
import { Dropdown } from "@gradio/form";
export let label: string = "";
export let label: string = "Dropdown";
export let value: string = "";
export let default_value: string = "";
export let style: string = "";

View File

@ -1,7 +1,7 @@
<script lang="ts">
import { Number } from "@gradio/form";
export let label: string;
export let label: string = "Number";
export let value: number = 0;
export let default_value: number;

View File

@ -1,7 +1,7 @@
<script lang="ts">
import { Radio } from "@gradio/form";
export let label: string;
export let label: string = "Radio";
export let value: string = "";
export let default_value: string;
export let style: string = "";

View File

@ -3,7 +3,7 @@
export let value: number = 0;
export let label: string;
export let label: string = "Slider";
export let default_value: number;
export let style: string = "";

View File

@ -3,7 +3,7 @@
<script lang="ts">
import { TextBox } from "@gradio/form";
export let label: string;
export let label: string = "Textbox";
export let value: string = " ";
export let default_value: string | false = false;
export let style: string = "";