huggingface-hub 1.0.0rc0__py3-none-any.whl → 1.0.0rc1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of huggingface-hub might be problematic. Click here for more details.

@@ -46,7 +46,7 @@ import sys
46
46
  from typing import TYPE_CHECKING
47
47
 
48
48
 
49
- __version__ = "1.0.0.rc0"
49
+ __version__ = "1.0.0.rc1"
50
50
 
51
51
  # Alphabetical order of definitions is ensured in tests
52
52
  # WARNING: any comment added in this dictionary definition will be lost when
@@ -516,7 +516,7 @@ _SUBMOD_ATTRS = {
516
516
  "HfHubAsyncTransport",
517
517
  "HfHubTransport",
518
518
  "cached_assets_path",
519
- "close_client",
519
+ "close_session",
520
520
  "dump_environment_info",
521
521
  "get_async_session",
522
522
  "get_session",
@@ -815,7 +815,7 @@ __all__ = [
815
815
  "cancel_access_request",
816
816
  "cancel_job",
817
817
  "change_discussion_status",
818
- "close_client",
818
+ "close_session",
819
819
  "comment_discussion",
820
820
  "create_branch",
821
821
  "create_collection",
@@ -1518,7 +1518,7 @@ if TYPE_CHECKING: # pragma: no cover
1518
1518
  HfHubAsyncTransport, # noqa: F401
1519
1519
  HfHubTransport, # noqa: F401
1520
1520
  cached_assets_path, # noqa: F401
1521
- close_client, # noqa: F401
1521
+ close_session, # noqa: F401
1522
1522
  dump_environment_info, # noqa: F401
1523
1523
  get_async_session, # noqa: F401
1524
1524
  get_session, # noqa: F401
@@ -11,17 +11,3 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
-
15
- from abc import ABC, abstractmethod
16
- from argparse import _SubParsersAction
17
-
18
-
19
- class BaseHuggingfaceCLICommand(ABC):
20
- @staticmethod
21
- @abstractmethod
22
- def register_subcommand(parser: _SubParsersAction):
23
- raise NotImplementedError()
24
-
25
- @abstractmethod
26
- def run(self):
27
- raise NotImplementedError()
@@ -11,10 +11,17 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
- """Contains a utility for good-looking prints."""
14
+ """Contains CLI utilities (styling, helpers)."""
15
15
 
16
16
  import os
17
- from typing import Union
17
+ from enum import Enum
18
+ from typing import Annotated, Optional, Union
19
+
20
+ import click
21
+ import typer
22
+
23
+ from huggingface_hub import __version__
24
+ from huggingface_hub.hf_api import HfApi
18
25
 
19
26
 
20
27
  class ANSI:
@@ -67,3 +74,73 @@ def tabulate(rows: list[list[Union[str, int]]], headers: list[str]) -> str:
67
74
  for row in rows:
68
75
  lines.append(row_format.format(*row))
69
76
  return "\n".join(lines)
77
+
78
+
79
+ #### TYPER UTILS
80
+
81
+
82
+ class AlphabeticalMixedGroup(typer.core.TyperGroup):
83
+ """
84
+ Typer Group that lists commands and sub-apps mixed and alphabetically.
85
+ """
86
+
87
+ def list_commands(self, ctx: click.Context) -> list[str]: # type: ignore[name-defined]
88
+ # click.Group stores both commands and sub-groups in `self.commands`
89
+ return sorted(self.commands.keys())
90
+
91
+
92
+ def typer_factory(help: str) -> typer.Typer:
93
+ return typer.Typer(
94
+ help=help,
95
+ add_completion=True,
96
+ rich_markup_mode=None,
97
+ no_args_is_help=True,
98
+ cls=AlphabeticalMixedGroup,
99
+ )
100
+
101
+
102
+ class RepoType(str, Enum):
103
+ model = "model"
104
+ dataset = "dataset"
105
+ space = "space"
106
+
107
+
108
+ RepoIdArg = Annotated[
109
+ str,
110
+ typer.Argument(
111
+ help="The ID of the repo (e.g. `username/repo-name`).",
112
+ ),
113
+ ]
114
+
115
+
116
+ RepoTypeOpt = Annotated[
117
+ RepoType,
118
+ typer.Option(
119
+ help="The type of repository (model, dataset, or space).",
120
+ ),
121
+ ]
122
+
123
+ TokenOpt = Annotated[
124
+ Optional[str],
125
+ typer.Option(
126
+ help="A User Access Token generated from https://huggingface.co/settings/tokens.",
127
+ ),
128
+ ]
129
+
130
+ PrivateOpt = Annotated[
131
+ bool,
132
+ typer.Option(
133
+ help="Whether to create a private repo if repo doesn't exist on the Hub. Ignored if the repo already exists.",
134
+ ),
135
+ ]
136
+
137
+ RevisionOpt = Annotated[
138
+ Optional[str],
139
+ typer.Option(
140
+ help="Git revision id which can be a branch name, a tag, or a commit hash.",
141
+ ),
142
+ ]
143
+
144
+
145
+ def get_hf_api(token: Optional[str] = None) -> HfApi:
146
+ return HfApi(token=token, library_name="hf", library_version=__version__)
@@ -30,17 +30,17 @@ Usage:
30
30
  hf auth whoami
31
31
  """
32
32
 
33
- from argparse import _SubParsersAction
34
- from typing import Optional
33
+ from typing import Annotated, Optional
34
+
35
+ import typer
35
36
 
36
- from huggingface_hub.commands import BaseHuggingfaceCLICommand
37
37
  from huggingface_hub.constants import ENDPOINT
38
38
  from huggingface_hub.errors import HfHubHTTPError
39
- from huggingface_hub.hf_api import HfApi
39
+ from huggingface_hub.hf_api import whoami
40
40
 
41
41
  from .._login import auth_list, auth_switch, login, logout
42
42
  from ..utils import get_stored_tokens, get_token, logging
43
- from ._cli_utils import ANSI
43
+ from ._cli_utils import ANSI, TokenOpt, typer_factory
44
44
 
45
45
 
46
46
  logger = logging.get_logger(__name__)
@@ -54,125 +54,42 @@ except ImportError:
54
54
  _inquirer_py_available = False
55
55
 
56
56
 
57
- class AuthCommands(BaseHuggingfaceCLICommand):
58
- @staticmethod
59
- def register_subcommand(parser: _SubParsersAction):
60
- # Create the main 'auth' command
61
- auth_parser = parser.add_parser("auth", help="Manage authentication (login, logout, etc.).")
62
- auth_subparsers = auth_parser.add_subparsers(help="Authentication subcommands")
63
-
64
- # Show help if no subcommand is provided
65
- auth_parser.set_defaults(func=lambda args: auth_parser.print_help())
66
-
67
- # Add 'login' as a subcommand of 'auth'
68
- login_parser = auth_subparsers.add_parser(
69
- "login", help="Log in using a token from huggingface.co/settings/tokens"
70
- )
71
- login_parser.add_argument(
72
- "--token",
73
- type=str,
74
- help="Token generated from https://huggingface.co/settings/tokens",
75
- )
76
- login_parser.add_argument(
77
- "--add-to-git-credential",
78
- action="store_true",
79
- help="Optional: Save token to git credential helper.",
80
- )
81
- login_parser.set_defaults(func=lambda args: AuthLogin(args))
82
-
83
- # Add 'logout' as a subcommand of 'auth'
84
- logout_parser = auth_subparsers.add_parser("logout", help="Log out")
85
- logout_parser.add_argument(
86
- "--token-name",
87
- type=str,
88
- help="Optional: Name of the access token to log out from.",
89
- )
90
- logout_parser.set_defaults(func=lambda args: AuthLogout(args))
91
-
92
- # Add 'whoami' as a subcommand of 'auth'
93
- whoami_parser = auth_subparsers.add_parser(
94
- "whoami", help="Find out which huggingface.co account you are logged in as."
95
- )
96
- whoami_parser.set_defaults(func=lambda args: AuthWhoami(args))
97
-
98
- # Existing subcommands
99
- auth_switch_parser = auth_subparsers.add_parser("switch", help="Switch between access tokens")
100
- auth_switch_parser.add_argument(
101
- "--token-name",
102
- type=str,
103
- help="Optional: Name of the access token to switch to.",
104
- )
105
- auth_switch_parser.add_argument(
106
- "--add-to-git-credential",
107
- action="store_true",
108
- help="Optional: Save token to git credential helper.",
109
- )
110
- auth_switch_parser.set_defaults(func=lambda args: AuthSwitch(args))
111
-
112
- auth_list_parser = auth_subparsers.add_parser("list", help="List all stored access tokens")
113
- auth_list_parser.set_defaults(func=lambda args: AuthList(args))
114
-
115
-
116
- class BaseAuthCommand:
117
- def __init__(self, args):
118
- self.args = args
119
- self._api = HfApi()
120
-
121
-
122
- class AuthLogin(BaseAuthCommand):
123
- def run(self):
124
- logging.set_verbosity_info()
125
- login(
126
- token=self.args.token,
127
- add_to_git_credential=self.args.add_to_git_credential,
128
- )
129
-
130
-
131
- class AuthLogout(BaseAuthCommand):
132
- def run(self):
133
- logging.set_verbosity_info()
134
- logout(token_name=self.args.token_name)
135
-
136
-
137
- class AuthSwitch(BaseAuthCommand):
138
- def run(self):
139
- logging.set_verbosity_info()
140
- token_name = self.args.token_name
141
- if token_name is None:
142
- token_name = self._select_token_name()
143
-
144
- if token_name is None:
145
- print("No token name provided. Aborting.")
146
- exit()
147
- auth_switch(token_name, add_to_git_credential=self.args.add_to_git_credential)
148
-
149
- def _select_token_name(self) -> Optional[str]:
150
- token_names = list(get_stored_tokens().keys())
151
-
152
- if not token_names:
153
- logger.error("No stored tokens found. Please login first.")
154
- return None
57
+ auth_cli = typer_factory(help="Manage authentication (login, logout, etc.).")
58
+
59
+
60
+ @auth_cli.command("login", help="Login using a token from huggingface.co/settings/tokens")
61
+ def auth_login(
62
+ token: TokenOpt = None,
63
+ add_to_git_credential: Annotated[
64
+ bool,
65
+ typer.Option(
66
+ help="Save to git credential helper. Useful only if you plan to run git commands directly.",
67
+ ),
68
+ ] = False,
69
+ ) -> None:
70
+ login(token=token, add_to_git_credential=add_to_git_credential)
71
+
72
+
73
+ @auth_cli.command("logout", help="Logout from a specific token")
74
+ def auth_logout(
75
+ token_name: Annotated[
76
+ Optional[str],
77
+ typer.Option(
78
+ help="Name of token to logout",
79
+ ),
80
+ ] = None,
81
+ ) -> None:
82
+ logout(token_name=token_name)
83
+
155
84
 
156
- if _inquirer_py_available:
157
- return self._select_token_name_tui(token_names)
158
- # if inquirer is not available, use a simpler terminal UI
159
- print("Available stored tokens:")
160
- for i, token_name in enumerate(token_names, 1):
161
- print(f"{i}. {token_name}")
162
- while True:
163
- try:
164
- choice = input("Enter the number of the token to switch to (or 'q' to quit): ")
165
- if choice.lower() == "q":
166
- return None
167
- index = int(choice) - 1
168
- if 0 <= index < len(token_names):
169
- return token_names[index]
170
- else:
171
- print("Invalid selection. Please try again.")
172
- except ValueError:
173
- print("Invalid input. Please enter a number or 'q' to quit.")
174
-
175
- def _select_token_name_tui(self, token_names: list[str]) -> Optional[str]:
85
+ def _select_token_name() -> Optional[str]:
86
+ token_names = list(get_stored_tokens().keys())
87
+
88
+ if not token_names:
89
+ logger.error("No stored tokens found. Please login first.")
90
+ return None
91
+
92
+ if _inquirer_py_available:
176
93
  choices = [Choice(token_name, name=token_name) for token_name in token_names]
177
94
  try:
178
95
  return inquirer.select(
@@ -183,30 +100,68 @@ class AuthSwitch(BaseAuthCommand):
183
100
  except KeyboardInterrupt:
184
101
  logger.info("Token selection cancelled.")
185
102
  return None
186
-
187
-
188
- class AuthList(BaseAuthCommand):
189
- def run(self):
190
- logging.set_verbosity_info()
191
- auth_list()
192
-
193
-
194
- class AuthWhoami(BaseAuthCommand):
195
- def run(self):
196
- token = get_token()
197
- if token is None:
198
- print("Not logged in")
199
- exit()
103
+ # if inquirer is not available, use a simpler terminal UI
104
+ print("Available stored tokens:")
105
+ for i, token_name in enumerate(token_names, 1):
106
+ print(f"{i}. {token_name}")
107
+ while True:
200
108
  try:
201
- info = self._api.whoami(token)
202
- print(ANSI.bold("user: "), info["name"])
203
- orgs = [org["name"] for org in info["orgs"]]
204
- if orgs:
205
- print(ANSI.bold("orgs: "), ",".join(orgs))
206
-
207
- if ENDPOINT != "https://huggingface.co":
208
- print(f"Authenticated through private endpoint: {ENDPOINT}")
209
- except HfHubHTTPError as e:
210
- print(e)
211
- print(ANSI.red(e.response.text))
212
- exit(1)
109
+ choice = input("Enter the number of the token to switch to (or 'q' to quit): ")
110
+ if choice.lower() == "q":
111
+ return None
112
+ index = int(choice) - 1
113
+ if 0 <= index < len(token_names):
114
+ return token_names[index]
115
+ else:
116
+ print("Invalid selection. Please try again.")
117
+ except ValueError:
118
+ print("Invalid input. Please enter a number or 'q' to quit.")
119
+
120
+
121
+ @auth_cli.command("switch", help="Switch between access tokens")
122
+ def auth_switch_cmd(
123
+ token_name: Annotated[
124
+ Optional[str],
125
+ typer.Option(
126
+ help="Name of the token to switch to",
127
+ ),
128
+ ] = None,
129
+ add_to_git_credential: Annotated[
130
+ bool,
131
+ typer.Option(
132
+ help="Save to git credential helper. Useful only if you plan to run git commands directly.",
133
+ ),
134
+ ] = False,
135
+ ) -> None:
136
+ if token_name is None:
137
+ token_name = _select_token_name()
138
+ if token_name is None:
139
+ print("No token name provided. Aborting.")
140
+ raise typer.Exit()
141
+ auth_switch(token_name, add_to_git_credential=add_to_git_credential)
142
+
143
+
144
+ @auth_cli.command("list", help="List all stored access tokens")
145
+ def auth_list_cmd() -> None:
146
+ auth_list()
147
+
148
+
149
+ @auth_cli.command("whoami", help="Find out which huggingface.co account you are logged in as.")
150
+ def auth_whoami() -> None:
151
+ token = get_token()
152
+ if token is None:
153
+ print("Not logged in")
154
+ raise typer.Exit()
155
+ try:
156
+ info = whoami(token)
157
+ print(ANSI.bold("user: "), info["name"])
158
+ orgs = [org["name"] for org in info["orgs"]]
159
+ if orgs:
160
+ print(ANSI.bold("orgs: "), ",".join(orgs))
161
+
162
+ if ENDPOINT != "https://huggingface.co":
163
+ print(f"Authenticated through private endpoint: {ENDPOINT}")
164
+ except HfHubHTTPError as e:
165
+ print(e)
166
+ print(ANSI.red(e.response.text))
167
+ raise typer.Exit(code=1)