huggingface-hub 0.35.1__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.

Files changed (127) hide show
  1. huggingface_hub/__init__.py +28 -45
  2. huggingface_hub/_commit_api.py +28 -28
  3. huggingface_hub/_commit_scheduler.py +11 -8
  4. huggingface_hub/_inference_endpoints.py +8 -8
  5. huggingface_hub/_jobs_api.py +20 -20
  6. huggingface_hub/_login.py +13 -39
  7. huggingface_hub/_oauth.py +8 -8
  8. huggingface_hub/_snapshot_download.py +14 -28
  9. huggingface_hub/_space_api.py +4 -4
  10. huggingface_hub/_tensorboard_logger.py +5 -5
  11. huggingface_hub/_upload_large_folder.py +15 -15
  12. huggingface_hub/_webhooks_payload.py +3 -3
  13. huggingface_hub/_webhooks_server.py +2 -2
  14. huggingface_hub/cli/__init__.py +0 -14
  15. huggingface_hub/cli/_cli_utils.py +80 -3
  16. huggingface_hub/cli/auth.py +104 -150
  17. huggingface_hub/cli/cache.py +102 -126
  18. huggingface_hub/cli/download.py +93 -110
  19. huggingface_hub/cli/hf.py +37 -41
  20. huggingface_hub/cli/jobs.py +689 -1017
  21. huggingface_hub/cli/lfs.py +120 -143
  22. huggingface_hub/cli/repo.py +158 -216
  23. huggingface_hub/cli/repo_files.py +50 -84
  24. huggingface_hub/cli/system.py +6 -25
  25. huggingface_hub/cli/upload.py +198 -212
  26. huggingface_hub/cli/upload_large_folder.py +90 -105
  27. huggingface_hub/commands/_cli_utils.py +2 -2
  28. huggingface_hub/commands/delete_cache.py +11 -11
  29. huggingface_hub/commands/download.py +4 -13
  30. huggingface_hub/commands/lfs.py +4 -4
  31. huggingface_hub/commands/repo_files.py +2 -2
  32. huggingface_hub/commands/tag.py +1 -3
  33. huggingface_hub/commands/upload.py +4 -4
  34. huggingface_hub/commands/upload_large_folder.py +3 -3
  35. huggingface_hub/commands/user.py +4 -5
  36. huggingface_hub/community.py +5 -5
  37. huggingface_hub/constants.py +3 -41
  38. huggingface_hub/dataclasses.py +16 -22
  39. huggingface_hub/errors.py +43 -30
  40. huggingface_hub/fastai_utils.py +8 -9
  41. huggingface_hub/file_download.py +154 -253
  42. huggingface_hub/hf_api.py +329 -558
  43. huggingface_hub/hf_file_system.py +104 -62
  44. huggingface_hub/hub_mixin.py +32 -54
  45. huggingface_hub/inference/_client.py +178 -163
  46. huggingface_hub/inference/_common.py +38 -54
  47. huggingface_hub/inference/_generated/_async_client.py +219 -259
  48. huggingface_hub/inference/_generated/types/automatic_speech_recognition.py +3 -3
  49. huggingface_hub/inference/_generated/types/base.py +10 -7
  50. huggingface_hub/inference/_generated/types/chat_completion.py +16 -16
  51. huggingface_hub/inference/_generated/types/depth_estimation.py +2 -2
  52. huggingface_hub/inference/_generated/types/document_question_answering.py +2 -2
  53. huggingface_hub/inference/_generated/types/feature_extraction.py +2 -2
  54. huggingface_hub/inference/_generated/types/fill_mask.py +2 -2
  55. huggingface_hub/inference/_generated/types/sentence_similarity.py +3 -3
  56. huggingface_hub/inference/_generated/types/summarization.py +2 -2
  57. huggingface_hub/inference/_generated/types/table_question_answering.py +4 -4
  58. huggingface_hub/inference/_generated/types/text2text_generation.py +2 -2
  59. huggingface_hub/inference/_generated/types/text_generation.py +10 -10
  60. huggingface_hub/inference/_generated/types/text_to_video.py +2 -2
  61. huggingface_hub/inference/_generated/types/token_classification.py +2 -2
  62. huggingface_hub/inference/_generated/types/translation.py +2 -2
  63. huggingface_hub/inference/_generated/types/zero_shot_classification.py +2 -2
  64. huggingface_hub/inference/_generated/types/zero_shot_image_classification.py +2 -2
  65. huggingface_hub/inference/_generated/types/zero_shot_object_detection.py +1 -3
  66. huggingface_hub/inference/_mcp/agent.py +3 -3
  67. huggingface_hub/inference/_mcp/constants.py +1 -2
  68. huggingface_hub/inference/_mcp/mcp_client.py +33 -22
  69. huggingface_hub/inference/_mcp/types.py +10 -10
  70. huggingface_hub/inference/_mcp/utils.py +4 -4
  71. huggingface_hub/inference/_providers/__init__.py +2 -13
  72. huggingface_hub/inference/_providers/_common.py +24 -25
  73. huggingface_hub/inference/_providers/black_forest_labs.py +6 -6
  74. huggingface_hub/inference/_providers/cohere.py +3 -3
  75. huggingface_hub/inference/_providers/fal_ai.py +25 -25
  76. huggingface_hub/inference/_providers/featherless_ai.py +4 -4
  77. huggingface_hub/inference/_providers/fireworks_ai.py +3 -3
  78. huggingface_hub/inference/_providers/hf_inference.py +13 -13
  79. huggingface_hub/inference/_providers/hyperbolic.py +4 -4
  80. huggingface_hub/inference/_providers/nebius.py +10 -10
  81. huggingface_hub/inference/_providers/novita.py +5 -5
  82. huggingface_hub/inference/_providers/nscale.py +4 -4
  83. huggingface_hub/inference/_providers/replicate.py +15 -15
  84. huggingface_hub/inference/_providers/sambanova.py +6 -6
  85. huggingface_hub/inference/_providers/together.py +7 -7
  86. huggingface_hub/lfs.py +24 -33
  87. huggingface_hub/repocard.py +16 -17
  88. huggingface_hub/repocard_data.py +56 -56
  89. huggingface_hub/serialization/__init__.py +0 -1
  90. huggingface_hub/serialization/_base.py +9 -9
  91. huggingface_hub/serialization/_dduf.py +7 -7
  92. huggingface_hub/serialization/_torch.py +28 -28
  93. huggingface_hub/utils/__init__.py +10 -4
  94. huggingface_hub/utils/_auth.py +5 -5
  95. huggingface_hub/utils/_cache_manager.py +31 -31
  96. huggingface_hub/utils/_deprecation.py +1 -1
  97. huggingface_hub/utils/_dotenv.py +3 -3
  98. huggingface_hub/utils/_fixes.py +0 -10
  99. huggingface_hub/utils/_git_credential.py +3 -3
  100. huggingface_hub/utils/_headers.py +7 -29
  101. huggingface_hub/utils/_http.py +369 -209
  102. huggingface_hub/utils/_pagination.py +4 -4
  103. huggingface_hub/utils/_paths.py +5 -5
  104. huggingface_hub/utils/_runtime.py +15 -13
  105. huggingface_hub/utils/_safetensors.py +21 -21
  106. huggingface_hub/utils/_subprocess.py +9 -9
  107. huggingface_hub/utils/_telemetry.py +3 -3
  108. huggingface_hub/utils/_typing.py +3 -3
  109. huggingface_hub/utils/_validators.py +53 -72
  110. huggingface_hub/utils/_xet.py +16 -16
  111. huggingface_hub/utils/_xet_progress_reporting.py +1 -1
  112. huggingface_hub/utils/insecure_hashlib.py +3 -9
  113. huggingface_hub/utils/tqdm.py +3 -3
  114. {huggingface_hub-0.35.1.dist-info → huggingface_hub-1.0.0rc1.dist-info}/METADATA +17 -26
  115. huggingface_hub-1.0.0rc1.dist-info/RECORD +161 -0
  116. huggingface_hub/inference/_providers/publicai.py +0 -6
  117. huggingface_hub/inference/_providers/scaleway.py +0 -28
  118. huggingface_hub/inference_api.py +0 -217
  119. huggingface_hub/keras_mixin.py +0 -500
  120. huggingface_hub/repository.py +0 -1477
  121. huggingface_hub/serialization/_tensorflow.py +0 -95
  122. huggingface_hub/utils/_hf_folder.py +0 -68
  123. huggingface_hub-0.35.1.dist-info/RECORD +0 -168
  124. {huggingface_hub-0.35.1.dist-info → huggingface_hub-1.0.0rc1.dist-info}/LICENSE +0 -0
  125. {huggingface_hub-0.35.1.dist-info → huggingface_hub-1.0.0rc1.dist-info}/WHEEL +0 -0
  126. {huggingface_hub-0.35.1.dist-info → huggingface_hub-1.0.0rc1.dist-info}/entry_points.txt +0 -0
  127. {huggingface_hub-0.35.1.dist-info → huggingface_hub-1.0.0rc1.dist-info}/top_level.txt +0 -0
@@ -16,14 +16,15 @@
16
16
 
17
17
  import os
18
18
  import time
19
- from argparse import Namespace, _SubParsersAction
19
+ from enum import Enum
20
20
  from functools import wraps
21
21
  from tempfile import mkstemp
22
- from typing import Any, Callable, Iterable, List, Literal, Optional, Union
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 BaseHuggingfaceCLICommand
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
- class CacheCommand(BaseHuggingfaceCLICommand):
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
- # Scan subcommand
67
- scan_parser = cache_subparsers.add_parser("scan", help="Scan cache directory.")
68
- scan_parser.add_argument(
69
- "--dir",
70
- type=str,
71
- default=None,
72
- help="cache directory to scan (optional). Default to the default HuggingFace cache.",
73
- )
74
- scan_parser.add_argument(
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
- action="count",
78
- default=0,
79
- help="show a more verbose output",
80
- )
81
- scan_parser.set_defaults(func=CacheCommand, cache_command="scan")
82
- # Delete subcommand
83
- delete_parser = cache_subparsers.add_parser("delete", help="Delete revisions from the cache directory.")
84
- delete_parser.add_argument(
85
- "--dir",
86
- type=str,
87
- default=None,
88
- help="cache directory (optional). Default to the default HuggingFace cache.",
89
- )
90
- delete_parser.add_argument(
91
- "--disable-tui",
92
- action="store_true",
93
- help=(
94
- "Disable Terminal User Interface (TUI) mode. Useful if your platform/terminal doesn't support the multiselect menu."
95
- ),
96
- )
97
- delete_parser.add_argument(
98
- "--sort",
99
- nargs="?",
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("Please specify a cache subcommand (scan or delete). Use -h for help.")
126
-
127
- def _run_scan(self):
128
- try:
129
- t0 = time.time()
130
- hf_cache_info = scan_cache_dir(self.cache_dir)
131
- t1 = time.time()
132
- except CacheNotFound as exc:
133
- cache_dir = exc.cache_dir
134
- print(f"Cache directory not found: {cache_dir}")
135
- return
136
- print(get_table(hf_cache_info, verbosity=self.verbosity))
137
- print(
138
- f"\nDone in {round(t1 - t0, 1)}s. Scanned {len(hf_cache_info.repos)} repo(s)"
139
- f" for a total of {ANSI.red(hf_cache_info.size_on_disk_str)}."
140
- )
141
- if len(hf_cache_info.warnings) > 0:
142
- message = f"Got {len(hf_cache_info.warnings)} warning(s) while scanning."
143
- if self.verbosity >= 3:
144
- print(ANSI.gray(message))
145
- for warning in hf_cache_info.warnings:
146
- print(ANSI.gray(str(warning)))
147
- else:
148
- print(ANSI.gray(message + " Use -vvv to print details."))
149
-
150
- def _run_delete(self):
151
- hf_cache_info = scan_cache_dir(self.cache_dir)
152
- if self.disable_tui:
153
- selected_hashes = _manual_review_no_tui(hf_cache_info, preselected=[], sort_by=self.sort_by)
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
- selected_hashes = _manual_review_tui(hf_cache_info, preselected=[], sort_by=self.sort_by)
156
- if len(selected_hashes) > 0 and _CANCEL_DELETION_STR not in selected_hashes:
157
- confirm_message = _get_expectations_str(hf_cache_info, selected_hashes) + " Confirm deletion ?"
158
- if self.disable_tui:
159
- confirmed = _ask_for_confirmation_no_tui(confirm_message)
160
- else:
161
- confirmed = _ask_for_confirmation_tui(confirm_message)
162
- if confirmed:
163
- strategy = hf_cache_info.delete_revisions(*selected_hashes)
164
- print("Start deletion.")
165
- strategy.execute()
166
- print(
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[SortingOption_T] = None):
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,9 +253,9 @@ 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[SortingOption_T] = None
281
- ) -> List:
282
- choices: List[Union["Choice", "Separator"]] = []
256
+ repos: Iterable[CachedRepoInfo], preselected: list[str], sort_by: Optional[str] = None
257
+ ) -> list:
258
+ choices: list[Union["Choice", "Separator"]] = []
283
259
  choices.append(
284
260
  Choice(
285
261
  _CANCEL_DELETION_STR, name="None of the following (if selected, nothing will be deleted).", enabled=False
@@ -306,8 +282,8 @@ 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[SortingOption_T] = None
310
- ) -> List[str]:
285
+ hf_cache_info: HFCacheInfo, preselected: list[str], sort_by: Optional[str] = None
286
+ ) -> list[str]:
311
287
  fd, tmp_path = mkstemp(suffix=".txt")
312
288
  os.close(fd)
313
289
  lines = []
@@ -358,14 +334,14 @@ def _ask_for_confirmation_no_tui(message: str, default: bool = True) -> bool:
358
334
  print(f"Invalid input. Must be one of {ALL}")
359
335
 
360
336
 
361
- def _get_expectations_str(hf_cache_info: HFCacheInfo, selected_hashes: List[str]) -> str:
337
+ def _get_expectations_str(hf_cache_info: HFCacheInfo, selected_hashes: list[str]) -> str:
362
338
  if _CANCEL_DELETION_STR in selected_hashes:
363
339
  return "Nothing will be deleted."
364
340
  strategy = hf_cache_info.delete_revisions(*selected_hashes)
365
341
  return f"{len(selected_hashes)} revisions selected counting for {strategy.expected_freed_size_str}."
366
342
 
367
343
 
368
- def _read_manual_review_tmp_file(tmp_path: str) -> List[str]:
344
+ def _read_manual_review_tmp_file(tmp_path: str) -> list[str]:
369
345
  with open(tmp_path) as f:
370
346
  content = f.read()
371
347
  lines = [line.strip() for line in content.split("\n")]
@@ -37,145 +37,128 @@ Usage:
37
37
  """
38
38
 
39
39
  import warnings
40
- from argparse import Namespace, _SubParsersAction
41
- from typing import List, Optional
40
+ from typing import Annotated, Optional
41
+
42
+ import typer
42
43
 
43
44
  from huggingface_hub import logging
44
45
  from huggingface_hub._snapshot_download import snapshot_download
45
- from huggingface_hub.commands import BaseHuggingfaceCLICommand
46
46
  from huggingface_hub.file_download import hf_hub_download
47
47
  from huggingface_hub.utils import disable_progress_bars, enable_progress_bars
48
48
 
49
+ from ._cli_utils import RepoIdArg, RepoTypeOpt, RevisionOpt, TokenOpt
50
+
49
51
 
50
52
  logger = logging.get_logger(__name__)
51
53
 
52
54
 
53
- class DownloadCommand(BaseHuggingfaceCLICommand):
54
- @staticmethod
55
- def register_subcommand(parser: _SubParsersAction):
56
- download_parser = parser.add_parser("download", help="Download files from the Hub")
57
- download_parser.add_argument(
58
- "repo_id", type=str, help="ID of the repo to download from (e.g. `username/repo-name`)."
59
- )
60
- download_parser.add_argument(
61
- "filenames", type=str, nargs="*", help="Files to download (e.g. `config.json`, `data/metadata.jsonl`)."
62
- )
63
- download_parser.add_argument(
64
- "--repo-type",
65
- choices=["model", "dataset", "space"],
66
- default="model",
67
- help="Type of repo to download from (defaults to 'model').",
68
- )
69
- download_parser.add_argument(
70
- "--revision",
71
- type=str,
72
- help="An optional Git revision id which can be a branch name, a tag, or a commit hash.",
73
- )
74
- download_parser.add_argument(
75
- "--include", nargs="*", type=str, help="Glob patterns to match files to download."
76
- )
77
- download_parser.add_argument(
78
- "--exclude", nargs="*", type=str, help="Glob patterns to exclude from files to download."
79
- )
80
- download_parser.add_argument(
81
- "--cache-dir", type=str, help="Path to the directory where to save the downloaded files."
82
- )
83
- download_parser.add_argument(
84
- "--local-dir",
85
- type=str,
86
- help=(
87
- "If set, the downloaded file will be placed under this directory. Check out"
88
- " https://huggingface.co/docs/huggingface_hub/guides/download#download-files-to-local-folder for more"
89
- " details."
90
- ),
91
- )
92
- download_parser.add_argument(
93
- "--force-download",
94
- action="store_true",
55
+ def download(
56
+ repo_id: RepoIdArg,
57
+ filenames: Annotated[
58
+ Optional[list[str]],
59
+ typer.Argument(
60
+ help="Files to download (e.g. `config.json`, `data/metadata.jsonl`).",
61
+ ),
62
+ ] = None,
63
+ repo_type: RepoTypeOpt = RepoTypeOpt.model,
64
+ revision: RevisionOpt = None,
65
+ include: Annotated[
66
+ Optional[list[str]],
67
+ typer.Option(
68
+ help="Glob patterns to include from files to download. eg: *.json",
69
+ ),
70
+ ] = None,
71
+ exclude: Annotated[
72
+ Optional[list[str]],
73
+ typer.Option(
74
+ help="Glob patterns to exclude from files to download.",
75
+ ),
76
+ ] = None,
77
+ cache_dir: Annotated[
78
+ Optional[str],
79
+ typer.Option(
80
+ help="Directory where to save files.",
81
+ ),
82
+ ] = None,
83
+ local_dir: Annotated[
84
+ Optional[str],
85
+ typer.Option(
86
+ help="If set, the downloaded file will be placed under this directory. Check out https://huggingface.co/docs/huggingface_hub/guides/download#download-files-to-local-folder for more details.",
87
+ ),
88
+ ] = None,
89
+ force_download: Annotated[
90
+ bool,
91
+ typer.Option(
95
92
  help="If True, the files will be downloaded even if they are already cached.",
96
- )
97
- download_parser.add_argument(
98
- "--token", type=str, help="A User Access Token generated from https://huggingface.co/settings/tokens"
99
- )
100
- download_parser.add_argument(
101
- "--quiet",
102
- action="store_true",
93
+ ),
94
+ ] = False,
95
+ token: TokenOpt = None,
96
+ quiet: Annotated[
97
+ bool,
98
+ typer.Option(
103
99
  help="If True, progress bars are disabled and only the path to the download files is printed.",
104
- )
105
- download_parser.add_argument(
106
- "--max-workers",
107
- type=int,
108
- default=8,
100
+ ),
101
+ ] = False,
102
+ max_workers: Annotated[
103
+ int,
104
+ typer.Option(
109
105
  help="Maximum number of workers to use for downloading files. Default is 8.",
110
- )
111
- download_parser.set_defaults(func=DownloadCommand)
112
-
113
- def __init__(self, args: Namespace) -> None:
114
- self.token = args.token
115
- self.repo_id: str = args.repo_id
116
- self.filenames: List[str] = args.filenames
117
- self.repo_type: str = args.repo_type
118
- self.revision: Optional[str] = args.revision
119
- self.include: Optional[List[str]] = args.include
120
- self.exclude: Optional[List[str]] = args.exclude
121
- self.cache_dir: Optional[str] = args.cache_dir
122
- self.local_dir: Optional[str] = args.local_dir
123
- self.force_download: bool = args.force_download
124
- self.quiet: bool = args.quiet
125
- self.max_workers: int = args.max_workers
126
-
127
- def run(self) -> None:
128
- if self.quiet:
129
- disable_progress_bars()
130
- with warnings.catch_warnings():
131
- warnings.simplefilter("ignore")
132
- print(self._download()) # Print path to downloaded files
133
- enable_progress_bars()
134
- else:
135
- logging.set_verbosity_info()
136
- print(self._download()) # Print path to downloaded files
137
- logging.set_verbosity_warning()
106
+ ),
107
+ ] = 8,
108
+ ) -> None:
109
+ """Download files from the Hub."""
138
110
 
139
- def _download(self) -> str:
111
+ def run_download() -> str:
112
+ filenames_list = filenames if filenames is not None else []
140
113
  # Warn user if patterns are ignored
141
- if len(self.filenames) > 0:
142
- if self.include is not None and len(self.include) > 0:
114
+ if len(filenames_list) > 0:
115
+ if include is not None and len(include) > 0:
143
116
  warnings.warn("Ignoring `--include` since filenames have being explicitly set.")
144
- if self.exclude is not None and len(self.exclude) > 0:
117
+ if exclude is not None and len(exclude) > 0:
145
118
  warnings.warn("Ignoring `--exclude` since filenames have being explicitly set.")
146
119
 
147
120
  # Single file to download: use `hf_hub_download`
148
- if len(self.filenames) == 1:
121
+ if len(filenames_list) == 1:
149
122
  return hf_hub_download(
150
- repo_id=self.repo_id,
151
- repo_type=self.repo_type,
152
- revision=self.revision,
153
- filename=self.filenames[0],
154
- cache_dir=self.cache_dir,
155
- force_download=self.force_download,
156
- token=self.token,
157
- local_dir=self.local_dir,
123
+ repo_id=repo_id,
124
+ repo_type=repo_type.value,
125
+ revision=revision,
126
+ filename=filenames_list[0],
127
+ cache_dir=cache_dir,
128
+ force_download=force_download,
129
+ token=token,
130
+ local_dir=local_dir,
158
131
  library_name="hf",
159
132
  )
160
133
 
161
134
  # Otherwise: use `snapshot_download` to ensure all files comes from same revision
162
- elif len(self.filenames) == 0:
163
- allow_patterns = self.include
164
- ignore_patterns = self.exclude
135
+ if len(filenames_list) == 0:
136
+ allow_patterns = include
137
+ ignore_patterns = exclude
165
138
  else:
166
- allow_patterns = self.filenames
139
+ allow_patterns = filenames_list
167
140
  ignore_patterns = None
168
141
 
169
142
  return snapshot_download(
170
- repo_id=self.repo_id,
171
- repo_type=self.repo_type,
172
- revision=self.revision,
143
+ repo_id=repo_id,
144
+ repo_type=repo_type.value,
145
+ revision=revision,
173
146
  allow_patterns=allow_patterns,
174
147
  ignore_patterns=ignore_patterns,
175
- force_download=self.force_download,
176
- cache_dir=self.cache_dir,
177
- token=self.token,
178
- local_dir=self.local_dir,
148
+ force_download=force_download,
149
+ cache_dir=cache_dir,
150
+ token=token,
151
+ local_dir=local_dir,
179
152
  library_name="hf",
180
- max_workers=self.max_workers,
153
+ max_workers=max_workers,
181
154
  )
155
+
156
+ if quiet:
157
+ disable_progress_bars()
158
+ with warnings.catch_warnings():
159
+ warnings.simplefilter("ignore")
160
+ print(run_download())
161
+ enable_progress_bars()
162
+ else:
163
+ print(run_download())
164
+ logging.set_verbosity_warning()
huggingface_hub/cli/hf.py CHANGED
@@ -12,51 +12,47 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- from argparse import ArgumentParser
16
15
 
17
- from huggingface_hub.cli.auth import AuthCommands
18
- from huggingface_hub.cli.cache import CacheCommand
19
- from huggingface_hub.cli.download import DownloadCommand
20
- from huggingface_hub.cli.jobs import JobsCommands
21
- from huggingface_hub.cli.lfs import LfsCommands
22
- from huggingface_hub.cli.repo import RepoCommands
23
- from huggingface_hub.cli.repo_files import RepoFilesCommand
24
- from huggingface_hub.cli.system import EnvironmentCommand, VersionCommand
25
- from huggingface_hub.cli.upload import UploadCommand
26
- from huggingface_hub.cli.upload_large_folder import UploadLargeFolderCommand
16
+ from huggingface_hub.cli._cli_utils import typer_factory
17
+ from huggingface_hub.cli.auth import auth_cli
18
+ from huggingface_hub.cli.cache import cache_cli
19
+ from huggingface_hub.cli.download import download
20
+ from huggingface_hub.cli.jobs import jobs_cli
21
+ from huggingface_hub.cli.lfs import lfs_enable_largefiles, lfs_multipart_upload
22
+ from huggingface_hub.cli.repo import repo_cli
23
+ from huggingface_hub.cli.repo_files import repo_files_cli
24
+ from huggingface_hub.cli.system import env, version
25
+
26
+ # from huggingface_hub.cli.jobs import jobs_app
27
+ from huggingface_hub.cli.upload import upload
28
+ from huggingface_hub.cli.upload_large_folder import upload_large_folder
29
+ from huggingface_hub.utils import logging
30
+
31
+
32
+ app = typer_factory(help="Hugging Face Hub CLI")
33
+
34
+
35
+ # top level single commands (defined in their respective files)
36
+ app.command(help="Download files from the Hub.")(download)
37
+ app.command(help="Upload a file or a folder to the Hub.")(upload)
38
+ app.command(help="Upload a large folder to the Hub. Recommended for resumable uploads.")(upload_large_folder)
39
+ app.command(name="env", help="Print information about the environment.")(env)
40
+ app.command(help="Print information about the hf version.")(version)
41
+ app.command(help="Configure your repository to enable upload of files > 5GB.", hidden=True)(lfs_enable_largefiles)
42
+ app.command(help="Upload large files to the Hub.", hidden=True)(lfs_multipart_upload)
43
+
44
+
45
+ # command groups
46
+ app.add_typer(auth_cli, name="auth")
47
+ app.add_typer(cache_cli, name="cache")
48
+ app.add_typer(repo_cli, name="repo")
49
+ app.add_typer(repo_files_cli, name="repo-files")
50
+ app.add_typer(jobs_cli, name="jobs")
27
51
 
28
52
 
29
53
  def main():
30
- parser = ArgumentParser("hf", usage="hf <command> [<args>]")
31
- commands_parser = parser.add_subparsers(help="hf command helpers")
32
-
33
- # Register commands
34
- AuthCommands.register_subcommand(commands_parser)
35
- CacheCommand.register_subcommand(commands_parser)
36
- DownloadCommand.register_subcommand(commands_parser)
37
- JobsCommands.register_subcommand(commands_parser)
38
- RepoCommands.register_subcommand(commands_parser)
39
- RepoFilesCommand.register_subcommand(commands_parser)
40
- UploadCommand.register_subcommand(commands_parser)
41
- UploadLargeFolderCommand.register_subcommand(commands_parser)
42
-
43
- # System commands
44
- EnvironmentCommand.register_subcommand(commands_parser)
45
- VersionCommand.register_subcommand(commands_parser)
46
-
47
- # LFS commands (hidden in --help)
48
- LfsCommands.register_subcommand(commands_parser)
49
-
50
- # Let's go
51
- args = parser.parse_args()
52
- if not hasattr(args, "func"):
53
- parser.print_help()
54
- exit(1)
55
-
56
- # Run
57
- service = args.func(args)
58
- if service is not None:
59
- service.run()
54
+ logging.set_verbosity_info()
55
+ app()
60
56
 
61
57
 
62
58
  if __name__ == "__main__":