Spaces:
Sleeping
Sleeping
File size: 6,550 Bytes
4b6f4f0 05977dd 4b6f4f0 05977dd 4b6f4f0 05977dd 4b6f4f0 05977dd 4b6f4f0 05977dd 4b6f4f0 05977dd 4b6f4f0 05977dd 4b6f4f0 05977dd 4b6f4f0 05977dd 4b6f4f0 05977dd 4b6f4f0 05977dd 4b6f4f0 05977dd 4b6f4f0 05977dd 4b6f4f0 05977dd 4b6f4f0 05977dd 4b6f4f0 05977dd 4b6f4f0 a364f6d 4b6f4f0 a364f6d 4b6f4f0 05977dd 4b6f4f0 a364f6d 4b6f4f0 a364f6d 4b6f4f0 05977dd a364f6d 05977dd a364f6d 05977dd a364f6d 05977dd 4b6f4f0 a364f6d 4b6f4f0 a364f6d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
import gradio as gr
import ast
import os
from io import StringIO
# Mapping of Gradio components to Toga equivalents
GRADIO_TO_TOGA = {
"Textbox": ("toga.TextInput", "style=Pack(padding=5)", "Text Input"),
"Image": ("toga.Label", "Placeholder: Image file picker", "Image Upload"),
"Button": ("toga.Button", "on_press=button_handler", "Submit"),
"Markdown": ("toga.Label", "style=Pack(padding=5, font_size=14)", "Markdown Text"),
"Audio": ("toga.Label", "Placeholder: Audio file picker", "Audio Upload"),
"Video": ("toga.Label", "Placeholder: Video file picker", "Video Upload"),
}
# Parse Gradio app code
def parse_gradio_code(code):
try:
tree = ast.parse(code)
components = []
functions = []
for node in ast.walk(tree):
if isinstance(node, ast.FunctionDef):
functions.append(node.name)
if isinstance(node, ast.Call) and hasattr(node.func, 'attr'):
if node.func.attr in GRADIO_TO_TOGA:
component = node.func.attr
args = [ast.dump(arg, annotate_fields=False) for arg in node.args]
kwargs = {kw.arg: ast.dump(kw.value, annotate_fields=False) for kw in node.keywords}
components.append({"type": component, "args": args, "kwargs": kwargs})
return components, functions
except Exception as e:
return [], [f"Error parsing code: {str(e)}"]
# Generate Toga code
def generate_toga_code(components, functions):
toga_code = [
"import toga",
"from toga.style import Pack",
"from toga.style.pack import COLUMN",
"",
"# Original functions (copy these from your Gradio app)",
f"# Detected functions: {', '.join(functions) if functions else 'None'}",
"",
"def build(app):",
" box = toga.Box(style=Pack(direction=COLUMN, padding=10))",
""
]
for idx, comp in enumerate(components):
toga_comp, extra, label_prefix = GRADIO_TO_TOGA.get(comp["type"], ("toga.Label", f"Placeholder: {comp['type']} not supported", "Unknown"))
if comp["type"] == "Textbox":
label = comp["kwargs"].get("label", f"'{label_prefix} {idx}'")
toga_code.append(f" label_{idx} = toga.Label({label}, style=Pack(padding=(5, 5, 0, 5)))")
toga_code.append(f" input_{idx} = {toga_comp}({extra})")
toga_code.append(f" box.add(label_{idx})")
toga_code.append(f" box.add(input_{idx})")
elif comp["type"] in ["Image", "Audio", "Video"]:
file_types = {
"Image": "['png', 'jpg', 'jpeg']",
"Audio": "['mp3', 'wav']",
"Video": "['mp4', 'avi']"
}.get(comp["type"], "['*']")
toga_code.append(f" {comp['type'].lower()}_label_{idx} = toga.Label('{label_prefix}: None selected', style=Pack(padding=5))")
toga_code.append(f" def select_{comp['type'].lower()}_{idx}(widget):")
toga_code.append(f" path = app.main_window.open_file_dialog('Select {comp['type']}', file_types={file_types})")
toga_code.append(f" if path:")
toga_code.append(f" {comp['type'].lower()}_label_{idx}.text = f'{label_prefix}: {{path}}'")
toga_code.append(f" {comp['type'].lower()}_button_{idx} = toga.Button('Upload {comp['type']}', on_press=select_{comp['type'].lower()}_{idx}, style=Pack(padding=5))")
toga_code.append(f" box.add(toga.Label('{label_prefix}', style=Pack(padding=(5, 5, 0, 5))))")
toga_code.append(f" box.add({comp['type'].lower()}_button_{idx})")
toga_code.append(f" box.add({comp['type'].lower()}_label_{idx})")
elif comp["type"] == "Button":
label = comp["kwargs"].get("value", f"'{label_prefix} {idx}'")
toga_code.append(f" def button_handler_{idx}(widget):")
toga_code.append(f" # Implement logic for {functions[0] if functions else 'function'}")
toga_code.append(f" pass")
toga_code.append(f" button_{idx} = {toga_comp}(label={label}, {extra})")
toga_code.append(f" box.add(button_{idx})")
elif comp["type"] == "Markdown":
text = comp["args"][0] if comp["args"] else f"'{label_prefix} {idx}'"
toga_code.append(f" markdown_{idx} = {toga_comp}({text}, {extra})")
toga_code.append(f" box.add(markdown_{idx})")
else:
toga_code.append(f" placeholder_{idx} = {toga_comp}('{extra}', style=Pack(padding=5))")
toga_code.append(f" box.add(placeholder_{idx})")
toga_code.extend([
"",
" return box",
"",
"def main():",
" return toga.App('Gradio to Toga App', 'org.example.gradio2toga', startup=build)",
"",
"if __name__ == '__main__':",
" main().main_loop()"
])
return "\n".join(toga_code)
# Conversion function
def convert_gradio_to_toga(file):
if not file:
return None, "Please upload a Gradio app Python file."
try:
code = file.decode('utf-8')
components, functions = parse_gradio_code(code)
if not components and functions and isinstance(functions[0], str):
return None, f"Error: {functions[0]}"
toga_code = generate_toga_code(components, functions)
output_path = "/tmp/toga_app.py"
with open(output_path, "w") as f:
f.write(toga_code)
return output_path, "Conversion successful! Download the Toga app below."
except Exception as e:
return None, f"Error: {str(e)}"
# Gradio interface
with gr.Blocks(theme=gr.themes.Soft()) as interface:
gr.Markdown("# Gradio to Toga Converter")
gr.Markdown("Upload a Gradio app (.py) to convert it to a Toga desktop app.")
file_input = gr.File(label="Upload Gradio App", file_types=[".py"])
convert_button = gr.Button("Convert to Toga")
output = gr.File(label="Download Toga App")
status = gr.Textbox(label="Status", interactive=False)
convert_button.click(
fn=convert_gradio_to_toga,
inputs=file_input,
outputs=[output, status]
)
# Run Gradio directly for Hugging Face Spaces
if __name__ == "__main__":
interface.launch(server_name="0.0.0.0", server_port=int(os.environ.get("PORT", 7860)), quiet=True) |