Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1 |
import gradio as gr
|
2 |
import ast
|
|
|
3 |
import os
|
4 |
from io import StringIO
|
5 |
|
@@ -19,35 +20,54 @@ def parse_gradio_code(code):
|
|
19 |
tree = ast.parse(code)
|
20 |
components = []
|
21 |
functions = []
|
|
|
22 |
|
23 |
for node in ast.walk(tree):
|
|
|
24 |
if isinstance(node, ast.FunctionDef):
|
25 |
-
functions.append(node
|
|
|
26 |
if isinstance(node, ast.Call) and hasattr(node.func, 'attr'):
|
27 |
if node.func.attr in GRADIO_TO_TOGA:
|
28 |
component = node.func.attr
|
29 |
args = [ast.dump(arg, annotate_fields=False) for arg in node.args]
|
30 |
kwargs = {kw.arg: ast.dump(kw.value, annotate_fields=False) for kw in node.keywords}
|
31 |
components.append({"type": component, "args": args, "kwargs": kwargs})
|
|
|
|
|
|
|
32 |
|
33 |
-
return components, functions
|
34 |
except Exception as e:
|
35 |
-
return [], [f"Error parsing code: {str(e)}"]
|
36 |
|
37 |
# Generate Toga code
|
38 |
-
def generate_toga_code(components, functions):
|
39 |
toga_code = [
|
40 |
"import toga",
|
41 |
"from toga.style import Pack",
|
42 |
"from toga.style.pack import COLUMN",
|
43 |
-
""
|
44 |
-
|
45 |
-
|
46 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
"def build(app):",
|
48 |
" box = toga.Box(style=Pack(direction=COLUMN, padding=10))",
|
49 |
""
|
50 |
-
]
|
51 |
|
52 |
for idx, comp in enumerate(components):
|
53 |
toga_comp, extra, label_prefix = GRADIO_TO_TOGA.get(comp["type"], ("toga.Label", f"Placeholder: {comp['type']} not supported", "Unknown"))
|
@@ -77,9 +97,11 @@ def generate_toga_code(components, functions):
|
|
77 |
|
78 |
elif comp["type"] == "Button":
|
79 |
label = comp["kwargs"].get("value", f"'{label_prefix} {idx}'")
|
|
|
|
|
80 |
toga_code.append(f" def button_handler_{idx}(widget):")
|
81 |
-
toga_code.append(f" #
|
82 |
-
toga_code.append(f" pass")
|
83 |
toga_code.append(f" button_{idx} = {toga_comp}(label={label}, {extra})")
|
84 |
toga_code.append(f" box.add(button_{idx})")
|
85 |
|
@@ -113,12 +135,12 @@ def convert_gradio_to_toga(file, code_text):
|
|
113 |
try:
|
114 |
# Use file if provided, else use text
|
115 |
code = file.decode('utf-8') if file else code_text
|
116 |
-
components, functions = parse_gradio_code(code)
|
117 |
|
118 |
if not components and functions and isinstance(functions[0], str):
|
119 |
return None, None, f"Error: {functions[0]}"
|
120 |
|
121 |
-
toga_code = generate_toga_code(components, functions)
|
122 |
output_path = "/tmp/toga_app.py"
|
123 |
with open(output_path, "w") as f:
|
124 |
f.write(toga_code)
|
|
|
1 |
import gradio as gr
|
2 |
import ast
|
3 |
+
import astor
|
4 |
import os
|
5 |
from io import StringIO
|
6 |
|
|
|
20 |
tree = ast.parse(code)
|
21 |
components = []
|
22 |
functions = []
|
23 |
+
imports = []
|
24 |
|
25 |
for node in ast.walk(tree):
|
26 |
+
# Extract function definitions
|
27 |
if isinstance(node, ast.FunctionDef):
|
28 |
+
functions.append(node)
|
29 |
+
# Extract Gradio component calls
|
30 |
if isinstance(node, ast.Call) and hasattr(node.func, 'attr'):
|
31 |
if node.func.attr in GRADIO_TO_TOGA:
|
32 |
component = node.func.attr
|
33 |
args = [ast.dump(arg, annotate_fields=False) for arg in node.args]
|
34 |
kwargs = {kw.arg: ast.dump(kw.value, annotate_fields=False) for kw in node.keywords}
|
35 |
components.append({"type": component, "args": args, "kwargs": kwargs})
|
36 |
+
# Extract imports
|
37 |
+
if isinstance(node, (ast.Import, ast.ImportFrom)):
|
38 |
+
imports.append(node)
|
39 |
|
40 |
+
return components, functions, imports
|
41 |
except Exception as e:
|
42 |
+
return [], [], [f"Error parsing code: {str(e)}"]
|
43 |
|
44 |
# Generate Toga code
|
45 |
+
def generate_toga_code(components, functions, imports):
|
46 |
toga_code = [
|
47 |
"import toga",
|
48 |
"from toga.style import Pack",
|
49 |
"from toga.style.pack import COLUMN",
|
50 |
+
""
|
51 |
+
]
|
52 |
+
|
53 |
+
# Add imports
|
54 |
+
toga_code.append("# Dependencies from Gradio app")
|
55 |
+
for imp in imports:
|
56 |
+
toga_code.append(astor.to_source(imp).strip())
|
57 |
+
toga_code.append("")
|
58 |
+
|
59 |
+
# Add function definitions
|
60 |
+
toga_code.append("# Functions from Gradio app")
|
61 |
+
for func in functions:
|
62 |
+
toga_code.append(astor.to_source(func).strip())
|
63 |
+
toga_code.append("")
|
64 |
+
|
65 |
+
# Generate UI
|
66 |
+
toga_code.extend([
|
67 |
"def build(app):",
|
68 |
" box = toga.Box(style=Pack(direction=COLUMN, padding=10))",
|
69 |
""
|
70 |
+
])
|
71 |
|
72 |
for idx, comp in enumerate(components):
|
73 |
toga_comp, extra, label_prefix = GRADIO_TO_TOGA.get(comp["type"], ("toga.Label", f"Placeholder: {comp['type']} not supported", "Unknown"))
|
|
|
97 |
|
98 |
elif comp["type"] == "Button":
|
99 |
label = comp["kwargs"].get("value", f"'{label_prefix} {idx}'")
|
100 |
+
# Check for associated function in click events
|
101 |
+
click_fn = comp["kwargs"].get("fn", f"{functions[0].name if functions else 'function'}")
|
102 |
toga_code.append(f" def button_handler_{idx}(widget):")
|
103 |
+
toga_code.append(f" # Call {click_fn} with inputs")
|
104 |
+
toga_code.append(f" pass # Implement logic using input values")
|
105 |
toga_code.append(f" button_{idx} = {toga_comp}(label={label}, {extra})")
|
106 |
toga_code.append(f" box.add(button_{idx})")
|
107 |
|
|
|
135 |
try:
|
136 |
# Use file if provided, else use text
|
137 |
code = file.decode('utf-8') if file else code_text
|
138 |
+
components, functions, imports = parse_gradio_code(code)
|
139 |
|
140 |
if not components and functions and isinstance(functions[0], str):
|
141 |
return None, None, f"Error: {functions[0]}"
|
142 |
|
143 |
+
toga_code = generate_toga_code(components, functions, imports)
|
144 |
output_path = "/tmp/toga_app.py"
|
145 |
with open(output_path, "w") as f:
|
146 |
f.write(toga_code)
|