Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,39 +1,27 @@
|
|
1 |
from flask import Flask, request, jsonify, Response
|
2 |
import os
|
3 |
import json
|
4 |
-
from huggingface_hub import HfApi, create_repo, upload_file
|
5 |
import random
|
6 |
import string
|
7 |
-
from flask_httpauth import HTTPTokenAuth
|
8 |
|
9 |
# Import documentation from assembler_docs.py
|
10 |
from assembler_docs import DOCUMENTATION
|
11 |
|
12 |
app = Flask(__name__)
|
13 |
|
14 |
-
#
|
15 |
-
auth = HTTPTokenAuth(scheme='Bearer')
|
16 |
-
|
17 |
-
# Hugging Face API token (set in Space settings or provided in request)
|
18 |
HF_TOKEN = os.getenv("HF_TOKEN")
|
19 |
if not HF_TOKEN:
|
20 |
raise ValueError("HF_TOKEN not set. Add it in Space settings.")
|
21 |
|
22 |
-
|
|
|
|
|
|
|
|
|
23 |
|
24 |
-
|
25 |
-
@auth.verify_token
|
26 |
-
def verify_token(token):
|
27 |
-
if not token:
|
28 |
-
return False
|
29 |
-
try:
|
30 |
-
# Attempt to verify the token by checking if it can access the user's profile or Space-Share
|
31 |
-
user_info = hf_api.whoami(token=token)
|
32 |
-
# Optionally, check if the token has write access to Space-Share
|
33 |
-
# This is a basic check; you might want to add more specific permission checks
|
34 |
-
return bool(user_info and "Space-Share" in user_info.get('orgs', [])) or token == HF_TOKEN
|
35 |
-
except Exception:
|
36 |
-
return False
|
37 |
|
38 |
def generate_space_name():
|
39 |
"""Generate a unique Space name."""
|
@@ -41,17 +29,12 @@ def generate_space_name():
|
|
41 |
return f"GeneratedSpace-{random_suffix}"
|
42 |
|
43 |
@app.route('/create-space', methods=['POST'])
|
44 |
-
@auth.login_required
|
45 |
def create_hf_space():
|
46 |
try:
|
47 |
-
# Use the authenticated token for Hugging Face operations
|
48 |
-
token = auth.current_user()
|
49 |
-
hf_api = HfApi(token=token)
|
50 |
-
|
51 |
# Parse JSON input
|
52 |
data = request.get_json()
|
53 |
if not data:
|
54 |
-
return jsonify({"error": "No JSON data provided"}),
|
55 |
|
56 |
# Extract parameters
|
57 |
space_type = data.get("space_type", "gradio") # Default to gradio if not specified
|
@@ -59,29 +42,38 @@ def create_hf_space():
|
|
59 |
params = data.get("parameters", {}) # Optional parameters
|
60 |
|
61 |
if not files:
|
62 |
-
return jsonify({"error": "No files provided in JSON"}),
|
63 |
|
64 |
# Validate space_type
|
65 |
valid_space_types = ["gradio", "static", "docker", "streamlit"]
|
66 |
if space_type not in valid_space_types:
|
67 |
-
return jsonify({"error": f"Invalid space_type. Must be one of {valid_space_types}"}),
|
68 |
|
69 |
# Create a unique Space name and repo under Space-Share namespace
|
70 |
space_name = generate_space_name()
|
71 |
full_repo_id = f"Space-Share/{space_name}"
|
72 |
|
73 |
try:
|
74 |
-
# Attempt to create the repository
|
75 |
repo_info = create_repo(
|
76 |
repo_id=space_name,
|
77 |
repo_type="space",
|
78 |
space_sdk=space_type,
|
79 |
-
token=
|
80 |
private=False,
|
81 |
-
exist_ok=True # Allow creation even if the repo might exist
|
82 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
except Exception as e:
|
84 |
-
return jsonify({"error": f"Failed to
|
85 |
|
86 |
# Handle multi-file uploads
|
87 |
for filename, content in files.items():
|
@@ -99,8 +91,9 @@ def create_hf_space():
|
|
99 |
path_in_repo=filename,
|
100 |
repo_id=full_repo_id,
|
101 |
repo_type="space",
|
102 |
-
token=
|
103 |
)
|
|
|
104 |
except Exception as e:
|
105 |
os.remove(f"temp_{filename}")
|
106 |
return jsonify({"error": f"Failed to upload file {filename}: {str(e)}"}), 500
|
@@ -123,8 +116,9 @@ def create_hf_space():
|
|
123 |
path_in_repo="requirements.txt",
|
124 |
repo_id=full_repo_id,
|
125 |
repo_type="space",
|
126 |
-
token=
|
127 |
)
|
|
|
128 |
except Exception as e:
|
129 |
os.remove("temp_requirements.txt")
|
130 |
return jsonify({"error": f"Failed to upload requirements.txt: {str(e)}"}), 500
|
@@ -148,8 +142,9 @@ CMD ["python", "app.py"]
|
|
148 |
path_in_repo="Dockerfile",
|
149 |
repo_id=full_repo_id,
|
150 |
repo_type="space",
|
151 |
-
token=
|
152 |
)
|
|
|
153 |
except Exception as e:
|
154 |
os.remove("temp_Dockerfile")
|
155 |
return jsonify({"error": f"Failed to upload Dockerfile: {str(e)}"}), 500
|
@@ -163,12 +158,11 @@ CMD ["python", "app.py"]
|
|
163 |
}), 200
|
164 |
|
165 |
except json.JSONDecodeError:
|
166 |
-
return jsonify({"error": "Invalid JSON format"}),
|
167 |
except Exception as e:
|
168 |
return jsonify({"error": str(e)}), 500
|
169 |
|
170 |
@app.route('/docs', methods=['GET'])
|
171 |
-
@auth.login_required
|
172 |
def get_docs():
|
173 |
"""Return the API documentation as plain text."""
|
174 |
return Response(DOCUMENTATION, mimetype='text/plain'), 200
|
|
|
1 |
from flask import Flask, request, jsonify, Response
|
2 |
import os
|
3 |
import json
|
4 |
+
from huggingface_hub import HfApi, create_repo, upload_file, login
|
5 |
import random
|
6 |
import string
|
|
|
7 |
|
8 |
# Import documentation from assembler_docs.py
|
9 |
from assembler_docs import DOCUMENTATION
|
10 |
|
11 |
app = Flask(__name__)
|
12 |
|
13 |
+
# Hugging Face API token (set in Space settings)
|
|
|
|
|
|
|
14 |
HF_TOKEN = os.getenv("HF_TOKEN")
|
15 |
if not HF_TOKEN:
|
16 |
raise ValueError("HF_TOKEN not set. Add it in Space settings.")
|
17 |
|
18 |
+
# Log in to Hugging Face Hub with the token
|
19 |
+
try:
|
20 |
+
login(token=HF_TOKEN)
|
21 |
+
except Exception as e:
|
22 |
+
raise ValueError(f"Failed to log in to Hugging Face Hub: {str(e)}")
|
23 |
|
24 |
+
hf_api = HfApi()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
|
26 |
def generate_space_name():
|
27 |
"""Generate a unique Space name."""
|
|
|
29 |
return f"GeneratedSpace-{random_suffix}"
|
30 |
|
31 |
@app.route('/create-space', methods=['POST'])
|
|
|
32 |
def create_hf_space():
|
33 |
try:
|
|
|
|
|
|
|
|
|
34 |
# Parse JSON input
|
35 |
data = request.get_json()
|
36 |
if not data:
|
37 |
+
return jsonify({"error": "No JSON data provided"}), 400
|
38 |
|
39 |
# Extract parameters
|
40 |
space_type = data.get("space_type", "gradio") # Default to gradio if not specified
|
|
|
42 |
params = data.get("parameters", {}) # Optional parameters
|
43 |
|
44 |
if not files:
|
45 |
+
return jsonify({"error": "No files provided in JSON"}), 400
|
46 |
|
47 |
# Validate space_type
|
48 |
valid_space_types = ["gradio", "static", "docker", "streamlit"]
|
49 |
if space_type not in valid_space_types:
|
50 |
+
return jsonify({"error": f"Invalid space_type. Must be one of {valid_space_types}"}), 400
|
51 |
|
52 |
# Create a unique Space name and repo under Space-Share namespace
|
53 |
space_name = generate_space_name()
|
54 |
full_repo_id = f"Space-Share/{space_name}"
|
55 |
|
56 |
try:
|
57 |
+
# Attempt to create the repository with explicit verification
|
58 |
repo_info = create_repo(
|
59 |
repo_id=space_name,
|
60 |
repo_type="space",
|
61 |
space_sdk=space_type,
|
62 |
+
token=HF_TOKEN,
|
63 |
private=False,
|
64 |
+
exist_ok=True # Allow creation even if the repo might exist
|
65 |
)
|
66 |
+
print(f"Repository created: {full_repo_id}")
|
67 |
+
except Exception as e:
|
68 |
+
return jsonify({"error": f"Failed to create repository {full_repo_id}: {str(e)}"}), 500
|
69 |
+
|
70 |
+
# Verify repository existence before uploading
|
71 |
+
try:
|
72 |
+
repo_exists = hf_api.repo_exists(repo_id=full_repo_id, repo_type="space")
|
73 |
+
if not repo_exists:
|
74 |
+
return jsonify({"error": f"Repository {full_repo_id} does not exist after creation attempt."}), 500
|
75 |
except Exception as e:
|
76 |
+
return jsonify({"error": f"Failed to verify repository {full_repo_id}: {str(e)}"}), 500
|
77 |
|
78 |
# Handle multi-file uploads
|
79 |
for filename, content in files.items():
|
|
|
91 |
path_in_repo=filename,
|
92 |
repo_id=full_repo_id,
|
93 |
repo_type="space",
|
94 |
+
token=HF_TOKEN
|
95 |
)
|
96 |
+
print(f"Uploaded file: {filename}")
|
97 |
except Exception as e:
|
98 |
os.remove(f"temp_{filename}")
|
99 |
return jsonify({"error": f"Failed to upload file {filename}: {str(e)}"}), 500
|
|
|
116 |
path_in_repo="requirements.txt",
|
117 |
repo_id=full_repo_id,
|
118 |
repo_type="space",
|
119 |
+
token=HF_TOKEN
|
120 |
)
|
121 |
+
print("Uploaded requirements.txt")
|
122 |
except Exception as e:
|
123 |
os.remove("temp_requirements.txt")
|
124 |
return jsonify({"error": f"Failed to upload requirements.txt: {str(e)}"}), 500
|
|
|
142 |
path_in_repo="Dockerfile",
|
143 |
repo_id=full_repo_id,
|
144 |
repo_type="space",
|
145 |
+
token=HF_TOKEN
|
146 |
)
|
147 |
+
print("Uploaded Dockerfile")
|
148 |
except Exception as e:
|
149 |
os.remove("temp_Dockerfile")
|
150 |
return jsonify({"error": f"Failed to upload Dockerfile: {str(e)}"}), 500
|
|
|
158 |
}), 200
|
159 |
|
160 |
except json.JSONDecodeError:
|
161 |
+
return jsonify({"error": "Invalid JSON format"}), 400
|
162 |
except Exception as e:
|
163 |
return jsonify({"error": str(e)}), 500
|
164 |
|
165 |
@app.route('/docs', methods=['GET'])
|
|
|
166 |
def get_docs():
|
167 |
"""Return the API documentation as plain text."""
|
168 |
return Response(DOCUMENTATION, mimetype='text/plain'), 200
|