Nathyboy commited on
Commit
1173096
Β·
verified Β·
1 Parent(s): 313946a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +90 -25
app.py CHANGED
@@ -1,4 +1,4 @@
1
- # app.py β€” HF Space launcher (Option B) with runtime downloads & WebUI ready link
2
  import os
3
  import subprocess
4
  import threading
@@ -6,9 +6,10 @@ import shlex
6
  import time
7
  import requests
8
  import gradio as gr
 
9
 
10
  # -----------------------------
11
- # Configuration
12
  # -----------------------------
13
  DOWNLOADS = {
14
  "lora": {
@@ -30,13 +31,13 @@ DOWNLOADS = {
30
  }
31
 
32
  WEBUI_ARGS = "--listen --xformers --enable-insecure-extension-access --medvram"
33
- LAUNCH_PY = "launch.py" # relative to repo root
34
 
35
  # -----------------------------
36
  # Utilities
37
  # -----------------------------
38
  def ensure_persistent_folders():
39
- """Ensure HF tree persistent folders exist."""
40
  folders = [
41
  "stable-diffusion-webui/deforum/input",
42
  "stable-diffusion-webui/deforum/output_committed/frames",
@@ -49,8 +50,9 @@ def ensure_persistent_folders():
49
  os.makedirs(f, exist_ok=True)
50
  print("βœ… Persistent folders ensured.")
51
 
 
52
  def download_file_with_retries(url, dest, max_retries=3, backoff=5):
53
- """Download a file with retries, skip if exists."""
54
  if os.path.exists(dest):
55
  print(f"βœ… Already exists: {dest}")
56
  return True
@@ -66,6 +68,7 @@ def download_file_with_retries(url, dest, max_retries=3, backoff=5):
66
  for chunk in r.iter_content(chunk_size=8192):
67
  if chunk:
68
  f.write(chunk)
 
69
  os.replace(dest + ".part", dest)
70
  print(f"βœ… Downloaded: {dest}")
71
  return True
@@ -74,40 +77,102 @@ def download_file_with_retries(url, dest, max_retries=3, backoff=5):
74
  attempt += 1
75
  time.sleep(backoff * attempt)
76
  print(f"❌ Failed to download after {max_retries} attempts: {url}")
77
- if os.path.exists(dest + ".part"):
78
- os.remove(dest + ".part")
 
 
 
 
79
  return False
80
 
 
81
  def fetch_models():
82
- """Download all configured models into HF tree persistent paths."""
83
  print("πŸ”½ Starting runtime model downloads (if missing)...")
84
  success_all = True
85
  for name, info in DOWNLOADS.items():
86
- ok = download_file_with_retries(info["url"], info["dest"])
 
 
87
  success_all = success_all and ok
88
  if success_all:
89
  print("βœ… All runtime downloads done (or already present).")
90
  else:
91
- print("⚠️ Some runtime downloads failed. Check logs.")
 
92
 
93
  # -----------------------------
94
- # Start WebUI routine (Option B)
95
  # -----------------------------
96
- WEBUI_LINK = None
97
-
98
  def start_webui():
99
- """Launch WebUI in background and detect ready URL."""
100
- global WEBUI_LINK
101
- ensure_persistent_folders()
102
- fetch_models()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
 
104
- args = ["python", LAUNCH_PY] + shlex.split(WEBUI_ARGS)
105
- print("▢️ Launching WebUI with:", " ".join(args))
106
 
107
- proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
 
 
 
 
 
 
 
 
108
 
109
- # Monitor output for "Running on" URL
110
- for line in iter(proc.stdout.readline, ""):
111
- print(line, end="")
112
- if "Running on local URL:" in line or "Running on" in line:
113
- parts = line.split("http")
 
1
+ # app.py - HF Space launcher (Option B, HF tree aware, auto-open WebUI)
2
  import os
3
  import subprocess
4
  import threading
 
6
  import time
7
  import requests
8
  import gradio as gr
9
+ import webbrowser
10
 
11
  # -----------------------------
12
+ # Configuration (edit if needed)
13
  # -----------------------------
14
  DOWNLOADS = {
15
  "lora": {
 
31
  }
32
 
33
  WEBUI_ARGS = "--listen --xformers --enable-insecure-extension-access --medvram"
34
+ LAUNCH_PY = "launch.py" # relative to repo root (per HF tree)
35
 
36
  # -----------------------------
37
  # Utilities
38
  # -----------------------------
39
  def ensure_persistent_folders():
40
+ """Make sure HF tree persistent folders exist (safe no-op if present)."""
41
  folders = [
42
  "stable-diffusion-webui/deforum/input",
43
  "stable-diffusion-webui/deforum/output_committed/frames",
 
50
  os.makedirs(f, exist_ok=True)
51
  print("βœ… Persistent folders ensured.")
52
 
53
+
54
  def download_file_with_retries(url, dest, max_retries=3, backoff=5):
55
+ """Download a file with simple retry/backoff. Skips if dest exists."""
56
  if os.path.exists(dest):
57
  print(f"βœ… Already exists: {dest}")
58
  return True
 
68
  for chunk in r.iter_content(chunk_size=8192):
69
  if chunk:
70
  f.write(chunk)
71
+ # atomically move into place
72
  os.replace(dest + ".part", dest)
73
  print(f"βœ… Downloaded: {dest}")
74
  return True
 
77
  attempt += 1
78
  time.sleep(backoff * attempt)
79
  print(f"❌ Failed to download after {max_retries} attempts: {url}")
80
+ # ensure partial file removed
81
+ try:
82
+ if os.path.exists(dest + ".part"):
83
+ os.remove(dest + ".part")
84
+ except Exception:
85
+ pass
86
  return False
87
 
88
+
89
  def fetch_models():
90
+ """Download all configured models into the HF tree persistent paths."""
91
  print("πŸ”½ Starting runtime model downloads (if missing)...")
92
  success_all = True
93
  for name, info in DOWNLOADS.items():
94
+ url = info["url"]
95
+ dest = info["dest"]
96
+ ok = download_file_with_retries(url, dest)
97
  success_all = success_all and ok
98
  if success_all:
99
  print("βœ… All runtime downloads done (or already present).")
100
  else:
101
+ print("⚠️ Some runtime downloads failed. Check logs for details.")
102
+
103
 
104
  # -----------------------------
105
+ # Start WebUI routine (clean + auto open)
106
  # -----------------------------
 
 
107
  def start_webui():
108
+ """
109
+ Option B β€” background WebUI launcher aware of HF tree and persistent folders.
110
+ 1) Ensure persistent folders exist.
111
+ 2) Download missing runtime models.
112
+ 3) Launch Automatic1111 WebUI (launch.py) with correct PORT binding.
113
+ 4) Automatically open WebUI URL when ready.
114
+ """
115
+ try:
116
+ ensure_persistent_folders()
117
+ fetch_models()
118
+
119
+ port = int(os.environ.get("PORT", 7860))
120
+ cmd = ["python", LAUNCH_PY] + shlex.split(WEBUI_ARGS) + [f"--port {port}"]
121
+ print("▢️ Launching WebUI with:", " ".join(cmd))
122
+
123
+ # Launch launch.py and capture stdout
124
+ proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
125
+
126
+ for line in iter(proc.stdout.readline, ""):
127
+ print(line, end="") # Show logs in HF Space logs
128
+
129
+ # Detect URL line
130
+ if "Running on local URL:" in line or "Running on" in line:
131
+ url_start = line.find("http")
132
+ if url_start != -1:
133
+ url = line[url_start:].strip()
134
+ print(f"🌐 WebUI ready: {url} β€” opening automatically")
135
+ webbrowser.open(url)
136
+
137
+ proc.wait()
138
+ print("ℹ️ launch.py exited normally.")
139
+ except subprocess.CalledProcessError as cpe:
140
+ print(f"❌ launch.py exited with non-zero status: {cpe.returncode}")
141
+ except Exception as e:
142
+ print("❌ Exception in start_webui():", e)
143
+
144
+
145
+ # -----------------------------
146
+ # Kick off WebUI in background thread
147
+ # -----------------------------
148
+ threading.Thread(target=start_webui, daemon=True).start()
149
+ print("🧡 WebUI thread started (background).")
150
+
151
+ # -----------------------------
152
+ # Minimal Gradio UI to keep Space alive + quick controls
153
+ # -----------------------------
154
+ def show_status():
155
+ msg_lines = ["βœ… HF Space running (Option B launcher)."]
156
+ # quick presence checks
157
+ if os.path.exists(LAUNCH_PY):
158
+ msg_lines.append(f"launch.py: found")
159
+ else:
160
+ msg_lines.append(f"launch.py: MISSING at root!")
161
+ # list basic model presence
162
+ for key, info in DOWNLOADS.items():
163
+ present = "yes" if os.path.exists(info["dest"]) else "no"
164
+ msg_lines.append(f"{key}: {present}")
165
+ return "\n".join(msg_lines)
166
 
 
 
167
 
168
+ with gr.Blocks() as demo:
169
+ gr.Markdown("## Automatic1111 WebUI β€” HF Space launcher (Option B)")
170
+ gr.Markdown(
171
+ "This Space launches Automatic1111 in a background thread and keeps a small Gradio UI alive "
172
+ "so Hugging Face marks the app as initialized."
173
+ )
174
+ status_btn = gr.Button("Check status")
175
+ status_out = gr.Textbox(lines=10)
176
+ status_btn.click(fn=show_status, inputs=None, outputs=status_out)
177
 
178
+ demo.launch(server_name="0.0.0.0", server_port=int(os.environ.get("PORT", 7860)))