mobenta's picture
Update app.py
2ab0f03 verified
import os
import git
import shutil
import zipfile
from huggingface_hub import HfApi, create_repo
import gradio as gr
import requests
# Initialize Hugging Face API
api = HfApi()
def clone_repo(repo_url, repo_type=None, auth_token=None):
try:
print(f"Cloning repository from URL: {repo_url}")
repo_name = repo_url.split('/')[-1]
if os.path.exists(repo_name):
print(f"Removing existing directory: {repo_name}")
shutil.rmtree(repo_name)
if "huggingface.co" in repo_url:
repo_id = "/".join(repo_url.split("/")[-2:])
if repo_type is None:
repo_type = 'model'
api.snapshot_download(repo_id=repo_id, repo_type=repo_type, token=auth_token, local_dir=repo_name)
else:
if auth_token:
repo_url = repo_url.replace("https://", f"https://{auth_token}@")
git.Repo.clone_from(repo_url, repo_name)
print(f"Repository cloned successfully: {repo_name}")
zip_file = f"{repo_name}.zip"
shutil.make_archive(repo_name, 'zip', repo_name)
print(f"Repository zipped successfully: {zip_file}")
return zip_file
except git.exc.GitCommandError as e:
if "could not read Username" in str(e):
return "Authentication error: Please provide a valid token for private repositories."
return f"Git error: {str(e)}"
except requests.exceptions.RequestException as e:
return "Network error: Unable to connect to the repository."
except Exception as e:
return f"An error occurred: {str(e)}"
def zip_download_link(repo_type, repo_url, auth_token):
result = clone_repo(repo_url, repo_type, auth_token)
if isinstance(result, str) and result.endswith(".zip"):
return gr.update(value=result), ""
else:
return gr.update(value=None), result
def push_to_huggingface(repo_type, repo_name, files_or_zip, hf_token):
try:
repo_name = repo_name.lstrip("/")
if not "/" in repo_name:
repo_name = f"{hf_token.split(':')[0]}/{repo_name}"
target_dir = f"./{repo_name}"
if os.path.exists(target_dir):
shutil.rmtree(target_dir)
os.makedirs(target_dir, exist_ok=True)
if isinstance(files_or_zip, list):
for file_obj in files_or_zip:
if file_obj.endswith(".zip"):
with zipfile.ZipFile(file_obj, 'r') as zip_ref:
zip_ref.extractall(target_dir)
else:
shutil.copy(file_obj, os.path.join(target_dir, os.path.basename(file_obj)))
else:
if files_or_zip.endswith(".zip"):
with zipfile.ZipFile(files_or_zip, 'r') as zip_ref:
zip_ref.extractall(target_dir)
else:
shutil.copy(files_or_zip, os.path.join(target_dir, os.path.basename(files_or_zip)))
if repo_type == "Space":
api.upload_folder(folder_path=target_dir, path_in_repo="", repo_id=repo_name, repo_type="space", token=hf_token)
return f"Files pushed to Hugging Face Space: {repo_name}"
else:
api.upload_folder(folder_path=target_dir, path_in_repo="", repo_id=repo_name, token=hf_token)
return f"Files pushed to Hugging Face repository: {repo_name}"
except Exception as e:
return f"An error occurred: {str(e)}"
def create_huggingface_space(space_name, space_type, hardware, visibility, hf_token):
try:
if "/" not in space_name:
space_name = f"{hf_token.split(':')[0]}/{space_name}"
create_repo(repo_id=space_name, repo_type="space", space_sdk=space_type, token=hf_token, private=(visibility == "private"))
return f"Successfully created Hugging Face Space: {space_name}"
except Exception as e:
return f"An error occurred while creating the Space: {str(e)}"
def remove_files_from_huggingface(repo_type, repo_name, file_paths, remove_all, hf_token):
try:
print(f"Removing files from {repo_type}: {repo_name}")
repo_name = repo_name.lstrip("/")
if not "/" in repo_name:
repo_name = f"{hf_token.split(':')[0]}/{repo_name}"
if remove_all:
try:
files = api.list_repo_files(repo_id=repo_name, repo_type=repo_type.lower(), token=hf_token)
if not files:
return "No files found to remove."
successful_removals = []
failed_removals = []
for file_path in files:
try:
api.delete_file(path_in_repo=file_path, repo_id=repo_name, repo_type=repo_type.lower(), token=hf_token)
successful_removals.append(file_path)
except Exception as e:
failed_removals.append((file_path, str(e)))
result = []
if successful_removals:
result.append(f"Successfully removed files: {', '.join(successful_removals)}")
if failed_removals:
result.append("Failed to remove the following files:")
for path, error in failed_removals:
result.append(f"- {path}: {error}")
return "\n".join(result)
except Exception as e:
return f"Error removing all files: {str(e)}"
else:
if isinstance(file_paths, str):
file_paths = [path.strip() for path in file_paths.split(',') if path.strip()]
if not file_paths:
return "Error: No valid file paths provided."
successful_removals = []
failed_removals = []
for file_path in file_paths:
try:
api.delete_file(path_in_repo=file_path, repo_id=repo_name, repo_type=repo_type.lower(), token=hf_token)
successful_removals.append(file_path)
except Exception as e:
failed_removals.append((file_path, str(e)))
result = []
if successful_removals:
result.append(f"Successfully removed files: {', '.join(successful_removals)}")
if failed_removals:
result.append("Failed to remove the following files:")
for path, error in failed_removals:
result.append(f"- {path}: {error}")
return "\n".join(result)
except Exception as e:
return f"An error occurred during file removal: {str(e)}"
# Define the Gradio interface using Blocks API
with gr.Blocks(css="footer {display:none;}.title {color: blue; font-size: 36px;}") as app:
gr.Markdown("""
# πŸš€ Hugging Face Repo & Space Manager
Welcome to the best tool for effortlessly managing your Hugging Face ecosystem! Whether you're a seasoned ML engineer or just getting started with AI, this all-in-one interface streamlines your workflow and boosts productivity.
## 🌟 Key Features & Why Use This Tool?
- **Seamless File Management**: Push, pull, and organize your files across Spaces and Repos with drag-and-drop simplicity.
- **Git Integration**: Clone repositories from GitHub or Hugging Face with a single click, and download them as ready-to-use ZIP files.
- **Smart File Removal**: Selectively clean up your Spaces and Repos, or perform a total reset with our bulk file removal option.
- **Time-Saver**: Automate repetitive tasks and focus on what matters - your AI projects.
- **User-Friendly**: No more command-line headaches. Our GUI makes complex operations a breeze.
- **Versatile**: From creating Spaces to managing large datasets, handle it all in one place.
- **Secure**: Built-in token management ensures your credentials stay safe while you work.
## πŸ”§ How to Use This Tool
1. **Create a New Space**: Start by creating a fresh Hugging Face Space for your project.
2. **Manage Existing Spaces**: Remove Files" tab to clean up your Space or Repository.
3. **Push Your Content**: Upload your files or a ZIP archive to your Space or Repository.
4. **Clone and Modify**: Modify the files locally, then push them back using the "Push to Hugging Face" feature.
Let's innovate together! πŸ€—βœ¨
---
Created with ❀️ by MoBenTa | Empowering AI enthusiasts worldwide
""")
with gr.Tabs():
with gr.Tab("🌟 Manage Hugging Face Space/Repo"):
with gr.Tabs():
with gr.TabItem("Create Space"):
space_name = gr.Textbox(label="Space Name (format: username/space-name)")
space_type = gr.Dropdown(["streamlit", "gradio", "static", "docker"], label="Space Type")
hardware = gr.Textbox(label="Hardware (optional)")
visibility = gr.Radio(choices=["public", "private"], label="Visibility")
create_hf_token = gr.Textbox(label="Hugging Face Token", type="password")
create_space_button = gr.Button("Create Space", variant="primary")
create_space_output = gr.Textbox(label="Creation Result")
create_space_button.click(
fn=create_huggingface_space,
inputs=[space_name, space_type, hardware, visibility, create_hf_token],
outputs=create_space_output
)
with gr.TabItem("Remove Files"):
remove_type = gr.Dropdown(["Space", "Repository"], label="Remove from")
remove_repo_name = gr.Textbox(label="Repository/Space Name")
remove_all_checkbox = gr.Checkbox(label="Remove All Files", info="Warning: This will remove all files from the repository!")
remove_file_paths = gr.Textbox(label="File Paths to Remove (comma-separated)", interactive=True)
remove_hf_token = gr.Textbox(label="Hugging Face Token", type="password")
remove_button = gr.Button("Remove Files", variant="primary")
remove_output = gr.Textbox(label="Removal Result")
def update_file_paths_interactivity(remove_all):
return gr.update(interactive=not remove_all)
remove_all_checkbox.change(
fn=update_file_paths_interactivity,
inputs=remove_all_checkbox,
outputs=remove_file_paths
)
remove_button.click(
fn=remove_files_from_huggingface,
inputs=[remove_type, remove_repo_name, remove_file_paths, remove_all_checkbox, remove_hf_token],
outputs=remove_output
)
with gr.Tab("☁️ Push to Hugging Face"):
push_type = gr.Dropdown(["Space", "Repository"], label="Push to")
repo_name = gr.Textbox(label="Repository/Space Name")
files_upload = gr.File(label="Upload File(s) or Zip", file_count="multiple", type="filepath")
hf_token = gr.Textbox(label="Hugging Face Token", type="password")
push_button = gr.Button("Push to Hugging Face", variant="primary")
push_output = gr.Textbox(label="Push Result")
push_button.click(
fn=push_to_huggingface,
inputs=[push_type, repo_name, files_upload, hf_token],
outputs=push_output
)
with gr.Tab("πŸ” Clone Repository"):
repo_type_input = gr.Radio(choices=["GitHub", "Hugging Face Model", "Hugging Face Dataset", "Hugging Face Space"], label="Repository Type")
repo_url_input = gr.Textbox(label="Repository URL")
auth_token_input = gr.Textbox(label="Authentication Token (optional)", type="password")
clone_button = gr.Button("Clone and Download", variant="primary")
output_zip = gr.File(label="Downloaded Repository")
clone_error_output = gr.Textbox(label="Cloning Result", visible=False)
def handle_clone_result(repo_type_input, repo_url, auth_token):
if repo_type_input == "GitHub":
repo_type = None
elif repo_type_input == "Hugging Face Model":
repo_type = "model"
elif repo_type_input == "Hugging Face Dataset":
repo_type = "dataset"
elif repo_type_input == "Hugging Face Space":
repo_type = "space"
else:
repo_type = "model"
file_output, error_message = zip_download_link(repo_type, repo_url, auth_token)
return file_output, error_message, gr.update(visible=bool(error_message))
clone_button.click(
fn=handle_clone_result,
inputs=[repo_type_input, repo_url_input, auth_token_input],
outputs=[output_zip, clone_error_output, clone_error_output]
)
if __name__ == "__main__":
app.launch()