huggingface-hub 0.13.3__py3-none-any.whl → 0.14.0.dev0__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 (40) hide show
  1. huggingface_hub/__init__.py +59 -5
  2. huggingface_hub/_commit_api.py +26 -71
  3. huggingface_hub/_login.py +17 -16
  4. huggingface_hub/_multi_commits.py +305 -0
  5. huggingface_hub/_snapshot_download.py +4 -0
  6. huggingface_hub/_space_api.py +6 -0
  7. huggingface_hub/_webhooks_payload.py +124 -0
  8. huggingface_hub/_webhooks_server.py +362 -0
  9. huggingface_hub/commands/lfs.py +3 -5
  10. huggingface_hub/commands/user.py +0 -3
  11. huggingface_hub/community.py +21 -0
  12. huggingface_hub/constants.py +3 -0
  13. huggingface_hub/file_download.py +54 -13
  14. huggingface_hub/hf_api.py +666 -139
  15. huggingface_hub/hf_file_system.py +441 -0
  16. huggingface_hub/hub_mixin.py +1 -1
  17. huggingface_hub/inference_api.py +2 -4
  18. huggingface_hub/keras_mixin.py +1 -1
  19. huggingface_hub/lfs.py +196 -176
  20. huggingface_hub/repocard.py +2 -2
  21. huggingface_hub/repository.py +1 -1
  22. huggingface_hub/templates/modelcard_template.md +1 -1
  23. huggingface_hub/utils/__init__.py +8 -11
  24. huggingface_hub/utils/_errors.py +4 -4
  25. huggingface_hub/utils/_experimental.py +65 -0
  26. huggingface_hub/utils/_git_credential.py +1 -80
  27. huggingface_hub/utils/_http.py +85 -2
  28. huggingface_hub/utils/_pagination.py +4 -3
  29. huggingface_hub/utils/_paths.py +2 -0
  30. huggingface_hub/utils/_runtime.py +12 -0
  31. huggingface_hub/utils/_subprocess.py +22 -0
  32. huggingface_hub/utils/_telemetry.py +2 -4
  33. huggingface_hub/utils/tqdm.py +23 -18
  34. {huggingface_hub-0.13.3.dist-info → huggingface_hub-0.14.0.dev0.dist-info}/METADATA +5 -1
  35. huggingface_hub-0.14.0.dev0.dist-info/RECORD +61 -0
  36. {huggingface_hub-0.13.3.dist-info → huggingface_hub-0.14.0.dev0.dist-info}/entry_points.txt +3 -0
  37. huggingface_hub-0.13.3.dist-info/RECORD +0 -56
  38. {huggingface_hub-0.13.3.dist-info → huggingface_hub-0.14.0.dev0.dist-info}/LICENSE +0 -0
  39. {huggingface_hub-0.13.3.dist-info → huggingface_hub-0.14.0.dev0.dist-info}/WHEEL +0 -0
  40. {huggingface_hub-0.13.3.dist-info → huggingface_hub-0.14.0.dev0.dist-info}/top_level.txt +0 -0
huggingface_hub/lfs.py CHANGED
@@ -16,27 +16,29 @@
16
16
  import io
17
17
  import os
18
18
  import re
19
+ import warnings
19
20
  from contextlib import AbstractContextManager
20
21
  from dataclasses import dataclass
21
22
  from math import ceil
22
23
  from os.path import getsize
23
- from typing import BinaryIO, Iterable, List, Optional, Tuple
24
+ from pathlib import Path
25
+ from typing import TYPE_CHECKING, BinaryIO, Dict, Iterable, List, Optional, Tuple
24
26
 
25
- import requests
26
27
  from requests.auth import HTTPBasicAuth
27
28
 
28
- from huggingface_hub.constants import ENDPOINT, REPO_TYPES_URL_PREFIXES
29
+ from huggingface_hub.constants import ENDPOINT, HF_HUB_ENABLE_HF_TRANSFER, REPO_TYPES_URL_PREFIXES
30
+ from huggingface_hub.utils import get_session
29
31
 
30
- from .utils import (
31
- get_token_to_send,
32
- hf_raise_for_status,
33
- http_backoff,
34
- validate_hf_hub_args,
35
- )
32
+ from .utils import get_token_to_send, hf_raise_for_status, http_backoff, logging, validate_hf_hub_args
36
33
  from .utils._typing import TypedDict
37
34
  from .utils.sha import sha256, sha_fileobj
38
35
 
39
36
 
37
+ if TYPE_CHECKING:
38
+ from ._commit_api import CommitOperationAdd
39
+
40
+ logger = logging.get_logger(__name__)
41
+
40
42
  OID_REGEX = re.compile(r"^[0-9a-f]{40}$")
41
43
 
42
44
  LFS_MULTIPART_UPLOAD_COMMAND = "lfs-multipart-upload"
@@ -89,44 +91,6 @@ class UploadInfo:
89
91
  return cls(size=size, sha256=sha, sample=sample)
90
92
 
91
93
 
92
- def _validate_lfs_action(lfs_action: dict):
93
- """validates response from the LFS batch endpoint"""
94
- if not (
95
- isinstance(lfs_action.get("href"), str)
96
- and (lfs_action.get("header") is None or isinstance(lfs_action.get("header"), dict))
97
- ):
98
- raise ValueError("lfs_action is improperly formatted")
99
- return lfs_action
100
-
101
-
102
- def _validate_batch_actions(lfs_batch_actions: dict):
103
- """validates response from the LFS batch endpoint"""
104
- if not (isinstance(lfs_batch_actions.get("oid"), str) and isinstance(lfs_batch_actions.get("size"), int)):
105
- raise ValueError("lfs_batch_actions is improperly formatted")
106
-
107
- upload_action = lfs_batch_actions.get("actions", {}).get("upload")
108
- verify_action = lfs_batch_actions.get("actions", {}).get("verify")
109
- if upload_action is not None:
110
- _validate_lfs_action(upload_action)
111
- if verify_action is not None:
112
- _validate_lfs_action(verify_action)
113
- return lfs_batch_actions
114
-
115
-
116
- def _validate_batch_error(lfs_batch_error: dict):
117
- """validates response from the LFS batch endpoint"""
118
- if not (isinstance(lfs_batch_error.get("oid"), str) and isinstance(lfs_batch_error.get("size"), int)):
119
- raise ValueError("lfs_batch_error is improperly formatted")
120
- error_info = lfs_batch_error.get("error")
121
- if not (
122
- isinstance(error_info, dict)
123
- and isinstance(error_info.get("message"), str)
124
- and isinstance(error_info.get("code"), int)
125
- ):
126
- raise ValueError("lfs_batch_error is improperly formatted")
127
- return lfs_batch_error
128
-
129
-
130
94
  @validate_hf_hub_args
131
95
  def post_lfs_batch_info(
132
96
  upload_infos: Iterable[UploadInfo],
@@ -167,12 +131,9 @@ def post_lfs_batch_info(
167
131
  if repo_type in REPO_TYPES_URL_PREFIXES:
168
132
  url_prefix = REPO_TYPES_URL_PREFIXES[repo_type]
169
133
  batch_url = f"{endpoint}/{url_prefix}{repo_id}.git/info/lfs/objects/batch"
170
- resp = requests.post(
134
+ resp = get_session().post(
171
135
  batch_url,
172
- headers={
173
- "Accept": "application/vnd.git-lfs+json",
174
- "Content-Type": "application/vnd.git-lfs+json",
175
- },
136
+ headers=LFS_HEADERS,
176
137
  json={
177
138
  "operation": "upload",
178
139
  "transfers": ["basic", "multipart"],
@@ -203,80 +164,117 @@ def post_lfs_batch_info(
203
164
  )
204
165
 
205
166
 
206
- def lfs_upload(
207
- fileobj: BinaryIO,
208
- upload_info: UploadInfo,
209
- upload_action: dict,
210
- verify_action: Optional[dict],
211
- token: Optional[str],
212
- ):
167
+ class PayloadPartT(TypedDict):
168
+ partNumber: int
169
+ etag: str
170
+
171
+
172
+ class CompletionPayloadT(TypedDict):
173
+ """Payload that will be sent to the Hub when uploading multi-part."""
174
+
175
+ oid: str
176
+ parts: List[PayloadPartT]
177
+
178
+
179
+ def lfs_upload(operation: "CommitOperationAdd", lfs_batch_action: Dict, token: Optional[str]) -> None:
213
180
  """
214
- Uploads a file using the git lfs protocol and determines automatically whether or not
215
- to use the multipart transfer protocol
181
+ Handles uploading a given object to the Hub with the LFS protocol.
182
+
183
+ Can be a No-op if the content of the file is already present on the hub large file storage.
216
184
 
217
185
  Args:
218
- fileobj (file-like object):
219
- The content of the file to upload
220
- upload_info (`UploadInfo`):
221
- Upload info for `fileobj`
222
- upload_action (`dict`):
223
- The `upload` action from the LFS Batch endpoint. Must contain
224
- a `href` field, and optionally a `header` field.
225
- verify_action (`dict`):
226
- The `verify` action from the LFS Batch endpoint. Must contain
227
- a `href` field, and optionally a `header` field. The `href` URL will
228
- be called after a successful upload.
186
+ operation (`CommitOperationAdd`):
187
+ The add operation triggering this upload.
188
+ lfs_batch_action (`dict`):
189
+ Upload instructions from the LFS batch endpoint for this object. See [`~utils.lfs.post_lfs_batch_info`] for
190
+ more details.
229
191
  token (`str`, *optional*):
230
- A [user access token](https://hf.co/settings/tokens) to authenticate requests
231
- against the Hub.
232
-
233
- Returns:
234
- `requests.Response`:
235
- the response from the completion request in case of a multi-part upload, and the
236
- response from the single PUT request in case of a single-part upload
192
+ A [user access token](https://hf.co/settings/tokens) to authenticate requests against the Hub
237
193
 
238
194
  Raises:
239
- `ValueError`: if some objects / responses are malformed
240
-
241
- `requests.HTTPError`
195
+ - `ValueError` if `lfs_batch_action` is improperly formatted
196
+ - `HTTPError` if the upload resulted in an error
242
197
  """
198
+ # 0. If LFS file is already present, skip upload
199
+ _validate_batch_actions(lfs_batch_action)
200
+ actions = lfs_batch_action.get("actions")
201
+ if actions is None:
202
+ # The file was already uploaded
203
+ logger.debug(f"Content of file {operation.path_in_repo} is already present upstream - skipping upload")
204
+ return
205
+
206
+ # 1. Validate server response (check required keys in dict)
207
+ upload_action = lfs_batch_action["actions"]["upload"]
243
208
  _validate_lfs_action(upload_action)
209
+ verify_action = lfs_batch_action["actions"].get("verify")
244
210
  if verify_action is not None:
245
211
  _validate_lfs_action(verify_action)
246
212
 
213
+ # 2. Upload file (either single part or multi-part)
247
214
  header = upload_action.get("header", {})
248
- chunk_size = header.get("chunk_size", None)
215
+ chunk_size = header.get("chunk_size")
249
216
  if chunk_size is not None:
250
- if isinstance(chunk_size, str):
251
- chunk_size = int(chunk_size, 10)
252
- else:
253
- raise ValueError("Malformed response from LFS batch endpoint: `chunk_size` should be a string")
254
- _upload_multi_part(
255
- completion_url=upload_action["href"],
256
- fileobj=fileobj,
257
- chunk_size=chunk_size,
258
- header=header,
259
- upload_info=upload_info,
260
- )
217
+ try:
218
+ chunk_size = int(chunk_size)
219
+ except (ValueError, TypeError):
220
+ raise ValueError(
221
+ f"Malformed response from LFS batch endpoint: `chunk_size` should be an integer. Got '{chunk_size}'."
222
+ )
223
+ _upload_multi_part(operation=operation, header=header, chunk_size=chunk_size, upload_url=upload_action["href"])
261
224
  else:
262
- _upload_single_part(
263
- upload_url=upload_action["href"],
264
- fileobj=fileobj,
265
- )
225
+ _upload_single_part(operation=operation, upload_url=upload_action["href"])
226
+
227
+ # 3. Verify upload went well
266
228
  if verify_action is not None:
267
- verify_resp = requests.post(
229
+ _validate_lfs_action(verify_action)
230
+ verify_resp = get_session().post(
268
231
  verify_action["href"],
269
- auth=HTTPBasicAuth(
270
- username="USER",
271
- # Token must be provided or retrieved
272
- password=get_token_to_send(token or True), # type: ignore
273
- ),
274
- json={"oid": upload_info.sha256.hex(), "size": upload_info.size},
232
+ auth=HTTPBasicAuth(username="USER", password=get_token_to_send(token or True)), # type: ignore
233
+ json={"oid": operation.upload_info.sha256.hex(), "size": operation.upload_info.size},
275
234
  )
276
235
  hf_raise_for_status(verify_resp)
236
+ logger.debug(f"{operation.path_in_repo}: Upload successful")
237
+
238
+
239
+ def _validate_lfs_action(lfs_action: dict):
240
+ """validates response from the LFS batch endpoint"""
241
+ if not (
242
+ isinstance(lfs_action.get("href"), str)
243
+ and (lfs_action.get("header") is None or isinstance(lfs_action.get("header"), dict))
244
+ ):
245
+ raise ValueError("lfs_action is improperly formatted")
246
+ return lfs_action
247
+
248
+
249
+ def _validate_batch_actions(lfs_batch_actions: dict):
250
+ """validates response from the LFS batch endpoint"""
251
+ if not (isinstance(lfs_batch_actions.get("oid"), str) and isinstance(lfs_batch_actions.get("size"), int)):
252
+ raise ValueError("lfs_batch_actions is improperly formatted")
253
+
254
+ upload_action = lfs_batch_actions.get("actions", {}).get("upload")
255
+ verify_action = lfs_batch_actions.get("actions", {}).get("verify")
256
+ if upload_action is not None:
257
+ _validate_lfs_action(upload_action)
258
+ if verify_action is not None:
259
+ _validate_lfs_action(verify_action)
260
+ return lfs_batch_actions
261
+
262
+
263
+ def _validate_batch_error(lfs_batch_error: dict):
264
+ """validates response from the LFS batch endpoint"""
265
+ if not (isinstance(lfs_batch_error.get("oid"), str) and isinstance(lfs_batch_error.get("size"), int)):
266
+ raise ValueError("lfs_batch_error is improperly formatted")
267
+ error_info = lfs_batch_error.get("error")
268
+ if not (
269
+ isinstance(error_info, dict)
270
+ and isinstance(error_info.get("message"), str)
271
+ and isinstance(error_info.get("code"), int)
272
+ ):
273
+ raise ValueError("lfs_batch_error is improperly formatted")
274
+ return lfs_batch_error
277
275
 
278
276
 
279
- def _upload_single_part(upload_url: str, fileobj: BinaryIO):
277
+ def _upload_single_part(operation: "CommitOperationAdd", upload_url: str) -> None:
280
278
  """
281
279
  Uploads `fileobj` as a single PUT HTTP request (basic LFS transfer protocol)
282
280
 
@@ -290,54 +288,47 @@ def _upload_single_part(upload_url: str, fileobj: BinaryIO):
290
288
 
291
289
  Raises: `requests.HTTPError` if the upload resulted in an error
292
290
  """
293
- upload_res = http_backoff("PUT", upload_url, data=fileobj)
294
- hf_raise_for_status(upload_res)
295
- return upload_res
296
-
291
+ with operation.as_file(with_tqdm=True) as fileobj:
292
+ response = http_backoff("PUT", upload_url, data=fileobj)
293
+ hf_raise_for_status(response)
297
294
 
298
- class PayloadPartT(TypedDict):
299
- partNumber: int
300
- etag: str
301
-
302
-
303
- class CompletionPayloadT(TypedDict):
304
- """Payload that will be sent to the Hub when uploading multi-part."""
305
295
 
306
- oid: str
307
- parts: List[PayloadPartT]
308
-
309
-
310
- def _upload_multi_part(
311
- completion_url: str,
312
- fileobj: BinaryIO,
313
- header: dict,
314
- chunk_size: int,
315
- upload_info: UploadInfo,
316
- ):
296
+ def _upload_multi_part(operation: "CommitOperationAdd", header: Dict, chunk_size: int, upload_url: str) -> None:
317
297
  """
318
- Uploads `fileobj` using HF multipart LFS transfer protocol.
319
-
320
- Args:
321
- completion_url (`str`):
322
- The URL to GET after completing all parts uploads.
323
- fileobj:
324
- The file-like object holding the data to upload.
325
- header (`dict`):
326
- The `header` field from the `upload` action from the LFS
327
- Batch endpoint response
328
- chunk_size (`int`):
329
- The size in bytes of the parts. `fileobj` will be uploaded in parts
330
- of `chunk_size` bytes (except for the last part who can be smaller)
331
- upload_info (`UploadInfo`):
332
- `UploadInfo` for `fileobj`.
298
+ Uploads file using HF multipart LFS transfer protocol.
299
+ """
300
+ # 1. Get upload URLs for each part
301
+ sorted_parts_urls = _get_sorted_parts_urls(header=header, upload_info=operation.upload_info, chunk_size=chunk_size)
302
+
303
+ # 2. Upload parts (either with hf_transfer or in pure Python)
304
+ use_hf_transfer = HF_HUB_ENABLE_HF_TRANSFER
305
+ if (
306
+ HF_HUB_ENABLE_HF_TRANSFER
307
+ and not isinstance(operation.path_or_fileobj, str)
308
+ and not isinstance(operation.path_or_fileobj, Path)
309
+ ):
310
+ warnings.warn(
311
+ "hf_transfer is enabled but does not support uploading from bytes or BinaryIO, falling back to regular"
312
+ " upload"
313
+ )
314
+ use_hf_transfer = False
333
315
 
334
- Returns: `requests.Response`: The response from requesting `completion_url`.
316
+ response_headers = (
317
+ _upload_parts_hf_transfer(operation=operation, sorted_parts_urls=sorted_parts_urls, chunk_size=chunk_size)
318
+ if use_hf_transfer
319
+ else _upload_parts_iteratively(operation=operation, sorted_parts_urls=sorted_parts_urls, chunk_size=chunk_size)
320
+ )
335
321
 
336
- Raises: `requests.HTTPError` if uploading any of the parts resulted in an error.
322
+ # 3. Send completion request
323
+ completion_res = get_session().post(
324
+ upload_url,
325
+ json=_get_completion_payload(response_headers, operation.upload_info.sha256.hex()),
326
+ headers=LFS_HEADERS,
327
+ )
328
+ hf_raise_for_status(completion_res)
337
329
 
338
- Raises: `requests.HTTPError` if requesting `completion_url` resulted in an error.
339
330
 
340
- """
331
+ def _get_sorted_parts_urls(header: Dict, upload_info: UploadInfo, chunk_size: int) -> List[str]:
341
332
  sorted_part_upload_urls = [
342
333
  upload_url
343
334
  for _, upload_url in sorted(
@@ -352,38 +343,67 @@ def _upload_multi_part(
352
343
  num_parts = len(sorted_part_upload_urls)
353
344
  if num_parts != ceil(upload_info.size / chunk_size):
354
345
  raise ValueError("Invalid server response to upload large LFS file")
346
+ return sorted_part_upload_urls
347
+
355
348
 
356
- completion_payload: CompletionPayloadT = {
357
- "oid": upload_info.sha256.hex(),
358
- "parts": [
349
+ def _get_completion_payload(response_headers: List[Dict], oid: str) -> CompletionPayloadT:
350
+ parts: List[PayloadPartT] = []
351
+ for part_number, header in enumerate(response_headers):
352
+ etag = header.get("etag")
353
+ if etag is None or etag == "":
354
+ raise ValueError(f"Invalid etag (`{etag}`) returned for part {part_number + 1}")
355
+ parts.append(
359
356
  {
360
- "partNumber": idx + 1,
361
- "etag": "",
357
+ "partNumber": part_number + 1,
358
+ "etag": etag,
362
359
  }
363
- for idx in range(num_parts)
364
- ],
365
- }
366
-
367
- for part_idx, part_upload_url in enumerate(sorted_part_upload_urls):
368
- with SliceFileObj(
369
- fileobj,
370
- seek_from=chunk_size * part_idx,
371
- read_limit=chunk_size,
372
- ) as fileobj_slice:
373
- part_upload_res = http_backoff("PUT", part_upload_url, data=fileobj_slice)
374
- hf_raise_for_status(part_upload_res)
375
- etag = part_upload_res.headers.get("etag")
376
- if etag is None or etag == "":
377
- raise ValueError(f"Invalid etag (`{etag}`) returned for part {part_idx +1} of {num_parts}")
378
- completion_payload["parts"][part_idx]["etag"] = etag
379
-
380
- completion_res = requests.post(
381
- completion_url,
382
- json=completion_payload,
383
- headers=LFS_HEADERS,
384
- )
385
- hf_raise_for_status(completion_res)
386
- return completion_res
360
+ )
361
+ return {"oid": oid, "parts": parts}
362
+
363
+
364
+ def _upload_parts_iteratively(
365
+ operation: "CommitOperationAdd", sorted_parts_urls: List[str], chunk_size: int
366
+ ) -> List[Dict]:
367
+ headers = []
368
+ with operation.as_file(with_tqdm=True) as fileobj:
369
+ for part_idx, part_upload_url in enumerate(sorted_parts_urls):
370
+ with SliceFileObj(
371
+ fileobj,
372
+ seek_from=chunk_size * part_idx,
373
+ read_limit=chunk_size,
374
+ ) as fileobj_slice:
375
+ part_upload_res = http_backoff("PUT", part_upload_url, data=fileobj_slice)
376
+ hf_raise_for_status(part_upload_res)
377
+ headers.append(part_upload_res.headers)
378
+ return headers # type: ignore
379
+
380
+
381
+ def _upload_parts_hf_transfer(
382
+ operation: "CommitOperationAdd", sorted_parts_urls: List[str], chunk_size: int
383
+ ) -> List[Dict]:
384
+ # Upload file using an external Rust-based package. Upload is faster but support less features (no progress bars).
385
+ try:
386
+ from hf_transfer import multipart_upload
387
+ except ImportError:
388
+ raise ValueError(
389
+ "Fast uploading using 'hf_transfer' is enabled (HF_HUB_ENABLE_HF_TRANSFER=1) but 'hf_transfer' package is"
390
+ " not available in your environment. Try `pip install hf_transfer`."
391
+ )
392
+
393
+ try:
394
+ return multipart_upload(
395
+ file_path=operation.path_or_fileobj,
396
+ parts_urls=sorted_parts_urls,
397
+ chunk_size=chunk_size,
398
+ max_files=128,
399
+ parallel_failures=127, # could be removed
400
+ max_retries=5,
401
+ )
402
+ except Exception as e:
403
+ raise RuntimeError(
404
+ "An error occurred while uploading using `hf_transfer`. Consider disabling HF_HUB_ENABLE_HF_TRANSFER for"
405
+ " better error handling."
406
+ ) from e
387
407
 
388
408
 
389
409
  class SliceFileObj(AbstractContextManager):
@@ -17,7 +17,7 @@ from huggingface_hub.repocard_data import (
17
17
  eval_results_to_model_index,
18
18
  model_index_to_eval_results,
19
19
  )
20
- from huggingface_hub.utils import is_jinja_available, yaml_dump
20
+ from huggingface_hub.utils import get_session, is_jinja_available, yaml_dump
21
21
 
22
22
  from .constants import REPOCARD_NAME
23
23
  from .utils import EntryNotFoundError, SoftTemporaryDirectory, validate_hf_hub_args
@@ -216,7 +216,7 @@ class RepoCard:
216
216
  headers = {"Accept": "text/plain"}
217
217
 
218
218
  try:
219
- r = requests.post("https://huggingface.co/api/validate-yaml", body, headers=headers)
219
+ r = get_session().post("https://huggingface.co/api/validate-yaml", body, headers=headers)
220
220
  r.raise_for_status()
221
221
  except requests.exceptions.HTTPError as exc:
222
222
  if r.status_code == 400:
@@ -1452,7 +1452,7 @@ class Repository:
1452
1452
 
1453
1453
  while self.commands_in_progress:
1454
1454
  if index % 10 == 0:
1455
- logger.error(
1455
+ logger.warning(
1456
1456
  f"Waiting for the following commands to finish before shutting down: {self.commands_in_progress}."
1457
1457
  )
1458
1458
 
@@ -67,7 +67,7 @@
67
67
 
68
68
  {{ bias_recommendations | default("Users (both direct and downstream) should be made aware of the risks, biases and limitations of the model. More information needed for further recommendations.", true)}}
69
69
 
70
- ### How to Get Started with the Model
70
+ ## How to Get Started with the Model
71
71
 
72
72
  Use the code below to get started with the model.
73
73
 
@@ -40,22 +40,19 @@ from ._errors import (
40
40
  hf_raise_for_status,
41
41
  )
42
42
  from ._fixes import SoftTemporaryDirectory, yaml_dump
43
- from ._git_credential import (
44
- erase_from_credential_store,
45
- list_credential_helpers,
46
- read_from_credential_store,
47
- set_git_credential,
48
- unset_git_credential,
49
- write_to_credential_store,
50
- )
43
+ from ._git_credential import list_credential_helpers, set_git_credential, unset_git_credential
51
44
  from ._headers import build_hf_headers, get_token_to_send
52
45
  from ._hf_folder import HfFolder
53
- from ._http import http_backoff
54
- from ._paths import filter_repo_objects
46
+ from ._http import configure_http_backend, get_session, http_backoff
47
+ from ._pagination import paginate
48
+ from ._paths import filter_repo_objects, IGNORE_GIT_FOLDER_PATTERNS
49
+ from ._experimental import experimental
55
50
  from ._runtime import (
56
51
  dump_environment_info,
57
52
  get_fastai_version,
58
53
  get_fastcore_version,
54
+ get_gradio_version,
55
+ is_gradio_available,
59
56
  get_graphviz_version,
60
57
  get_hf_hub_version,
61
58
  get_hf_transfer_version,
@@ -77,7 +74,7 @@ from ._runtime import (
77
74
  is_tf_available,
78
75
  is_torch_available,
79
76
  )
80
- from ._subprocess import run_interactive_subprocess, run_subprocess
77
+ from ._subprocess import capture_output, run_interactive_subprocess, run_subprocess
81
78
  from ._validators import (
82
79
  HFValidationError,
83
80
  smoothly_deprecate_use_auth_token,
@@ -20,9 +20,9 @@ class HfHubHTTPError(HTTPError):
20
20
  Example:
21
21
  ```py
22
22
  import requests
23
- from huggingface_hub.utils import hf_raise_for_status, HfHubHTTPError
23
+ from huggingface_hub.utils import get_session, hf_raise_for_status, HfHubHTTPError
24
24
 
25
- response = requests.post(...)
25
+ response = get_session().post(...)
26
26
  try:
27
27
  hf_raise_for_status(response)
28
28
  except HfHubHTTPError as e:
@@ -211,9 +211,9 @@ def hf_raise_for_status(response: Response, endpoint_name: Optional[str] = None)
211
211
  Example:
212
212
  ```py
213
213
  import requests
214
- from huggingface_hub.utils import hf_raise_for_status, HfHubHTTPError
214
+ from huggingface_hub.utils import get_session, hf_raise_for_status, HfHubHTTPError
215
215
 
216
- response = requests.post(...)
216
+ response = get_session().post(...)
217
217
  try:
218
218
  hf_raise_for_status(response)
219
219
  except HfHubHTTPError as e:
@@ -0,0 +1,65 @@
1
+ # coding=utf-8
2
+ # Copyright 2023-present, the HuggingFace Inc. team.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ """Contains utilities to flag a feature as "experimental" in Huggingface Hub."""
16
+ import warnings
17
+ from functools import wraps
18
+ from typing import Callable
19
+
20
+ from .. import constants
21
+
22
+
23
+ def experimental(fn: Callable) -> Callable:
24
+ """Decorator to flag a feature as experimental.
25
+
26
+ An experimental feature trigger a warning when used as it might be subject to breaking changes in the future.
27
+ Warnings can be disabled by setting the environment variable `HF_EXPERIMENTAL_WARNING` to `0`.
28
+
29
+ Args:
30
+ fn (`Callable`):
31
+ The function to flag as experimental.
32
+
33
+ Returns:
34
+ `Callable`: The decorated function.
35
+
36
+ Example:
37
+
38
+ ```python
39
+ >>> from huggingface_hub.utils import experimental
40
+
41
+ >>> @experimental
42
+ ... def my_function():
43
+ ... print("Hello world!")
44
+
45
+ >>> my_function()
46
+ UserWarning: 'my_function' is experimental and might be subject to breaking changes in the future. You can disable
47
+ this warning by setting `HF_HUB_DISABLE_EXPERIMENTAL_WARNING=1` as environment variable.
48
+ Hello world!
49
+ ```
50
+ """
51
+
52
+ @wraps(fn)
53
+ def _inner_fn(*args, **kwargs):
54
+ if not constants.HF_HUB_DISABLE_EXPERIMENTAL_WARNING:
55
+ warnings.warn(
56
+ (
57
+ f"'{fn.__name__}' is experimental and might be subject to breaking changes in the future. You can"
58
+ " disable this warning by setting `HF_HUB_DISABLE_EXPERIMENTAL_WARNING=1` as environment"
59
+ " variable."
60
+ ),
61
+ UserWarning,
62
+ )
63
+ return fn(*args, **kwargs)
64
+
65
+ return _inner_fn