File size: 4,907 Bytes
0ad74ed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import argparse
import pathlib
import shutil
import sys
import tempfile
import textwrap
from typing import Optional

from huggingface_hub import CommitOperationAdd, HfApi


def upload_demo_to_space(
    demo_name: str, space_id: str, hf_token: str, gradio_version: Optional[str]
):
    """
    Upload a demo from the demo directory to a Hugging Face Space in chunks of 50 files per commit.

    Args:
        demo_name: The name of the demo to upload.
        space_id: The ID of the space to upload the demo to (e.g., username/space_name).
        hf_token: Hugging Face API token with write permissions to the space.
        gradio_version: If provided, sets the Gradio version in the created space.

    Returns:
        str: URL of the uploaded Hugging Face Space.
    """

    print(f"Uploading demo '{demo_name}' to space '{space_id}'...")

    def split_into_chunks(lst: list, n: int) -> list[list]:
        for i in range(0, len(lst), n):
            yield lst[i : i + n]

    api = HfApi()

    print("Creating repository...")

    # Create the repository if it doesn't exist
    space_url = api.create_repo(
        repo_id=space_id,
        space_sdk="gradio",
        repo_type="space",
        token=hf_token,
        exist_ok=True,
    )

    space_id = space_url.repo_id

    with tempfile.TemporaryDirectory() as tmpdir:
        demo_path = pathlib.Path.cwd() / "demo" / demo_name
        if not demo_path.exists():
            raise FileNotFoundError(f"Demo path '{demo_path}' does not exist.")

        shutil.copytree(demo_path, tmpdir, dirs_exist_ok=True)

        # update README.md with Gradio version if provided
        if gradio_version:
            readme = pathlib.Path(tmpdir, "README.md")
            readme_content = f"""
            ---
            title: {space_id.split("/")[-1]} 
            emoji: 💩
            colorFrom: indigo
            colorTo: indigo
            sdk: gradio
            sdk_version: {gradio_version}
            app_file: run.py
            pinned: false
            ---
            """
            readme.write_text(textwrap.dedent(readme_content))

        print("Uploading files to Hugging Face Space...")

        # Create the repository if it doesn't exist
        api.create_repo(
            repo_id=space_id,
            space_sdk="gradio",
            repo_type="space",
            token=hf_token,
            exist_ok=True,
        )

        print("Uploading files...")

        all_files = sorted([p for p in pathlib.Path(tmpdir).rglob("*") if p.is_file()])
        relative_files = [p.relative_to(tmpdir) for p in all_files]

        # Create CommitOperationAdd objects for all files
        operations = [
            CommitOperationAdd(
                path_in_repo=str(rel_path).replace("\\", "/"),
                path_or_fileobj=str(pathlib.Path(tmpdir) / rel_path),
            )
            for rel_path in relative_files
        ]

        # Split operations into chunks of 50
        operation_chunks = list(split_into_chunks(operations, 50))

        for idx, chunk in enumerate(operation_chunks, start=1):
            commit_message = f"Commit {idx}: Add {len(chunk)} file(s)"
            try:
                api.create_commit(
                    repo_id=space_id,
                    operations=chunk,
                    commit_message=commit_message,
                    token=hf_token,
                    repo_type="space",
                )
                print(f"Successfully committed chunk {idx} with {len(chunk)} file(s).")
            except Exception as e:
                print(f"Failed to commit chunk {idx}: {e}")
                raise e

    return f"https://huggingface.co/spaces/{space_id}"


if __name__ == "__main__":
    print("Starting upload...")
    parser = argparse.ArgumentParser(
        description="Upload a demo to a Hugging Face Space in chunks."
    )
    parser.add_argument("demo_name", type=str, help="Name of the demo to upload")
    parser.add_argument(
        "space_id",
        type=str,
        help="ID of the space to upload the demo to (e.g., username/space_name)",
    )
    parser.add_argument("hf_token", type=str, help="Hugging Face API token")
    parser.add_argument(
        "--gradio-version",
        type=str,
        help="If provided, sets the Gradio version in the created space to the given version.",
    )
    args = parser.parse_args()
    try:
        print("Uploading demo to Hugging Face Space...")
        new_space_url = upload_demo_to_space(
            args.demo_name, args.space_id, args.hf_token, args.gradio_version
        )
        print("Demo successfully uploaded to:")
        # do not change the final print statement,
        # it must appear as the last line of the logs for CI to pick up the URL
        print(new_space_url)
    except Exception as error:
        print(f"An error occurred during upload: {error}")
        sys.exit(1)