Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: switch visibility with update_repo_settings #2537 #2541

Merged

Conversation

WizKnight
Copy link
Contributor

This PR enhances the update_repo_settings method to provide more control over repository settings, and deprecates the update_repo_visibility method:

Key changes:

  • Added a private parameter to set repositories as public or private.
  • Made the gated and private parameters optional, allowing updates to either setting independently.
  • Added checks to ensure at least one of gated or private is provided.
  • Payload Optimization: gated and private are only included in the request payload if they have non-None values.
  • Updated the docstring for update_repo_settings and replaced all references to update_repo_visibility in the documentation.
  • Added the @_deprecate_method decorator to update_repo_visibility, marking it for removal in v0.29.x.

@WizKnight
Copy link
Contributor Author

Hey @Wauplin, the changes in this PR are implemented as per the TO-DOs in issue #2537.

Copy link
Contributor

@hanouticelina hanouticelina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @WizKnight! thank you for working on this 🤗 I left some comments and I think they are still other references of update_repo_visibility in other files and docs to update

src/huggingface_hub/hf_api.py Outdated Show resolved Hide resolved
src/huggingface_hub/hf_api.py Outdated Show resolved Hide resolved
src/huggingface_hub/utils/__init__.py Outdated Show resolved Hide resolved
src/huggingface_hub/hf_api.py Outdated Show resolved Hide resolved
src/huggingface_hub/hf_api.py Outdated Show resolved Hide resolved
@WizKnight
Copy link
Contributor Author

Hey @hanouticelina :), changes were added in the recent commit.

@HuggingFaceDocBuilderDev

The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

Copy link
Contributor

@hanouticelina hanouticelina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @WizKnight! thanks a lot for this iteration! 😄 I left a small comment and there is also this one that needs to be addressed.
I just realized that update_repo_visibility() is used in other tests in tests/test_file_download.py and tests/test_snapshot_download.py. Could you replace update_repo_visibility() with update_repo_settings() in those files as well?
The failing test seems unrelated, I'll take a look

src/huggingface_hub/hf_api.py Outdated Show resolved Hide resolved
@Wauplin
Copy link
Contributor

Wauplin commented Sep 20, 2024

I just realized that update_repo_visibility() is used in other tests in tests/test_file_download.py and tests/test_snapshot_download.py. Could you replace update_repo_visibility() with update_repo_settings() in those files as well?

For deprecated methods, we have a expect_deprecation decorator that can be used in tests (see here). The goal is to continue to have the method tested since it's still officially supported and we are also testing that the method is correctly deprecated (i.e. correctly triggers warning).

So in the case of the deprecate use of it here, you can do

    @expect_deprecation("update_repo_visibility")
    def test_download_private_model(self):
        self.api.update_repo_visibility(repo_id=self.repo_id, private=True)

(+ adapt the import)

(sorry it's the kind of undocumentated things...)

Copy link
Contributor

@Wauplin Wauplin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @WizKnight! Here are a few changes I'd make in addition to @hanouticelina's comment above :)

tests/test_hf_api.py Outdated Show resolved Hide resolved
src/huggingface_hub/hf_api.py Show resolved Hide resolved
src/huggingface_hub/hf_api.py Outdated Show resolved Hide resolved
src/huggingface_hub/hf_api.py Outdated Show resolved Hide resolved
@@ -3625,10 +3633,13 @@ def update_repo_settings(
# Build headers
headers = self._build_hf_headers(token=token)

# Preparing the JSON payload for the PUT request
payload = {"gated": gated, "private": private}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prepare the payload in 2 steps:

payload: Dict = {}

if gated is not None:
    if gated not in ["auto", "manual", False]:
        raise ValueError(f"Invalid gated status, must be one of 'auto', 'manual', or False. Got '{gated}'.")
    payload["gated"] = gated

if private is not None:
    payload["private"] = private

The advantage of doing so is that adding a new parameter will just be a matter of adding a new if statement. Also, it makes it easier to log/print the payload value in case of debugging an issue. Doing a {key: value for key, value in payload.items() if value is not None} is not wrong per-se but makes it slightly less readable and less debuggable

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was planning on a similar approach, but I opted for the dictionary comprehension {key: value for key, value in payload.items() if value is not None} to make the code more efficient.

Copy link
Contributor

@Wauplin Wauplin Sep 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sometimes readibility / maintenance is more important than efficiency :)


```py
>>> from huggingface_hub import HfApi

>>> api = HfApi()
>>> api.update_repo_settings(repo_id=repo_id, gated="auto") # Set automatic gating for a model
>>> api.update_repo_settings(repo_id=repo_id, gated="auto", private=True) # Set automatic gating and visibility for a model
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would structure the documentation as such:

## Change repository settings

(...) current content

### Update visibility

(...) current content + update example

### Setup gated access

(...) current content

Setting a repo as gating and setting repo visibility is 2 different topics, even if related to accessibility. Usually either a repo is public, either private, either public and gated. Setting a repo as private and gated is possible but doesn't make sense.

Copy link
Contributor

@hanouticelina hanouticelina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @WizKnight ! thanks again for this 😄 I left two minor comments.

The tests failure comes from the test test_repo_id_no_warning() which is flagged with the expect_deprecation decorator and contains also a context manager warnings.catch_warnings and they both try to capture the same warning.
The FutureWarning is "consumed" by pytest.warns in the expect_deprecation decorator, so it never reaches the warnings.catch_warnings context manager inside the test. This is why the record list does not contain the FutureWarning and the test fails.

@Wauplin do we still need this test ? it tests that there is no warnings when passing repo_id as positional argument into some HfApi functions (create_repo, delete_repo, and update_repo_visibility).

@@ -3596,14 +3602,16 @@ def update_repo_settings(
The gated release status for the repository.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The gated release status for the repository.
The gated status for the repository. If set to `None` (default), the `gated` setting of the repository won't be updated

@@ -3596,14 +3602,16 @@ def update_repo_settings(
The gated release status for the repository.
* "auto": The repository is gated, and access requests are automatically approved or denied based on predefined criteria.
* "manual": The repository is gated, and access requests require manual approval.
* False (default): The repository is not gated, and anyone can access it.
* False : The gated status for the repository. If set to `None` (default), the `gated` setting of the repository won't be updated.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* False : The gated status for the repository. If set to `None` (default), the `gated` setting of the repository won't be updated.
* False : The repository is not gated, and anyone can access it.

@Wauplin
Copy link
Contributor

Wauplin commented Sep 23, 2024

@Wauplin do we still need this test ? it tests that there is no warnings when passing repo_id as positional argument into some HfApi functions (create_repo, delete_repo, and update_repo_visibility).

Clearly not needed anymore indeed! Let's just delete it instead of trying to fix the warning capture thingy (we could extend expect_deprecation to handle multiple inputs but really not worth it)

@WizKnight
Copy link
Contributor Author

HfApi functions (create_repo, delete_repo, and update_repo_visibility).

Hey @Wauplin and @hanouticelina, so do I remove these HfApi functions (create_repo, delete_repo, and update_repo_visibility) completely or extend those functions with expect_deprecation ??

@Wauplin
Copy link
Contributor

Wauplin commented Sep 23, 2024

No no, the only thing to do is to remove the test test_repo_id_no_warning. It's an outdated and legacy one. The methods create_repo and delete_repo are far from been deprecated!

@WizKnight
Copy link
Contributor Author

Hey @Wauplin I removed the test test_repo_id_no_warning completely and iterated on @hanouticelina minor comments in the recent commit.

@Wauplin Wauplin marked this pull request as ready for review September 26, 2024 13:06
@Wauplin
Copy link
Contributor

Wauplin commented Sep 26, 2024

(I've switched the PR as "ready for review". In general @WizKnight you can switch a PR to "ready" as soon as you request someone to review it)

Copy link
Contributor

@hanouticelina hanouticelina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @WizKnight 👋 thanks a lot for this PR! looks good to me 🙂 failing tests are unrelated, let's wait for @Wauplin's final review and we will be good to merge

Copy link
Contributor

@Wauplin Wauplin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good! Thanks for the back and forth @WizKnight @hanouticelina 🤗

Failing test is indeed unrelated. I left minor comments otherwise we are good to merge :)

docs/source/en/guides/repository.md Outdated Show resolved Hide resolved
docs/source/en/guides/repository.md Outdated Show resolved Hide resolved
docs/source/en/guides/repository.md Outdated Show resolved Hide resolved
@Wauplin
Copy link
Contributor

Wauplin commented Sep 26, 2024

CI's green, let's merge 🎉 Thanks again @WizKnight 🤗

@Wauplin Wauplin merged commit f984cdc into huggingface:main Sep 26, 2024
16 checks passed
@WizKnight
Copy link
Contributor Author

Hey @Wauplin & @hanouticelina , I really appreciate the opportunity!! Thankyou once again🤗

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants