""" Main application file for Hugging Face Space Creator Enterprise-grade Gradio application for converting Python code to deployable Gradio apps """ import gradio as gr import tempfile import os import sys from pathlib import Path # Add utils and components to path sys.path.append(str(Path(__file__).parent)) from utils.converter import convert_code from utils.deployer import deploy_to_space from utils.file_handler import ( create_zip_archive, read_file_content, parse_notebook, save_individual_file ) from utils.validator import validate_inputs from components.header import create_header from components.sidebar import create_sidebar from components.api_guide import create_api_guide from components.file_downloader import create_file_download_section # Constants MAX_FILE_SIZE = 10 * 1024 * 1024 # 10MB SUPPORTED_EXTENSIONS = ['.py', '.ipynb', '.txt'] class SpaceCreatorApp: """Main application class for Hugging Face Space Creator""" def __init__(self): self.temp_files = [] self.current_step = 1 self.generated_files = {} def cleanup(self): """Clean up temporary files""" for file_path in self.temp_files: try: if os.path.exists(file_path): os.remove(file_path) except: pass self.temp_files = [] def process_step1(self, input_text, input_file, groq_api_key): """Step 1: Convert code to Gradio app""" try: # Validate inputs validation_errors = validate_inputs(groq_api_key, None, None, "Convert Only") if validation_errors: return None, None, None, None, self._format_errors(validation_errors), 1 # Get source code code_content = self._extract_code(input_text, input_file) if not code_content.strip(): return None, None, None, None, "Please provide Python code to convert.", 1 # Convert code conversion_result = convert_code(code_content, groq_api_key) # Store generated files self.generated_files = { "app.py": conversion_result["app_py"], "requirements.txt": conversion_result["requirements_txt"], "README.md": conversion_result["readme_md"] } # Create individual files for download file_paths = {} for filename, content in self.generated_files.items(): file_path = save_individual_file(filename, content) self.temp_files.append(file_path) file_paths[filename] = file_path status = self._create_status_message("success", "Code conversion successful!") return (file_paths["app.py"], file_paths["requirements.txt"], file_paths["README.md"], None, status, 2) except Exception as e: error_msg = self._create_status_message("error", f"Conversion failed: {str(e)}") return None, None, None, None, error_msg, 1 def process_step2(self, hf_token, space_name, deploy_mode): """Step 2: Deploy to Hugging Face""" try: if deploy_mode != "Deploy to Hugging Face Space": status = self._create_status_message("info", "Skipping deployment as requested.") return None, status, 2 # Validate deployment inputs validation_errors = validate_inputs(None, hf_token, space_name, "Deploy") if validation_errors: return None, self._format_errors(validation_errors), 2 # Deploy to Hugging Face deploy_url = deploy_to_space(hf_token, space_name, self.generated_files) # Create zip archive of all files zip_bytes = create_zip_archive(self.generated_files) zip_path = save_individual_file("gradio_app_full_package.zip", zip_bytes, binary=True) self.temp_files.append(zip_path) status = self._create_status_message("success", f"Deployment successful! Space URL: {deploy_url}") return zip_path, status, 3 except Exception as e: error_msg = self._create_status_message("error", f"Deployment failed: {str(e)}") return None, error_msg, 2 def _extract_code(self, input_text, input_file): """Extract code from text or file""" code_content = "" if input_file is not None: file_content = read_file_content(input_file) if input_file.name.endswith('.ipynb') if hasattr(input_file, 'name') else False: with tempfile.NamedTemporaryFile(mode='w', suffix='.ipynb', delete=False, encoding='utf-8') as tmp: tmp.write(file_content) tmp_path = tmp.name try: code_content = parse_notebook(tmp_path) finally: os.unlink(tmp_path) else: code_content = file_content elif input_text.strip(): code_content = input_text return code_content def _format_errors(self, errors): """Format validation errors""" error_html = '
' return error_html def _create_status_message(self, msg_type, message): """Create formatted status message""" icons = { "success": "check_circle", "error": "error", "warning": "warning", "info": "info" } colors = { "success": "#10B981", "error": "#EF4444", "warning": "#F59E0B", "info": "#3B82F6" } return f''' ''' def create_app(): """Create the Gradio application interface""" app = SpaceCreatorApp() with gr.Blocks( title="Hugging Face Space Creator", theme=gr.themes.Soft(primary_hue="yellow"), css="static/css/style.css" ) as demo: # Custom CSS gr.HTML('') # Header create_header() with gr.Row(): # Sidebar with steps with gr.Column(scale=1, min_width=300): current_step = gr.State(1) sidebar = create_sidebar(current_step) # Main content area with gr.Column(scale=3): # Step 1: Code Input and Conversion with gr.Group(visible=True) as step1_group: gr.Markdown("### Step 1: Provide Your Code") with gr.Tabs(): with gr.Tab("Upload File", id="upload_tab"): file_input = gr.File( label="Upload Python or Jupyter Notebook", file_types=SUPPORTED_EXTENSIONS, type="filepath" ) with gr.Tab("Paste Code", id="paste_tab"): text_input = gr.Textbox( label="Python Code", lines=20, placeholder="# Paste your Python code here...\n\n# Example:\ndef add(a, b):\n return a + b\n\ndef greet(name):\n return f\"Hello, {name}!\"", elem_id="code_editor" ) gr.Markdown("### Step 1b: API Configuration") with gr.Row(): with gr.Column(): groq_api_key = gr.Textbox( label="Groq API Key", type="password", placeholder="Enter your Groq API key starting with gsk_", info="Required for AI-powered conversion" ) # API Key Creation Guide api_guide = create_api_guide() with gr.Row(): convert_btn = gr.Button( "Convert Code", variant="primary", size="lg", elem_id="convert_btn" ) # Step 2: Generated Files with gr.Group(visible=False) as step2_group: gr.Markdown("### Step 2: Generated Files") with gr.Row(): with gr.Column(): app_py_download = gr.File( label="app.py", file_types=[".py"], interactive=False ) with gr.Column(): requirements_download = gr.File( label="requirements.txt", file_types=[".txt"], interactive=False ) with gr.Column(): readme_download = gr.File( label="README.md", file_types=[".md"], interactive=False ) gr.Markdown("### Step 2b: Deployment Options") with gr.Row(): with gr.Column(): hf_token = gr.Textbox( label="Hugging Face Token", type="password", placeholder="Enter your Hugging Face token starting with hf_", info="Required for deployment" ) with gr.Column(): space_name = gr.Textbox( label="Space Name", placeholder="my-gradio-application", info="Lowercase letters, numbers, and hyphens only" ) deploy_mode = gr.Radio( choices=["Download Only", "Deploy to Hugging Face Space"], label="Select Action", value="Download Only", elem_id="deploy_mode" ) with gr.Row(): back_btn_step2 = gr.Button("Back", variant="secondary") deploy_btn = gr.Button("Proceed to Deployment", variant="primary") # Step 3: Deployment Results with gr.Group(visible=False) as step3_group: gr.Markdown("### Step 3: Deployment Complete") with gr.Row(): with gr.Column(): full_package_download = gr.File( label="Complete Application Package", file_types=[".zip"], interactive=False ) deployment_status = gr.Markdown() with gr.Row(): back_btn_step3 = gr.Button("Start New Project", variant="secondary") finish_btn = gr.Button("Finish", variant="primary") # Status output status_output = gr.HTML( value='', elem_id="status_output" ) # Event handlers convert_btn.click( fn=app.process_step1, inputs=[text_input, file_input, groq_api_key], outputs=[ app_py_download, requirements_download, readme_download, full_package_download, status_output, current_step ] ).then( fn=lambda step: (gr.update(visible=step==1), gr.update(visible=step==2), gr.update(visible=step==3)), inputs=[current_step], outputs=[step1_group, step2_group, step3_group] ) deploy_btn.click( fn=app.process_step2, inputs=[hf_token, space_name, deploy_mode], outputs=[full_package_download, status_output, current_step] ).then( fn=lambda step: (gr.update(visible=step==1), gr.update(visible=step==2), gr.update(visible=step==3)), inputs=[current_step], outputs=[step1_group, step2_group, step3_group] ) back_btn_step2.click( fn=lambda: (1, gr.update(visible=True), gr.update(visible=False), gr.update(visible=False)), outputs=[current_step, step1_group, step2_group, step3_group] ) back_btn_step3.click( fn=lambda: (1, gr.update(visible=True), gr.update(visible=False), gr.update(visible=False)), outputs=[current_step, step1_group, step2_group, step3_group] ).then( fn=app.cleanup, inputs=None, outputs=None ) finish_btn.click( fn=app.cleanup, inputs=None, outputs=None ) return demo if __name__ == "__main__": print("Starting Hugging Face Space Creator...") print("=" * 50) print("Enterprise-grade Python to Gradio App Converter") print("=" * 50) app = create_app() app.launch( server_name="0.0.0.0", server_port=7860, share=False, debug=True, favicon_path=None )