Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -3,7 +3,11 @@ from app_logic import (
|
|
3 |
create_space,
|
4 |
view_space_files,
|
5 |
update_space_file,
|
|
|
|
|
6 |
)
|
|
|
|
|
7 |
|
8 |
# Gradio interface
|
9 |
def main_ui():
|
@@ -11,32 +15,69 @@ def main_ui():
|
|
11 |
gr.Markdown(
|
12 |
"""
|
13 |
# ๐ ๏ธ Hugging Face Space Builder
|
14 |
-
Create, view, and update Hugging Face Spaces
|
|
|
15 |
"""
|
16 |
)
|
17 |
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
)
|
26 |
-
|
27 |
-
|
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 |
-
|
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",
|
@@ -47,21 +88,15 @@ Example:
|
|
47 |
# ```python
|
48 |
print("Hello World!")
|
49 |
# ```
|
50 |
-
|
51 |
-
|
52 |
-
|
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)
|
@@ -69,44 +104,42 @@ This is a test.
|
|
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 |
-
|
79 |
-
|
80 |
-
)
|
81 |
file_content_update_input = gr.Textbox(
|
82 |
-
label="New File Content",
|
83 |
-
|
84 |
-
lines=10,
|
85 |
-
interactive=True
|
86 |
)
|
87 |
commit_message_update_input = gr.Textbox(
|
88 |
-
label="Commit Message",
|
89 |
-
|
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=[
|
99 |
outputs=create_output_md,
|
100 |
)
|
101 |
view_btn.click(
|
102 |
fn=view_space_files,
|
103 |
-
inputs=[
|
104 |
outputs=view_output_md,
|
105 |
)
|
106 |
update_btn.click(
|
107 |
fn=update_space_file,
|
108 |
inputs=[
|
109 |
-
|
110 |
space_name_update_input,
|
111 |
owner_update_input,
|
112 |
file_path_update_input,
|
@@ -115,7 +148,6 @@ This is a test.
|
|
115 |
],
|
116 |
outputs=update_output_md,
|
117 |
)
|
118 |
-
|
119 |
return demo
|
120 |
|
121 |
if __name__ == "__main__":
|
|
|
3 |
create_space,
|
4 |
view_space_files,
|
5 |
update_space_file,
|
6 |
+
load_token_from_image_and_set_env, # New import
|
7 |
+
KEYLOCK_DECODE_AVAILABLE # New import
|
8 |
)
|
9 |
+
# PIL Image for type hint if needed, though gr.Image handles it
|
10 |
+
# from PIL import Image
|
11 |
|
12 |
# Gradio interface
|
13 |
def main_ui():
|
|
|
15 |
gr.Markdown(
|
16 |
"""
|
17 |
# ๐ ๏ธ Hugging Face Space Builder
|
18 |
+
Create, view, and update Hugging Face Spaces.
|
19 |
+
Provide your Hugging Face API token directly or load it from a steganographic image.
|
20 |
"""
|
21 |
)
|
22 |
|
23 |
+
# --- Authentication Section ---
|
24 |
+
with gr.Accordion("๐ Authentication Methods", open=True):
|
25 |
+
gr.Markdown(
|
26 |
+
"""
|
27 |
+
**Token Precedence:**
|
28 |
+
1. If a token is successfully loaded from an image (and `HF_TOKEN` is set in the environment), it will be used.
|
29 |
+
2. Otherwise, the token entered in the 'Enter API Token Directly' textbox will be used.
|
30 |
+
3. If a system-wide `HF_TOKEN` environment variable was already set when this app started, it might also be used if methods 1 & 2 don't yield a token.
|
31 |
+
"""
|
32 |
+
)
|
33 |
+
gr.Markdown("---")
|
34 |
+
gr.Markdown("### Method 1: Enter API Token Directly")
|
35 |
+
api_token_ui_input = gr.Textbox( # Renamed to avoid confusion with resolved_api_token
|
36 |
+
label="Hugging Face API Token (hf_xxx)",
|
37 |
+
type="password",
|
38 |
+
placeholder="Enter your HF token OR load from image below",
|
39 |
+
info="Get from hf.co/settings/tokens. Needs 'write' access. This is used if image loading fails or is not used."
|
40 |
+
)
|
41 |
+
|
42 |
+
if KEYLOCK_DECODE_AVAILABLE:
|
43 |
+
gr.Markdown("---")
|
44 |
+
gr.Markdown("### Method 2: Load API Token from Steganographic Image")
|
45 |
+
with gr.Row():
|
46 |
+
keylock_image_input = gr.Image(
|
47 |
+
label="Stego Image (PNG containing HF_TOKEN)",
|
48 |
+
type="pil", # Pass PIL image to backend
|
49 |
+
# sources=["upload"], # Optional: Restrict to upload only
|
50 |
+
# height=200, # Optional: for display consistency
|
51 |
+
# width=200,
|
52 |
+
)
|
53 |
+
keylock_password_input = gr.Textbox(
|
54 |
+
label="Image Password",
|
55 |
+
type="password",
|
56 |
+
placeholder="Password for image decryption"
|
57 |
+
)
|
58 |
+
keylock_decode_button = gr.Button("Load Token from Image", variant="secondary")
|
59 |
+
keylock_status_output = gr.Markdown(label="Image Decoding Status", value="Status will appear here...")
|
60 |
+
|
61 |
+
keylock_decode_button.click(
|
62 |
+
fn=load_token_from_image_and_set_env,
|
63 |
+
inputs=[keylock_image_input, keylock_password_input],
|
64 |
+
outputs=[keylock_status_output]
|
65 |
)
|
66 |
+
else:
|
67 |
+
gr.Markdown(
|
68 |
+
"_(Image decoding feature (KeyLock-Decode) is disabled as the library could not be imported.)_"
|
69 |
+
)
|
70 |
+
|
71 |
+
# --- Main Application Tabs ---
|
72 |
with gr.Tabs():
|
73 |
with gr.TabItem("๐ Create New Space"):
|
74 |
+
# ... (rest of the Create Space UI, inputs will use api_token_ui_input)
|
75 |
with gr.Row():
|
76 |
space_name_create_input = gr.Textbox(label="Space Name", placeholder="my-awesome-app (no slashes)", scale=2)
|
77 |
owner_create_input = gr.Textbox(label="Owner Username/Org", placeholder="Leave blank for your HF username", scale=1)
|
|
|
78 |
sdk_create_input = gr.Dropdown(
|
79 |
+
label="Space SDK", choices=["gradio", "streamlit", "docker", "static"], value="gradio",
|
80 |
+
info="Select the type of Space."
|
|
|
|
|
81 |
)
|
82 |
markdown_input_create = gr.Textbox(
|
83 |
label="Markdown File Structure & Content",
|
|
|
88 |
# ```python
|
89 |
print("Hello World!")
|
90 |
# ```
|
91 |
+
""",
|
92 |
+
lines=15, interactive=True,
|
93 |
+
info="Define files using '### File: path/to/your/file.ext' followed by content."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
)
|
95 |
create_btn = gr.Button("Create Space", variant="primary")
|
96 |
create_output_md = gr.Markdown(label="Result")
|
97 |
|
98 |
with gr.TabItem("๐ View Space Files"):
|
99 |
+
# ... (rest of the View Space Files UI, inputs will use api_token_ui_input)
|
100 |
with gr.Row():
|
101 |
space_name_view_input = gr.Textbox(label="Space Name", placeholder="my-existing-app (no slashes)", scale=2)
|
102 |
owner_view_input = gr.Textbox(label="Owner Username/Org", placeholder="Leave blank if it's your space", scale=1)
|
|
|
104 |
view_output_md = gr.Markdown(label="Files in Space")
|
105 |
|
106 |
with gr.TabItem("โ๏ธ Update Space File"):
|
107 |
+
# ... (rest of the Update Space File UI, inputs will use api_token_ui_input)
|
108 |
with gr.Row():
|
109 |
space_name_update_input = gr.Textbox(label="Space Name", placeholder="my-target-app (no slashes)", scale=2)
|
110 |
owner_update_input = gr.Textbox(label="Owner Username/Org", placeholder="Leave blank if it's your space", scale=1)
|
|
|
111 |
file_path_update_input = gr.Textbox(
|
112 |
+
label="File Path in Repository", placeholder="e.g., app.py or src/utils.py",
|
113 |
+
info="The full path to the file within the space."
|
114 |
+
)
|
|
|
115 |
file_content_update_input = gr.Textbox(
|
116 |
+
label="New File Content", placeholder="Enter the complete new content for the file.",
|
117 |
+
lines=10, interactive=True
|
|
|
|
|
118 |
)
|
119 |
commit_message_update_input = gr.Textbox(
|
120 |
+
label="Commit Message", placeholder="e.g., Update app.py with new feature",
|
121 |
+
info="Describe the changes."
|
|
|
122 |
)
|
123 |
update_btn = gr.Button("Update File", variant="primary")
|
124 |
update_output_md = gr.Markdown(label="Result")
|
125 |
|
126 |
# Event handlers
|
127 |
+
# Pass the UI token input to all backend functions.
|
128 |
+
# The backend's _get_api_token helper will decide the actual token to use.
|
129 |
create_btn.click(
|
130 |
fn=create_space,
|
131 |
+
inputs=[api_token_ui_input, space_name_create_input, owner_create_input, sdk_create_input, markdown_input_create],
|
132 |
outputs=create_output_md,
|
133 |
)
|
134 |
view_btn.click(
|
135 |
fn=view_space_files,
|
136 |
+
inputs=[api_token_ui_input, space_name_view_input, owner_view_input],
|
137 |
outputs=view_output_md,
|
138 |
)
|
139 |
update_btn.click(
|
140 |
fn=update_space_file,
|
141 |
inputs=[
|
142 |
+
api_token_ui_input,
|
143 |
space_name_update_input,
|
144 |
owner_update_input,
|
145 |
file_path_update_input,
|
|
|
148 |
],
|
149 |
outputs=update_output_md,
|
150 |
)
|
|
|
151 |
return demo
|
152 |
|
153 |
if __name__ == "__main__":
|