Spaces:
Running on Zero
Running on Zero
| """One-shot push: stage the Space layout in a tempdir and upload it to | |
| `EngEmmanuel/EchoLVFM` (private by default). | |
| The Space repo mirrors the local layout — `space/`, `utils/`, `vae/`, `src/` | |
| sit as siblings at the Space root, with `space/README.md` and | |
| `space/requirements.txt` promoted to root so HF picks them up. The README's | |
| frontmatter declares `app_file: space/app.py`, so the Space launcher finds | |
| the entrypoint inside the `space/` package — and `space/app.py`'s existing | |
| `sys.path` shim makes `from space import ...` and `from utils.hub import ...` | |
| resolve identically locally and on the Space. | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import shutil | |
| import subprocess | |
| import sys | |
| import tempfile | |
| from pathlib import Path | |
| REPO_ROOT = Path(__file__).resolve().parents[2] | |
| DEFAULT_REPO_ID = "EngEmmanuel/EchoLVFM" | |
| # Folders copied verbatim into the Space upload, preserving their layout. | |
| DEPS = ["space", "utils", "vae", "src"] | |
| # Stale paths from the previous (flat) push that need wiping before the | |
| # mirrored structure lands. `hf repos delete-files` takes literal paths | |
| # and shallow `*` globs (no `**` recursion), so list each subdir's known | |
| # files explicitly to be sure the wipe lands. | |
| STALE_PATTERNS = [ | |
| "app.py", "assets.py", "inference.py", "metrics.py", "video_io.py", | |
| "samples/*", "samples/*/*", | |
| "assets/*", | |
| "scripts/build_samples.py", "scripts/sync_to_hub.py", | |
| ] | |
| def _parse_args() -> argparse.Namespace: | |
| p = argparse.ArgumentParser(description=__doc__) | |
| p.add_argument("--repo-id", default=DEFAULT_REPO_ID) | |
| p.add_argument("--public", action="store_true", | |
| help="Create the Space as public (default: private).") | |
| return p.parse_args() | |
| def _stage(tmp: Path) -> None: | |
| """Materialise the Space-shaped tree under `tmp/`.""" | |
| ignore = shutil.ignore_patterns("__pycache__", "*.pyc", "*.pyo") | |
| for name in DEPS: | |
| shutil.copytree(REPO_ROOT / name, tmp / name, ignore=ignore) | |
| # Promote the Space README + requirements to the upload root so HF picks | |
| # them up; the originals live under `space/` for editing convenience. | |
| shutil.move(str(tmp / "space" / "README.md"), str(tmp / "README.md")) | |
| shutil.move(str(tmp / "space" / "requirements.txt"), | |
| str(tmp / "requirements.txt")) | |
| def main() -> int: | |
| args = _parse_args() | |
| create_cmd = [ | |
| "hf", "repos", "create", args.repo_id, | |
| "--type", "space", "--space-sdk", "gradio", "--exist-ok", | |
| ] | |
| if not args.public: | |
| create_cmd.append("--private") | |
| print("$", " ".join(create_cmd)) | |
| rc = subprocess.call(create_cmd) | |
| if rc != 0: | |
| return rc | |
| # Wipe the stale flat-file root from a prior push. Best-effort — | |
| # `delete-files` returns non-zero when patterns match nothing, which | |
| # is fine on a fresh repo. | |
| delete_cmd = [ | |
| "hf", "repos", "delete-files", args.repo_id, *STALE_PATTERNS, | |
| "--type", "space", | |
| "--commit-message", "Drop stale flat-file root before mirrored push", | |
| ] | |
| print("$", " ".join(delete_cmd)) | |
| subprocess.call(delete_cmd) | |
| with tempfile.TemporaryDirectory(prefix="echolvfm_space_") as td: | |
| tmp = Path(td) | |
| _stage(tmp) | |
| upload_cmd = [ | |
| "hf", "upload", args.repo_id, str(tmp), ".", | |
| "--type", "space", | |
| "--commit-message", | |
| "Sync EchoLVFM Space (mirrored layout: space/, utils/, vae/, src/)", | |
| ] | |
| print("$", " ".join(upload_cmd)) | |
| return subprocess.call(upload_cmd) | |
| if __name__ == "__main__": | |
| sys.exit(main()) | |