diff --git a/gradio/blocks.py b/gradio/blocks.py
index 8edeeef0a7..c9ad3cb85e 100644
--- a/gradio/blocks.py
+++ b/gradio/blocks.py
@@ -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,
}
diff --git a/gradio/components.py b/gradio/components.py
index 440ad2fe2b..97e8406470 100644
--- a/gradio/components.py
+++ b/gradio/components.py
@@ -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:
diff --git a/gradio/interface.py b/gradio/interface.py
index 82d6ba2fbe..61986154f7 100644
--- a/gradio/interface.py
+++ b/gradio/interface.py
@@ -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:
diff --git a/gradio/templates/frontend/index.html b/gradio/templates/frontend/index.html
index b8f70bf43c..d48bdde20f 100644
--- a/gradio/templates/frontend/index.html
+++ b/gradio/templates/frontend/index.html
@@ -55,7 +55,7 @@
Gradio
-
+
diff --git a/gradio/test_data/blocks_configs.py b/gradio/test_data/blocks_configs.py
index 5032076a75..91712ce3f5 100644
--- a/gradio/test_data/blocks_configs.py
+++ b/gradio/test_data/blocks_configs.py
@@ -7,9 +7,7 @@ XRAY_CONFIG = {
"props": {
"default_value": "Detect Disease From Scan
\nWith this model you can lorem ipsum
\n\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": "Detect Disease From Scan
\nWith this model you can lorem ipsum
\n\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": "Detect Disease From Scan
\nWith this model you can lorem ipsum
\n\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,
},
},
],
diff --git a/gradio/utils.py b/gradio/utils.py
index 8dc67e0351..c797f159ca 100644
--- a/gradio/utils.py
+++ b/gradio/utils.py
@@ -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
diff --git a/test/test_utils.py b/test/test_utils.py
index fed9be68b6..e3f036bb24 100644
--- a/test/test_utils.py
+++ b/test/test_utils.py
@@ -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()
diff --git a/ui/packages/app/src/Render.svelte b/ui/packages/app/src/Render.svelte
index 9f7bc7ea15..f35b48a46e 100644
--- a/ui/packages/app/src/Render.svelte
+++ b/ui/packages/app/src/Render.svelte
@@ -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";
diff --git a/ui/packages/app/src/components/Checkbox/Checkbox.svelte b/ui/packages/app/src/components/Checkbox/Checkbox.svelte
index 43723d7dbe..98ab96ecba 100644
--- a/ui/packages/app/src/components/Checkbox/Checkbox.svelte
+++ b/ui/packages/app/src/components/Checkbox/Checkbox.svelte
@@ -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;
diff --git a/ui/packages/app/src/components/CheckboxGroup/CheckboxGroup.svelte b/ui/packages/app/src/components/CheckboxGroup/CheckboxGroup.svelte
index e87f0c979c..b08367e305 100644
--- a/ui/packages/app/src/components/CheckboxGroup/CheckboxGroup.svelte
+++ b/ui/packages/app/src/components/CheckboxGroup/CheckboxGroup.svelte
@@ -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;
diff --git a/ui/packages/app/src/components/Dropdown/Dropdown.svelte b/ui/packages/app/src/components/Dropdown/Dropdown.svelte
index 6521104adc..cb2f7c998e 100644
--- a/ui/packages/app/src/components/Dropdown/Dropdown.svelte
+++ b/ui/packages/app/src/components/Dropdown/Dropdown.svelte
@@ -1,6 +1,6 @@