Skip to content

Commit 3cd3286

Browse files
WizKnightWauplin
andauthored
[Feature] Add update_repo_settings function to HfApi #2447 (#2502)
* [Feature] Update Repo Settings * resolve merge conflicts * fix merge issue * merge issues * Add `update_repo_settings` function to HfApi * Add `update_repo_settings` function to HfApi * Enhance HfApi with `update_repo_settings` function * Enhance HfApi with `update_repo_settings` function * Enhance HfApi with `update_repo_settings` function * Enhance HfApi with `update_repo_settings` function * Enhance HfApi with `update_repo_settings` function * Apply suggestions from code review --------- Co-authored-by: Lucain <lucain@huggingface.co> Co-authored-by: Lucain Pouget <lucainp@gmail.com>
1 parent 2f27522 commit 3cd3286

File tree

4 files changed

+91
-0
lines changed

4 files changed

+91
-0
lines changed

docs/source/en/guides/repository.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,19 @@ A repository can be public or private. A private repository is only visible to y
155155
>>> update_repo_visibility(repo_id=repo_id, private=True)
156156
```
157157

158+
### Setup gated access
159+
160+
To give more control over how repos are used, the Hub allows repo authors to enable **access requests** for their repos. User must agree to share their contact information (username and email address) with the repo authors to access the files when enabled. A repo with access requests enabled is called a **gated repo**.
161+
162+
You can set a repo as gated using [`update_repo_settings`]:
163+
164+
```py
165+
>>> from huggingface_hub import HfApi
166+
167+
>>> api = HfApi()
168+
>>> api.update_repo_settings(repo_id=repo_id, gated="auto") # Set automatic gating for a model
169+
```
170+
158171
### Rename your repository
159172

160173
You can rename your repository on the Hub using [`move_repo`]. Using this method, you can also move the repo from a user to

src/huggingface_hub/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@
252252
"update_collection_item",
253253
"update_collection_metadata",
254254
"update_inference_endpoint",
255+
"update_repo_settings",
255256
"update_repo_visibility",
256257
"update_webhook",
257258
"upload_file",
@@ -761,6 +762,7 @@ def __dir__():
761762
update_collection_item, # noqa: F401
762763
update_collection_metadata, # noqa: F401
763764
update_inference_endpoint, # noqa: F401
765+
update_repo_settings, # noqa: F401
764766
update_repo_visibility, # noqa: F401
765767
update_webhook, # noqa: F401
766768
upload_file, # noqa: F401

src/huggingface_hub/hf_api.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3564,6 +3564,62 @@ def update_repo_visibility(
35643564
hf_raise_for_status(r)
35653565
return r.json()
35663566

3567+
@validate_hf_hub_args
3568+
def update_repo_settings(
3569+
self,
3570+
repo_id: str,
3571+
*,
3572+
gated: Literal["auto", "manual", False] = False,
3573+
token: Union[str, bool, None] = None,
3574+
repo_type: Optional[str] = None,
3575+
) -> None:
3576+
"""
3577+
Update the gated settings of a repository.
3578+
To give more control over how repos are used, the Hub allows repo authors to enable **access requests** for their repos.
3579+
3580+
Args:
3581+
repo_id (`str`):
3582+
A namespace (user or an organization) and a repo name separated by a /.
3583+
gated (`Literal["auto", "manual", False]`, *optional*):
3584+
The gated release status for the repository.
3585+
* "auto": The repository is gated, and access requests are automatically approved or denied based on predefined criteria.
3586+
* "manual": The repository is gated, and access requests require manual approval.
3587+
* False (default): The repository is not gated, and anyone can access it.
3588+
token (`Union[str, bool, None]`, *optional*):
3589+
A valid user access token (string). Defaults to the locally saved token,
3590+
which is the recommended method for authentication (see
3591+
https://huggingface.co/docs/huggingface_hub/quick-start#authentication).
3592+
To disable authentication, pass False.
3593+
repo_type (`str`, *optional*):
3594+
The type of the repository to update settings from (`"model"`, `"dataset"` or `"space"`.
3595+
Defaults to `"model"`.
3596+
3597+
Raises:
3598+
[`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError)
3599+
If gated is not one of "auto", "manual", or False.
3600+
[`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError)
3601+
If repo_type is not one of the values in constants.REPO_TYPES.
3602+
[`~utils.HfHubHTTPError`]:
3603+
If the request to the Hugging Face Hub API fails.
3604+
"""
3605+
if gated not in ["auto", "manual", False]:
3606+
raise ValueError(f"Invalid gated status, must be one of 'auto', 'manual', or False. Got '{gated}'.")
3607+
3608+
if repo_type not in constants.REPO_TYPES:
3609+
raise ValueError(f"Invalid repo type, must be one of {constants.REPO_TYPES}")
3610+
if repo_type is None:
3611+
repo_type = constants.REPO_TYPE_MODEL # default repo type
3612+
3613+
# Build headers
3614+
headers = self._build_hf_headers(token=token)
3615+
3616+
r = get_session().put(
3617+
url=f"{self.endpoint}/api/{repo_type}s/{repo_id}/settings",
3618+
headers=headers,
3619+
json={"gated": gated},
3620+
)
3621+
hf_raise_for_status(r)
3622+
35673623
def move_repo(
35683624
self,
35693625
from_id: str,
@@ -9678,6 +9734,7 @@ def _parse_revision_from_pr_url(pr_url: str) -> str:
96789734
create_repo = api.create_repo
96799735
delete_repo = api.delete_repo
96809736
update_repo_visibility = api.update_repo_visibility
9737+
update_repo_settings = api.update_repo_settings
96819738
super_squash_history = api.super_squash_history
96829739
move_repo = api.move_repo
96839740
upload_file = api.upload_file

tests/test_hf_api.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,25 @@ def test_move_repo_invalid_repo_id(self) -> None:
281281
with pytest.raises(ValueError, match=r"Invalid repo_id*"):
282282
self._api.move_repo(from_id="invalid_repo_id", to_id="namespace/repo_name")
283283

284+
@use_tmp_repo(repo_type="model")
285+
def test_update_repo_settings(self, repo_url: RepoUrl):
286+
repo_id = repo_url.repo_id
287+
288+
for gated_value in ["auto", "manual", False]:
289+
self._api.update_repo_settings(repo_id=repo_id, gated=gated_value)
290+
info = self._api.model_info(repo_id, expand="gated")
291+
assert info.gated == gated_value
292+
293+
@use_tmp_repo(repo_type="dataset")
294+
def test_update_dataset_repo_settings(self, repo_url: RepoUrl):
295+
repo_id = repo_url.repo_id
296+
repo_type = repo_url.repo_type
297+
298+
for gated_value in ["auto", "manual", False]:
299+
self._api.update_repo_settings(repo_id=repo_id, repo_type=repo_type, gated=gated_value)
300+
info = self._api.dataset_info(repo_id, expand="gated")
301+
assert info.gated == gated_value
302+
284303

285304
class CommitApiTest(HfApiCommonTest):
286305
def setUp(self) -> None:

0 commit comments

Comments
 (0)