|
import io |
|
import os |
|
import time |
|
from importlib.resources import files |
|
from pathlib import Path |
|
|
|
import gradio |
|
import huggingface_hub |
|
from gradio_client import Client, handle_file |
|
from httpx import ReadTimeout |
|
from huggingface_hub.errors import RepositoryNotFoundError |
|
|
|
from trackio.sqlite_storage import SQLiteStorage |
|
|
|
SPACE_URL = "https://huggingface.co/spaces/{space_id}" |
|
|
|
|
|
def deploy_as_space( |
|
space_id: str, |
|
dataset_id: str | None = None, |
|
): |
|
if ( |
|
os.getenv("SYSTEM") == "spaces" |
|
): |
|
return |
|
|
|
trackio_path = files("trackio") |
|
|
|
hf_api = huggingface_hub.HfApi() |
|
whoami = None |
|
login = False |
|
try: |
|
whoami = hf_api.whoami() |
|
if whoami["auth"]["accessToken"]["role"] != "write": |
|
login = True |
|
except OSError: |
|
login = True |
|
if login: |
|
print("Need 'write' access token to create a Spaces repo.") |
|
huggingface_hub.login(add_to_git_credential=False) |
|
whoami = hf_api.whoami() |
|
|
|
huggingface_hub.create_repo( |
|
space_id, |
|
space_sdk="gradio", |
|
repo_type="space", |
|
exist_ok=True, |
|
) |
|
|
|
with open(Path(trackio_path, "README.md"), "r") as f: |
|
readme_content = f.read() |
|
readme_content = readme_content.replace("{GRADIO_VERSION}", gradio.__version__) |
|
readme_buffer = io.BytesIO(readme_content.encode("utf-8")) |
|
hf_api.upload_file( |
|
path_or_fileobj=readme_buffer, |
|
path_in_repo="README.md", |
|
repo_id=space_id, |
|
repo_type="space", |
|
) |
|
|
|
huggingface_hub.utils.disable_progress_bars() |
|
hf_api.upload_folder( |
|
repo_id=space_id, |
|
repo_type="space", |
|
folder_path=trackio_path, |
|
ignore_patterns=["README.md"], |
|
) |
|
|
|
hf_token = huggingface_hub.utils.get_token() |
|
if hf_token is not None: |
|
huggingface_hub.add_space_secret(space_id, "HF_TOKEN", hf_token) |
|
if dataset_id is not None: |
|
huggingface_hub.add_space_variable(space_id, "TRACKIO_DATASET_ID", dataset_id) |
|
|
|
|
|
def create_space_if_not_exists( |
|
space_id: str, |
|
dataset_id: str | None = None, |
|
) -> None: |
|
""" |
|
Creates a new Hugging Face Space if it does not exist. If a dataset_id is provided, it will be added as a space variable. |
|
|
|
Args: |
|
space_id: The ID of the Space to create. |
|
dataset_id: The ID of the Dataset to add to the Space. |
|
""" |
|
if "/" not in space_id: |
|
raise ValueError( |
|
f"Invalid space ID: {space_id}. Must be in the format: username/reponame or orgname/reponame." |
|
) |
|
if dataset_id is not None and "/" not in dataset_id: |
|
raise ValueError( |
|
f"Invalid dataset ID: {dataset_id}. Must be in the format: username/datasetname or orgname/datasetname." |
|
) |
|
try: |
|
huggingface_hub.repo_info(space_id, repo_type="space") |
|
print(f"* Found existing space: {SPACE_URL.format(space_id=space_id)}") |
|
if dataset_id is not None: |
|
huggingface_hub.add_space_variable( |
|
space_id, "TRACKIO_DATASET_ID", dataset_id |
|
) |
|
return |
|
except RepositoryNotFoundError: |
|
pass |
|
|
|
print(f"* Creating new space: {SPACE_URL.format(space_id=space_id)}") |
|
deploy_as_space(space_id, dataset_id) |
|
|
|
client = None |
|
for _ in range(30): |
|
try: |
|
client = Client(space_id, verbose=False) |
|
if client: |
|
break |
|
except ReadTimeout: |
|
print("* Space is not yet ready. Waiting 5 seconds...") |
|
time.sleep(5) |
|
except ValueError as e: |
|
print(f"* Space gave error {e}. Trying again in 5 seconds...") |
|
time.sleep(5) |
|
|
|
|
|
def upload_db_to_space(project: str, space_id: str) -> None: |
|
""" |
|
Uploads the database of a local Trackio project to a Hugging Face Space. |
|
|
|
Args: |
|
project: The name of the project to upload. |
|
space_id: The ID of the Space to upload to. |
|
""" |
|
db_path = SQLiteStorage.get_project_db_path(project) |
|
client = Client(space_id, verbose=False) |
|
client.predict( |
|
api_name="/upload_db_to_space", |
|
project=project, |
|
uploaded_db=handle_file(db_path), |
|
hf_token=huggingface_hub.utils.get_token(), |
|
) |
|
|