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.
- huggingface_hub/__init__.py +59 -5
- huggingface_hub/_commit_api.py +26 -71
- huggingface_hub/_login.py +17 -16
- huggingface_hub/_multi_commits.py +305 -0
- huggingface_hub/_snapshot_download.py +4 -0
- huggingface_hub/_space_api.py +6 -0
- huggingface_hub/_webhooks_payload.py +124 -0
- huggingface_hub/_webhooks_server.py +362 -0
- huggingface_hub/commands/lfs.py +3 -5
- huggingface_hub/commands/user.py +0 -3
- huggingface_hub/community.py +21 -0
- huggingface_hub/constants.py +3 -0
- huggingface_hub/file_download.py +54 -13
- huggingface_hub/hf_api.py +666 -139
- huggingface_hub/hf_file_system.py +441 -0
- huggingface_hub/hub_mixin.py +1 -1
- huggingface_hub/inference_api.py +2 -4
- huggingface_hub/keras_mixin.py +1 -1
- huggingface_hub/lfs.py +196 -176
- huggingface_hub/repocard.py +2 -2
- huggingface_hub/repository.py +1 -1
- huggingface_hub/templates/modelcard_template.md +1 -1
- huggingface_hub/utils/__init__.py +8 -11
- huggingface_hub/utils/_errors.py +4 -4
- huggingface_hub/utils/_experimental.py +65 -0
- huggingface_hub/utils/_git_credential.py +1 -80
- huggingface_hub/utils/_http.py +85 -2
- huggingface_hub/utils/_pagination.py +4 -3
- huggingface_hub/utils/_paths.py +2 -0
- huggingface_hub/utils/_runtime.py +12 -0
- huggingface_hub/utils/_subprocess.py +22 -0
- huggingface_hub/utils/_telemetry.py +2 -4
- huggingface_hub/utils/tqdm.py +23 -18
- {huggingface_hub-0.13.3.dist-info → huggingface_hub-0.14.0.dev0.dist-info}/METADATA +5 -1
- huggingface_hub-0.14.0.dev0.dist-info/RECORD +61 -0
- {huggingface_hub-0.13.3.dist-info → huggingface_hub-0.14.0.dev0.dist-info}/entry_points.txt +3 -0
- huggingface_hub-0.13.3.dist-info/RECORD +0 -56
- {huggingface_hub-0.13.3.dist-info → huggingface_hub-0.14.0.dev0.dist-info}/LICENSE +0 -0
- {huggingface_hub-0.13.3.dist-info → huggingface_hub-0.14.0.dev0.dist-info}/WHEEL +0 -0
- {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
|
|
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 =
|
|
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
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
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
|
-
|
|
215
|
-
|
|
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
|
-
|
|
219
|
-
The
|
|
220
|
-
|
|
221
|
-
Upload
|
|
222
|
-
|
|
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
|
|
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"
|
|
215
|
+
chunk_size = header.get("chunk_size")
|
|
249
216
|
if chunk_size is not None:
|
|
250
|
-
|
|
251
|
-
chunk_size = int(chunk_size
|
|
252
|
-
|
|
253
|
-
raise ValueError(
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
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
|
-
|
|
264
|
-
|
|
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
|
-
|
|
229
|
+
_validate_lfs_action(verify_action)
|
|
230
|
+
verify_resp = get_session().post(
|
|
268
231
|
verify_action["href"],
|
|
269
|
-
auth=HTTPBasicAuth(
|
|
270
|
-
|
|
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(
|
|
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
|
-
|
|
294
|
-
|
|
295
|
-
|
|
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
|
-
|
|
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
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
357
|
-
|
|
358
|
-
|
|
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":
|
|
361
|
-
"etag":
|
|
357
|
+
"partNumber": part_number + 1,
|
|
358
|
+
"etag": etag,
|
|
362
359
|
}
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
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):
|
huggingface_hub/repocard.py
CHANGED
|
@@ -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 =
|
|
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:
|
huggingface_hub/repository.py
CHANGED
|
@@ -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
|
-
|
|
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 .
|
|
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,
|
huggingface_hub/utils/_errors.py
CHANGED
|
@@ -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 =
|
|
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 =
|
|
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
|