|
|
|
|
|
""" |
|
Handles deployment of generated code to Hugging Face Spaces. |
|
|
|
This module provides functions to wrap generated code into a runnable |
|
Gradio or Static HTML app and to programmatically create and upload |
|
it to a user's Hugging Face Space. |
|
""" |
|
import tempfile |
|
import webbrowser |
|
import logging |
|
from urllib.parse import urlencode |
|
|
|
from huggingface_hub import HfApi, HfFolder |
|
import gradio as gr |
|
|
|
def _create_space_readme(space_name: str, sdk: str) -> str: |
|
"""Generates a standard README.md file for the new Space.""" |
|
return f"""--- |
|
title: {space_name} |
|
emoji: π |
|
colorFrom: blue |
|
colorTo: green |
|
sdk: {sdk} |
|
--- |
|
|
|
# {space_name} |
|
|
|
This Space was generated by [AnyCoder](<YOUR_APP_SPACE_URL>). |
|
""" |
|
|
|
def deploy_to_hf_space( |
|
code: str, |
|
space_name: str, |
|
sdk: str, |
|
hf_token: str |
|
) -> str: |
|
""" |
|
Creates or updates a Hugging Face Space and uploads the generated code. |
|
|
|
Args: |
|
code: The code to deploy (HTML or Python). |
|
space_name: The desired name for the Space. |
|
sdk: The SDK for the Space ('static', 'gradio', 'streamlit'). |
|
hf_token: The user's Hugging Face write token. |
|
|
|
Returns: |
|
A success or error message with a link to the Space. |
|
""" |
|
if not code or not code.strip(): |
|
return "Cannot deploy: No code has been generated." |
|
if not space_name or not space_name.strip(): |
|
return "Cannot deploy: Please provide a name for your app." |
|
if not hf_token: |
|
|
|
return deploy_via_url(code, space_name, sdk) |
|
|
|
try: |
|
api = HfApi(token=hf_token) |
|
user_info = api.whoami(token=hf_token) |
|
username = user_info['name'] |
|
repo_id = f"{username}/{space_name.strip()}" |
|
|
|
api.create_repo(repo_id, repo_type="space", space_sdk=sdk, exist_ok=True) |
|
|
|
if sdk == 'static': |
|
file_content = code |
|
file_path_in_repo = "index.html" |
|
else: |
|
file_content = code |
|
file_path_in_repo = "app.py" |
|
|
|
|
|
api.upload_file( |
|
path_or_fileobj=file_content.encode('utf-8'), |
|
path_in_repo=file_path_in_repo, |
|
repo_id=repo_id, |
|
repo_type="space" |
|
) |
|
|
|
readme_content = _create_space_readme(space_name, sdk) |
|
api.upload_file( |
|
path_or_fileobj=readme_content.encode('utf-8'), |
|
path_in_repo="README.md", |
|
repo_id=repo_id, |
|
repo_type="space" |
|
) |
|
|
|
space_url = f"https://huggingface.co/spaces/{repo_id}" |
|
return f"β
Deployed successfully! [Open your Space]({space_url})" |
|
|
|
except Exception as e: |
|
logging.error(f"Failed to deploy to Hugging Face Space: {e}") |
|
return f"β Deployment failed: {str(e)}" |
|
|
|
def deploy_via_url(code: str, space_name: str, sdk: str) -> str: |
|
""" |
|
Opens a new browser tab with pre-filled parameters to create a Space. |
|
This is a fallback for users who are not logged in via OAuth. |
|
""" |
|
if sdk == 'static': |
|
app_file = "index.html" |
|
content = code |
|
else: |
|
app_file = "app.py" |
|
|
|
content = code |
|
|
|
params = urlencode({ |
|
"name": space_name, |
|
"sdk": sdk, |
|
"files[0][path]": app_file, |
|
"files[0][content]": content |
|
}) |
|
base_url = "https://huggingface.co/new-space" |
|
full_url = f"{base_url}?{params}" |
|
|
|
webbrowser.open_new_tab(full_url) |
|
return "π Your app is ready to launch! Check the new browser tab." |