app-jmbbwx-74 / utils.py
AiCoderv2's picture
Deploy Gradio app with multiple files
629446c verified
import os
import json
import zipfile
import shutil
import subprocess
import tempfile
from pathlib import Path
from typing import Dict, List, Optional
import threading
import time
from http.server import HTTPServer, SimpleHTTPRequestHandler
import socket
class FileHandler:
"""Handle file operations for website projects"""
def __init__(self):
self.projects_dir = Path("projects")
self.projects_dir.mkdir(exist_ok=True)
def create_project(self, project_name: str, files: Dict[str, str]) -> Path:
"""Create a new project with generated files"""
project_path = self.projects_dir / project_name
# Remove existing project if it exists
if project_path.exists():
shutil.rmtree(project_path)
project_path.mkdir(exist_ok=True)
# Write all files
for file_path, content in files.items():
full_path = project_path / file_path
full_path.parent.mkdir(parents=True, exist_ok=True)
with open(full_path, 'w', encoding='utf-8') as f:
f.write(content)
return project_path
def get_project_files(self, project_path: Path) -> Dict[str, str]:
"""Get all files in a project"""
files = {}
if project_path.exists():
for file_path in project_path.rglob("*"):
if file_path.is_file():
relative_path = file_path.relative_to(project_path)
files[str(relative_path)] = self.get_file_content(project_path, str(relative_path))
return files
def get_file_content(self, project_path: Path, filename: str) -> str:
"""Get content of a specific file"""
file_path = project_path / filename
if file_path.exists():
with open(file_path, 'r', encoding='utf-8') as f:
return f.read()
return ""
def create_zip(self, project_path: Path) -> str:
"""Create a ZIP file of the project"""
zip_path = f"{project_path}.zip"
with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
for file_path in project_path.rglob("*"):
if file_path.is_file():
arcname = file_path.relative_to(project_path.parent)
zipf.write(file_path, arcname)
return zip_path
class PreviewManager:
"""Manage live preview of websites"""
def __init__(self):
self.active_servers = {}
self.port_counter = 8000
def get_free_port(self) -> int:
"""Find a free port for the preview server"""
while True:
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(('localhost', self.port_counter))
return self.port_counter
except OSError:
self.port_counter += 1
def create_preview(self, project_path: Path) -> str:
"""Create a live preview server for the project"""
port = self.get_free_port()
# Start server in a separate thread
server_thread = threading.Thread(
target=self._run_server,
args=(project_path, port),
daemon=True
)
server_thread.start()
# Give server time to start
time.sleep(0.5)
self.active_servers[str(project_path)] = port
return f"http://localhost:{port}"
def update_preview(self, project_path: Path) -> str:
"""Update the preview (server already running)"""
if str(project_path) in self.active_servers:
port = self.active_servers[str(project_path)]
return f"http://localhost:{port}"
return self.create_preview(project_path)
def _run_server(self, project_path: Path, port: int):
"""Run HTTP server for preview"""
os.chdir(project_path)
class CustomHandler(SimpleHTTPRequestHandler):
def __init__(self, *args, **kwargs):
super().__init__(*args, directory=project_path, **kwargs)
def end_headers(self):
# Add CORS headers
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
self.send_header('Access-Control-Allow-Headers', 'Content-Type')
super().end_headers()
try:
httpd = HTTPServer(('localhost', port), CustomHandler)
httpd.serve_forever()
except Exception as e:
print(f"Server error: {e}")
def detect_file_language(filename: str) -> str:
"""Detect programming language from file extension"""
ext = Path(filename).suffix.lower()
lang_map = {
'.html': 'html',
'.css': 'css',
'.js': 'javascript',
'.json': 'json',
'.md': 'markdown',
'.py': 'python',
'.jsx': 'jsx',
'.tsx': 'typescript',
'.ts': 'typescript',
'.xml': 'xml',
'.yaml': 'yaml',
'.yml': 'yaml',
'.sql': 'sql',
'.php': 'php',
'.rb': 'ruby',
'.go': 'go',
'.java': 'java',
'.c': 'c',
'.cpp': 'cpp',
'.h': 'c',
'.hpp': 'cpp',
'.scss': 'scss',
'.sass': 'sass',
'.less': 'less',
'.vue': 'vue',
'.svelte': 'svelte'
}
return lang_map.get(ext, 'text')
def format_file_size(size_bytes: int) -> str:
"""Format file size in human readable format"""
if size_bytes == 0:
return "0B"
size_names = ["B", "KB", "MB", "GB"]
i = 0
while size_bytes >= 1024 and i < len(size_names) - 1:
size_bytes /= 1024.0
i += 1
return f"{size_bytes:.1f}{size_names[i]}"