0: @_deprecate_arguments( 1: version="2.0", 2: deprecated_args={"space_storage"}, 3: custom_message="Use `space_volumes` to mount volumes on a Space.", 4: ) 5: @validate_hf_hub_args 6: def create_repo( 7: self, 8: repo_id: str, 9: *, 10: token: str | bool | None = None, 11: private: bool | None = None, 12: visibility: RepoVisibility_T | None = None, 13: repo_type: str | None = None, 14: exist_ok: bool = False, 15: resource_group_id: str | None = None, 16: region: REPO_REGIONS | None = None, 17: space_sdk: str | None = None, 18: space_hardware: SpaceHardware | None = None, 19: space_storage: SpaceStorage | None = None, 20: space_sleep_time: int | None = None, 21: space_secrets: list[dict[str, str]] | None = None, 22: space_variables: list[dict[str, str]] | None = None, 23: space_volumes: list[Volume] | None = None, 24: ) -> RepoUrl: 25: """Create an empty repo on the HuggingFace Hub. 26: 27: Args: 28: repo_id (`str`): 29: A namespace (user or an organization) and a repo name separated 30: by a `/`. 31: token (`bool` or `str`, *optional*): 32: A valid user access token (string). Defaults to the locally saved 33: token, which is the recommended method for authentication (see 34: https://huggingface.co/docs/huggingface_hub/quick-start#authentication). 35: To disable authentication, pass `False`. 36: private (`bool`, *optional*): 37: Whether to make the repo private. If `None` (default), the repo will be public unless the organization's default is private. This value is ignored if the repo already exists. Cannot be passed together with `visibility`. 38: visibility (`Literal["public", "private", "protected"]`, *optional*): 39: Visibility of the repo. Can be `"public"` or `"private"`, or `"protected"` for Spaces. If `None` 40: (default), the repo will be public unless the organization's default is private. This value is ignored 41: if the repo already exists. 42: repo_type (`str`, *optional*): 43: Set to `"dataset"` or `"space"` if uploading to a dataset or 44: space, `None` or `"model"` if uploading to a model. Default is 45: `None`. 46: exist_ok (`bool`, *optional*, defaults to `False`): 47: If `True`, do not raise an error if repo already exists. 48: resource_group_id (`str`, *optional*): 49: Resource group in which to create the repo. Resource groups is only available for Enterprise Hub organizations and 50: allow to define which members of the organization can access the resource. The ID of a resource group 51: can be found in the URL of the resource's page on the Hub (e.g. `"66670e5163145ca562cb1988"`). 52: To learn more about resource groups, see https://huggingface.co/docs/hub/en/security-resource-groups. 53: region (`Literal["us", "eu"]`, *optional*): 54: Cloud region in which to create the repo. Can be one of `"us"` or `"eu"`. If not specified, the repo will be 55: created in the default region. Requires Team plan or above. 56: space_sdk (`str`, *optional*): 57: Choice of SDK to use if repo_type is "space". Can be "streamlit", "gradio", "docker", or "static". 58: space_hardware (`SpaceHardware` or `str`, *optional*): 59: Choice of Hardware if repo_type is "space". See [`SpaceHardware`] for a complete list. 60: space_storage (`SpaceStorage` or `str`, *optional*): 61: Choice of persistent storage tier. Example: `"small"`. See [`SpaceStorage`] for a complete list. 62: space_sleep_time (`int`, *optional*): 63: Number of seconds of inactivity to wait before a Space is put to sleep. Set to `-1` if you don't want 64: your Space to sleep (default behavior for upgraded hardware). For free hardware, you can't configure 65: the sleep time (value is fixed to 48 hours of inactivity). 66: See https://huggingface.co/docs/hub/spaces-gpus#sleep-time for more details. 67: space_secrets (`list[dict[str, str]]`, *optional*): 68: A list of secret keys to set in your Space. Each item is in the form `{"key": ..., "value": ..., "description": ...}` where description is optional. 69: For more details, see https://huggingface.co/docs/hub/spaces-overview#managing-secrets. 70: space_variables (`list[dict[str, str]]`, *optional*): 71: A list of public environment variables to set in your Space. Each item is in the form `{"key": ..., "value": ..., "description": ...}` where description is optional. 72: For more details, see https://huggingface.co/docs/hub/spaces-overview#managing-secrets-and-environment-variables. 73: space_volumes (`list[Volume]`, *optional*): 74: A list of [`Volume`] objects to mount in the Space at creation time. Each volume has a `type` 75: (`"bucket"`, `"model"`, `"dataset"`, or `"space"`), a `source` (repo or bucket ID), a `mount_path` 76: (path inside the container), and optional `revision`, `read_only`, and `path` fields. 77: Only applicable if repo_type is "space". 78: 79: Returns: 80: [`RepoUrl`]: URL to the newly created repo. Value is a subclass of `str` containing 81: attributes like `endpoint`, `repo_type` and `repo_id`. 82: """ 83: organization, name = repo_id.split("/") if "/" in repo_id else (None, repo_id) 84: 85: path = f"{self.endpoint}/api/repos/create" 86: 87: if repo_type not in constants.REPO_TYPES_WITH_KERNEL: 88: raise ValueError("Invalid repo type") 89: 90: resolved_visibility = _resolve_repo_visibility(private=private, visibility=visibility, repo_type=repo_type) 91: 92: payload: dict[str, Any] = {"name": name, "organization": organization} 93: if resolved_visibility is not None: 94: payload["visibility"] = resolved_visibility 95: if repo_type is not None: 96: payload["type"] = repo_type 97: if repo_type == "space": 98: if space_sdk is None: 99: raise ValueError( 100: "No space_sdk provided. `create_repo` expects space_sdk to be one" 101: f" of {constants.SPACES_SDK_TYPES} when repo_type is 'space'`" 102: ) 103: if space_sdk not in constants.SPACES_SDK_TYPES: 104: raise ValueError(f"Invalid space_sdk. Please choose one of {constants.SPACES_SDK_TYPES}.") 105: payload["sdk"] = space_sdk 106: 107: if space_sdk is not None and repo_type != "space": 108: warnings.warn("Ignoring provided space_sdk because repo_type is not 'space'.") 109: 110: space_args: list[tuple[str, str, Any]] = [ 111: # input arg, payload key, value 112: ("space_hardware", "hardware", space_hardware), 113: ("space_storage", "storageTier", space_storage), 114: ("space_sleep_time", "sleepTimeSeconds", space_sleep_time), 115: ("space_secrets", "secrets", space_secrets), 116: ("space_variables", "variables", space_variables), 117: ("space_volumes", "volumes", [v.to_dict() for v in space_volumes] if space_volumes else None), 118: ] 119: 120: if repo_type == constants.REPO_TYPE_SPACE: 121: for _, key, value in space_args: 122: if value is not None: 123: payload[key] = value 124: if space_sleep_time is not None and space_hardware == SpaceHardware.CPU_BASIC: 125: warnings.warn( 126: "If your Space runs on the default 'cpu-basic' hardware, it will go to sleep if inactive for more" 127: " than 48 hours. This value is not configurable. If you don't want your Space to deactivate or if" 128: " you want to set a custom sleep time, you need to upgrade to a paid Hardware.", 129: UserWarning, 130: ) 131: else: 132: if provided_space_args := [arg for arg, _, value in space_args if value is not None]: 133: warnings.warn(f"Ignoring provided {', '.join(provided_space_args)} because repo_type is not 'space'.") 134: 135: if resource_group_id is not None: 136: payload["resourceGroupId"] = resource_group_id 137: if region is not None: 138: payload["region"] = region 139: 140: headers = self._build_hf_headers(token=token) 141: while True: 142: r = get_session().post(path, headers=headers, json=payload) 143: if r.status_code == 409 and "Cannot create repo: another conflicting operation is in progress" in r.text: 144: # Since https://github.com/huggingface/moon-landing/pull/7272 (private repo), it is not possible to 145: # concurrently create repos on the Hub for a same user. This is rarely an issue, except when running 146: # tests. To avoid any inconvenience, we retry to create the repo for this specific error. 147: # NOTE: This could have being fixed directly in the tests but adding it here should fixed CIs for all 148: # dependent libraries. 149: # NOTE: If a fix is implemented server-side, we should be able to remove this retry mechanism. 150: logger.debug("Create repo failed due to a concurrency issue. Retrying...") 151: continue 152: break 153: 154: try: 155: hf_raise_for_status(r) 156: except HfHubHTTPError as err: 157: if exist_ok and err.response.status_code == 409: 158: # Repo already exists and `exist_ok=True` 159: pass 160: elif exist_ok and err.response.status_code == 403: 161: # No write permission on the namespace but repo might already exist 162: try: 163: self.repo_info(repo_id=repo_id, repo_type=repo_type, token=token) 164: if repo_type is None or repo_type == constants.REPO_TYPE_MODEL: 165: return RepoUrl(f"{self.endpoint}/{repo_id}") 166: return RepoUrl(f"{self.endpoint}/{constants.REPO_TYPES_URL_PREFIXES[repo_type]}{repo_id}") 167: except HfHubHTTPError: 168: raise err 169: else: 170: raise 171: 172: d = r.json() 173: return RepoUrl(d["url"], endpoint=self.endpoint) 174: