space / app.py
codeboosterstech's picture
Create app.py
03ee311 verified
"""
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 = '<div class="error-message"><h4>Validation Errors:</h4><ul>'
for error in errors:
error_html += f'<li>{error}</li>'
error_html += '</ul></div>'
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'''
<div class="status-message {msg_type}">
<span class="material-icons" style="color: {colors[msg_type]}; vertical-align: middle;">
{icons[msg_type]}
</span>
<span style="vertical-align: middle; margin-left: 8px;">{message}</span>
</div>
'''
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('<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">')
# 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='<div class="status-container"></div>',
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
)