Spaces:
Running
Running
from __future__ import annotations | |
from gradio.blocks import Block, Blocks | |
from typing import Dict | |
from fastapi import FastAPI | |
""" | |
--------------------------------------------------------------------------------------------------------- | |
-- Base Classes | |
""" | |
# Base class for the RowLayout, ColumnLayout and TabLayout classes | |
class LayoutBase: | |
main_layout: Block # Stores the main layout from the gradio package of this class. | |
name: str # Name of the class. Used to differentiate from other layouts and for debug purposes. | |
global_children_dict: Dict[str, Block] # Stores the children components with given name. | |
renderables: list # Stores the renderable elements such as components and layouts. | |
def __init__(self) -> None: | |
self.main_layout = None | |
self.name = "Layout Base" | |
self.global_children_dict = {} | |
self.renderables = [] | |
""" | |
components are coming from the gradio package | |
these components are inherited from the Block class eventually | |
""" | |
def add_component(self, name: str, component: Block) -> None: | |
self.renderables.append(component) | |
self.global_children_dict[name] = component | |
""" | |
layout has to be from RowLayout, ColumnLayout or TabLayout classes | |
the parent class includes all the components that children layouts have | |
""" | |
def add_layout(self, layout: LayoutBase) -> None: | |
self.renderables.append(layout) | |
self.global_children_dict.update(layout.global_children_dict) | |
def render(self) -> None: | |
with self.main_layout: | |
for renderable in self.renderables: | |
renderable.render() | |
self.main_layout.render() | |
def clear(self) -> None: | |
self.global_children_dict.clear() | |
# we can be sure that all objects are cleaned | |
for renderable in self.renderables: | |
if isinstance(renderable, LayoutBase): | |
renderable.clear() | |
self.renderables.clear() | |
""" | |
the inherited class has to implement this function. | |
block_dict is coming from Application class's _attach_event function or parent class's attach_event function | |
""" | |
def attach_event(self, block_dict: Dict[str, Block]) -> None: | |
raise NotImplementedError | |
# Responsible for rendering, attaching events and launching | |
class Application: | |
app: Blocks # Base application component from the gradio package. | |
children: list[LayoutBase] # Stores the layouts | |
# Blocks constructor parameters are omitted for brevity | |
def __init__(self, title: str) -> None: | |
self.app = Blocks(title=title) | |
self.children = [] | |
""" | |
adding given RowLayout, ColumnLayout or TabLayout classes to children variable | |
""" | |
def add(self, child: LayoutBase): | |
self.children.append(child) | |
def _render(self): | |
with self.app: | |
for child in self.children: | |
child.render() | |
self.app.render() | |
def _attach_event(self): | |
block_dict: Dict[str, Block] = {} | |
for child in self.children: | |
block_dict.update(child.global_children_dict) | |
with self.app: | |
for child in self.children: | |
try: | |
child.attach_event(block_dict=block_dict) | |
except NotImplementedError: | |
print(f"{child.name}'s attach_event is not implemented") | |
""" | |
clearing the children layouts | |
we don't need them because they are going to live in the app.blocks and app.fns variables | |
""" | |
def _clear(self): | |
from gc import collect | |
for child in self.children: | |
child.clear() | |
self.children.clear() | |
collect() | |
# launch function parameters are omitted for the brevity | |
def launch(self) -> tuple[FastAPI, str, str]: | |
self._render() | |
self._attach_event() | |
self._clear() | |
return self.app.launch() | |
from gradio import Row, Column, Tab, Textbox | |
class RowLayout(LayoutBase): | |
def __init__(self, name: str) -> None: | |
super().__init__() | |
self.main_layout = Row(render=False) | |
self.global_children_dict[name] = self.main_layout | |
class ColumnLayout(LayoutBase): | |
def __init__(self, name: str) -> None: | |
super().__init__() | |
self.main_layout = Column(render=False) | |
self.global_children_dict[name] = self.main_layout | |
class TabLayout(LayoutBase): | |
def __init__(self, name: str) -> None: | |
super().__init__() | |
self.main_layout = Tab(label=name, render=False) | |
self.global_children_dict[name] = self.main_layout | |
""" | |
--------------------------------------------------------------------------------------------------------- | |
-- Example | |
""" | |
def change_text(new_str: str): | |
return Textbox(value=new_str) | |
class RowExample(RowLayout): | |
def __init__(self, name: str) -> None: | |
super().__init__(name=name) | |
self.left_textbox = Textbox( | |
value="Left Textbox", interactive=True, render=False | |
) | |
self.right_textbox = Textbox(value="Right Textbox", render=False) | |
self.add_component("left_textbox", self.left_textbox) | |
self.add_component("right_textbox", self.right_textbox) | |
def attach_event(self, block_dict: Dict[str, Block]) -> None: | |
self.left_textbox.change( | |
change_text, | |
inputs=self.left_textbox, | |
outputs=self.right_textbox, | |
) | |
class FirstTab(TabLayout): | |
def __init__(self, name: str) -> None: | |
super().__init__(name) | |
self.row = RowExample(name="first tab row layout") | |
self.add_layout(self.row) | |
def attach_event(self, block_dict: Dict[str, Block]) -> None: | |
self.row.attach_event(block_dict) | |
class SecondTab(TabLayout): | |
def __init__(self, name: str) -> None: | |
super().__init__(name) | |
self.column = ColumnLayout(name="second tab column layout") | |
self.top_textbox = Textbox(value="Top Textbox", interactive=False, render=False) | |
self.bottom_textbox = Textbox(value="Bottom Textbox", render=False) | |
self.column.add_component("top_textbox", self.top_textbox) | |
self.column.add_component("bottom_textbox", self.bottom_textbox) | |
self.add_layout(self.column) | |
def attach_event(self, block_dict: Dict[str, Block]) -> None: | |
block_dict["left_textbox"].change( | |
change_text, | |
inputs=block_dict["left_textbox"], | |
outputs=self.bottom_textbox, | |
) | |
""" | |
--------------------------------------------------------------------------------------------------------- | |
-- Main | |
""" | |
gui = Application(title="Wrap Gradio") | |
first_tab = FirstTab(name="First Tab") | |
second_tab = SecondTab(name="Second Tab") | |
gui.add(first_tab) | |
gui.add(second_tab) | |
gui.launch() | |