Spaces:
Sleeping
Sleeping
| 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() | |