Spaces:
Sleeping
Sleeping
File size: 10,363 Bytes
9a7a411 |
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 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 |
import os
import sys
import shutil
from pathlib import Path
from huggingface_hub import snapshot_download
import importlib.util
from dotenv import load_dotenv
load_dotenv()
def setup_cache_directory():
"""Create a hidden cache directory '.cache'.
If an existing 'cache' directory exists, migrate its contents into '.cache'.
Set restrictive permissions (owner rwx) and on macOS set the Finder hidden flag
unless the environment variable `HIDE_CACHE` is explicitly set to '0'.
"""
hidden_cache = Path(".cache")
public_cache = Path("cache")
# If the hidden cache doesn't exist but a public one does, move it.
try:
if not hidden_cache.exists():
if public_cache.exists():
# Prefer move to preserve contents and metadata
public_cache.rename(hidden_cache)
else:
hidden_cache.mkdir(exist_ok=True)
else:
# ensure it exists
hidden_cache.mkdir(exist_ok=True)
# Restrict permissions to owner only (rwx------)
try:
hidden_cache.chmod(0o700)
except Exception:
# chmod may fail on some filesystems or platforms; ignore
pass
# On macOS, optionally set Finder hidden flag for extra concealment
if sys.platform == "darwin":
hide_flag = os.environ.get("HIDE_CACHE", "1")
if hide_flag != "0":
try:
# 'chflags hidden <path>' will make the folder hidden in Finder
os.system(f"/usr/bin/chflags hidden {hidden_cache}")
except Exception:
pass
return hidden_cache
except Exception:
# Fallback: try to create a simple cache folder named 'cache'
public_cache.mkdir(exist_ok=True)
return public_cache
def create_symbolic_links(cache_dir):
"""Create symbolic links for Generated, static, and view_session directories.
The strategy is to make sure we have real directories in cache and symbolic links from root to cache.
This ensures the BytePlus app can access these directories even when running from cache.
"""
root_dir = Path.cwd()
directories_to_link = ["Generated", "static", "view_session"]
for dir_name in directories_to_link:
# Root directory path (should be symlink)
root_link = root_dir / dir_name
# Cache directory path (should be real directory)
cache_target = cache_dir / dir_name
try:
# Ensure we have a real directory in cache
if cache_target.is_symlink():
# Remove the symlink in cache if it exists
cache_target.unlink()
print(f"Removed cache symlink: {cache_target}")
if not cache_target.exists():
cache_target.mkdir(parents=True, exist_ok=True)
print(f"Created cache directory: {cache_target}")
# Set proper permissions on cache directory (755)
cache_target.chmod(0o755)
print(f"Set permissions 755 on: {cache_target}")
# Ensure root has symlink to cache (if it doesn't already exist)
if not root_link.is_symlink():
if root_link.exists():
# If it's a real directory, we might need to move content or just replace
if root_link.is_dir():
# Try to move content to cache first
try:
for item in root_link.iterdir():
dest = cache_target / item.name
if not dest.exists():
shutil.move(str(item), str(dest))
shutil.rmtree(root_link)
print(f"Moved content from {root_link} to {cache_target}")
except Exception as e:
print(f"Could not move content: {e}")
shutil.rmtree(root_link)
else:
root_link.unlink()
# Create the symlink from root to cache
root_link.symlink_to(cache_target)
print(f"Created root symlink: {root_link} -> {cache_target}")
else:
print(f"Root symlink already exists: {root_link}")
except Exception as e:
print(f"Error setting up links for {dir_name}: {e}")
# Fallback: ensure at least the cache directory exists
try:
if not cache_target.exists():
cache_target.mkdir(parents=True, exist_ok=True)
cache_target.chmod(0o755)
print(f"Created fallback cache directory: {cache_target}")
except Exception as fe:
print(f"Fallback failed for {dir_name}: {fe}")
def ensure_directory_permissions():
"""Ensure proper permissions on key directories in the current working directory."""
directories_to_fix = ["Generated", "static", "view_session"]
for dir_name in directories_to_fix:
dir_path = Path(dir_name)
try:
if not dir_path.exists():
# Create directory if it doesn't exist
dir_path.mkdir(parents=True, exist_ok=True)
print(f"Created directory: {dir_path}")
# Set directory permissions to 755 (owner rwx, group rx, others rx)
dir_path.chmod(0o755)
print(f"Set permissions 755 on directory: {dir_path}")
# Set permissions on all subdirectories and files
for item in dir_path.rglob('*'):
try:
if item.is_dir():
item.chmod(0o755)
else:
item.chmod(0o644) # Files: owner rw, group r, others r
except Exception as e:
print(f"Warning: Could not set permissions on {item}: {e}")
except Exception as e:
print(f"Error ensuring permissions for {dir_name}: {e}")
def download_space(cache_dir):
token = os.environ.get("HF_TOKEN")
repo_id = os.environ.get("REPO_ID")
if not token or not repo_id:
return False
try:
snapshot_download(
repo_id=repo_id,
repo_type="space",
local_dir=cache_dir,
token=token
)
return True
except:
return False
def load_app(cache_dir):
sys.path.insert(0, str(cache_dir))
app_path = cache_dir / "app.py"
spec = importlib.util.spec_from_file_location("app", app_path)
app = importlib.util.module_from_spec(spec)
spec.loader.exec_module(app)
# First try the common 'demo' attribute used by many Gradio Spaces
if hasattr(app, "demo"):
return app.demo
# Otherwise, search for any attribute with a callable 'launch' method
for name in dir(app):
try:
attr = getattr(app, name)
except Exception:
continue
# Skip classes (types) since their 'launch' will be an unbound function
if isinstance(attr, type):
continue
if hasattr(attr, "launch") and callable(getattr(attr, "launch")):
return attr
# Next, accept top-level callables that return an object with a 'launch' method.
# This covers Spaces that expose a factory function instead of a 'demo' object.
factory_names = [
"create_secure_interface",
"create_app",
"create_demo",
"main",
"generator",
]
for name in factory_names:
if hasattr(app, name):
try:
candidate = getattr(app, name)
if callable(candidate):
created = candidate()
if hasattr(created, "launch") and callable(getattr(created, "launch")):
return created
# If the factory itself is a Gradio Interface (callable with launch), return it
if hasattr(candidate, "launch") and callable(getattr(candidate, "launch")):
return candidate
except Exception:
# ignore failures from calling the factory and continue searching
pass
# Also accept any top-level callable that when called returns an object with 'launch'
for name in dir(app):
if name.startswith("__"):
continue
try:
attr = getattr(app, name)
except Exception:
continue
if callable(attr):
try:
created = attr()
if hasattr(created, "launch") and callable(getattr(created, "launch")):
return created
except Exception:
# if calling fails, skip
continue
# If nothing found, raise a helpful error describing the problem
available = [n for n in dir(app) if not n.startswith("__")]
raise AttributeError(
"Could not find a demo application in the downloaded space."
f" Looked for attribute 'demo' and any attribute with a callable 'launch'."
f" Available top-level names: {available}"
)
if __name__ == "__main__":
print("Setting up BytePlus Image Generation Studio...")
# First ensure proper permissions on existing directories
ensure_directory_permissions()
# Setup cache directory
cache_dir = setup_cache_directory()
print(f"Cache directory: {cache_dir}")
# Download the space
if download_space(cache_dir):
print("Successfully downloaded BytePlus space")
# Create symbolic links for directory access
create_symbolic_links(cache_dir)
# Load and launch the app
try:
demo = load_app(cache_dir)
print("Launching BytePlus Image Generation Studio...")
demo.launch()
except Exception as e:
print(f"Error launching app: {e}")
sys.exit(1)
else:
print("Failed to download space. Please check your HF_TOKEN and REPO_ID environment variables.")
sys.exit(1) |