99import time
1010from importlib .resources import files
1111from pathlib import Path
12+ from typing import Literal
1213
1314if sys .version_info >= (3 , 11 ):
1415 import tomllib
2021import huggingface_hub
2122from gradio_client import Client , handle_file
2223from httpx import ReadTimeout
24+ from huggingface_hub import Volume
2325from huggingface_hub .errors import HfHubHTTPError , RepositoryNotFoundError
2426
2527import trackio
26- from trackio .bucket_storage import create_bucket_if_not_exists , upload_project_to_bucket
27- from trackio .space_volumes import (
28- attach_bucket_volume ,
28+ from trackio .bucket_storage import (
29+ create_bucket_if_not_exists ,
30+ upload_project_to_bucket ,
31+ upload_project_to_bucket_for_static ,
2932)
3033from trackio .sqlite_storage import SQLiteStorage
3134from trackio .utils import (
@@ -233,14 +236,25 @@ def deploy_as_space(
233236 if hf_token := huggingface_hub .utils .get_token ():
234237 huggingface_hub .add_space_secret (space_id , "HF_TOKEN" , hf_token )
235238 if bucket_id is not None :
236- changed = attach_bucket_volume (
237- space_id ,
238- bucket_id ,
239- mount_path = "/data" ,
239+ runtime = hf_api .get_space_runtime (space_id )
240+ existing = list (runtime .volumes ) if runtime .volumes else []
241+ already_mounted = any (
242+ v .type == "bucket" and v .source == bucket_id and v .mount_path == "/data"
243+ for v in existing
240244 )
241- huggingface_hub .add_space_variable (space_id , "TRACKIO_DIR" , "/data/trackio" )
242- if changed :
245+ if not already_mounted :
246+ non_bucket = [
247+ v
248+ for v in existing
249+ if not (v .type == "bucket" and v .source == bucket_id )
250+ ]
251+ hf_api .set_space_volumes (
252+ space_id ,
253+ non_bucket
254+ + [Volume (type = "bucket" , source = bucket_id , mount_path = "/data" )],
255+ )
243256 print (f"* Attached bucket { bucket_id } at '/data'" )
257+ huggingface_hub .add_space_variable (space_id , "TRACKIO_DIR" , "/data/trackio" )
244258 elif dataset_id is not None :
245259 huggingface_hub .add_space_variable (space_id , "TRACKIO_DATASET_ID" , dataset_id )
246260 if logo_light_url := os .environ .get ("TRACKIO_LOGO_LIGHT_URL" ):
@@ -687,7 +701,7 @@ def sync(
687701 private : bool | None = None ,
688702 force : bool = False ,
689703 run_in_background : bool = False ,
690- sdk : str = "gradio" ,
704+ sdk : Literal [ "gradio" , "static" ] = "gradio" ,
691705 dataset_id : str | None = None ,
692706 bucket_id : str | None = None ,
693707) -> str :
@@ -712,7 +726,7 @@ def sync(
712726 sdk (`str`, *optional*, defaults to `"gradio"`):
713727 The type of Space to deploy. `"gradio"` deploys a Gradio Space with a live
714728 server. `"static"` deploys a static Space that reads from an HF Dataset
715- (no server needed).
729+ or HF Bucket (no server needed).
716730 dataset_id (`str`, *optional*):
717731 The ID of the HF Dataset to sync to. When provided, uses the legacy
718732 Dataset backend instead of Buckets.
@@ -734,6 +748,20 @@ def sync(
734748
735749 def _do_sync ():
736750 if sdk == "static" :
751+ try :
752+ info = huggingface_hub .HfApi ().space_info (space_id )
753+ if info .sdk == "gradio" :
754+ if not force :
755+ answer = input (
756+ f"Space '{ space_id } ' is currently a Gradio Space. "
757+ f"Convert to static? [y/N] "
758+ )
759+ if answer .lower () not in ("y" , "yes" ):
760+ print ("Aborted." )
761+ return
762+ except RepositoryNotFoundError :
763+ pass
764+
737765 if dataset_id is not None :
738766 upload_dataset_for_static (project , dataset_id , private = private )
739767 hf_token = huggingface_hub .utils .get_token () if private else None
@@ -746,7 +774,7 @@ def _do_sync():
746774 )
747775 elif bucket_id is not None :
748776 create_bucket_if_not_exists (bucket_id , private = private )
749- upload_project_to_bucket (project , bucket_id )
777+ upload_project_to_bucket_for_static (project , bucket_id )
750778 print (
751779 f"* Project data uploaded to bucket: https://huggingface.co/buckets/{ bucket_id } "
752780 )
0 commit comments