broadfield-dev commited on
Commit
6063cc9
Β·
verified Β·
1 Parent(s): 48c6364

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +100 -251
app.py CHANGED
@@ -1,274 +1,123 @@
1
  import gradio as gr
2
- import os
3
- import re
4
- import tempfile
5
- import shutil
6
- import git
7
- from huggingface_hub import (
8
- create_repo,
9
- upload_folder,
10
- list_repo_files,
11
- delete_file,
12
- Repository,
13
- whoami,
14
  )
15
- import logging
16
- from pathlib import Path
17
-
18
- # Configure logging
19
- logging.basicConfig(level=logging.INFO)
20
- logger = logging.getLogger(__name__)
21
-
22
- # Function to parse markdown input
23
- def parse_markdown(markdown_input):
24
- """Parse markdown input to extract space details and file structure."""
25
- space_info = {"repo_name": "", "owner": "", "sdk": "gradio", "files": []}
26
- current_file = None
27
- file_content = []
28
- in_file_content = False
29
-
30
- lines = markdown_input.strip().split("\n")
31
- for line in lines:
32
- line = line.strip()
33
- # Extract space name
34
- if line.startswith("# Space:"):
35
- space_info["repo_name"] = line.replace("# Space:", "").strip()
36
- if "/" in space_info["repo_name"]:
37
- space_info["owner"], space_info["repo_name"] = space_info["repo_name"].split("/", 1)
38
- # Detect file structure section
39
- elif line.startswith("## File Structure"):
40
- continue
41
- # Detect file in structure
42
- elif line.startswith("πŸ“„") or line.startswith("πŸ“"):
43
- if current_file and file_content:
44
- space_info["files"].append({"path": current_file, "content": "\n".join(file_content)})
45
- file_content = []
46
- current_file = line[2:].strip()
47
- in_file_content = False
48
- # Detect file content section
49
- elif line.startswith("### File:"):
50
- if current_file and file_content:
51
- space_info["files"].append({"path": current_file, "content": "\n".join(file_content)})
52
- file_content = []
53
- current_file = line.replace("### File:", "").strip()
54
- in_file_content = True
55
- # Handle file content
56
- elif in_file_content and line.startswith("```"):
57
- if file_content:
58
- space_info["files"].append({"path": current_file, "content": "\n".join(file_content)})
59
- file_content = []
60
- in_file_content = False
61
- else:
62
- in_file_content = True
63
- elif in_file_content:
64
- file_content.append(line)
65
-
66
- # Append the last file
67
- if current_file and file_content:
68
- space_info["files"].append({"path": current_file, "content": "\n".join(file_content)})
69
-
70
- return space_info
71
-
72
- # Function to create and populate a Space
73
- def create_space(api_token, space_name, owner, sdk, markdown_input):
74
- """Create a Hugging Face Space and populate it with files from markdown input."""
75
- try:
76
- # Authenticate with Hugging Face Hub
77
- if not api_token:
78
- return "Error: Please provide a valid Hugging Face API token."
79
-
80
- # Get user info
81
- user_info = whoami(token=api_token)
82
- if not owner:
83
- owner = user_info["name"]
84
- repo_id = f"{owner}/{space_name}"
85
-
86
- # Create temporary directory
87
- with tempfile.TemporaryDirectory() as temp_dir:
88
- repo_path = os.path.join(temp_dir, space_name)
89
- os.makedirs(repo_path, exist_ok=True)
90
-
91
- # Parse markdown input
92
- space_info = parse_markdown(markdown_input)
93
- if space_info["repo_name"] != f"{owner}/{space_name}":
94
- return "Error: Space name in markdown does not match provided owner/space_name."
95
-
96
- # Write files to temporary directory
97
- for file_info in space_info["files"]:
98
- file_path = os.path.join(repo_path, file_info["path"])
99
- os.makedirs(os.path.dirname(file_path), exist_ok=True)
100
- with open(file_path, "w", encoding="utf-8") as f:
101
- f.write(file_info["content"])
102
- logger.info(f"Wrote file: {file_path}")
103
-
104
- # Create repository on Hugging Face
105
- try:
106
- create_repo(
107
- repo_id=repo_id,
108
- token=api_token,
109
- repo_type="space",
110
- space_sdk=sdk,
111
- private=False,
112
- )
113
- logger.info(f"Created Space: {repo_id}")
114
- except Exception as e:
115
- if "already exists" in str(e):
116
- logger.info(f"Space {repo_id} already exists, proceeding to update.")
117
- else:
118
- return f"Error creating Space: {str(e)}"
119
-
120
- # Initialize Git repository
121
- repo = git.Repo.init(repo_path)
122
- repo.git.add(all=True)
123
- repo.index.commit("Initial commit from Gradio app")
124
-
125
- # Push to Hugging Face Space
126
- upload_folder(
127
- repo_id=repo_id,
128
- folder_path=repo_path,
129
- path_in_repo=".",
130
- token=api_token,
131
- commit_message="Initial Space setup",
132
- )
133
-
134
- return f"Successfully created Space: https://huggingface.co/spaces/{repo_id}"
135
-
136
- except Exception as e:
137
- logger.error(f"Error: {str(e)}")
138
- return f"Error: {str(e)}"
139
-
140
- # Function to view Space files
141
- def view_space_files(api_token, space_name, owner):
142
- """List files in a Hugging Face Space."""
143
- try:
144
- if not api_token:
145
- return "Error: Please provide a valid Hugging Face API token."
146
- repo_id = f"{owner}/{space_name}" if owner else space_name
147
- files = list_repo_files(repo_id=repo_id, token=api_token, repo_type="space")
148
- return "\n".join(files) or "No files found in the Space."
149
- except Exception as e:
150
- return f"Error: {str(e)}"
151
-
152
- # Function to update a Space file
153
- def update_space_file(api_token, space_name, owner, file_path, file_content, commit_message):
154
- """Update a file in a Hugging Face Space with a commit."""
155
- try:
156
- if not api_token:
157
- return "Error: Please provide a valid Hugging Face API token."
158
- repo_id = f"{owner}/{space_name}" if owner else space_name
159
-
160
- # Create temporary directory for cloning
161
- with tempfile.TemporaryDirectory() as temp_dir:
162
- repo_path = os.path.join(temp_dir, space_name)
163
- repo = Repository(
164
- local_dir=repo_path,
165
- clone_from=f"https://huggingface.co/spaces/{repo_id}",
166
- repo_type="space",
167
- use_auth_token=api_token,
168
- )
169
-
170
- # Write updated file
171
- full_path = os.path.join(repo_path, file_path)
172
- os.makedirs(os.path.dirname(full_path), exist_ok=True)
173
- with open(full_path, "w", encoding="utf-8") as f:
174
- f.write(file_content)
175
-
176
- # Commit and push changes
177
- repo.git_add(file_path)
178
- repo.git_commit(commit_message or f"Update {file_path}")
179
- repo.git_push()
180
-
181
- return f"Successfully updated {file_path} in Space: https://huggingface.co/spaces/{repo_id}"
182
-
183
- except Exception as e:
184
- return f"Error: {str(e)}"
185
 
186
  # Gradio interface
187
- def main():
188
- with gr.Blocks(theme=gr.themes.Soft()) as demo:
189
- gr.Markdown("# Hugging Face Space Builder")
190
- gr.Markdown("Create, view, and update Hugging Face Spaces with a custom file structure.")
191
-
192
- # Authentication
193
- with gr.Group():
194
- gr.Markdown("## Authentication")
195
- api_token = gr.Textbox(
196
- label="Hugging Face API Token",
197
- type="password",
198
- placeholder="Enter your Hugging Face API token",
199
- )
200
-
201
- # Create Space
202
- with gr.Group():
203
- gr.Markdown("## Create a New Space")
204
- space_name = gr.Textbox(label="Space Name", placeholder="my-space")
205
- owner = gr.Textbox(
206
- label="Owner (optional)", placeholder="Leave blank for current user"
207
- )
208
- sdk = gr.Dropdown(
209
- label="SDK", choices=["gradio", "streamlit", "docker", "static"], value="gradio"
210
- )
211
- markdown_input = gr.Textbox(
212
- label="Markdown File Structure",
213
- placeholder="Paste markdown with file structure and contents",
214
- lines=10,
215
- )
216
- create_btn = gr.Button("Create Space")
217
- create_output = gr.Textbox(label="Result")
218
-
219
- # View Space Files
220
- with gr.Group():
221
- gr.Markdown("## View Space Files")
222
- view_space_name = gr.Textbox(label="Space Name", placeholder="my-space")
223
- view_owner = gr.Textbox(
224
- label="Owner (optional)", placeholder="Leave blank for current user"
225
- )
226
- view_btn = gr.Button("List Files")
227
- view_output = gr.Textbox(label="Files in Space")
228
 
229
- # Update Space File
230
- with gr.Group():
231
- gr.Markdown("## Update Space File")
232
- update_space_name = gr.Textbox(label="Space Name", placeholder="my-space")
233
- update_owner = gr.Textbox(
234
- label="Owner (optional)", placeholder="Leave blank for current user"
235
- )
236
- file_path = gr.Textbox(label="File Path", placeholder="path/to/file.py")
237
- file_content = gr.Textbox(
238
- label="File Content", placeholder="Enter new file content", lines=10
239
- )
240
- commit_message = gr.Textbox(
241
- label="Commit Message", placeholder="Update file content"
242
- )
243
- update_btn = gr.Button("Update File")
244
- update_output = gr.Textbox(label="Result")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
 
246
  # Event handlers
247
  create_btn.click(
248
  fn=create_space,
249
- inputs=[api_token, space_name, owner, sdk, markdown_input],
250
- outputs=create_output,
251
  )
252
  view_btn.click(
253
  fn=view_space_files,
254
- inputs=[api_token, view_space_name, view_owner],
255
- outputs=view_output,
256
  )
257
  update_btn.click(
258
  fn=update_space_file,
259
  inputs=[
260
- api_token,
261
- update_space_name,
262
- update_owner,
263
- file_path,
264
- file_content,
265
- commit_message,
266
  ],
267
- outputs=update_output,
268
  )
269
 
270
  return demo
271
 
272
  if __name__ == "__main__":
273
- demo = main()
274
  demo.launch()
 
1
  import gradio as gr
2
+ from app_logic import (
3
+ create_space,
4
+ view_space_files,
5
+ update_space_file,
 
 
 
 
 
 
 
 
6
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
 
8
  # Gradio interface
9
+ def main_ui():
10
+ with gr.Blocks(theme=gr.themes.Soft(primary_hue=gr.themes.colors.blue, secondary_hue=gr.themes.colors.sky), title="Hugging Face Space Builder") as demo:
11
+ gr.Markdown(
12
+ """
13
+ # πŸ› οΈ Hugging Face Space Builder
14
+ Create, view, and update Hugging Face Spaces with a custom file structure defined via markdown input.
15
+ """
16
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
+ with gr.Row():
19
+ with gr.Column(scale=1):
20
+ api_token_input = gr.Textbox(
21
+ label="Hugging Face API Token",
22
+ type="password",
23
+ placeholder="Enter your HF token (hf_xxx)",
24
+ info="Get your token from hf.co/settings/tokens. Needs 'write' access for creating/updating spaces."
25
+ )
26
+ with gr.Column(scale=2):
27
+ gr.Markdown(" ") # Spacer or additional info can go here
28
+
29
+ with gr.Tabs():
30
+ with gr.TabItem("πŸš€ Create New Space"):
31
+ with gr.Row():
32
+ space_name_create_input = gr.Textbox(label="Space Name", placeholder="my-awesome-app (no slashes)", scale=2)
33
+ owner_create_input = gr.Textbox(label="Owner Username/Org", placeholder="Leave blank for your HF username", scale=1)
34
+
35
+ sdk_create_input = gr.Dropdown(
36
+ label="Space SDK",
37
+ choices=["gradio", "streamlit", "docker", "static"],
38
+ value="gradio",
39
+ info="Select the type of Space (Gradio, Streamlit, etc.)."
40
+ )
41
+ markdown_input_create = gr.Textbox(
42
+ label="Markdown File Structure & Content",
43
+ placeholder="""Define files using '### File: path/to/file.ext'
44
+ followed by content, optionally in code blocks.
45
+ Example:
46
+ ### File: app.py
47
+ ```python
48
+ print("Hello World!")
49
+ ```
50
+
51
+ ### File: README.md
52
+ ```markdown
53
+ # My Awesome App
54
+ This is a test.
55
+ ```
56
+ """, # Triple backticks within the example are commented out for display
57
+ lines=15,
58
+ interactive=True,
59
+ info="Define files using '### File: path/to/your/file.ext' followed by content, optionally in ```code blocks```."
60
+ )
61
+ create_btn = gr.Button("Create Space", variant="primary")
62
+ create_output_md = gr.Markdown(label="Result")
63
+
64
+ with gr.TabItem("πŸ“„ View Space Files"):
65
+ with gr.Row():
66
+ space_name_view_input = gr.Textbox(label="Space Name", placeholder="my-existing-app (no slashes)", scale=2)
67
+ owner_view_input = gr.Textbox(label="Owner Username/Org", placeholder="Leave blank if it's your space", scale=1)
68
+ view_btn = gr.Button("List Files", variant="primary")
69
+ view_output_md = gr.Markdown(label="Files in Space")
70
+
71
+ with gr.TabItem("✏️ Update Space File"):
72
+ with gr.Row():
73
+ space_name_update_input = gr.Textbox(label="Space Name", placeholder="my-target-app (no slashes)", scale=2)
74
+ owner_update_input = gr.Textbox(label="Owner Username/Org", placeholder="Leave blank if it's your space", scale=1)
75
+
76
+ file_path_update_input = gr.Textbox(
77
+ label="File Path in Repository",
78
+ placeholder="e.g., app.py or src/utils.py",
79
+ info="The full path to the file within the space you want to update/create."
80
+ )
81
+ file_content_update_input = gr.Textbox(
82
+ label="New File Content",
83
+ placeholder="Enter the complete new content for the file.",
84
+ lines=10,
85
+ interactive=True
86
+ )
87
+ commit_message_update_input = gr.Textbox(
88
+ label="Commit Message",
89
+ placeholder="e.g., Update app.py with new feature",
90
+ info="Describe the changes you're making."
91
+ )
92
+ update_btn = gr.Button("Update File", variant="primary")
93
+ update_output_md = gr.Markdown(label="Result")
94
 
95
  # Event handlers
96
  create_btn.click(
97
  fn=create_space,
98
+ inputs=[api_token_input, space_name_create_input, owner_create_input, sdk_create_input, markdown_input_create],
99
+ outputs=create_output_md,
100
  )
101
  view_btn.click(
102
  fn=view_space_files,
103
+ inputs=[api_token_input, space_name_view_input, owner_view_input],
104
+ outputs=view_output_md,
105
  )
106
  update_btn.click(
107
  fn=update_space_file,
108
  inputs=[
109
+ api_token_input,
110
+ space_name_update_input,
111
+ owner_update_input,
112
+ file_path_update_input,
113
+ file_content_update_input,
114
+ commit_message_update_input,
115
  ],
116
+ outputs=update_output_md,
117
  )
118
 
119
  return demo
120
 
121
  if __name__ == "__main__":
122
+ demo = main_ui()
123
  demo.launch()