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.
Files changed (51) hide show
  1. {hfutils-0.2.0/hfutils.egg-info → hfutils-0.2.2}/PKG-INFO +1 -1
  2. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/config/meta.py +1 -1
  3. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/index/__init__.py +1 -0
  4. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/index/fetch.py +11 -9
  5. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/index/make.py +35 -13
  6. hfutils-0.2.2/hfutils/index/validate.py +111 -0
  7. {hfutils-0.2.0 → hfutils-0.2.2/hfutils.egg-info}/PKG-INFO +1 -1
  8. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils.egg-info/SOURCES.txt +1 -0
  9. {hfutils-0.2.0 → hfutils-0.2.2}/LICENSE +0 -0
  10. {hfutils-0.2.0 → hfutils-0.2.2}/MANIFEST.in +0 -0
  11. {hfutils-0.2.0 → hfutils-0.2.2}/README.md +0 -0
  12. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/__init__.py +0 -0
  13. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/archive/__init__.py +0 -0
  14. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/archive/base.py +0 -0
  15. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/archive/rar.py +0 -0
  16. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/archive/sevenz.py +0 -0
  17. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/archive/tar.py +0 -0
  18. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/archive/zip.py +0 -0
  19. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/config/__init__.py +0 -0
  20. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/entry/__init__.py +0 -0
  21. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/entry/base.py +0 -0
  22. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/entry/cli.py +0 -0
  23. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/entry/dispatch.py +0 -0
  24. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/entry/download.py +0 -0
  25. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/entry/ls.py +0 -0
  26. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/entry/upload.py +0 -0
  27. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/index/hash.py +0 -0
  28. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/operate/__init__.py +0 -0
  29. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/operate/base.py +0 -0
  30. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/operate/download.py +0 -0
  31. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/operate/upload.py +0 -0
  32. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/operate/validate.py +0 -0
  33. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/utils/__init__.py +0 -0
  34. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/utils/binary.py +0 -0
  35. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/utils/download.py +0 -0
  36. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/utils/temp.py +0 -0
  37. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/utils/tqdm_.py +0 -0
  38. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils/utils/walk.py +0 -0
  39. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils.egg-info/dependency_links.txt +0 -0
  40. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils.egg-info/entry_points.txt +0 -0
  41. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils.egg-info/requires.txt +0 -0
  42. {hfutils-0.2.0 → hfutils-0.2.2}/hfutils.egg-info/top_level.txt +0 -0
  43. {hfutils-0.2.0 → hfutils-0.2.2}/requirements-7z.txt +0 -0
  44. {hfutils-0.2.0 → hfutils-0.2.2}/requirements-build.txt +0 -0
  45. {hfutils-0.2.0 → hfutils-0.2.2}/requirements-doc.txt +0 -0
  46. {hfutils-0.2.0 → hfutils-0.2.2}/requirements-rar.txt +0 -0
  47. {hfutils-0.2.0 → hfutils-0.2.2}/requirements-test.txt +0 -0
  48. {hfutils-0.2.0 → hfutils-0.2.2}/requirements-transfer.txt +0 -0
  49. {hfutils-0.2.0 → hfutils-0.2.2}/requirements.txt +0 -0
  50. {hfutils-0.2.0 → hfutils-0.2.2}/setup.cfg +0 -0
  51. {hfutils-0.2.0 → hfutils-0.2.2}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hfutils
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: Useful utilities for huggingface
5
5
  Home-page: https://github.com/deepghs/hfutils
6
6
  Author: narugo1992
@@ -7,7 +7,7 @@ Overview:
7
7
  __TITLE__ = 'hfutils'
8
8
 
9
9
  #: Version of this project.
10
- __VERSION__ = '0.2.0'
10
+ __VERSION__ = '0.2.2'
11
11
 
12
12
  #: Short description of the project, will be included in ``setup.py``.
13
13
  __DESCRIPTION__ = 'Useful utilities for huggingface'
@@ -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
- http_get(
260
- url_to_download,
261
- f,
262
- proxies=proxies,
263
- resume_size=0,
264
- headers=headers,
265
- expected_size=info['size'],
266
- displayed_filename=file_in_archive,
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, filename: str, repo_type: RepoTypeTyping = 'dataset', revision: str = 'main',
96
- idx_repo_id: Optional[str] = None, idx_filename: Optional[str] = None,
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, hf_token: Optional[str] = None):
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 filename: The path to the tar archive file.
105
- :type filename: str
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 idx_filename: The path to save the index file in the index repository, defaults to None.
113
- :type idx_filename: str, optional
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(filename))
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=filename,
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=idx_filename or default_index_filename,
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}/{filename}',
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
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hfutils
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: Useful utilities for huggingface
5
5
  Home-page: https://github.com/deepghs/hfutils
6
6
  Author: narugo1992
@@ -35,6 +35,7 @@ hfutils/index/__init__.py
35
35
  hfutils/index/fetch.py
36
36
  hfutils/index/hash.py
37
37
  hfutils/index/make.py
38
+ hfutils/index/validate.py
38
39
  hfutils/operate/__init__.py
39
40
  hfutils/operate/base.py
40
41
  hfutils/operate/download.py
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