WoWoWoWololo's picture
render equal to False are added
0b4fcec verified
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()