| from __future__ import annotations |
|
|
| from dataclasses import asdict, dataclass |
| from pathlib import Path |
|
|
| SPACE_REQUIRED_FILES = [ |
| "app.py", |
| "plant_space_app.py", |
| "requirements.txt", |
| "README.md", |
| "config/models.yaml", |
| "config/training.yaml", |
| ] |
|
|
|
|
| @dataclass(frozen=True) |
| class SpaceBuildStatus: |
| required_files_present: bool |
| missing_files: list[str] |
| readme_has_space_metadata: bool |
| has_space_remote: bool |
|
|
| def as_dict(self) -> dict: |
| return asdict(self) |
|
|
|
|
| def missing_required_files(root: str | Path = ".") -> list[str]: |
| repo_root = Path(root) |
| return [path for path in SPACE_REQUIRED_FILES if not (repo_root / path).exists()] |
|
|
|
|
| def readme_has_space_metadata(root: str | Path = ".") -> bool: |
| readme_path = Path(root) / "README.md" |
| if not readme_path.exists(): |
| return False |
| text = readme_path.read_text(encoding="utf-8") |
| return text.startswith("---\n") and "\nsdk: gradio\n" in text and "\napp_file: app.py\n" in text |
|
|
|
|
| def has_space_remote(remote_output: str, remote_name: str = "space") -> bool: |
| return any(line.startswith(f"{remote_name}\t") for line in remote_output.splitlines()) |
|
|
|
|
| def space_build_status(root: str | Path = ".", remote_output: str = "") -> SpaceBuildStatus: |
| missing = missing_required_files(root) |
| return SpaceBuildStatus( |
| required_files_present=not missing, |
| missing_files=missing, |
| readme_has_space_metadata=readme_has_space_metadata(root), |
| has_space_remote=( |
| has_space_remote(remote_output, "space") |
| or has_space_remote(remote_output, "space-workbench") |
| or has_space_remote(remote_output, "space-plant") |
| ), |
| ) |
|
|
|
|
| def create_space_commands( |
| hf_user: str, |
| space_name: str = "openbmb-local-ai-workbench", |
| branch: str = "main", |
| remote_name: str = "space", |
| app_file: str = "app.py", |
| ) -> list[str]: |
| if not hf_user.strip(): |
| raise ValueError("hf_user is required") |
| if not space_name.strip(): |
| raise ValueError("space_name is required") |
| if not remote_name.strip(): |
| raise ValueError("remote_name is required") |
| if not app_file.strip(): |
| raise ValueError("app_file is required") |
| return [ |
| "hf auth login", |
| f"hf repo create {hf_user}/{space_name} --type space --space-sdk gradio", |
| f"git remote add {remote_name} https://huggingface.co/spaces/{hf_user}/{space_name}", |
| f"git push {remote_name} {branch}", |
| f"Space metadata app_file must be {app_file} for this deployment.", |
| ] |
|
|
|
|
| def hackathon_space_commands(branch: str = "main") -> dict[str, list[str]]: |
| return { |
| "workbench": create_space_commands( |
| "build-small-hackathon", |
| "workbench", |
| branch, |
| remote_name="space-workbench", |
| app_file="app.py", |
| ), |
| "plant": create_space_commands( |
| "build-small-hackathon", |
| "plant_identification_tool", |
| branch, |
| remote_name="space-plant", |
| app_file="plant_space_app.py", |
| ), |
| } |
|
|