Spaces:
Sleeping
Sleeping
File size: 6,971 Bytes
4b6f4f0 a62df18 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 d02164f a62df18 4b6f4f0 d02164f 4b6f4f0 a62df18 4b6f4f0 05977dd 4b6f4f0 a62df18 4b6f4f0 a62df18 4b6f4f0 05977dd d02164f a364f6d d02164f 05977dd a62df18 a364f6d 05977dd d02164f a62df18 05977dd 4b6f4f0 d02164f 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 147 148 149 |
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, code_text):
if not file and not code_text:
return None, None, "Please upload a Gradio app Python file or paste code in the textbox."
try:
# Use file if provided, else use text
code = file.decode('utf-8') if file else code_text
components, functions = parse_gradio_code(code)
if not components and functions and isinstance(functions[0], str):
return None, 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, toga_code, "Conversion successful! Preview the Toga code below and download the app."
except Exception as e:
return None, 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) or paste the code below to convert to a Toga desktop app.")
file_input = gr.File(label="Upload Gradio App", file_types=[".py"])
code_input = gr.Textbox(label="Paste Gradio Code", lines=10, placeholder="Paste your Gradio Python code here...")
convert_button = gr.Button("Convert to Toga")
toga_preview = gr.Textbox(label="Toga Code Preview", lines=15, interactive=False)
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, code_input],
outputs=[output, toga_preview, status]
)
# Run Gradio 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) |