150150R = TypeVar("R") # Return type
151151CollectionItemType_T = Literal["model", "dataset", "space", "paper", "collection"]
152152CollectionSort_T = Literal["lastModified", "trending", "upvotes"]
153+ RepoVisibility_T = Literal["public", "private", "protected"]
153154
154155ExpandModelProperty_T = Literal[
155156 "author",
249250_BUCKET_PATHS_INFO_BATCH_SIZE = 1000
250251_BUCKET_BATCH_ADD_CHUNK_SIZE = 100
251252_BUCKET_BATCH_DELETE_CHUNK_SIZE = 1000
252-
253253logger = logging.get_logger(__name__)
254254
255255
256+ def _resolve_repo_visibility(
257+ *,
258+ private: Optional[bool],
259+ visibility: Optional[RepoVisibility_T],
260+ repo_type: Optional[str],
261+ ) -> Optional[RepoVisibility_T]:
262+ if private is not None and visibility is not None:
263+ raise ValueError("Received both `private` and `visibility` arguments. Please provide only one of them.")
264+
265+ if visibility is None:
266+ if private is None:
267+ return None
268+ return "private" if private else "public"
269+
270+ if visibility == "protected" and repo_type != constants.REPO_TYPE_SPACE:
271+ raise ValueError("Only Spaces can be 'protected'. Please set visibility to 'public' or 'private'.")
272+ return visibility
273+
274+
256275def repo_type_and_id_from_hf_id(hf_id: str, hub_url: Optional[str] = None) -> tuple[Optional[str], Optional[str], str]:
257276 """
258277 Returns the repo type and ID from a huggingface.co URL linking to a
@@ -4108,6 +4127,7 @@ def create_repo(
41084127 *,
41094128 token: Union[str, bool, None] = None,
41104129 private: Optional[bool] = None,
4130+ visibility: Optional[RepoVisibility_T] = None,
41114131 repo_type: Optional[str] = None,
41124132 exist_ok: bool = False,
41134133 resource_group_id: Optional[str] = None,
@@ -4130,7 +4150,11 @@ def create_repo(
41304150 https://huggingface.co/docs/huggingface_hub/quick-start#authentication).
41314151 To disable authentication, pass `False`.
41324152 private (`bool`, *optional*):
4133- 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.
4153+ 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`.
4154+ visibility (`Literal["public", "private", "protected"]`, *optional*):
4155+ Visibility of the repo. Can be `"public"` or `"private"`, or `"protected"` for Spaces. If `None`
4156+ (default), the repo will be public unless the organization's default is private. This value is ignored
4157+ if the repo already exists.
41344158 repo_type (`str`, *optional*):
41354159 Set to `"dataset"` or `"space"` if uploading to a dataset or
41364160 space, `None` or `"model"` if uploading to a model. Default is
@@ -4171,9 +4195,11 @@ def create_repo(
41714195 if repo_type not in constants.REPO_TYPES:
41724196 raise ValueError("Invalid repo type")
41734197
4198+ resolved_visibility = _resolve_repo_visibility(private=private, visibility=visibility, repo_type=repo_type)
4199+
41744200 json: dict[str, Any] = {"name": name, "organization": organization}
4175- if private is not None:
4176- json["private "] = private
4201+ if resolved_visibility is not None:
4202+ json["visibility "] = resolved_visibility
41774203 if repo_type is not None:
41784204 json["type"] = repo_type
41794205 if repo_type == "space":
@@ -4303,14 +4329,15 @@ def update_repo_settings(
43034329 *,
43044330 gated: Optional[Literal["auto", "manual", False]] = None,
43054331 private: Optional[bool] = None,
4332+ visibility: Optional[RepoVisibility_T] = None,
43064333 token: Union[str, bool, None] = None,
43074334 repo_type: Optional[str] = None,
43084335 ) -> None:
43094336 """
43104337 Update the settings of a repository, including gated access and visibility.
43114338
43124339 To give more control over how repos are used, the Hub allows repo authors to enable
4313- access requests for their repos, and also to set the visibility of the repo to private .
4340+ access requests for their repos, and also to change the visibility of the repo.
43144341
43154342 Args:
43164343 repo_id (`str`):
@@ -4321,7 +4348,9 @@ def update_repo_settings(
43214348 * "manual": The repository is gated, and access requests require manual approval.
43224349 * False : The repository is not gated, and anyone can access it.
43234350 private (`bool`, *optional*):
4324- Whether the repository should be private.
4351+ Whether the repository should be private. Cannot be passed together with `visibility`.
4352+ visibility (`Literal["public", "private", "protected"]`, *optional*):
4353+ Visibility of the repository. Can be `"public"` or `"private"`, or `"protected"` for Spaces.
43254354 token (`Union[str, bool, None]`, *optional*):
43264355 A valid user access token (string). Defaults to the locally saved token,
43274356 which is the recommended method for authentication (see
@@ -4347,6 +4376,8 @@ def update_repo_settings(
43474376 if repo_type is None:
43484377 repo_type = constants.REPO_TYPE_MODEL # default repo type
43494378
4379+ resolved_visibility = _resolve_repo_visibility(private=private, visibility=visibility, repo_type=repo_type)
4380+
43504381 # Prepare the JSON payload for the PUT request
43514382 payload: dict = {}
43524383
@@ -4355,8 +4386,8 @@ def update_repo_settings(
43554386 raise ValueError(f"Invalid gated status, must be one of 'auto', 'manual', or False. Got '{gated}'.")
43564387 payload["gated"] = gated
43574388
4358- if private is not None:
4359- payload["private "] = private
4389+ if resolved_visibility is not None:
4390+ payload["visibility "] = resolved_visibility
43604391
43614392 if len(payload) == 0:
43624393 raise ValueError("At least one setting must be updated.")
@@ -7776,6 +7807,7 @@ def duplicate_repo(
77767807 *,
77777808 repo_type: Optional[str] = None,
77787809 private: Optional[bool] = None,
7810+ visibility: Optional[RepoVisibility_T] = None,
77797811 token: Union[bool, str, None] = None,
77807812 exist_ok: bool = False,
77817813 space_hardware: Optional[SpaceHardware] = None,
@@ -7800,7 +7832,10 @@ def duplicate_repo(
78007832 `None` or `"model"` if duplicating a model. Default is `None`.
78017833 private (`bool`, *optional*):
78027834 Whether the new repo should be private or not. Defaults to the same
7803- privacy as the original repo.
7835+ privacy as the original repo. Cannot be passed together with `visibility`.
7836+ visibility (`Literal["public", "private", "protected"]`, *optional*):
7837+ Visibility of the new repo. Can be `"public"` or `"private"`, or `"protected"` for Spaces. Defaults
7838+ to the same visibility as the original repo.
78047839 token (`bool` or `str`, *optional*):
78057840 A valid user access token (string). Defaults to the locally saved
78067841 token, which is the recommended method for authentication (see
@@ -7862,6 +7897,8 @@ def duplicate_repo(
78627897 if repo_type not in constants.REPO_TYPES:
78637898 raise ValueError("Invalid repo type")
78647899
7900+ resolved_visibility = _resolve_repo_visibility(private=private, visibility=visibility, repo_type=repo_type)
7901+
78657902 # Map repo_type to API path segment
78667903 api_prefix = {
78677904 None: "models",
@@ -7883,8 +7920,8 @@ def duplicate_repo(
78837920
78847921 payload: dict[str, Any] = {"repository": f"{to_namespace}/{to_repo_name}"}
78857922
7886- if private is not None:
7887- payload["private "] = private
7923+ if resolved_visibility is not None:
7924+ payload["visibility "] = resolved_visibility
78887925
78897926 # Space-specific options
78907927 function_args = [
@@ -7935,6 +7972,7 @@ def duplicate_space(
79357972 to_id: Optional[str] = None,
79367973 *,
79377974 private: Optional[bool] = None,
7975+ visibility: Optional[RepoVisibility_T] = None,
79387976 token: Union[bool, str, None] = None,
79397977 exist_ok: bool = False,
79407978 hardware: Optional[SpaceHardware] = None,
@@ -7955,7 +7993,10 @@ def duplicate_space(
79557993 ID of the new Space. Example: `"dog/CLIP-Interrogator"`. If not provided, the new Space will have the same
79567994 name as the original Space, but in your account.
79577995 private (`bool`, *optional*):
7958- Whether the new Space should be private or not. Defaults to the same privacy as the original Space.
7996+ Whether the new Space should be private or not. Defaults to the same privacy as the original Space. Cannot be passed together with `visibility`.
7997+ visibility (`Literal["public", "private", "protected"]`, *optional*):
7998+ Visibility of the new Space. Can be `"public"`, `"private"`, or `"protected"`. Defaults to the same
7999+ visibility as the original Space.
79598000 token (`bool` or `str`, *optional*):
79608001 A valid user access token (string). Defaults to the locally saved
79618002 token, which is the recommended method for authentication (see
@@ -7999,7 +8040,7 @@ def duplicate_space(
79998040 RepoUrl('https://huggingface.co/spaces/nateraw/dreambooth-training',...)
80008041
80018042 # Can set custom destination id and visibility flag.
8002- >>> duplicate_space("multimodalart/dreambooth-training", to_id="my-dreambooth", private=True )
8043+ >>> duplicate_space("multimodalart/dreambooth-training", to_id="my-dreambooth", visibility="private" )
80038044 RepoUrl('https://huggingface.co/spaces/nateraw/my-dreambooth',...)
80048045 ```
80058046
@@ -8013,6 +8054,7 @@ def duplicate_space(
80138054 from_id=from_id,
80148055 repo_type="space",
80158056 private=private,
8057+ visibility=visibility,
80168058 token=token,
80178059 exist_ok=exist_ok,
80188060 space_hardware=hardware,
0 commit comments