import gradio as gr import os import json import importlib import sys from contextlib import redirect_stdout, redirect_stderr import io # Set environment variable to avoid matplotlib permission issues os.environ['MPLCONFIGDIR'] = '/tmp' # Example app implementations APP_REGISTRY = { "hello_world": { "title": "Hello World", "description": "A simple greeting app", "function": None # will be populated }, "calculator": { "title": "Calculator", "description": "A basic arithmetic calculator", "function": None # will be populated }, "image_filter": { "title": "Image Filter", "description": "Apply visual effects to images", "function": None # will be populated } } # Hello World implementation def create_hello_world(): def greet(name): return f"Hello, {name}!" demo = gr.Interface( fn=greet, inputs=gr.Textbox(label="Your Name"), outputs=gr.Textbox(label="Greeting"), title="Hello World App", description="A simple greeting app", examples=[["World"], ["Friend"], ["Gradio"]] ) return demo # Calculator implementation def create_calculator(): def calculate(num1, num2, operation): if operation == "Add": return num1 + num2 elif operation == "Subtract": return num1 - num2 elif operation == "Multiply": return num1 * num2 elif operation == "Divide": if num2 == 0: return "Error: Division by zero" return num1 / num2 demo = gr.Interface( fn=calculate, inputs=[ gr.Number(label="First Number"), gr.Number(label="Second Number"), gr.Radio(["Add", "Subtract", "Multiply", "Divide"], label="Operation") ], outputs=gr.Textbox(label="Result"), title="Calculator App", description="Perform basic arithmetic operations", examples=[ [5, 3, "Add"], [10, 4, "Subtract"], [6, 7, "Multiply"], [20, 4, "Divide"] ] ) return demo # Image Filter implementation def create_image_filter(): def apply_filter(image, filter_type): if image is None: return None import numpy as np from PIL import Image img_array = np.array(image) if filter_type == "Grayscale": result = np.mean(img_array, axis=2).astype(np.uint8) return Image.fromarray(result) elif filter_type == "Invert": result = 255 - img_array return Image.fromarray(result) elif filter_type == "Sepia": sepia = np.array([[0.393, 0.769, 0.189], [0.349, 0.686, 0.168], [0.272, 0.534, 0.131]]) sepia_img = img_array.dot(sepia.T) sepia_img[sepia_img > 255] = 255 return Image.fromarray(sepia_img.astype(np.uint8)) return image demo = gr.Interface( fn=apply_filter, inputs=[ gr.Image(type="pil"), gr.Radio(["Grayscale", "Invert", "Sepia"], label="Filter") ], outputs=gr.Image(type="pil"), title="Image Filter App", description="Apply different filters to your images", examples=[ ["https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=500", "Grayscale"], ["https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=500", "Invert"], ["https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=500", "Sepia"] ] ) return demo # Register demo creation functions APP_REGISTRY["hello_world"]["function"] = create_hello_world APP_REGISTRY["calculator"]["function"] = create_calculator APP_REGISTRY["image_filter"]["function"] = create_image_filter # Example of code for each app as a string (for display purposes) APP_CODES = { "hello_world": """ import gradio as gr def greet(name): return f"Hello, {name}!" demo = gr.Interface( fn=greet, inputs=gr.Textbox(label="Your Name"), outputs=gr.Textbox(label="Greeting"), title="Hello World App", description="A simple greeting app", examples=[["World"], ["Friend"], ["Gradio"]] ) """, "calculator": """ import gradio as gr def calculate(num1, num2, operation): if operation == "Add": return num1 + num2 elif operation == "Subtract": return num1 - num2 elif operation == "Multiply": return num1 * num2 elif operation == "Divide": if num2 == 0: return "Error: Division by zero" return num1 / num2 demo = gr.Interface( fn=calculate, inputs=[ gr.Number(label="First Number"), gr.Number(label="Second Number"), gr.Radio(["Add", "Subtract", "Multiply", "Divide"], label="Operation") ], outputs=gr.Textbox(label="Result"), title="Calculator App", description="Perform basic arithmetic operations", examples=[ [5, 3, "Add"], [10, 4, "Subtract"], [6, 7, "Multiply"], [20, 4, "Divide"] ] ) """, "image_filter": """ import gradio as gr import numpy as np from PIL import Image def apply_filter(image, filter_type): if image is None: return None img_array = np.array(image) if filter_type == "Grayscale": result = np.mean(img_array, axis=2).astype(np.uint8) return Image.fromarray(result) elif filter_type == "Invert": result = 255 - img_array return Image.fromarray(result) elif filter_type == "Sepia": sepia = np.array([[0.393, 0.769, 0.189], [0.349, 0.686, 0.168], [0.272, 0.534, 0.131]]) sepia_img = img_array.dot(sepia.T) sepia_img[sepia_img > 255] = 255 return Image.fromarray(sepia_img.astype(np.uint8)) return image demo = gr.Interface( fn=apply_filter, inputs=[ gr.Image(type="pil"), gr.Radio(["Grayscale", "Invert", "Sepia"], label="Filter") ], outputs=gr.Image(type="pil"), title="Image Filter App", description="Apply different filters to your images", examples=[ ["https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=500", "Grayscale"], ["https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=500", "Invert"], ["https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=500", "Sepia"] ] ) """ } # Create an app selector that loads apps dynamically def create_main_app(): with gr.Blocks(title="Dynamic Gradio App Generator") as demo: gr.Markdown("# 🔄 Dynamic Gradio App Generator") gr.Markdown("Select an app type to load it dynamically without refreshing the page") # Create placeholders for dynamic app loading app_blocks_container = gr.Blocks(visible=False) with app_blocks_container: # This container will be dynamically replaced app_placeholder = gr.Markdown("Loading app...") with gr.Row(): with gr.Column(scale=1): # App selection area gr.Markdown("### Choose an App Template") app_selection = gr.Radio( choices=list(APP_REGISTRY.keys()), value="hello_world", label="Available Templates", info="Select a template to view and run it", interactive=True ) # Description display app_description = gr.Markdown(f"**{APP_REGISTRY['hello_world']['title']}**: {APP_REGISTRY['hello_world']['description']}") # Load button load_btn = gr.Button("Load Selected App", variant="primary") # Code display with gr.Accordion("View Code", open=False): code_display = gr.Code( language="python", value=APP_CODES["hello_world"], label="App Code" ) # Status message status_msg = gr.Markdown("Select an app and click 'Load Selected App'") with gr.Column(scale=2): # This is where our dynamically loaded app will appear app_container = gr.Group(visible=True) with app_container: gr.Markdown("### App Preview") gr.Markdown("No app loaded yet. Select an app and click 'Load Selected App'.") # Update description and code when selection changes def update_description_and_code(selection): return ( f"**{APP_REGISTRY[selection]['title']}**: {APP_REGISTRY[selection]['description']}", APP_CODES[selection] ) app_selection.change( update_description_and_code, inputs=app_selection, outputs=[app_description, code_display] ) # Load the selected app @gr.on(load_btn, "click") def load_selected_app(selection): try: # Create the app app_func = APP_REGISTRY[selection]["function"] app = app_func() # Update the container content (this is done via JavaScript) return { status_msg: f"Successfully loaded {APP_REGISTRY[selection]['title']}", app_container: gr.update(visible=False), # Hide temporarily for replacement } except Exception as e: error_msg = str(e) return { status_msg: f"Error loading app: {error_msg}", app_container: gr.update(visible=True), } # This uses Gradio's JavaScript event handling to dynamically mount the app demo.load(None, js=""" function() { let loadedAppIframe = null; let intervalId = null; // Function to handle the "Load Selected App" button click document.addEventListener('click', function(event) { // Find button by text or class if (event.target.textContent === 'Load Selected App' || (event.target.parentElement && event.target.parentElement.textContent === 'Load Selected App')) { // Get the selected app const radioButtons = document.querySelectorAll('input[type="radio"]'); let selectedApp = null; for (const radio of radioButtons) { if (radio.checked) { selectedApp = radio.value; break; } } if (!selectedApp) return; // Stop any previous timer if (intervalId) { clearInterval(intervalId); } // Show loading indicator const appContainer = document.querySelector('.app-preview'); if (appContainer) { appContainer.innerHTML = '
Loading app...
'; } // Create route for app const appUrl = '/' + selectedApp; // Clean up previous iframe if exists if (loadedAppIframe) { loadedAppIframe.remove(); } // Create an iframe and load the app loadedAppIframe = document.createElement('iframe'); loadedAppIframe.style.width = '100%'; loadedAppIframe.style.height = '600px'; loadedAppIframe.style.border = 'none'; loadedAppIframe.src = appUrl; // Find the app container column (second column) const columns = document.querySelectorAll('.gradio-column'); if (columns.length > 1) { columns[1].innerHTML = ''; // Clear existing content columns[1].appendChild(loadedAppIframe); } // Update the status const statusEl = document.querySelector('#status-message'); if (statusEl) { statusEl.textContent = 'App loaded successfully'; } } }); } """) return demo # Function to create and mount all apps def create_app(): # Create the main selector app main_app = create_main_app() # Create all the individual apps for app_name, app_info in APP_REGISTRY.items(): app_func = app_info["function"] if app_func: app_instance = app_func() # This is for Gradio 4.x - it mounts each app at its own route main_app = gr.mount_gradio_app(main_app, app_instance, f"/{app_name}") return main_app # Launch the app if __name__ == "__main__": demo = create_app() demo.launch(server_name="0.0.0.0", server_port=7860)