Spaces:
Sleeping
Sleeping
File size: 6,650 Bytes
40dafca 64a8c65 780f03f 40dafca 64a8c65 780f03f 64a8c65 780f03f 64a8c65 40dafca 64a8c65 40dafca 64a8c65 40dafca 64a8c65 40dafca 64a8c65 40dafca 780f03f 40dafca 64a8c65 40dafca 64a8c65 780f03f 40dafca 64a8c65 40dafca 64a8c65 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
#!/usr/bin/env python3
"""
HuggingFace Spaces main launcher for BytePlus Image Generation Studio
Alternative directory strategy for Spaces where the repository may not contain
the required folders (Generated/, static/, view_session/):
1) Create these folders under a persistent/writable base (prefer /data, fallback /tmp)
2) Symlink them into the working directory so the app can use relative paths
This works even when the repo itself doesn't track those directories.
"""
import os
import sys
from pathlib import Path
import importlib.util
def _is_writable(p: Path) -> bool:
try:
p.mkdir(parents=True, exist_ok=True)
test_file = p / ".__writable_test__"
test_file.write_text("ok")
test_file.unlink(missing_ok=True)
return True
except Exception:
return False
def _pick_persistent_base() -> Path:
"""Pick a persistent base directory on Spaces.
- Prefer /data if available/writable (persisted across restarts)
- Fallback to /tmp if /data is unavailable
"""
candidates = [Path("/data/byteplus"), Path("/data"), Path("/tmp/byteplus")]
for c in candidates:
base = c if c.name == "byteplus" else c / "byteplus"
if _is_writable(base):
return base
# Final fallback
return Path("/tmp/byteplus")
def _ensure_dir(path: Path):
path.mkdir(parents=True, exist_ok=True)
try:
path.chmod(0o755)
except Exception:
pass
def _safe_symlink(target: Path, link_path: Path):
"""Create/repair a symlink from link_path -> target.
If link_path exists as a real dir, attempt to migrate contents, then replace with symlink.
"""
try:
if link_path.is_symlink() or link_path.exists():
# If it's already the correct symlink, keep it
try:
if link_path.is_symlink() and link_path.resolve() == target.resolve():
return
except Exception:
pass
if link_path.is_symlink():
link_path.unlink()
elif link_path.is_dir():
# Migrate existing contents to target
target.mkdir(parents=True, exist_ok=True)
for item in link_path.iterdir():
dest = target / item.name
try:
if item.is_dir():
if dest.exists():
# Merge: move children
for sub in item.iterdir():
sub.rename(dest / sub.name)
item.rmdir()
else:
item.rename(dest)
else:
if dest.exists():
dest.unlink()
item.rename(dest)
except Exception as e:
print(f"β οΈ Migration warning for {item}: {e}")
# Now remove the original dir
try:
link_path.rmdir()
except Exception:
pass
else:
# Regular file: remove to replace with symlink
link_path.unlink(missing_ok=True)
# Ensure target exists before linking
target.mkdir(parents=True, exist_ok=True)
link_path.symlink_to(target, target_is_directory=True)
print(f"π Linked {link_path} -> {target}")
except Exception as e:
print(f"β οΈ Could not create symlink {link_path} -> {target}: {e}")
# Fallback: ensure local directory exists
try:
_ensure_dir(link_path)
print(f"π Fallback: created local dir {link_path}")
except Exception as ie:
print(f"β Fallback failed for {link_path}: {ie}")
def ensure_persistent_dirs_and_symlinks():
"""Ensure required dirs exist in persistent storage and are symlinked into CWD."""
print("ποΈ Ensuring required directories via persistent storage and symlinks...")
base = _pick_persistent_base()
print(f"π¦ Using storage base: {base}")
# Create persistent dirs
gen_p = base / "Generated"
static_p = base / "static"
view_p = base / "view_session"
for d in [gen_p, static_p, view_p, static_p / "css", static_p / "js", static_p / "images"]:
_ensure_dir(d)
# Symlink into working directory
cwd = Path.cwd()
_safe_symlink(gen_p, cwd / "Generated")
_safe_symlink(static_p, cwd / "static")
_safe_symlink(view_p, cwd / "view_session")
print("π― Symlinked working directories are ready!")
def load_byteplus_app():
"""Load and return the BytePlus application."""
try:
# Load the BytePlus app module
spec = importlib.util.spec_from_file_location("byteplus_app", "byteplus_app.py")
byteplus_module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(byteplus_module)
# Try to find the Gradio app
if hasattr(byteplus_module, 'demo'):
return byteplus_module.demo
elif hasattr(byteplus_module, 'app'):
return byteplus_module.app
elif hasattr(byteplus_module, 'interface'):
return byteplus_module.interface
else:
# Look for any object with a launch method
for attr_name in dir(byteplus_module):
attr = getattr(byteplus_module, attr_name)
if hasattr(attr, 'launch') and callable(attr.launch):
return attr
raise ValueError("Could not find Gradio app in byteplus_app.py")
except Exception as e:
print(f"β Error loading BytePlus app: {e}")
raise
def main():
"""Main function to setup and launch BytePlus."""
print("π Starting BytePlus Image Generation Studio for HuggingFace Spaces...")
# Ensure persistent storage dirs exist and are symlinked into CWD
ensure_persistent_dirs_and_symlinks()
# Load and launch the BytePlus app
try:
print("π₯ Loading BytePlus Image Generation Studio...")
demo = load_byteplus_app()
print("π Launching BytePlus Image Generation Studio...")
# Ensure proper binding for Spaces
port = int(os.getenv("PORT", "7860"))
demo.launch(server_name="0.0.0.0", server_port=port)
except Exception as e:
print(f"β Error launching BytePlus: {e}")
import traceback
traceback.print_exc()
sys.exit(1)
if __name__ == "__main__":
main() |