hfutils 0.2.0__tar.gz → 0.2.2__tar.gz
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.
- {hfutils-0.2.0/hfutils.egg-info → hfutils-0.2.2}/PKG-INFO +1 -1
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/config/meta.py +1 -1
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/index/__init__.py +1 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/index/fetch.py +11 -9
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/index/make.py +35 -13
- hfutils-0.2.2/hfutils/index/validate.py +111 -0
- {hfutils-0.2.0 → hfutils-0.2.2/hfutils.egg-info}/PKG-INFO +1 -1
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils.egg-info/SOURCES.txt +1 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/LICENSE +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/MANIFEST.in +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/README.md +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/__init__.py +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/archive/__init__.py +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/archive/base.py +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/archive/rar.py +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/archive/sevenz.py +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/archive/tar.py +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/archive/zip.py +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/config/__init__.py +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/entry/__init__.py +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/entry/base.py +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/entry/cli.py +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/entry/dispatch.py +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/entry/download.py +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/entry/ls.py +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/entry/upload.py +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/index/hash.py +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/operate/__init__.py +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/operate/base.py +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/operate/download.py +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/operate/upload.py +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/operate/validate.py +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/utils/__init__.py +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/utils/binary.py +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/utils/download.py +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/utils/temp.py +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/utils/tqdm_.py +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/utils/walk.py +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils.egg-info/dependency_links.txt +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils.egg-info/entry_points.txt +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils.egg-info/requires.txt +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/hfutils.egg-info/top_level.txt +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/requirements-7z.txt +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/requirements-build.txt +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/requirements-doc.txt +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/requirements-rar.txt +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/requirements-test.txt +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/requirements-transfer.txt +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/requirements.txt +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/setup.cfg +0 -0
- {hfutils-0.2.0 → hfutils-0.2.2}/setup.py +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
from .fetch import hf_tar_list_files, hf_tar_file_download, hf_tar_get_index, hf_tar_file_exists, \
|
|
2
2
|
ArchiveStandaloneFileIncompleteDownload, ArchiveStandaloneFileHashNotMatch
|
|
3
3
|
from .make import tar_create_index, hf_tar_create_index, tar_get_index_info, hf_tar_create_from_directory
|
|
4
|
+
from .validate import hf_tar_item_validate, hf_tar_validate
|
|
@@ -240,6 +240,7 @@ def hf_tar_file_download(repo_id: str, archive_in_repo: str, file_in_archive: st
|
|
|
240
240
|
f'in {repo_type}s/{repo_id}@{revision}/{archive_in_repo}.')
|
|
241
241
|
|
|
242
242
|
info = files[_n_path(file_in_archive)]
|
|
243
|
+
|
|
243
244
|
url_to_download = hf_hub_url(repo_id, archive_in_repo, repo_type=repo_type, revision=revision, endpoint=endpoint)
|
|
244
245
|
headers = build_hf_headers(
|
|
245
246
|
token=hf_token,
|
|
@@ -256,15 +257,16 @@ def hf_tar_file_download(repo_id: str, archive_in_repo: str, file_in_archive: st
|
|
|
256
257
|
os.makedirs(os.path.dirname(local_file), exist_ok=True)
|
|
257
258
|
try:
|
|
258
259
|
with open(local_file, 'wb') as f:
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
260
|
+
if info['size'] > 0:
|
|
261
|
+
http_get(
|
|
262
|
+
url_to_download,
|
|
263
|
+
f,
|
|
264
|
+
proxies=proxies,
|
|
265
|
+
resume_size=0,
|
|
266
|
+
headers=headers,
|
|
267
|
+
expected_size=info['size'],
|
|
268
|
+
displayed_filename=file_in_archive,
|
|
269
|
+
)
|
|
268
270
|
|
|
269
271
|
if os.path.getsize(local_file) != info['size']:
|
|
270
272
|
raise ArchiveStandaloneFileIncompleteDownload(
|
|
@@ -92,25 +92,27 @@ def tar_create_index(src_tar_file, dst_index_file: Optional[str] = None,
|
|
|
92
92
|
return dst_index_file
|
|
93
93
|
|
|
94
94
|
|
|
95
|
-
def hf_tar_create_index(repo_id: str,
|
|
96
|
-
|
|
95
|
+
def hf_tar_create_index(repo_id: str, archive_in_repo: str,
|
|
96
|
+
repo_type: RepoTypeTyping = 'dataset', revision: str = 'main',
|
|
97
|
+
idx_repo_id: Optional[str] = None, idx_file_in_repo: Optional[str] = None,
|
|
97
98
|
idx_repo_type: Optional[RepoTypeTyping] = None, idx_revision: Optional[str] = None,
|
|
98
|
-
chunk_for_hash: int = 1 << 20, with_hash: bool = True,
|
|
99
|
+
chunk_for_hash: int = 1 << 20, with_hash: bool = True, skip_when_synced: bool = True,
|
|
100
|
+
hf_token: Optional[str] = None, ):
|
|
99
101
|
"""
|
|
100
102
|
Create an index file for a tar archive file in a Hugging Face repository.
|
|
101
103
|
|
|
102
104
|
:param repo_id: The identifier of the repository.
|
|
103
105
|
:type repo_id: str
|
|
104
|
-
:param
|
|
105
|
-
:type
|
|
106
|
+
:param archive_in_repo: The path to the tar archive file.
|
|
107
|
+
:type archive_in_repo: str
|
|
106
108
|
:param repo_type: The type of the Hugging Face repository, defaults to 'dataset'.
|
|
107
109
|
:type repo_type: RepoTypeTyping, optional
|
|
108
110
|
:param revision: The revision of the repository, defaults to 'main'.
|
|
109
111
|
:type revision: str, optional
|
|
110
112
|
:param idx_repo_id: The identifier of the index repository, defaults to None.
|
|
111
113
|
:type idx_repo_id: str, optional
|
|
112
|
-
:param
|
|
113
|
-
:type
|
|
114
|
+
:param idx_file_in_repo: The path to save the index file in the index repository, defaults to None.
|
|
115
|
+
:type idx_file_in_repo: str, optional
|
|
114
116
|
:param idx_repo_type: The type of the index repository, defaults to None.
|
|
115
117
|
:type idx_repo_type: RepoTypeTyping, optional
|
|
116
118
|
:param idx_revision: The revision of the index repository, defaults to None.
|
|
@@ -119,31 +121,51 @@ def hf_tar_create_index(repo_id: str, filename: str, repo_type: RepoTypeTyping =
|
|
|
119
121
|
:type chunk_for_hash: int, optional
|
|
120
122
|
:param with_hash: Whether to include file hashes in the index, defaults to True.
|
|
121
123
|
:type with_hash: bool, optional
|
|
124
|
+
:param skip_when_synced: Skip syncing when index is ready, defaults to True.
|
|
125
|
+
:type skip_when_synced: bool
|
|
122
126
|
:param hf_token: The Hugging Face access token, defaults to None.
|
|
123
127
|
:type hf_token: str, optional
|
|
124
128
|
"""
|
|
129
|
+
body, _ = os.path.splitext(archive_in_repo)
|
|
130
|
+
default_index_filename = f'{body}.json'
|
|
131
|
+
|
|
132
|
+
from .validate import hf_tar_validate
|
|
133
|
+
if skip_when_synced and hf_tar_validate(
|
|
134
|
+
repo_id=repo_id,
|
|
135
|
+
repo_type=repo_type,
|
|
136
|
+
archive_in_repo=archive_in_repo,
|
|
137
|
+
revision=revision,
|
|
138
|
+
|
|
139
|
+
idx_repo_id=idx_repo_id or repo_id,
|
|
140
|
+
idx_repo_type=idx_repo_type or repo_type,
|
|
141
|
+
idx_file_in_repo=idx_file_in_repo or default_index_filename,
|
|
142
|
+
idx_revision=idx_revision or revision,
|
|
143
|
+
|
|
144
|
+
hf_token=hf_token,
|
|
145
|
+
):
|
|
146
|
+
logging.info(f'Entry {repo_type}s/{repo_id}/{archive_in_repo} already indexed, skipped.')
|
|
147
|
+
return
|
|
148
|
+
|
|
125
149
|
with TemporaryDirectory() as td:
|
|
126
|
-
local_tar_file = os.path.join(td, os.path.basename(
|
|
150
|
+
local_tar_file = os.path.join(td, os.path.basename(archive_in_repo))
|
|
127
151
|
download_file_to_file(
|
|
128
152
|
repo_id=repo_id,
|
|
129
153
|
repo_type=repo_type,
|
|
130
|
-
file_in_repo=
|
|
154
|
+
file_in_repo=archive_in_repo,
|
|
131
155
|
local_file=local_tar_file,
|
|
132
156
|
revision=revision,
|
|
133
157
|
hf_token=hf_token,
|
|
134
158
|
)
|
|
135
159
|
dst_index_file = tar_create_index(local_tar_file, chunk_for_hash=chunk_for_hash, with_hash=with_hash)
|
|
136
160
|
|
|
137
|
-
body, _ = os.path.splitext(filename)
|
|
138
|
-
default_index_filename = f'{body}.json'
|
|
139
161
|
upload_file_to_file(
|
|
140
162
|
repo_id=idx_repo_id or repo_id,
|
|
141
163
|
repo_type=idx_repo_type or repo_type,
|
|
142
|
-
file_in_repo=
|
|
164
|
+
file_in_repo=idx_file_in_repo or default_index_filename,
|
|
143
165
|
local_file=dst_index_file,
|
|
144
166
|
revision=idx_revision or revision,
|
|
145
167
|
hf_token=hf_token,
|
|
146
|
-
message=f'Create index for {repo_type}s/{repo_id}@{revision}/{
|
|
168
|
+
message=f'Create index for {repo_type}s/{repo_id}@{revision}/{archive_in_repo}',
|
|
147
169
|
)
|
|
148
170
|
|
|
149
171
|
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from huggingface_hub.hf_api import RepoFile
|
|
4
|
+
from huggingface_hub.utils import EntryNotFoundError, RepositoryNotFoundError
|
|
5
|
+
|
|
6
|
+
from .fetch import hf_tar_get_index
|
|
7
|
+
from ..operate.base import RepoTypeTyping, get_hf_client
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def hf_tar_item_validate(file_item: RepoFile, size: int, hash_: Optional[str] = None, hash_lfs: Optional[str] = None):
|
|
11
|
+
"""
|
|
12
|
+
Validate a file item in a tar archive.
|
|
13
|
+
|
|
14
|
+
This function checks if the file item matches the expected size and hash.
|
|
15
|
+
|
|
16
|
+
:param file_item: The file item from the Hugging Face repository.
|
|
17
|
+
:type file_item: RepoFile
|
|
18
|
+
:param size: The expected size of the file.
|
|
19
|
+
:type size: int
|
|
20
|
+
:param hash_: The expected SHA-1 hash of the file.
|
|
21
|
+
:type hash_: str, optional
|
|
22
|
+
:param hash_lfs: The expected SHA-256 hash of the file if stored in LFS.
|
|
23
|
+
:type hash_lfs: str, optional
|
|
24
|
+
:return: True if the file item is valid, False otherwise.
|
|
25
|
+
:rtype: bool
|
|
26
|
+
"""
|
|
27
|
+
# size not match
|
|
28
|
+
if (file_item.lfs and size != file_item.lfs.size) or \
|
|
29
|
+
(not file_item.lfs and size != file_item.size):
|
|
30
|
+
return False
|
|
31
|
+
|
|
32
|
+
# compare tar file hash
|
|
33
|
+
item_hashes = [file_item.blob_id]
|
|
34
|
+
if file_item.lfs:
|
|
35
|
+
item_hashes.append(file_item.lfs.sha256)
|
|
36
|
+
item_hashes = set(filter(bool, item_hashes))
|
|
37
|
+
cmp_hashes = [hash_, hash_lfs]
|
|
38
|
+
cmp_hashes = set(filter(bool, cmp_hashes))
|
|
39
|
+
return bool(cmp_hashes & item_hashes)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def hf_tar_validate(repo_id: str, archive_in_repo: str, repo_type: RepoTypeTyping = 'dataset', revision: str = 'main',
|
|
43
|
+
idx_repo_id: Optional[str] = None, idx_file_in_repo: Optional[str] = None,
|
|
44
|
+
idx_repo_type: Optional[RepoTypeTyping] = None, idx_revision: Optional[str] = None,
|
|
45
|
+
hf_token: Optional[str] = None):
|
|
46
|
+
"""
|
|
47
|
+
Validate a tar archive in a Hugging Face repository.
|
|
48
|
+
|
|
49
|
+
This function validates if the tar archive in the Hugging Face repository matches the expected size and hash.
|
|
50
|
+
|
|
51
|
+
:param repo_id: The ID of the Hugging Face repository.
|
|
52
|
+
:type repo_id: str
|
|
53
|
+
:param archive_in_repo: The path to the tar archive in the repository.
|
|
54
|
+
:type archive_in_repo: str
|
|
55
|
+
:param repo_type: The type of the Hugging Face repository, defaults to 'dataset'.
|
|
56
|
+
:type repo_type: RepoTypeTyping, optional
|
|
57
|
+
:param revision: The revision of the repository, defaults to 'main'.
|
|
58
|
+
:type revision: str, optional
|
|
59
|
+
:param idx_repo_id: The ID of the repository where the index file is stored.
|
|
60
|
+
:type idx_repo_id: Optional[str], optional
|
|
61
|
+
:param idx_file_in_repo: The path to the index file in the repository.
|
|
62
|
+
:type idx_file_in_repo: Optional[str], optional
|
|
63
|
+
:param idx_repo_type: The type of the repository where the index file is stored.
|
|
64
|
+
:type idx_repo_type: Optional[RepoTypeTyping], optional
|
|
65
|
+
:param idx_revision: The revision of the repository where the index file is stored.
|
|
66
|
+
:type idx_revision: Optional[str], optional
|
|
67
|
+
:param hf_token: The Hugging Face token for authentication, defaults to None.
|
|
68
|
+
:type hf_token: Optional[str], optional
|
|
69
|
+
:raises EntryNotFoundError: If the specified entry is not found in the repository.
|
|
70
|
+
:raises IsADirectoryError: If the specified entry is a directory.
|
|
71
|
+
:return: True if the tar archive is valid, False otherwise.
|
|
72
|
+
:rtype: bool
|
|
73
|
+
"""
|
|
74
|
+
hf_client = get_hf_client(hf_token)
|
|
75
|
+
|
|
76
|
+
items = list(hf_client.get_paths_info(
|
|
77
|
+
repo_id=repo_id,
|
|
78
|
+
repo_type=repo_type,
|
|
79
|
+
paths=[archive_in_repo],
|
|
80
|
+
revision=revision,
|
|
81
|
+
))
|
|
82
|
+
if len(items) == 0:
|
|
83
|
+
raise EntryNotFoundError(f'Entry {repo_type}s/{repo_id}/{archive_in_repo} not found.')
|
|
84
|
+
elif not isinstance(items[0], RepoFile):
|
|
85
|
+
raise IsADirectoryError(f'Entry {repo_type}s/{repo_id}/{archive_in_repo} is a directory, not a file.')
|
|
86
|
+
else:
|
|
87
|
+
item = items[0]
|
|
88
|
+
|
|
89
|
+
try:
|
|
90
|
+
index = hf_tar_get_index(
|
|
91
|
+
repo_id=repo_id,
|
|
92
|
+
archive_in_repo=archive_in_repo,
|
|
93
|
+
repo_type=repo_type,
|
|
94
|
+
revision=revision,
|
|
95
|
+
|
|
96
|
+
idx_repo_id=idx_repo_id,
|
|
97
|
+
idx_file_in_repo=idx_file_in_repo,
|
|
98
|
+
idx_repo_type=idx_repo_type,
|
|
99
|
+
idx_revision=idx_revision,
|
|
100
|
+
|
|
101
|
+
hf_token=hf_token,
|
|
102
|
+
)
|
|
103
|
+
except (EntryNotFoundError, RepositoryNotFoundError):
|
|
104
|
+
return False
|
|
105
|
+
|
|
106
|
+
return hf_tar_item_validate(
|
|
107
|
+
file_item=item,
|
|
108
|
+
size=index['filesize'],
|
|
109
|
+
hash_=index.get('hash'),
|
|
110
|
+
hash_lfs=index.get('hash_lfs'),
|
|
111
|
+
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|