hfutils 0.4.0__tar.gz → 0.4.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.4.0/hfutils.egg-info → hfutils-0.4.2}/PKG-INFO +2 -1
- {hfutils-0.4.0 → hfutils-0.4.2}/README.md +1 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/config/meta.py +1 -1
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/entry/cli.py +2 -0
- hfutils-0.4.2/hfutils/entry/ils.py +288 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/index/fetch.py +12 -1
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/index/local_fetch.py +12 -1
- {hfutils-0.4.0 → hfutils-0.4.2/hfutils.egg-info}/PKG-INFO +2 -1
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils.egg-info/SOURCES.txt +1 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/LICENSE +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/MANIFEST.in +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/__init__.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/__main__.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/archive/__init__.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/archive/base.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/archive/rar.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/archive/sevenz.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/archive/tar.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/archive/zip.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/cache/__init__.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/cache/delete.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/config/__init__.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/entry/__init__.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/entry/base.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/entry/clone.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/entry/dispatch.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/entry/download.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/entry/index.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/entry/ls.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/entry/ls_repo.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/entry/rollback.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/entry/tree.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/entry/upload.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/entry/whoami.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/index/__init__.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/index/hash.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/index/make.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/index/validate.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/operate/__init__.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/operate/base.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/operate/download.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/operate/upload.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/operate/validate.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/repository/__init__.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/repository/base.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/repository/clone.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/repository/rollback.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/utils/__init__.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/utils/archive.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/utils/binary.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/utils/data.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/utils/download.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/utils/irregular_repo.json +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/utils/logging.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/utils/model.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/utils/number.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/utils/path.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/utils/session.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/utils/temp.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/utils/tqdm_.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/utils/type_.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils/utils/walk.py +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils.egg-info/dependency_links.txt +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils.egg-info/entry_points.txt +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils.egg-info/requires.txt +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/hfutils.egg-info/top_level.txt +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/requirements-7z.txt +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/requirements-build.txt +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/requirements-doc.txt +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/requirements-rar.txt +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/requirements-test.txt +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/requirements-transfer.txt +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/requirements.txt +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/setup.cfg +0 -0
- {hfutils-0.4.0 → hfutils-0.4.2}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: hfutils
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Summary: Useful utilities for huggingface
|
|
5
5
|
Home-page: https://github.com/deepghs/hfutils
|
|
6
6
|
Author: narugo1992
|
|
@@ -88,6 +88,7 @@ Requires-Dist: py7zr; extra == "7z"
|
|
|
88
88
|
[](https://github.com/deepghs/hfutils/actions?query=workflow%3A%22Package+Release%22)
|
|
89
89
|
[](https://codecov.io/gh/deepghs/hfutils)
|
|
90
90
|
|
|
91
|
+
[](https://discord.gg/TwdHJ42N72)
|
|
91
92
|

|
|
92
93
|
[](https://github.com/deepghs/hfutils/stargazers)
|
|
93
94
|
[](https://github.com/deepghs/hfutils/network)
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
[](https://github.com/deepghs/hfutils/actions?query=workflow%3A%22Package+Release%22)
|
|
10
10
|
[](https://codecov.io/gh/deepghs/hfutils)
|
|
11
11
|
|
|
12
|
+
[](https://discord.gg/TwdHJ42N72)
|
|
12
13
|

|
|
13
14
|
[](https://github.com/deepghs/hfutils/stargazers)
|
|
14
15
|
[](https://github.com/deepghs/hfutils/network)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from .clone import _add_clone_subcommand
|
|
2
2
|
from .dispatch import hfutilcli
|
|
3
3
|
from .download import _add_download_subcommand
|
|
4
|
+
from .ils import _add_ils_subcommand
|
|
4
5
|
from .index import _add_index_subcommand
|
|
5
6
|
from .ls import _add_ls_subcommand
|
|
6
7
|
from .ls_repo import _add_ls_repo_subcommand
|
|
@@ -19,6 +20,7 @@ _DECORATORS = [
|
|
|
19
20
|
_add_rollback_subcommand,
|
|
20
21
|
_add_clone_subcommand,
|
|
21
22
|
_add_tree_subcommand,
|
|
23
|
+
_add_ils_subcommand,
|
|
22
24
|
]
|
|
23
25
|
|
|
24
26
|
cli = hfutilcli
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module provides functionality for listing files from a HuggingFace repository's index tar file.
|
|
3
|
+
|
|
4
|
+
It includes a command-line interface (CLI) for interacting with HuggingFace repositories,
|
|
5
|
+
specifically for listing and displaying information about files within a repository's
|
|
6
|
+
index tar file. The module offers various options for sorting, filtering, and displaying
|
|
7
|
+
detailed information about the files and the repository itself.
|
|
8
|
+
|
|
9
|
+
Key features:
|
|
10
|
+
|
|
11
|
+
1. List files from a HuggingFace repository's index tar file
|
|
12
|
+
2. Display detailed file information
|
|
13
|
+
3. Show repository and index file statistics
|
|
14
|
+
4. Sort files by different criteria (offset, name, size)
|
|
15
|
+
5. Validate the index file's status (up-to-date or outdated)
|
|
16
|
+
|
|
17
|
+
This module is part of a larger system for interacting with HuggingFace repositories
|
|
18
|
+
and provides a user-friendly interface for exploring the contents of index tar files.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
import os.path
|
|
22
|
+
import statistics
|
|
23
|
+
import warnings
|
|
24
|
+
from typing import Optional, Literal
|
|
25
|
+
|
|
26
|
+
import click
|
|
27
|
+
from hbutils.scale import size_to_bytes_str
|
|
28
|
+
from hbutils.string import plural_word, titleize
|
|
29
|
+
from huggingface_hub import configure_http_backend
|
|
30
|
+
|
|
31
|
+
from .base import CONTEXT_SETTINGS
|
|
32
|
+
from ..index import hf_tar_get_index, hf_tar_validate
|
|
33
|
+
from ..operate.base import REPO_TYPES
|
|
34
|
+
from ..utils import get_requests_session, get_file_type, FileItemType
|
|
35
|
+
from ..utils.path import RepoTypeTyping, hf_normpath
|
|
36
|
+
|
|
37
|
+
_FT_NAME_MAP = {
|
|
38
|
+
FileItemType.IMAGE: 'image',
|
|
39
|
+
FileItemType.ARCHIVE: 'archive/compressed',
|
|
40
|
+
FileItemType.MODEL: 'model',
|
|
41
|
+
FileItemType.DATA: 'data',
|
|
42
|
+
FileItemType.FILE: 'other',
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _add_ils_subcommand(cli: click.Group) -> click.Group:
|
|
47
|
+
"""
|
|
48
|
+
Add the 'ils' subcommand to the given click Group.
|
|
49
|
+
|
|
50
|
+
This function defines and adds the 'ils' (Index List) subcommand to the provided
|
|
51
|
+
click Group. The 'ils' command allows users to list files from a HuggingFace
|
|
52
|
+
repository's index tar file and display various information about the repository
|
|
53
|
+
and its contents.
|
|
54
|
+
|
|
55
|
+
:param cli: The click Group to which the 'ils' subcommand will be added.
|
|
56
|
+
:type cli: click.Group
|
|
57
|
+
|
|
58
|
+
:return: The modified click Group with the 'ils' subcommand added.
|
|
59
|
+
:rtype: click.Group
|
|
60
|
+
|
|
61
|
+
Usage:
|
|
62
|
+
This function is typically called when setting up the CLI for the application.
|
|
63
|
+
It adds the 'ils' command with various options for customizing the output.
|
|
64
|
+
|
|
65
|
+
Example:
|
|
66
|
+
cli = click.Group()
|
|
67
|
+
cli = _add_ils_subcommand(cli)
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
@cli.command('ils', help='List files from HuggingFace repository\'s index tar file.\n\n'
|
|
71
|
+
'Set environment $HF_TOKEN to use your own access token.',
|
|
72
|
+
context_settings=CONTEXT_SETTINGS)
|
|
73
|
+
@click.option('-r', '--repository', 'repo_id', type=str, required=True,
|
|
74
|
+
help='Repository to download from.')
|
|
75
|
+
@click.option('--idx_repository', 'idx_repo_id', type=str, default=None,
|
|
76
|
+
help='Index repository to download from.', show_default=True)
|
|
77
|
+
@click.option('-t', '--type', 'repo_type', type=click.Choice(REPO_TYPES), default='dataset',
|
|
78
|
+
help='Type of the HuggingFace repository.', show_default=True)
|
|
79
|
+
@click.option('-R', '--revision', 'revision', type=str, default='main',
|
|
80
|
+
help='Revision of repository.', show_default=True)
|
|
81
|
+
@click.option('-a', '--archive_file', 'archive_file', type=str, required=True,
|
|
82
|
+
help='Archive file in repository.', show_default=True)
|
|
83
|
+
@click.option('-i', '--idx_file', 'idx_file', type=str, default=None,
|
|
84
|
+
help='', show_default=True)
|
|
85
|
+
@click.option('-l', '--list', 'show_detailed', is_flag=True, type=bool, default=False,
|
|
86
|
+
help='Show detailed file information.', show_default=True)
|
|
87
|
+
@click.option('-s', '--sort_by', 'sort_by', type=click.Choice(['offset', 'name', 'size']), default='offset',
|
|
88
|
+
help='Sort order of files.', show_default=True)
|
|
89
|
+
@click.option('-o', '--order_by', 'order_by', type=click.Choice(['asc', 'desc']), default='asc',
|
|
90
|
+
help='Order of the mentioned sorting.', show_default=True)
|
|
91
|
+
@click.option('-I', '--information', 'show_information', type=bool, is_flag=True, default=False,
|
|
92
|
+
help='Show information of index file.', show_default=True)
|
|
93
|
+
def ls(repo_id: str, idx_repo_id: Optional[str], repo_type: RepoTypeTyping, revision: str,
|
|
94
|
+
show_detailed: bool, show_information: bool,
|
|
95
|
+
sort_by: Literal['offset', 'name', 'size'], order_by: Literal['asc', 'desc'],
|
|
96
|
+
archive_file: str, idx_file: Optional[str] = None):
|
|
97
|
+
"""
|
|
98
|
+
List files from a HuggingFace repository's index tar file.
|
|
99
|
+
|
|
100
|
+
This function retrieves and displays information about files in a HuggingFace
|
|
101
|
+
repository's index tar file. It can show detailed file information, repository
|
|
102
|
+
statistics, and allows for sorting and filtering of the file list.
|
|
103
|
+
|
|
104
|
+
:param repo_id: The ID of the HuggingFace repository.
|
|
105
|
+
:type repo_id: str
|
|
106
|
+
:param idx_repo_id: The ID of the index repository (if different from repo_id).
|
|
107
|
+
:type idx_repo_id: Optional[str]
|
|
108
|
+
:param repo_type: The type of the HuggingFace repository (e.g., 'dataset', 'model').
|
|
109
|
+
:type repo_type: RepoTypeTyping
|
|
110
|
+
:param revision: The revision of the repository to use.
|
|
111
|
+
:type revision: str
|
|
112
|
+
:param show_detailed: Flag to show detailed file information.
|
|
113
|
+
:type show_detailed: bool
|
|
114
|
+
:param show_information: Flag to show general information about the index file.
|
|
115
|
+
:type show_information: bool
|
|
116
|
+
:param sort_by: Criterion to sort the files by ('offset', 'name', or 'size').
|
|
117
|
+
:type sort_by: Literal['offset', 'name', 'size']
|
|
118
|
+
:param order_by: Order of sorting ('asc' or 'desc').
|
|
119
|
+
:type order_by: Literal['asc', 'desc']
|
|
120
|
+
:param archive_file: The name of the archive file in the repository.
|
|
121
|
+
:type archive_file: str
|
|
122
|
+
:param idx_file: The name of the index file (if different from default).
|
|
123
|
+
:type idx_file: Optional[str]
|
|
124
|
+
|
|
125
|
+
:return: None
|
|
126
|
+
|
|
127
|
+
This function performs the following steps:
|
|
128
|
+
|
|
129
|
+
1. Configures the HTTP backend for HuggingFace Hub.
|
|
130
|
+
2. Retrieves the index information for the specified repository and archive.
|
|
131
|
+
3. If show_information is True, displays general statistics about the repository and files.
|
|
132
|
+
4. If not showing information, lists the files according to the specified sorting and filtering options.
|
|
133
|
+
|
|
134
|
+
The function uses click styles to format the output for better readability in the terminal.
|
|
135
|
+
"""
|
|
136
|
+
configure_http_backend(get_requests_session)
|
|
137
|
+
|
|
138
|
+
idx_info = hf_tar_get_index(
|
|
139
|
+
repo_id=repo_id,
|
|
140
|
+
repo_type=repo_type,
|
|
141
|
+
revision=revision,
|
|
142
|
+
archive_in_repo=archive_file,
|
|
143
|
+
|
|
144
|
+
idx_repo_id=idx_repo_id or repo_id,
|
|
145
|
+
idx_repo_type=repo_type,
|
|
146
|
+
idx_revision=revision,
|
|
147
|
+
idx_file_in_repo=idx_file,
|
|
148
|
+
)
|
|
149
|
+
if show_information:
|
|
150
|
+
print('Repo ID: ' + click.style(repo_id, underline=True, fg='blue'))
|
|
151
|
+
if idx_repo_id:
|
|
152
|
+
print('Index Repo ID: ' + click.style(idx_repo_id, underline=True, fg='blue'))
|
|
153
|
+
print('Repo Type: ' + click.style(repo_type, underline=True, fg='blue'))
|
|
154
|
+
print('Revision: ' + click.style(revision, underline=True, fg='blue'))
|
|
155
|
+
print('Archive File: ' + click.style(archive_file, underline=True, fg='blue'))
|
|
156
|
+
if idx_file:
|
|
157
|
+
print('Index File: ' + click.style(idx_file, underline=True, fg='blue'))
|
|
158
|
+
print()
|
|
159
|
+
|
|
160
|
+
print('File Size: ' + click.style(size_to_bytes_str(idx_info['filesize'], precision=3), fg='blue')
|
|
161
|
+
+ ' (' + click.style(plural_word(idx_info['filesize'], "Byte"), underline=True) + ')')
|
|
162
|
+
print('Native Hash: ' + click.style(idx_info['hash'], underline=True))
|
|
163
|
+
print('LFS Hash: ' + click.style(idx_info['hash_lfs'], underline=True))
|
|
164
|
+
print('Files: ' + click.style(plural_word(len(idx_info['files']), 'file'), underline=True, fg='blue'))
|
|
165
|
+
if idx_info['files']:
|
|
166
|
+
d_files = {}
|
|
167
|
+
for file in idx_info['files'].keys():
|
|
168
|
+
type_ = get_file_type(file)
|
|
169
|
+
d_files[type_] = d_files.get(type_, 0) + 1
|
|
170
|
+
for type_, type_name in _FT_NAME_MAP.items():
|
|
171
|
+
if d_files.get(type_, 0) > 0:
|
|
172
|
+
print(f' {titleize(type_name)} Files: '
|
|
173
|
+
+ click.style(plural_word(d_files[type_], "file"), underline=True))
|
|
174
|
+
pass
|
|
175
|
+
|
|
176
|
+
d_exts = {}
|
|
177
|
+
for file in idx_info['files'].keys():
|
|
178
|
+
_, ext = os.path.splitext(file)
|
|
179
|
+
d_exts[ext] = d_exts.get(ext, 0) + 1
|
|
180
|
+
print('File Extensions:')
|
|
181
|
+
for ext, count in sorted(d_exts.items(), key=lambda x: (-x[1], x[0])):
|
|
182
|
+
print(f' {ext or "<none>"} : ' + click.style(plural_word(count, "file"), underline=True))
|
|
183
|
+
|
|
184
|
+
# Convert to numpy array for easier calculations
|
|
185
|
+
file_sizes = [file_info['size'] for file, file_info in idx_info['files'].items()]
|
|
186
|
+
|
|
187
|
+
# Basic statistics
|
|
188
|
+
total_size = sum(file_sizes)
|
|
189
|
+
mean_size = statistics.mean(file_sizes)
|
|
190
|
+
median_size = statistics.median(file_sizes)
|
|
191
|
+
min_size = min(file_sizes)
|
|
192
|
+
max_size = max(file_sizes)
|
|
193
|
+
|
|
194
|
+
# Quartiles
|
|
195
|
+
sorted_sizes = sorted(file_sizes)
|
|
196
|
+
n = len(sorted_sizes)
|
|
197
|
+
q1 = sorted_sizes[n // 4]
|
|
198
|
+
q3 = sorted_sizes[(3 * n) // 4]
|
|
199
|
+
iqr = q3 - q1
|
|
200
|
+
std_dev = statistics.stdev(file_sizes)
|
|
201
|
+
|
|
202
|
+
with warnings.catch_warnings():
|
|
203
|
+
warnings.simplefilter("ignore", UserWarning)
|
|
204
|
+
print(f"Total Size: " +
|
|
205
|
+
click.style(size_to_bytes_str(total_size, precision=3), underline=True, fg='blue'))
|
|
206
|
+
print(f" Average File Size: " +
|
|
207
|
+
click.style(size_to_bytes_str(mean_size, precision=3), underline=True, fg='blue'))
|
|
208
|
+
print(f" Median File Size: " +
|
|
209
|
+
click.style(size_to_bytes_str(median_size, precision=3), underline=True, fg='blue'))
|
|
210
|
+
print(f" Smallest File Size: " +
|
|
211
|
+
click.style(size_to_bytes_str(min_size, precision=3), underline=True))
|
|
212
|
+
print(f" Largest File Size: " +
|
|
213
|
+
click.style(size_to_bytes_str(max_size, precision=3), underline=True))
|
|
214
|
+
print(f" Standard Deviation: " +
|
|
215
|
+
click.style(size_to_bytes_str(std_dev, precision=3), underline=True))
|
|
216
|
+
print("Quartiles:")
|
|
217
|
+
print(f" Q1 (25th Percentile): {size_to_bytes_str(q1, precision=3)}")
|
|
218
|
+
print(f" Q2 (50th Percentile, Median): {size_to_bytes_str(median_size, precision=3)}")
|
|
219
|
+
print(f" Q3 (75th Percentile): {size_to_bytes_str(q3, precision=3)}")
|
|
220
|
+
print(f" Interquartile Range (IQR): {size_to_bytes_str(iqr, precision=3)}")
|
|
221
|
+
print()
|
|
222
|
+
|
|
223
|
+
is_ready = hf_tar_validate(
|
|
224
|
+
repo_id=repo_id,
|
|
225
|
+
repo_type=repo_type,
|
|
226
|
+
revision=revision,
|
|
227
|
+
archive_in_repo=archive_file,
|
|
228
|
+
|
|
229
|
+
idx_repo_id=idx_repo_id or repo_id,
|
|
230
|
+
idx_repo_type=repo_type,
|
|
231
|
+
idx_revision=revision,
|
|
232
|
+
idx_file_in_repo=idx_file,
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
print('Status: ' + (
|
|
236
|
+
click.style('Up-To-Date', fg='green', underline=True) if is_ready else
|
|
237
|
+
click.style('Outdated', fg='yellow', underline=True)
|
|
238
|
+
))
|
|
239
|
+
if not is_ready:
|
|
240
|
+
print('Index file is recommended to get refreshed.')
|
|
241
|
+
|
|
242
|
+
else:
|
|
243
|
+
rows = []
|
|
244
|
+
for file, file_info in sorted(idx_info['files'].items(), key=lambda x: (x[1]['offset'], x[0])):
|
|
245
|
+
rows.append({
|
|
246
|
+
'file': hf_normpath(file),
|
|
247
|
+
'offset': file_info['offset'],
|
|
248
|
+
'size': file_info['size'],
|
|
249
|
+
|
|
250
|
+
't_file': str(file),
|
|
251
|
+
't_offset': str(file_info['offset']),
|
|
252
|
+
't_size': plural_word(file_info['size'], "Byte"),
|
|
253
|
+
't_size_text': size_to_bytes_str(file_info['size'], precision=3),
|
|
254
|
+
't_sha256': file_info['sha256'],
|
|
255
|
+
})
|
|
256
|
+
if sort_by == 'offset':
|
|
257
|
+
rows = sorted(rows, key=lambda x: (x['offset'], x['file']), reverse=(order_by != 'asc'))
|
|
258
|
+
elif sort_by == 'name':
|
|
259
|
+
rows = sorted(rows, key=lambda x: (x['file'], x['offset']), reverse=(order_by != 'asc'))
|
|
260
|
+
elif sort_by == 'size':
|
|
261
|
+
rows = sorted(rows, key=lambda x: (x['size'], x['offset'], x['file']), reverse=(order_by != 'asc'))
|
|
262
|
+
else:
|
|
263
|
+
raise ValueError(f'Unknown sort_by {sort_by!r}.') # pragma: no cover
|
|
264
|
+
|
|
265
|
+
if len(rows):
|
|
266
|
+
if show_detailed:
|
|
267
|
+
max_t_file_len = max(len(row['t_file']) for row in rows)
|
|
268
|
+
max_t_offset_len = max(len(row['t_offset']) for row in rows)
|
|
269
|
+
max_t_size_text_len = max(len(row['t_size_text']) for row in rows)
|
|
270
|
+
max_t_sha256_len = max(len(row['t_sha256']) for row in rows)
|
|
271
|
+
|
|
272
|
+
for row in rows:
|
|
273
|
+
print(' ' * (max_t_offset_len - len(row['t_offset'])) + row['t_offset'], end=' | ')
|
|
274
|
+
fc = get_file_type(row['t_file'])
|
|
275
|
+
print(' ' * (max_t_file_len - len(row['t_file']))
|
|
276
|
+
+ click.style(row['t_file'], fg=fc.render_color), end=' ')
|
|
277
|
+
print(' ' * (max_t_size_text_len - len(row['t_size_text']))
|
|
278
|
+
+ click.style(row['t_size_text'], underline=True), end=' ')
|
|
279
|
+
print(' ' * (max_t_sha256_len - len(row['t_sha256']))
|
|
280
|
+
+ click.style(row['t_sha256']))
|
|
281
|
+
|
|
282
|
+
else:
|
|
283
|
+
for row in rows:
|
|
284
|
+
file = row['file']
|
|
285
|
+
fc = get_file_type(file)
|
|
286
|
+
print(click.style(file, fg=fc.render_color))
|
|
287
|
+
|
|
288
|
+
return cli
|
|
@@ -438,7 +438,7 @@ def hf_tar_file_download(repo_id: str, archive_in_repo: str, file_in_archive: st
|
|
|
438
438
|
idx_repo_type: Optional[RepoTypeTyping] = None, idx_revision: Optional[str] = None,
|
|
439
439
|
proxies: Optional[Dict] = None, user_agent: Union[Dict, str, None] = None,
|
|
440
440
|
headers: Optional[Dict[str, str]] = None, endpoint: Optional[str] = None,
|
|
441
|
-
hf_token: Optional[str] = None):
|
|
441
|
+
force_download: bool = False, hf_token: Optional[str] = None):
|
|
442
442
|
"""
|
|
443
443
|
Download a file from a tar archive file in a Hugging Face repository.
|
|
444
444
|
|
|
@@ -470,6 +470,10 @@ def hf_tar_file_download(repo_id: str, archive_in_repo: str, file_in_archive: st
|
|
|
470
470
|
:type headers: Dict[str, str], optional
|
|
471
471
|
:param endpoint: The Hugging Face API endpoint.
|
|
472
472
|
:type endpoint: str, optional
|
|
473
|
+
:param force_download: Force download the file to destination path.
|
|
474
|
+
Defualt to `False`, downloading will be skipped if the local file
|
|
475
|
+
is fully matched with expected file.
|
|
476
|
+
:type force_download: bool
|
|
473
477
|
:param hf_token: The Hugging Face access token.
|
|
474
478
|
:type hf_token: str, optional
|
|
475
479
|
:raises FileNotFoundError: Raise this when file not exist in tar archive.
|
|
@@ -533,6 +537,13 @@ def hf_tar_file_download(repo_id: str, archive_in_repo: str, file_in_archive: st
|
|
|
533
537
|
end_bytes = info['offset'] + info['size'] - 1
|
|
534
538
|
headers['Range'] = f'bytes={start_bytes}-{end_bytes}'
|
|
535
539
|
|
|
540
|
+
if not force_download and os.path.exists(local_file) and \
|
|
541
|
+
os.path.isfile(local_file) and os.path.getsize(local_file) == info['size']:
|
|
542
|
+
_expected_sha256 = info.get('sha256')
|
|
543
|
+
if not _expected_sha256 or _f_sha256(local_file) == _expected_sha256:
|
|
544
|
+
# file already ready, no need to download it again
|
|
545
|
+
return
|
|
546
|
+
|
|
536
547
|
if os.path.dirname(local_file):
|
|
537
548
|
os.makedirs(os.path.dirname(local_file), exist_ok=True)
|
|
538
549
|
try:
|
|
@@ -171,7 +171,7 @@ def tar_file_size(archive_file: str, file_in_archive: str, idx_file: Optional[st
|
|
|
171
171
|
|
|
172
172
|
|
|
173
173
|
def tar_file_download(archive_file: str, file_in_archive: str, local_file: str,
|
|
174
|
-
idx_file: Optional[str] = None, chunk_size: int = 1 << 20):
|
|
174
|
+
idx_file: Optional[str] = None, chunk_size: int = 1 << 20, force_download: bool = False):
|
|
175
175
|
"""
|
|
176
176
|
Extract and download a specific file from the tar archive to a local file.
|
|
177
177
|
|
|
@@ -190,6 +190,10 @@ def tar_file_download(archive_file: str, file_in_archive: str, local_file: str,
|
|
|
190
190
|
:type idx_file: Optional[str]
|
|
191
191
|
:param chunk_size: The size of chunks to read and write, in bytes. Default is 1MB.
|
|
192
192
|
:type chunk_size: int
|
|
193
|
+
:param force_download: Force download the file to destination path.
|
|
194
|
+
Defualt to `False`, downloading will be skipped if the local file
|
|
195
|
+
is fully matched with expected file.
|
|
196
|
+
:type force_download: bool
|
|
193
197
|
|
|
194
198
|
:raises FileNotFoundError: If the specified file is not found in the archive.
|
|
195
199
|
:raises ArchiveStandaloneFileIncompleteDownload: If the downloaded file size doesn't match the expected size.
|
|
@@ -212,6 +216,13 @@ def tar_file_download(archive_file: str, file_in_archive: str, local_file: str,
|
|
|
212
216
|
|
|
213
217
|
info = files[_n_path(file_in_archive)]
|
|
214
218
|
|
|
219
|
+
if not force_download and os.path.exists(local_file) and \
|
|
220
|
+
os.path.isfile(local_file) and os.path.getsize(local_file) == info['size']:
|
|
221
|
+
_expected_sha256 = info.get('sha256')
|
|
222
|
+
if not _expected_sha256 or _f_sha256(local_file) == _expected_sha256:
|
|
223
|
+
# file already ready, no need to download it again
|
|
224
|
+
return
|
|
225
|
+
|
|
215
226
|
if os.path.dirname(local_file):
|
|
216
227
|
os.makedirs(os.path.dirname(local_file), exist_ok=True)
|
|
217
228
|
try:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: hfutils
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Summary: Useful utilities for huggingface
|
|
5
5
|
Home-page: https://github.com/deepghs/hfutils
|
|
6
6
|
Author: narugo1992
|
|
@@ -88,6 +88,7 @@ Requires-Dist: py7zr; extra == "7z"
|
|
|
88
88
|
[](https://github.com/deepghs/hfutils/actions?query=workflow%3A%22Package+Release%22)
|
|
89
89
|
[](https://codecov.io/gh/deepghs/hfutils)
|
|
90
90
|
|
|
91
|
+
[](https://discord.gg/TwdHJ42N72)
|
|
91
92
|

|
|
92
93
|
[](https://github.com/deepghs/hfutils/stargazers)
|
|
93
94
|
[](https://github.com/deepghs/hfutils/network)
|
|
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
|
|
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
|