-
Notifications
You must be signed in to change notification settings - Fork 848
Add optional cache to whoami
#3568
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
base: main
Are you sure you want to change the base?
Conversation
|
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. |
| if token is False: | ||
| raise ValueError("Cannot use `token=False` with `whoami` method as it requires authentication.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a change in behavior, right? Previously, if token=False, we could still get the token from get_token(), but now we raise an exception?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, since token=False explicitly means "do not retrieve the token locally". The breaking change is that previously it would raise an HTTP 401 unauthorized issue, and now a ValueError. I don't believe though that it's better like this to fail early.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry I had to step away earlier but to clarify, I do agree that this change is the way to go and is inline with the docstring. But what I was saying was that previously, you would actually use the locally-saved token, even if a user passed token=False, because token or self.token or get_token() would keep going until a truthy value was found, so the logic would still fall back to a local token via get_token().
Unless I'm misunderstanding something, this would be a breaking change -- although I do agree that this is the right way to go. In fact, maybe a nit but I'd say we go even farther, and replace token = self.token with token = self.token if token is None else token, because again, this would mean that if a user does whoami(token=False), but has a token saved to the class would end up using that token, which is contrary to the docstring.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
^agree that we should do token = self.token if token is None else token since token can be False (as we do in _build_hf_headers).
Co-authored-by: Abubakar Abid <abubakar@huggingface.co>
Co-authored-by: Abubakar Abid <abubakar@huggingface.co>
julien-c
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice
abidlabs
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small comment but otherwise LGTM, thanks @Wauplin!
hanouticelina
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks! this is a nice addition 👍
| if token is True or token is None: | ||
| effective_token = get_token() | ||
| if effective_token is None: | ||
| raise LocalTokenNotFoundError( | ||
| "Token is required to call the /whoami-v2 endpoint, but no token found. You must provide a token or be logged in to " | ||
| "Hugging Face with `hf auth login` or `huggingface_hub.login`. See https://huggingface.co/settings/tokens." | ||
| ) | ||
| token = effective_token |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(nit) not sure if we need an intermediate variable here
| if token is True or token is None: | |
| effective_token = get_token() | |
| if effective_token is None: | |
| raise LocalTokenNotFoundError( | |
| "Token is required to call the /whoami-v2 endpoint, but no token found. You must provide a token or be logged in to " | |
| "Hugging Face with `hf auth login` or `huggingface_hub.login`. See https://huggingface.co/settings/tokens." | |
| ) | |
| token = effective_token | |
| if token is True or token is None: | |
| token = get_token() | |
| if token is None: | |
| raise LocalTokenNotFoundError( | |
| "Token is required to call the /whoami-v2 endpoint, but no token found. You must provide a token or be logged in to " | |
| "Hugging Face with `hf auth login` or `huggingface_hub.login`. See https://huggingface.co/settings/tokens." | |
| ) |
| if cache: | ||
| if token in self._whoami_cache: | ||
| return self._whoami_cache[token] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just an excuse to use more Walrus operators in the codebase :)
| if cache: | |
| if token in self._whoami_cache: | |
| return self._whoami_cache[token] | |
| if cache and (cached_token := self._whoami_cache.get(token)): | |
| return cached_token |
| if token is False: | ||
| raise ValueError("Cannot use `token=False` with `whoami` method as it requires authentication.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
^agree that we should do token = self.token if token is None else token since token can be False (as we do in _build_hf_headers).
Suggested by @abidlabs on private slack after gradio-app/trackio#344 being opened to fix rate limits errors while dealing with
whoami.The root problem is that
/whoami-v2is heavily IP-rate-limited to avoid abuse. This is usually not a problem since user needs to do it only once to check if they are logged in. But in some subsequent libraries, thewhoamiendpoint is used to determine what will be the default namespace for a newly create repo (default to user's username). If the library calls that endpoint too often, it will lead to a HTTP 429 rate limit that could have been easily prevented. PR gradio-app/trackio#344 introduced a cache intrackiobut let's make it available athuggingface_hublevel directly. Note that we do not want to cache the result by default as this would not be consistent with any other methods inHfApi.HfApiremains a simple HTTP client and by default, someone calling a method expects an HTTP endpoint to be actually called.With this PR:
whoami(..., cache=True)to cache results from/whoami-v2endpointHfApiinstanceAlso added some tests + docs.