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"] ] ) """ } # Main app with inline app loading for Gradio 3.50.2 def create_main_app(): with gr.Blocks(title="Dynamic Gradio App Generator", css="footer {visibility: hidden}") as demo: gr.Markdown("# 🔄 Dynamic Gradio App Generator") gr.Markdown("Select an app type to load it dynamically") # Keep track of the current loaded app current_app_name = gr.State(value=None) current_app_instance = gr.State(value=None) 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'") # App container (this will be dynamically updated with different apps) with gr.Row(id="app-container"): app_placeholder = gr.Markdown("No app loaded yet. Select an app and click 'Load Selected App'.") # Update description 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] ) # Function to load the selected app within the main app def load_app(app_name, previous_app_name, previous_app_instance): if app_name not in APP_REGISTRY: return ( gr.update(value="App not found!"), f"Error: App '{app_name}' not found", previous_app_name, previous_app_instance ) # If we already have this app loaded, just return it if app_name == previous_app_name and previous_app_instance is not None: return ( gr.update(visible=False), f"{APP_REGISTRY[app_name]['title']} is already loaded", app_name, previous_app_instance ) try: # Create a new instance of the selected app new_app_instance = APP_REGISTRY[app_name]["function"]() # Return values to update the UI return ( gr.update(visible=False), f"Successfully loaded {APP_REGISTRY[app_name]['title']}", app_name, new_app_instance ) except Exception as e: error_msg = str(e) return ( gr.update(value=f"Error loading app: {error_msg}"), f"Error: {error_msg}", previous_app_name, previous_app_instance ) # Handle app loading when button is clicked load_btn.click( load_app, inputs=[app_selection, current_app_name, current_app_instance], outputs=[app_placeholder, status_msg, current_app_name, current_app_instance] ) # Custom JavaScript to handle dynamic app loading demo.load(None, None, None, _js=""" function() { // Function to handle app loading and swapping window.loadGradioApp = function(appName, appInstance) { const appContainer = document.getElementById('app-container'); if (!appContainer) return; // Clear existing app container while (appContainer.firstChild) { appContainer.removeChild(appContainer.firstChild); } // Add new app to container if (appInstance && appInstance.wrapper) { appContainer.appendChild(appInstance.wrapper); } }; // Function to check for app updates window.checkAppUpdates = function() { const gradioEl = document.querySelector("gradio-app"); if (!gradioEl) return; const shadowRoot = gradioEl.shadowRoot || gradioEl; const appContainer = shadowRoot.querySelector("#app-container"); if (!appContainer) return; // Find any newly loaded app by looking for interface/blocks elements const newAppElements = shadowRoot.querySelectorAll(".gradio-container:not([id='main-container'])"); if (newAppElements.length > 0) { let foundNew = false; newAppElements.forEach(el => { // Only move elements that aren't already in our container if (!appContainer.contains(el)) { // Move the app to our container appContainer.innerHTML = ''; appContainer.appendChild(el); foundNew = true; } }); if (foundNew) { // Hide the placeholder message const placeholder = shadowRoot.querySelector("#app-container gradio-markdown"); if (placeholder) { placeholder.style.display = "none"; } } } }; // Set up an interval to check for app updates setInterval(window.checkAppUpdates, 500); } """) return demo # Helper function to save the app name for persistence def save_app_name(app_name): try: with open("current_app.txt", "w") as f: f.write(app_name) return True except: return False # Create the main app main_app = create_main_app() # Launch the app if __name__ == "__main__": main_app.launch(server_name="0.0.0.0", server_port=7860, share=False)