huggingface-hub 1.0.0rc0__py3-none-any.whl → 1.0.0rc2__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.
- huggingface_hub/__init__.py +4 -4
- huggingface_hub/_commit_api.py +126 -66
- huggingface_hub/_commit_scheduler.py +4 -7
- huggingface_hub/_login.py +9 -15
- huggingface_hub/_tensorboard_logger.py +2 -5
- huggingface_hub/_webhooks_server.py +8 -20
- huggingface_hub/cli/__init__.py +0 -14
- huggingface_hub/cli/_cli_utils.py +79 -2
- huggingface_hub/cli/auth.py +104 -149
- huggingface_hub/cli/cache.py +97 -121
- huggingface_hub/cli/download.py +93 -110
- huggingface_hub/cli/hf.py +37 -41
- huggingface_hub/cli/jobs.py +687 -1014
- huggingface_hub/cli/lfs.py +116 -139
- huggingface_hub/cli/repo.py +290 -214
- huggingface_hub/cli/repo_files.py +50 -84
- huggingface_hub/cli/system.py +6 -25
- huggingface_hub/cli/upload.py +198 -212
- huggingface_hub/cli/upload_large_folder.py +90 -105
- huggingface_hub/dataclasses.py +3 -12
- huggingface_hub/errors.py +1 -1
- huggingface_hub/fastai_utils.py +22 -32
- huggingface_hub/file_download.py +18 -21
- huggingface_hub/hf_api.py +258 -410
- huggingface_hub/hf_file_system.py +17 -44
- huggingface_hub/inference/_client.py +25 -47
- huggingface_hub/inference/_generated/_async_client.py +25 -47
- huggingface_hub/inference/_mcp/agent.py +2 -5
- huggingface_hub/inference/_mcp/mcp_client.py +2 -5
- huggingface_hub/inference/_providers/__init__.py +11 -0
- huggingface_hub/inference/_providers/_common.py +1 -0
- huggingface_hub/inference/_providers/publicai.py +6 -0
- huggingface_hub/inference/_providers/scaleway.py +28 -0
- huggingface_hub/lfs.py +14 -8
- huggingface_hub/repocard.py +12 -16
- huggingface_hub/serialization/_base.py +3 -6
- huggingface_hub/serialization/_torch.py +16 -34
- huggingface_hub/utils/__init__.py +1 -1
- huggingface_hub/utils/_cache_manager.py +41 -71
- huggingface_hub/utils/_chunk_utils.py +2 -3
- huggingface_hub/utils/_http.py +32 -35
- huggingface_hub/utils/logging.py +8 -11
- {huggingface_hub-1.0.0rc0.dist-info → huggingface_hub-1.0.0rc2.dist-info}/METADATA +7 -2
- {huggingface_hub-1.0.0rc0.dist-info → huggingface_hub-1.0.0rc2.dist-info}/RECORD +48 -46
- {huggingface_hub-1.0.0rc0.dist-info → huggingface_hub-1.0.0rc2.dist-info}/LICENSE +0 -0
- {huggingface_hub-1.0.0rc0.dist-info → huggingface_hub-1.0.0rc2.dist-info}/WHEEL +0 -0
- {huggingface_hub-1.0.0rc0.dist-info → huggingface_hub-1.0.0rc2.dist-info}/entry_points.txt +0 -0
- {huggingface_hub-1.0.0rc0.dist-info → huggingface_hub-1.0.0rc2.dist-info}/top_level.txt +0 -0
huggingface_hub/cli/auth.py
CHANGED
|
@@ -30,17 +30,17 @@ Usage:
|
|
|
30
30
|
hf auth whoami
|
|
31
31
|
"""
|
|
32
32
|
|
|
33
|
-
from
|
|
34
|
-
|
|
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
|
|
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
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
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
|
-
|
|
189
|
-
|
|
190
|
-
|
|
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
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
print(
|
|
209
|
-
except
|
|
210
|
-
print(
|
|
211
|
-
|
|
212
|
-
|
|
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)
|
huggingface_hub/cli/cache.py
CHANGED
|
@@ -16,14 +16,15 @@
|
|
|
16
16
|
|
|
17
17
|
import os
|
|
18
18
|
import time
|
|
19
|
-
from
|
|
19
|
+
from enum import Enum
|
|
20
20
|
from functools import wraps
|
|
21
21
|
from tempfile import mkstemp
|
|
22
|
-
from typing import Any, Callable, Iterable,
|
|
22
|
+
from typing import Annotated, Any, Callable, Iterable, Optional, Union
|
|
23
|
+
|
|
24
|
+
import typer
|
|
23
25
|
|
|
24
26
|
from ..utils import CachedRepoInfo, CachedRevisionInfo, CacheNotFound, HFCacheInfo, scan_cache_dir
|
|
25
|
-
from . import
|
|
26
|
-
from ._cli_utils import ANSI, tabulate
|
|
27
|
+
from ._cli_utils import ANSI, tabulate, typer_factory
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
# --- DELETE helpers (from delete_cache.py) ---
|
|
@@ -36,10 +37,16 @@ try:
|
|
|
36
37
|
except ImportError:
|
|
37
38
|
_inquirer_py_available = False
|
|
38
39
|
|
|
39
|
-
SortingOption_T = Literal["alphabetical", "lastUpdated", "lastUsed", "size"]
|
|
40
40
|
_CANCEL_DELETION_STR = "CANCEL_DELETION"
|
|
41
41
|
|
|
42
42
|
|
|
43
|
+
class SortingOption(str, Enum):
|
|
44
|
+
alphabetical = "alphabetical"
|
|
45
|
+
lastUpdated = "lastUpdated"
|
|
46
|
+
lastUsed = "lastUsed"
|
|
47
|
+
size = "size"
|
|
48
|
+
|
|
49
|
+
|
|
43
50
|
def require_inquirer_py(fn: Callable) -> Callable:
|
|
44
51
|
@wraps(fn)
|
|
45
52
|
def _inner(*args, **kwargs):
|
|
@@ -54,122 +61,93 @@ def require_inquirer_py(fn: Callable) -> Callable:
|
|
|
54
61
|
return _inner
|
|
55
62
|
|
|
56
63
|
|
|
57
|
-
|
|
58
|
-
@staticmethod
|
|
59
|
-
def register_subcommand(parser: _SubParsersAction):
|
|
60
|
-
cache_parser = parser.add_parser("cache", help="Manage local cache directory.")
|
|
61
|
-
cache_subparsers = cache_parser.add_subparsers(dest="cache_command", help="Cache subcommands")
|
|
64
|
+
cache_cli = typer_factory(help="Manage local cache directory.")
|
|
62
65
|
|
|
63
|
-
# Show help if no subcommand is provided
|
|
64
|
-
cache_parser.set_defaults(func=lambda args: cache_parser.print_help())
|
|
65
66
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
67
|
+
@cache_cli.command("scan", help="Scan the cache directory")
|
|
68
|
+
def cache_scan(
|
|
69
|
+
dir: Annotated[
|
|
70
|
+
Optional[str],
|
|
71
|
+
typer.Option(
|
|
72
|
+
help="Cache directory to scan (defaults to Hugging Face cache).",
|
|
73
|
+
),
|
|
74
|
+
] = None,
|
|
75
|
+
verbose: Annotated[
|
|
76
|
+
int,
|
|
77
|
+
typer.Option(
|
|
75
78
|
"-v",
|
|
76
79
|
"--verbose",
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
choices=["alphabetical", "lastUpdated", "lastUsed", "size"],
|
|
101
|
-
help=(
|
|
102
|
-
"Sort repositories by the specified criteria. Options: "
|
|
103
|
-
"'alphabetical' (A-Z), "
|
|
104
|
-
"'lastUpdated' (newest first), "
|
|
105
|
-
"'lastUsed' (most recent first), "
|
|
106
|
-
"'size' (largest first)."
|
|
107
|
-
),
|
|
108
|
-
)
|
|
109
|
-
delete_parser.set_defaults(func=CacheCommand, cache_command="delete")
|
|
110
|
-
|
|
111
|
-
def __init__(self, args: Namespace) -> None:
|
|
112
|
-
self.args = args
|
|
113
|
-
self.verbosity: int = getattr(args, "verbose", 0)
|
|
114
|
-
self.cache_dir: Optional[str] = getattr(args, "dir", None)
|
|
115
|
-
self.disable_tui: bool = getattr(args, "disable_tui", False)
|
|
116
|
-
self.sort_by: Optional[SortingOption_T] = getattr(args, "sort", None)
|
|
117
|
-
self.cache_command: Optional[str] = getattr(args, "cache_command", None)
|
|
118
|
-
|
|
119
|
-
def run(self):
|
|
120
|
-
if self.cache_command == "scan":
|
|
121
|
-
self._run_scan()
|
|
122
|
-
elif self.cache_command == "delete":
|
|
123
|
-
self._run_delete()
|
|
80
|
+
count=True,
|
|
81
|
+
help="Increase verbosity (-v, -vv, -vvv).",
|
|
82
|
+
),
|
|
83
|
+
] = 0,
|
|
84
|
+
) -> None:
|
|
85
|
+
try:
|
|
86
|
+
t0 = time.time()
|
|
87
|
+
hf_cache_info = scan_cache_dir(dir)
|
|
88
|
+
t1 = time.time()
|
|
89
|
+
except CacheNotFound as exc:
|
|
90
|
+
print(f"Cache directory not found: {str(exc.cache_dir)}")
|
|
91
|
+
return
|
|
92
|
+
print(get_table(hf_cache_info, verbosity=verbose))
|
|
93
|
+
print(
|
|
94
|
+
f"\nDone in {round(t1 - t0, 1)}s. Scanned {len(hf_cache_info.repos)} repo(s)"
|
|
95
|
+
f" for a total of {ANSI.red(hf_cache_info.size_on_disk_str)}."
|
|
96
|
+
)
|
|
97
|
+
if len(hf_cache_info.warnings) > 0:
|
|
98
|
+
message = f"Got {len(hf_cache_info.warnings)} warning(s) while scanning."
|
|
99
|
+
if verbose >= 3:
|
|
100
|
+
print(ANSI.gray(message))
|
|
101
|
+
for warning in hf_cache_info.warnings:
|
|
102
|
+
print(ANSI.gray(str(warning)))
|
|
124
103
|
else:
|
|
125
|
-
print(
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
)
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
104
|
+
print(ANSI.gray(message + " Use -vvv to print details."))
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
@cache_cli.command("delete", help="Delete revisions from the cache directory")
|
|
108
|
+
def cache_delete(
|
|
109
|
+
dir: Annotated[
|
|
110
|
+
Optional[str],
|
|
111
|
+
typer.Option(
|
|
112
|
+
help="Cache directory (defaults to Hugging Face cache).",
|
|
113
|
+
),
|
|
114
|
+
] = None,
|
|
115
|
+
disable_tui: Annotated[
|
|
116
|
+
bool,
|
|
117
|
+
typer.Option(
|
|
118
|
+
help="Disable Terminal User Interface (TUI) mode. Useful if your platform/terminal doesn't support the multiselect menu.",
|
|
119
|
+
),
|
|
120
|
+
] = False,
|
|
121
|
+
sort: Annotated[
|
|
122
|
+
Optional[SortingOption],
|
|
123
|
+
typer.Option(
|
|
124
|
+
help="Sort repositories by the specified criteria. Options: 'alphabetical' (A-Z), 'lastUpdated' (newest first), 'lastUsed' (most recent first), 'size' (largest first).",
|
|
125
|
+
),
|
|
126
|
+
] = None,
|
|
127
|
+
) -> None:
|
|
128
|
+
hf_cache_info = scan_cache_dir(dir)
|
|
129
|
+
sort_by = sort.value if sort is not None else None
|
|
130
|
+
if disable_tui:
|
|
131
|
+
selected_hashes = _manual_review_no_tui(hf_cache_info, preselected=[], sort_by=sort_by)
|
|
132
|
+
else:
|
|
133
|
+
selected_hashes = _manual_review_tui(hf_cache_info, preselected=[], sort_by=sort_by)
|
|
134
|
+
if len(selected_hashes) > 0 and _CANCEL_DELETION_STR not in selected_hashes:
|
|
135
|
+
confirm_message = _get_expectations_str(hf_cache_info, selected_hashes) + " Confirm deletion ?"
|
|
136
|
+
if disable_tui:
|
|
137
|
+
confirmed = _ask_for_confirmation_no_tui(confirm_message)
|
|
154
138
|
else:
|
|
155
|
-
|
|
156
|
-
if
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
strategy
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
f"Done. Deleted {len(strategy.repos)} repo(s) and"
|
|
168
|
-
f" {len(strategy.snapshots)} revision(s) for a total of"
|
|
169
|
-
f" {strategy.expected_freed_size_str}."
|
|
170
|
-
)
|
|
171
|
-
return
|
|
172
|
-
print("Deletion is cancelled. Do nothing.")
|
|
139
|
+
confirmed = _ask_for_confirmation_tui(confirm_message)
|
|
140
|
+
if confirmed:
|
|
141
|
+
strategy = hf_cache_info.delete_revisions(*selected_hashes)
|
|
142
|
+
print("Start deletion.")
|
|
143
|
+
strategy.execute()
|
|
144
|
+
print(
|
|
145
|
+
f"Done. Deleted {len(strategy.repos)} repo(s) and"
|
|
146
|
+
f" {len(strategy.snapshots)} revision(s) for a total of"
|
|
147
|
+
f" {strategy.expected_freed_size_str}."
|
|
148
|
+
)
|
|
149
|
+
return
|
|
150
|
+
print("Deletion is cancelled. Do nothing.")
|
|
173
151
|
|
|
174
152
|
|
|
175
153
|
def get_table(hf_cache_info: HFCacheInfo, *, verbosity: int = 0) -> str:
|
|
@@ -228,7 +206,7 @@ def get_table(hf_cache_info: HFCacheInfo, *, verbosity: int = 0) -> str:
|
|
|
228
206
|
)
|
|
229
207
|
|
|
230
208
|
|
|
231
|
-
def _get_repo_sorting_key(repo: CachedRepoInfo, sort_by: Optional[
|
|
209
|
+
def _get_repo_sorting_key(repo: CachedRepoInfo, sort_by: Optional[str] = None):
|
|
232
210
|
if sort_by == "alphabetical":
|
|
233
211
|
return (repo.repo_type, repo.repo_id.lower())
|
|
234
212
|
elif sort_by == "lastUpdated":
|
|
@@ -242,9 +220,7 @@ def _get_repo_sorting_key(repo: CachedRepoInfo, sort_by: Optional[SortingOption_
|
|
|
242
220
|
|
|
243
221
|
|
|
244
222
|
@require_inquirer_py
|
|
245
|
-
def _manual_review_tui(
|
|
246
|
-
hf_cache_info: HFCacheInfo, preselected: list[str], sort_by: Optional[SortingOption_T] = None
|
|
247
|
-
) -> list[str]:
|
|
223
|
+
def _manual_review_tui(hf_cache_info: HFCacheInfo, preselected: list[str], sort_by: Optional[str] = None) -> list[str]:
|
|
248
224
|
choices = _get_tui_choices_from_scan(repos=hf_cache_info.repos, preselected=preselected, sort_by=sort_by)
|
|
249
225
|
checkbox = inquirer.checkbox(
|
|
250
226
|
message="Select revisions to delete:",
|
|
@@ -277,7 +253,7 @@ def _ask_for_confirmation_tui(message: str, default: bool = True) -> bool:
|
|
|
277
253
|
|
|
278
254
|
|
|
279
255
|
def _get_tui_choices_from_scan(
|
|
280
|
-
repos: Iterable[CachedRepoInfo], preselected: list[str], sort_by: Optional[
|
|
256
|
+
repos: Iterable[CachedRepoInfo], preselected: list[str], sort_by: Optional[str] = None
|
|
281
257
|
) -> list:
|
|
282
258
|
choices: list[Union["Choice", "Separator"]] = []
|
|
283
259
|
choices.append(
|
|
@@ -306,7 +282,7 @@ def _get_tui_choices_from_scan(
|
|
|
306
282
|
|
|
307
283
|
|
|
308
284
|
def _manual_review_no_tui(
|
|
309
|
-
hf_cache_info: HFCacheInfo, preselected: list[str], sort_by: Optional[
|
|
285
|
+
hf_cache_info: HFCacheInfo, preselected: list[str], sort_by: Optional[str] = None
|
|
310
286
|
) -> list[str]:
|
|
311
287
|
fd, tmp_path = mkstemp(suffix=".txt")
|
|
312
288
|
os.close(fd)
|