Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions demo/blocks_plug/run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import gradio as gr

identity_demo, input_demo, output_demo = gr.Blocks(), gr.Blocks(), gr.Blocks()

with identity_demo:
gr.Interface(lambda x:x, "text", "text")

with input_demo:
t = gr.Textbox(label="Enter your text here")
with gr.Row():
btn = gr.Button("Submit")
clr = gr.Button("Clear")
clr.click(lambda x: "", t, t)

with output_demo:
gr.Textbox("This is a static output")

with gr.Blocks() as demo:
gr.Markdown("Three demos in one!")
with gr.Tabs():
with gr.TabItem("Text Identity"):
identity_demo.render()
with gr.TabItem("Text Input"):
input_demo.render()
with gr.TabItem("Text Static"):
output_demo.render()


if __name__ == "__main__":
demo.launch()
50 changes: 37 additions & 13 deletions gradio/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,41 @@


class Block:
def __init__(self, without_rendering=False, css=None, **kwargs):
self._id = None
def __init__(self, css=None, render=True, **kwargs):
self._id = Context.id
Context.id += 1
self.css = css if css is not None else {}
if without_rendering:
return
self.render()
if render:
self.render()
check_deprecated_parameters(self.__class__.__name__, **kwargs)

def render(self):
"""
Adds self into appropriate BlockContext
"""
self._id = Context.id
Context.id += 1
if Context.block is not None:
Context.block.children.append(self)
if Context.root_block is not None:
Context.root_block.blocks[self._id] = self

def unrender(self):
Comment thread
abidlabs marked this conversation as resolved.
"""
Removes self from BlockContext if it has been rendered (otherwise does nothing).
Only deletes the first occurrence of self in BlockContext. Removes from the
layout and collection of Blocks, but does not delete any event triggers.
"""
if Context.block is not None:
try:
Context.block.children.remove(self)
except ValueError:
pass
if Context.root_block is not None:
try:
del Context.root_block.blocks[self._id]
except KeyError:
pass
return self

def get_block_name(self) -> str:
"""
Gets block's class name.
Expand Down Expand Up @@ -99,14 +115,18 @@ def set_event_trigger(

class BlockContext(Block):
def __init__(
self, visible: bool = True, css: Optional[Dict[str, str]] = None, **kwargs
self,
visible: bool = True,
css: Optional[Dict[str, str]] = None,
render: bool = True,
**kwargs,
):
"""
css: Css rules to apply to block.
"""
self.children = []
self.visible = visible
super().__init__(css=css, **kwargs)
super().__init__(css=css, render=render, **kwargs)

def __enter__(self):
self.parent = Context.block
Expand Down Expand Up @@ -226,8 +246,8 @@ def __init__(
else os.getenv("GRADIO_ANALYTICS_ENABLED", "True") == "True"
)

super().__init__(**kwargs)
self.blocks = {}
super().__init__(render=False, **kwargs)
self.blocks: Dict[int, Block] = {}
self.fns: List[BlockFunction] = []
self.dependencies = []
self.mode = mode
Expand All @@ -240,8 +260,12 @@ def __init__(
self.favicon_path = None

def render(self):
self._id = Context.id
Context.id += 1
if Context.root_block is not None:
Context.root_block.blocks.update(self.blocks)
Context.root_block.fns.extend(self.fns)
Context.root_block.dependencies.extend(self.dependencies)
if Context.block is not None:
Context.block.children.extend(self.children)

def process_api(
self,
Expand Down
21 changes: 8 additions & 13 deletions gradio/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,9 @@ def __init__(
self,
*,
css: Optional[Dict] = None,
without_rendering: bool = False,
**kwargs,
):
super().__init__(without_rendering=without_rendering, css=css, **kwargs)
super().__init__(css=css, **kwargs)

def __str__(self):
return self.__repr__()
Expand Down Expand Up @@ -3091,7 +3090,6 @@ def __init__(
self,
default_value: str = "",
*,
label: Optional[str] = None,
css: Optional[Dict] = None,
**kwargs,
):
Expand All @@ -3101,7 +3099,7 @@ def __init__(
label (str): component name
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to update docstring with the label's removal

css (dict): optional css parameters for the component
"""
super().__init__(label=label, css=css, **kwargs)
super().__init__(css=css, **kwargs)
self.md = MarkdownIt()
unindented_default_value = inspect.cleandoc(default_value)
self.default_value = self.md.render(unindented_default_value)
Expand Down Expand Up @@ -3194,11 +3192,10 @@ def __init__(
components: List[Component],
samples: List[List[Any]],
type: str = "values",
label: Optional[str] = None,
css: Optional[Dict] = None,
**kwargs,
):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not related to this PR but, Dataset has no docstring, let's add one?

super().__init__(label=label, css=css, **kwargs)
super().__init__(css=css, **kwargs)
self.components = components
self.type = type
self.headers = [c.label for c in components]
Expand Down Expand Up @@ -3275,11 +3272,10 @@ def __init__(
self,
component: Component,
*,
label: Optional[str] = None,
css: Optional[Dict] = None,
**kwargs,
):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not related to this PR but, Interpretation has no docstring, let's add one?

super().__init__(label=label, css=css, **kwargs)
super().__init__(css=css, **kwargs)
self.component = component

def get_template_context(self):
Expand Down Expand Up @@ -3343,13 +3339,12 @@ def component(cls_name: str):

def get_component_instance(comp: str | dict | Component):
if isinstance(comp, str):
return component(comp)()
elif isinstance(
comp, dict
): # a dict with `name` as the input component type and other keys as parameters
component_cls = component(comp)
return component_cls()
elif isinstance(comp, dict):
name = comp.pop("name")
component_cls = component(name)
return component_cls(**comp, without_rendering=True)
return component_cls(**comp)
elif isinstance(comp, Component):
return comp
else:
Expand Down
8 changes: 5 additions & 3 deletions gradio/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
from typing import TYPE_CHECKING, List

if TYPE_CHECKING: # Only import for type checking (is False at runtime).
from gradio.blocks import Block
from gradio.blocks import BlockContext, Blocks


class Context:
root_block: Block = None # The current root block that holds all blocks.
block: Block = None # The current block that all children should be added to.
root_block: Blocks = None # The current root block that holds all blocks.
block: BlockContext = (
None # The current block that all children should be added to.
)
id = 0 # Running id to uniquely refer to any block that gets defined
28 changes: 6 additions & 22 deletions gradio/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,8 @@ def __init__(
inputs[inputs.index("state")] = state_variable
outputs[outputs.index("state")] = state_variable

self.input_components = [get_component_instance(i) for i in inputs]
self.output_components = [get_component_instance(o) for o in outputs]
self.input_components = [get_component_instance(i).unrender() for i in inputs]
Comment thread
omerXfaruq marked this conversation as resolved.
self.output_components = [get_component_instance(o).unrender() for o in outputs]
for o in self.output_components:
o.interactive = (
False # Force output components to be treated as non-interactive
Expand Down Expand Up @@ -549,6 +549,9 @@ def load_example(example_id):
status_tracker=status_tracker,
)

if self.article:
Markdown(self.article)

def __call__(self, *params):
if (
self.api_mode
Expand All @@ -574,25 +577,6 @@ def __repr__(self):
repr += "\n|-{}".format(str(component))
return repr

def render_basic_interface(self):
Interface(
fn=self.predict,
inputs=self.input_components,
outputs=self.output_components,
examples=self.examples,
examples_per_page=self.examples_per_page,
live=self.live,
layout=self.layout,
interpretation=self.interpretation,
num_shap=self.num_shap,
title=self.title,
description=self.description,
article=self.article,
allow_flagging=self.allow_flagging,
flagging_options=self.flagging_options,
flagging_dir=self.flagging_dir,
)

def run_prediction(
self,
processed_input: List[Any],
Expand Down Expand Up @@ -755,7 +739,7 @@ def __init__(
with Tabs():
for (interface, tab_name) in zip(interface_list, tab_names):
with TabItem(label=tab_name):
interface.render_basic_interface()
interface.render()


def close_all(verbose: bool = True) -> None:
Expand Down
4 changes: 2 additions & 2 deletions test/test_interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,9 @@ def test_tabbed_interface_config_matches_manual_tab(self):
with Blocks() as demo:
with Tabs():
with TabItem(label="tab1"):
interface1.render_basic_interface()
interface1.render()
with TabItem(label="tab2"):
interface2.render_basic_interface()
interface2.render()

interface3 = Interface(lambda x: x, "textbox", "textbox")
interface4 = Interface(lambda x: x, "image", "image")
Expand Down