Spaces:
Sleeping
Sleeping
File size: 6,923 Bytes
4b6f4f0 |
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 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
from flask import Flask, request, send_file, render_template_string
import gradio as gr
import ast
import os
from io import StringIO
app = Flask(__name__)
# Mapping of Gradio components to Toga equivalents
GRADIO_TO_TOGA = {
"Textbox": ("toga.TextInput", "placeholder='Enter Text'"),
"Image": ("toga.Label", "Placeholder: Use file picker for image"),
"Button": ("toga.Button", "on_press=button_handler"),
"Markdown": ("toga.Label", ""),
"Audio": ("toga.Label", "Placeholder: Audio not supported"),
"Video": ("toga.Label", "Placeholder: Video not supported"),
}
# Parse Gradio app code and extract components
def parse_gradio_code(code):
try:
tree = ast.parse(code)
components = []
functions = []
for node in ast.walk(tree):
# Extract function definitions
if isinstance(node, ast.FunctionDef):
functions.append(node.name)
# Extract Gradio component calls
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 [], [str(e)]
# Generate Toga code from parsed components
def generate_toga_code(components, functions):
toga_code = [
"import toga",
"from toga.style import Pack",
"from toga.style.pack import COLUMN, ROW",
"import os",
"",
"# Placeholder for original functions",
"# Copy your original function definitions here",
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 = GRADIO_TO_TOGA.get(comp["type"], ("toga.Label", f"Placeholder: {comp['type']} not supported"))
# Handle component-specific logic
if comp["type"] == "Textbox":
label = comp["kwargs"].get("label", f"'Text Input {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}(style=Pack(padding=5))")
toga_code.append(f" box.add(label_{idx})")
toga_code.append(f" box.add(input_{idx})")
elif comp["type"] == "Image":
toga_code.append(f" image_label_{idx} = toga.Label('Image: None selected', style=Pack(padding=5))")
toga_code.append(f" def select_image_{idx}(widget):")
toga_code.append(f" path = app.main_window.open_file_dialog('Select Image', file_types=['png', 'jpg', 'jpeg'])")
toga_code.append(f" if path:")
toga_code.append(f" image_label_{idx}.text = f'Image: {{path}}'")
toga_code.append(f" image_button_{idx} = toga.Button('Upload Image', on_press=select_image_{idx}, style=Pack(padding=5))")
toga_code.append(f" box.add(toga.Label('Upload Image', style=Pack(padding=(5, 5, 0, 5))))")
toga_code.append(f" box.add(image_button_{idx})")
toga_code.append(f" box.add(image_label_{idx})")
elif comp["type"] == "Button":
label = comp["kwargs"].get("value", f"'Submit {idx}'")
toga_code.append(f" def button_handler_{idx}(widget):")
toga_code.append(f" # Placeholder: Implement logic for {functions[0] if functions else 'function'}")
toga_code.append(f" pass")
toga_code.append(f" button_{idx} = {toga_comp}(label={label}, style=Pack(padding=5))")
toga_code.append(f" box.add(button_{idx})")
elif comp["type"] == "Markdown":
text = comp["args"][0] if comp["args"] else "'Markdown Text'"
toga_code.append(f" markdown_{idx} = {toga_comp}({text}, style=Pack(padding=5, font_size=16))")
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)
# Gradio interface for file upload
def convert_gradio_to_toga(file):
if not file:
return "Please upload a Gradio app Python file."
try:
# Read uploaded file
code = file.decode('utf-8')
components, functions = parse_gradio_code(code)
if not components and functions and isinstance(functions[0], str):
return f"Error parsing code: {functions[0]}"
# Generate Toga code
toga_code = generate_toga_code(components, functions)
# Save Toga code to a temporary file
output_path = "toga_app.py"
with open(output_path, "w") as f:
f.write(toga_code)
return send_file(output_path, as_attachment=True, download_name="toga_app.py")
except Exception as e:
return f"Error: {str(e)}"
# Gradio interface
def create_gradio_interface():
with gr.Blocks() as interface:
gr.Markdown("# Gradio to Toga Converter")
file_input = gr.File(label="Upload Gradio Python File")
convert_button = gr.Button("Convert to Toga")
output = gr.File(label="Download Toga App")
convert_button.click(
fn=convert_gradio_to_toga,
inputs=file_input,
outputs=output
)
return interface
# Flask route
@app.route('/')
def serve_gradio():
interface = create_gradio_interface()
# For Hugging Face Spaces, launch Gradio
interface.launch(share=False, server_name="0.0.0.0", server_port=int(os.environ.get("PORT", 7860)))
return render_template_string("""
<!DOCTYPE html>
<html>
<head>
<title>Gradio to Toga Converter</title>
</head>
<body>
<h1>Gradio to Toga Converter</h1>
<p>Access the Gradio interface to upload your Gradio app and download the Toga equivalent.</p>
</body>
</html>
""")
if __name__ == "__main__":
app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 7860))) |