hfutils 0.3.6__tar.gz → 0.3.8__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.3.6/hfutils.egg-info → hfutils-0.3.8}/PKG-INFO +24 -23
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/config/meta.py +1 -1
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/entry/download.py +10 -1
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/entry/index.py +5 -1
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/entry/ls.py +4 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/entry/ls_repo.py +4 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/entry/upload.py +4 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/entry/whoami.py +4 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/index/__init__.py +2 -1
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/index/make.py +59 -1
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/operate/download.py +4 -1
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/operate/validate.py +11 -3
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/utils/__init__.py +1 -0
- hfutils-0.3.8/hfutils/utils/session.py +115 -0
- {hfutils-0.3.6 → hfutils-0.3.8/hfutils.egg-info}/PKG-INFO +24 -23
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils.egg-info/SOURCES.txt +1 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils.egg-info/requires.txt +1 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/requirements.txt +2 -1
- {hfutils-0.3.6 → hfutils-0.3.8}/LICENSE +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/MANIFEST.in +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/README.md +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/__init__.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/__main__.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/archive/__init__.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/archive/base.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/archive/rar.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/archive/sevenz.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/archive/tar.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/archive/zip.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/cache/__init__.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/cache/delete.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/config/__init__.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/entry/__init__.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/entry/base.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/entry/cli.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/entry/clone.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/entry/dispatch.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/entry/rollback.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/index/fetch.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/index/hash.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/index/local_fetch.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/index/validate.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/operate/__init__.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/operate/base.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/operate/upload.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/repository/__init__.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/repository/base.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/repository/clone.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/repository/rollback.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/utils/binary.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/utils/download.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/utils/irregular_repo.json +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/utils/logging.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/utils/number.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/utils/path.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/utils/temp.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/utils/tqdm_.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils/utils/walk.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils.egg-info/dependency_links.txt +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils.egg-info/entry_points.txt +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/hfutils.egg-info/top_level.txt +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/requirements-7z.txt +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/requirements-build.txt +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/requirements-doc.txt +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/requirements-rar.txt +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/requirements-test.txt +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/requirements-transfer.txt +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/setup.cfg +0 -0
- {hfutils-0.3.6 → hfutils-0.3.8}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: hfutils
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.8
|
|
4
4
|
Summary: Useful utilities for huggingface
|
|
5
5
|
Home-page: https://github.com/deepghs/hfutils
|
|
6
6
|
Author: narugo1992
|
|
@@ -29,6 +29,29 @@ Requires-Dist: tzlocal
|
|
|
29
29
|
Requires-Dist: natsort
|
|
30
30
|
Requires-Dist: urlobject
|
|
31
31
|
Requires-Dist: fsspec>=2024
|
|
32
|
+
Requires-Dist: random_user_agent
|
|
33
|
+
Provides-Extra: test
|
|
34
|
+
Requires-Dist: coverage>=5; extra == "test"
|
|
35
|
+
Requires-Dist: mock>=4.0.3; extra == "test"
|
|
36
|
+
Requires-Dist: flake8~=3.5; extra == "test"
|
|
37
|
+
Requires-Dist: testfixtures>=6.18.5; extra == "test"
|
|
38
|
+
Requires-Dist: pytest~=6.2.5; extra == "test"
|
|
39
|
+
Requires-Dist: pytest-cov~=3.0.0; extra == "test"
|
|
40
|
+
Requires-Dist: pytest-mock~=3.6.1; extra == "test"
|
|
41
|
+
Requires-Dist: pytest-xdist>=1.34.0; extra == "test"
|
|
42
|
+
Requires-Dist: pytest-rerunfailures~=10.2; extra == "test"
|
|
43
|
+
Requires-Dist: pytest-timeout~=2.0.2; extra == "test"
|
|
44
|
+
Requires-Dist: pytest-benchmark~=3.4.0; extra == "test"
|
|
45
|
+
Requires-Dist: easydict<2,>=1.7; extra == "test"
|
|
46
|
+
Requires-Dist: testtools>=2; extra == "test"
|
|
47
|
+
Requires-Dist: where>=1.0.2; extra == "test"
|
|
48
|
+
Requires-Dist: responses>=0.20.0; extra == "test"
|
|
49
|
+
Requires-Dist: natsort; extra == "test"
|
|
50
|
+
Provides-Extra: rar
|
|
51
|
+
Requires-Dist: rarfile; extra == "rar"
|
|
52
|
+
Provides-Extra: build
|
|
53
|
+
Requires-Dist: pyinstaller<5,>=4.7; extra == "build"
|
|
54
|
+
Requires-Dist: setuptools<70; extra == "build"
|
|
32
55
|
Provides-Extra: doc
|
|
33
56
|
Requires-Dist: Jinja2>=3.0.0; extra == "doc"
|
|
34
57
|
Requires-Dist: sphinx>=3.2.0; extra == "doc"
|
|
@@ -49,32 +72,10 @@ Requires-Dist: ipykernel>=6.15; extra == "doc"
|
|
|
49
72
|
Requires-Dist: py-cpuinfo>=8.0.0; extra == "doc"
|
|
50
73
|
Requires-Dist: click>=7.0.0; extra == "doc"
|
|
51
74
|
Requires-Dist: pandas; extra == "doc"
|
|
52
|
-
Provides-Extra: test
|
|
53
|
-
Requires-Dist: coverage>=5; extra == "test"
|
|
54
|
-
Requires-Dist: mock>=4.0.3; extra == "test"
|
|
55
|
-
Requires-Dist: flake8~=3.5; extra == "test"
|
|
56
|
-
Requires-Dist: testfixtures>=6.18.5; extra == "test"
|
|
57
|
-
Requires-Dist: pytest~=6.2.5; extra == "test"
|
|
58
|
-
Requires-Dist: pytest-cov~=3.0.0; extra == "test"
|
|
59
|
-
Requires-Dist: pytest-mock~=3.6.1; extra == "test"
|
|
60
|
-
Requires-Dist: pytest-xdist>=1.34.0; extra == "test"
|
|
61
|
-
Requires-Dist: pytest-rerunfailures~=10.2; extra == "test"
|
|
62
|
-
Requires-Dist: pytest-timeout~=2.0.2; extra == "test"
|
|
63
|
-
Requires-Dist: pytest-benchmark~=3.4.0; extra == "test"
|
|
64
|
-
Requires-Dist: easydict<2,>=1.7; extra == "test"
|
|
65
|
-
Requires-Dist: testtools>=2; extra == "test"
|
|
66
|
-
Requires-Dist: where>=1.0.2; extra == "test"
|
|
67
|
-
Requires-Dist: responses>=0.20.0; extra == "test"
|
|
68
|
-
Requires-Dist: natsort; extra == "test"
|
|
69
75
|
Provides-Extra: transfer
|
|
70
76
|
Requires-Dist: hf-transfer; extra == "transfer"
|
|
71
77
|
Provides-Extra: 7z
|
|
72
78
|
Requires-Dist: py7zr; extra == "7z"
|
|
73
|
-
Provides-Extra: build
|
|
74
|
-
Requires-Dist: pyinstaller<5,>=4.7; extra == "build"
|
|
75
|
-
Requires-Dist: setuptools<70; extra == "build"
|
|
76
|
-
Provides-Extra: rar
|
|
77
|
-
Requires-Dist: rarfile; extra == "rar"
|
|
78
79
|
|
|
79
80
|
# hfutils
|
|
80
81
|
|
|
@@ -3,10 +3,12 @@ import warnings
|
|
|
3
3
|
from typing import Optional
|
|
4
4
|
|
|
5
5
|
import click
|
|
6
|
+
from huggingface_hub import configure_http_backend
|
|
6
7
|
|
|
7
8
|
from .base import CONTEXT_SETTINGS, command_wrap, ClickErrorException
|
|
8
9
|
from ..operate import download_file_to_file, download_archive_as_directory, download_directory_as_directory
|
|
9
10
|
from ..operate.base import REPO_TYPES, RepoTypeTyping
|
|
11
|
+
from ..utils import get_requests_session
|
|
10
12
|
|
|
11
13
|
|
|
12
14
|
class NoRemotePathAssignedWithDownload(ClickErrorException):
|
|
@@ -49,6 +51,8 @@ def _add_download_subcommand(cli: click.Group) -> click.Group:
|
|
|
49
51
|
help='Password for the archive file. Only applied when -a is used.', show_default=True)
|
|
50
52
|
@click.option('-w', '--wildcard', 'wildcard', type=str, default=None,
|
|
51
53
|
help='Wildcard for files to download. Only applied when -d is used.', show_default=True)
|
|
54
|
+
@click.option('-s', '--soft_mode_when_check', 'soft_mode_when_check', is_flag=True, type=bool, default=False,
|
|
55
|
+
help='Just check the file size when validating the downloaded files.', show_default=True)
|
|
52
56
|
@click.option('--tmpdir', 'tmpdir', type=str, default=None,
|
|
53
57
|
help='Use custom temporary Directory.', show_default=True)
|
|
54
58
|
@command_wrap()
|
|
@@ -56,7 +60,7 @@ def _add_download_subcommand(cli: click.Group) -> click.Group:
|
|
|
56
60
|
repo_id: str, repo_type: RepoTypeTyping,
|
|
57
61
|
file_in_repo: Optional[str], archive_in_repo: Optional[str], dir_in_repo: Optional[str],
|
|
58
62
|
output_path: str, revision: str, max_workers: int,
|
|
59
|
-
password: Optional[str], wildcard: Optional[str], tmpdir: Optional[str]
|
|
63
|
+
password: Optional[str], wildcard: Optional[str], soft_mode_when_check: bool, tmpdir: Optional[str]
|
|
60
64
|
):
|
|
61
65
|
"""
|
|
62
66
|
Download data from HuggingFace repositories.
|
|
@@ -81,9 +85,13 @@ def _add_download_subcommand(cli: click.Group) -> click.Group:
|
|
|
81
85
|
:type password: str, optional
|
|
82
86
|
:param wildcard: Wildcard for files to download. Only applied when -d is used.
|
|
83
87
|
:type password: str, optional
|
|
88
|
+
:param soft_mode_when_check: Just check the size of the expected file when enabled. Default is False.
|
|
89
|
+
:type soft_mode_when_check: bool
|
|
84
90
|
:param tmpdir: Use custom temporary Directory.
|
|
85
91
|
:type tmpdir: str, optional
|
|
86
92
|
"""
|
|
93
|
+
configure_http_backend(get_requests_session)
|
|
94
|
+
|
|
87
95
|
if tmpdir:
|
|
88
96
|
os.environ['TMPDIR'] = tmpdir
|
|
89
97
|
|
|
@@ -126,6 +134,7 @@ def _add_download_subcommand(cli: click.Group) -> click.Group:
|
|
|
126
134
|
revision=revision,
|
|
127
135
|
silent=False,
|
|
128
136
|
max_workers=max_workers,
|
|
137
|
+
soft_mode_when_check=soft_mode_when_check,
|
|
129
138
|
)
|
|
130
139
|
|
|
131
140
|
else:
|
|
@@ -18,13 +18,15 @@ from typing import Optional
|
|
|
18
18
|
|
|
19
19
|
import click
|
|
20
20
|
from hbutils.string import plural_word
|
|
21
|
+
from huggingface_hub import configure_http_backend
|
|
21
22
|
|
|
22
23
|
from .base import CONTEXT_SETTINGS
|
|
23
24
|
from ..cache import delete_detached_cache
|
|
24
25
|
from ..index import hf_tar_validate, tar_create_index
|
|
25
26
|
from ..operate import get_hf_fs, download_file_to_file, upload_directory_as_directory
|
|
26
27
|
from ..operate.base import REPO_TYPES, RepoTypeTyping, get_hf_client
|
|
27
|
-
from ..utils import tqdm, hf_fs_path, parse_hf_fs_path, TemporaryDirectory, hf_normpath, ColoredFormatter
|
|
28
|
+
from ..utils import tqdm, hf_fs_path, parse_hf_fs_path, TemporaryDirectory, hf_normpath, ColoredFormatter, \
|
|
29
|
+
get_requests_session
|
|
28
30
|
|
|
29
31
|
|
|
30
32
|
def _add_index_subcommand(cli: click.Group) -> click.Group:
|
|
@@ -86,6 +88,8 @@ def _add_index_subcommand(cli: click.Group) -> click.Group:
|
|
|
86
88
|
This function is typically invoked through the CLI interface, like:
|
|
87
89
|
$ python script.py index -r my_repo -x my_index_repo -t dataset -R main --min_upload_interval 120
|
|
88
90
|
"""
|
|
91
|
+
configure_http_backend(get_requests_session)
|
|
92
|
+
|
|
89
93
|
logger = logging.getLogger()
|
|
90
94
|
logger.setLevel(logging.INFO)
|
|
91
95
|
console_handler = logging.StreamHandler()
|
|
@@ -5,10 +5,12 @@ from typing import Union, List
|
|
|
5
5
|
|
|
6
6
|
import click
|
|
7
7
|
import tzlocal
|
|
8
|
+
from huggingface_hub import configure_http_backend
|
|
8
9
|
from huggingface_hub.hf_api import RepoFolder, RepoFile
|
|
9
10
|
|
|
10
11
|
from .base import CONTEXT_SETTINGS
|
|
11
12
|
from ..operate.base import REPO_TYPES, get_hf_client
|
|
13
|
+
from ..utils import get_requests_session
|
|
12
14
|
|
|
13
15
|
mimetypes.add_type('image/webp', '.webp')
|
|
14
16
|
|
|
@@ -124,6 +126,8 @@ def _add_ls_subcommand(cli: click.Group) -> click.Group:
|
|
|
124
126
|
:param show_detailed: Flag to indicate whether to show detailed file information.
|
|
125
127
|
:type show_detailed: bool
|
|
126
128
|
"""
|
|
129
|
+
configure_http_backend(get_requests_session)
|
|
130
|
+
|
|
127
131
|
hf_client = get_hf_client()
|
|
128
132
|
items: List[ListItem] = []
|
|
129
133
|
for item in hf_client.list_repo_tree(
|
|
@@ -2,10 +2,12 @@ import fnmatch
|
|
|
2
2
|
from typing import Optional
|
|
3
3
|
|
|
4
4
|
import click
|
|
5
|
+
from huggingface_hub import configure_http_backend
|
|
5
6
|
from huggingface_hub.utils import LocalTokenNotFoundError
|
|
6
7
|
|
|
7
8
|
from .base import CONTEXT_SETTINGS, ClickErrorException
|
|
8
9
|
from ..operate.base import REPO_TYPES, get_hf_client
|
|
10
|
+
from ..utils import get_requests_session
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
class NoLocalAuthentication(ClickErrorException):
|
|
@@ -46,6 +48,8 @@ def _add_ls_repo_subcommand(cli: click.Group) -> click.Group:
|
|
|
46
48
|
:param pattern: Pattern of the repository names.
|
|
47
49
|
:type pattern: str
|
|
48
50
|
"""
|
|
51
|
+
configure_http_backend(get_requests_session)
|
|
52
|
+
|
|
49
53
|
hf_client = get_hf_client()
|
|
50
54
|
if not author:
|
|
51
55
|
try:
|
|
@@ -2,10 +2,12 @@ import warnings
|
|
|
2
2
|
from typing import Optional
|
|
3
3
|
|
|
4
4
|
import click
|
|
5
|
+
from huggingface_hub import configure_http_backend
|
|
5
6
|
|
|
6
7
|
from .base import CONTEXT_SETTINGS, command_wrap, ClickErrorException
|
|
7
8
|
from ..operate import upload_file_to_file, upload_directory_as_archive, upload_directory_as_directory
|
|
8
9
|
from ..operate.base import REPO_TYPES, RepoTypeTyping, get_hf_client
|
|
10
|
+
from ..utils import get_requests_session
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
class NoRemotePathAssignedWithUpload(ClickErrorException):
|
|
@@ -78,6 +80,8 @@ def _add_upload_subcommand(cli: click.Group) -> click.Group:
|
|
|
78
80
|
:param public: Set public repository when created.
|
|
79
81
|
:type public: bool
|
|
80
82
|
"""
|
|
83
|
+
configure_http_backend(get_requests_session)
|
|
84
|
+
|
|
81
85
|
if not file_in_repo and not archive_in_repo and not dir_in_repo:
|
|
82
86
|
raise NoRemotePathAssignedWithUpload('No remote path in repository assigned.\n'
|
|
83
87
|
'One of the -f, -a, or -d option is required.')
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import click
|
|
2
2
|
from hbutils.string import plural_word
|
|
3
|
+
from huggingface_hub import configure_http_backend
|
|
3
4
|
from huggingface_hub.utils import LocalTokenNotFoundError
|
|
4
5
|
|
|
5
6
|
from .base import CONTEXT_SETTINGS
|
|
6
7
|
from ..operate.base import get_hf_client
|
|
8
|
+
from ..utils import get_requests_session
|
|
7
9
|
|
|
8
10
|
|
|
9
11
|
def _add_whoami_subcommand(cli: click.Group) -> click.Group:
|
|
@@ -28,6 +30,8 @@ def _add_whoami_subcommand(cli: click.Group) -> click.Group:
|
|
|
28
30
|
This function retrieves the current user's identification from the Hugging Face Hub API and displays it.
|
|
29
31
|
|
|
30
32
|
"""
|
|
33
|
+
configure_http_backend(get_requests_session)
|
|
34
|
+
|
|
31
35
|
hf_client = get_hf_client()
|
|
32
36
|
try:
|
|
33
37
|
info = hf_client.whoami()
|
|
@@ -1,5 +1,6 @@
|
|
|
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, hf_tar_file_size, hf_tar_file_info
|
|
3
3
|
from .local_fetch import tar_get_index, tar_file_info, tar_file_download, tar_file_size, tar_file_exists, tar_list_files
|
|
4
|
-
from .make import tar_create_index, hf_tar_create_index, tar_get_index_info, hf_tar_create_from_directory
|
|
4
|
+
from .make import tar_create_index, hf_tar_create_index, tar_get_index_info, hf_tar_create_from_directory, \
|
|
5
|
+
tar_create_index_for_directory
|
|
5
6
|
from .validate import hf_tar_item_validate, hf_tar_validate
|
|
@@ -1,3 +1,22 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module provides functionalities for handling and indexing TAR archive files, especially for use with
|
|
3
|
+
the Hugging Face ecosystem. It includes functions to create and retrieve index information of TAR archives,
|
|
4
|
+
which is crucial for efficient data retrieval and management in large datasets. The module also integrates
|
|
5
|
+
with Hugging Face's repository system, allowing for operations like uploading and downloading TAR files
|
|
6
|
+
and their indices.
|
|
7
|
+
|
|
8
|
+
Key functionalities include:
|
|
9
|
+
|
|
10
|
+
- Extracting index information from TAR files.
|
|
11
|
+
- Creating index files for TAR archives locally or in a directory.
|
|
12
|
+
- Integrating with Hugging Face repositories to manage TAR archives and their indices.
|
|
13
|
+
|
|
14
|
+
The module utilizes cryptographic hash functions for data integrity checks and supports operations on both local
|
|
15
|
+
and remote repositories. It is designed to work seamlessly with the Hugging Face platform, enabling users to
|
|
16
|
+
handle large datasets efficiently.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import glob
|
|
1
20
|
import json
|
|
2
21
|
import logging
|
|
3
22
|
import os
|
|
@@ -47,7 +66,7 @@ def tar_get_index_info(src_tar_file, chunk_for_hash: int = 1 << 20, with_hash: b
|
|
|
47
66
|
logging.info(f'Indexing tar file {src_tar_file!r} ...')
|
|
48
67
|
files = {}
|
|
49
68
|
with tarfile.open(src_tar_file, mode='r|') as tar:
|
|
50
|
-
for tarinfo in tqdm(tar, desc='Indexing tar file ...', silent=silent):
|
|
69
|
+
for tarinfo in tqdm(tar, desc=f'Indexing tar file {src_tar_file!r} ...', silent=silent):
|
|
51
70
|
tarinfo: tarfile.TarInfo
|
|
52
71
|
if tarinfo.isreg():
|
|
53
72
|
info = {
|
|
@@ -90,11 +109,50 @@ def tar_create_index(src_tar_file, dst_index_file: Optional[str] = None,
|
|
|
90
109
|
"""
|
|
91
110
|
body, _ = os.path.splitext(src_tar_file)
|
|
92
111
|
dst_index_file = dst_index_file or f'{body}.json'
|
|
112
|
+
if os.path.dirname(dst_index_file):
|
|
113
|
+
os.makedirs(os.path.dirname(dst_index_file), exist_ok=True)
|
|
93
114
|
with open(dst_index_file, 'w') as f:
|
|
94
115
|
json.dump(tar_get_index_info(src_tar_file, chunk_for_hash, with_hash, silent), f)
|
|
95
116
|
return dst_index_file
|
|
96
117
|
|
|
97
118
|
|
|
119
|
+
def tar_create_index_for_directory(src_tar_directory: str, dst_index_directory: Optional[str] = None,
|
|
120
|
+
chunk_for_hash: int = 1 << 20, with_hash: bool = True, silent: bool = False):
|
|
121
|
+
"""
|
|
122
|
+
Create index files for all tar archives in a specified directory.
|
|
123
|
+
|
|
124
|
+
This function scans through the given directory to find all tar files, generates an index for each,
|
|
125
|
+
and saves these indices to the specified destination directory. If no destination directory is provided,
|
|
126
|
+
indices are saved in the same directory as the tar files.
|
|
127
|
+
|
|
128
|
+
:param src_tar_directory: The path to the directory containing tar files.
|
|
129
|
+
:type src_tar_directory: str
|
|
130
|
+
:param dst_index_directory: The path to the directory where index files will be saved, defaults to the same as src_tar_directory.
|
|
131
|
+
:type dst_index_directory: str, optional
|
|
132
|
+
:param chunk_for_hash: The chunk size for hashing, defaults to 1 << 20 (1 MB).
|
|
133
|
+
:type chunk_for_hash: int, optional
|
|
134
|
+
:param with_hash: Whether to include file hashes in the index, defaults to True.
|
|
135
|
+
:type with_hash: bool, optional
|
|
136
|
+
:param silent: Whether to suppress progress bars and logging messages, defaults to False.
|
|
137
|
+
:type silent: bool, optional
|
|
138
|
+
:return: The path to the directory where index files are saved.
|
|
139
|
+
:rtype: str
|
|
140
|
+
"""
|
|
141
|
+
dst_index_directory = dst_index_directory or src_tar_directory
|
|
142
|
+
for tar_file in tqdm(glob.glob(os.path.join(src_tar_directory, '**', '*.tar'), recursive=True), silent=silent):
|
|
143
|
+
p_idx_file = os.path.join(dst_index_directory, os.path.relpath(tar_file, src_tar_directory))
|
|
144
|
+
idx_body, _ = os.path.splitext(p_idx_file)
|
|
145
|
+
idx_file = f'{idx_body}.json'
|
|
146
|
+
tar_create_index(
|
|
147
|
+
src_tar_file=tar_file,
|
|
148
|
+
dst_index_file=idx_file,
|
|
149
|
+
chunk_for_hash=chunk_for_hash,
|
|
150
|
+
with_hash=with_hash,
|
|
151
|
+
silent=silent,
|
|
152
|
+
)
|
|
153
|
+
return dst_index_directory
|
|
154
|
+
|
|
155
|
+
|
|
98
156
|
def hf_tar_create_index(repo_id: str, archive_in_repo: str,
|
|
99
157
|
repo_type: RepoTypeTyping = 'dataset', revision: str = 'main',
|
|
100
158
|
idx_repo_id: Optional[str] = None, idx_file_in_repo: Optional[str] = None,
|
|
@@ -85,7 +85,7 @@ def download_directory_as_directory(
|
|
|
85
85
|
repo_type: RepoTypeTyping = 'dataset', revision: str = 'main',
|
|
86
86
|
silent: bool = False, ignore_patterns: List[str] = _IGNORE_PATTERN_UNSET,
|
|
87
87
|
resume_download: bool = True, max_workers: int = 8, max_retries: int = 5,
|
|
88
|
-
hf_token: Optional[str] = None
|
|
88
|
+
soft_mode_when_check: bool = False, hf_token: Optional[str] = None
|
|
89
89
|
):
|
|
90
90
|
"""
|
|
91
91
|
Download all files in a directory from a Hugging Face repository to a local directory.
|
|
@@ -112,6 +112,8 @@ def download_directory_as_directory(
|
|
|
112
112
|
:type max_retries: int
|
|
113
113
|
:param resume_download: Resume the existing download.
|
|
114
114
|
:type resume_download: bool
|
|
115
|
+
:param soft_mode_when_check: Just check the size of the expected file when enabled. Default is False.
|
|
116
|
+
:type soft_mode_when_check: bool
|
|
115
117
|
:param hf_token: Huggingface token for API client, use ``HF_TOKEN`` variable if not assigned.
|
|
116
118
|
:type hf_token: str, optional
|
|
117
119
|
"""
|
|
@@ -138,6 +140,7 @@ def download_directory_as_directory(
|
|
|
138
140
|
file_in_repo=file_in_repo,
|
|
139
141
|
revision=revision,
|
|
140
142
|
hf_token=hf_token,
|
|
143
|
+
soft_mode=soft_mode_when_check,
|
|
141
144
|
):
|
|
142
145
|
logging.info(f'Local file {rel_file} is ready, download skipped.')
|
|
143
146
|
else:
|
|
@@ -9,7 +9,8 @@ from huggingface_hub.utils import EntryNotFoundError
|
|
|
9
9
|
from .base import RepoTypeTyping, get_hf_client
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
def _raw_check_local_file(repo_file: RepoFile, local_file: str, chunk_for_hash: int = 1 << 20
|
|
12
|
+
def _raw_check_local_file(repo_file: RepoFile, local_file: str, chunk_for_hash: int = 1 << 20,
|
|
13
|
+
soft_mode: bool = False) -> bool:
|
|
13
14
|
"""
|
|
14
15
|
Checks if the local file matches the file on the Hugging Face Hub repository.
|
|
15
16
|
|
|
@@ -19,6 +20,8 @@ def _raw_check_local_file(repo_file: RepoFile, local_file: str, chunk_for_hash:
|
|
|
19
20
|
:type local_file: str
|
|
20
21
|
:param chunk_for_hash: The chunk size for calculating the hash. Default is 1 << 20.
|
|
21
22
|
:type chunk_for_hash: int
|
|
23
|
+
:param soft_mode: Just check the size of the expected file when enabled. Default is False.
|
|
24
|
+
:type soft_mode: bool
|
|
22
25
|
:return: True if the local file matches the file on the repository, False otherwise.
|
|
23
26
|
:rtype: bool
|
|
24
27
|
"""
|
|
@@ -28,6 +31,9 @@ def _raw_check_local_file(repo_file: RepoFile, local_file: str, chunk_for_hash:
|
|
|
28
31
|
f'the remote file {repo_file.path!r} ({repo_file.size}).')
|
|
29
32
|
return False
|
|
30
33
|
|
|
34
|
+
if soft_mode:
|
|
35
|
+
return True
|
|
36
|
+
|
|
31
37
|
if repo_file.lfs:
|
|
32
38
|
sha = sha256()
|
|
33
39
|
expected_hash = repo_file.lfs.sha256
|
|
@@ -54,7 +60,7 @@ def _raw_check_local_file(repo_file: RepoFile, local_file: str, chunk_for_hash:
|
|
|
54
60
|
|
|
55
61
|
def is_local_file_ready(local_file: str, repo_id: str, file_in_repo: str,
|
|
56
62
|
repo_type: RepoTypeTyping = 'dataset', revision: str = 'main',
|
|
57
|
-
hf_token: Optional[str] = None) -> bool:
|
|
63
|
+
soft_mode: bool = False, hf_token: Optional[str] = None) -> bool:
|
|
58
64
|
"""
|
|
59
65
|
Checks if the local file is ready by comparing it with the file on the Hugging Face Hub repository.
|
|
60
66
|
|
|
@@ -68,6 +74,8 @@ def is_local_file_ready(local_file: str, repo_id: str, file_in_repo: str,
|
|
|
68
74
|
:type repo_type: RepoTypeTyping
|
|
69
75
|
:param revision: The revision of the repository. Default is 'main'.
|
|
70
76
|
:type revision: str
|
|
77
|
+
:param soft_mode: Just check the size of the expected file when enabled. Default is False.
|
|
78
|
+
:type soft_mode: bool
|
|
71
79
|
:param hf_token: The Hugging Face API token. Default is None.
|
|
72
80
|
:type hf_token: Optional[str]
|
|
73
81
|
:return: True if the local file matches the file on the repository, False otherwise.
|
|
@@ -83,6 +91,6 @@ def is_local_file_ready(local_file: str, repo_id: str, file_in_repo: str,
|
|
|
83
91
|
if len(infos) == 0:
|
|
84
92
|
raise EntryNotFoundError(f'Entry {repo_type}s/{repo_id}/{file_in_repo} not found.')
|
|
85
93
|
elif len(infos) == 1:
|
|
86
|
-
return _raw_check_local_file(infos[0], local_file)
|
|
94
|
+
return _raw_check_local_file(infos[0], local_file, soft_mode=soft_mode)
|
|
87
95
|
else:
|
|
88
96
|
assert False, f'Should not reach here, multiple files with the same name found - {infos!r}' # pragma: no cover
|
|
@@ -3,6 +3,7 @@ from .download import download_file
|
|
|
3
3
|
from .logging import ColoredFormatter
|
|
4
4
|
from .number import number_to_tag
|
|
5
5
|
from .path import hf_normpath, hf_fs_path, parse_hf_fs_path, HfFileSystemPath
|
|
6
|
+
from .session import TimeoutHTTPAdapter, get_requests_session, get_random_ua
|
|
6
7
|
from .temp import TemporaryDirectory
|
|
7
8
|
from .tqdm_ import tqdm
|
|
8
9
|
from .walk import walk_files
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module provides functionality for creating and managing HTTP sessions with customizable retry logic,
|
|
3
|
+
timeout settings, and user-agent rotation using random user-agent generation. It is designed to help with
|
|
4
|
+
robust web scraping and API consumption by handling common HTTP errors and timeouts gracefully.
|
|
5
|
+
|
|
6
|
+
Main Features:
|
|
7
|
+
|
|
8
|
+
- Automatic retries on specified HTTP response status codes.
|
|
9
|
+
- Configurable request timeout.
|
|
10
|
+
- Rotating user-agent for each session to mimic different browsers and operating systems.
|
|
11
|
+
- Optional SSL verification.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from functools import lru_cache
|
|
15
|
+
from typing import Optional, Dict
|
|
16
|
+
|
|
17
|
+
import requests
|
|
18
|
+
from random_user_agent.params import SoftwareName, OperatingSystem
|
|
19
|
+
from random_user_agent.user_agent import UserAgent
|
|
20
|
+
from requests.adapters import HTTPAdapter, Retry
|
|
21
|
+
|
|
22
|
+
DEFAULT_TIMEOUT = 15 # seconds
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class TimeoutHTTPAdapter(HTTPAdapter):
|
|
26
|
+
"""
|
|
27
|
+
A custom HTTPAdapter that enforces a default timeout on all requests.
|
|
28
|
+
|
|
29
|
+
:param args: Variable length argument list for HTTPAdapter.
|
|
30
|
+
:param kwargs: Arbitrary keyword arguments. 'timeout' can be specified to set a custom timeout.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(self, *args, **kwargs):
|
|
34
|
+
self.timeout = DEFAULT_TIMEOUT
|
|
35
|
+
if "timeout" in kwargs:
|
|
36
|
+
self.timeout = kwargs["timeout"]
|
|
37
|
+
del kwargs["timeout"]
|
|
38
|
+
super().__init__(*args, **kwargs)
|
|
39
|
+
|
|
40
|
+
def send(self, request, **kwargs):
|
|
41
|
+
"""
|
|
42
|
+
Sends the Request object, applying the timeout setting.
|
|
43
|
+
|
|
44
|
+
:param request: The Request object to send.
|
|
45
|
+
:type request: requests.PreparedRequest
|
|
46
|
+
:param kwargs: Keyword arguments that may contain 'timeout'.
|
|
47
|
+
:return: The response to the request.
|
|
48
|
+
"""
|
|
49
|
+
timeout = kwargs.get("timeout")
|
|
50
|
+
if timeout is None:
|
|
51
|
+
kwargs["timeout"] = self.timeout
|
|
52
|
+
return super().send(request, **kwargs)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def get_requests_session(max_retries: int = 5, timeout: int = DEFAULT_TIMEOUT, verify: bool = True,
|
|
56
|
+
headers: Optional[Dict[str, str]] = None, session: Optional[requests.Session] = None) \
|
|
57
|
+
-> requests.Session:
|
|
58
|
+
"""
|
|
59
|
+
Creates a requests session with retry logic, timeout settings, and random user-agent headers.
|
|
60
|
+
|
|
61
|
+
:param max_retries: Maximum number of retries on failed requests.
|
|
62
|
+
:type max_retries: int
|
|
63
|
+
:param timeout: Request timeout in seconds.
|
|
64
|
+
:type timeout: int
|
|
65
|
+
:param verify: Whether to verify SSL certificates.
|
|
66
|
+
:type verify: bool
|
|
67
|
+
:param headers: Additional headers to include in the requests.
|
|
68
|
+
:type headers: Optional[Dict[str, str]]
|
|
69
|
+
:param session: An existing requests.Session instance to use.
|
|
70
|
+
:type session: Optional[requests.Session]
|
|
71
|
+
:return: A configured requests.Session object.
|
|
72
|
+
:rtype: requests.Session
|
|
73
|
+
"""
|
|
74
|
+
session = session or requests.session()
|
|
75
|
+
retries = Retry(
|
|
76
|
+
total=max_retries, backoff_factor=1,
|
|
77
|
+
status_forcelist=[408, 429, 500, 501, 502, 503, 504, 505, 506, 507, 509, 510, 511],
|
|
78
|
+
allowed_methods=["HEAD", "GET", "POST", "PUT", "DELETE", "OPTIONS", "TRACE"],
|
|
79
|
+
)
|
|
80
|
+
adapter = TimeoutHTTPAdapter(max_retries=retries, timeout=timeout, pool_connections=32, pool_maxsize=32)
|
|
81
|
+
session.mount('http://', adapter)
|
|
82
|
+
session.mount('https://', adapter)
|
|
83
|
+
session.headers.update({
|
|
84
|
+
"User-Agent": get_random_ua(),
|
|
85
|
+
**dict(headers or {}),
|
|
86
|
+
})
|
|
87
|
+
if not verify:
|
|
88
|
+
session.verify = False
|
|
89
|
+
|
|
90
|
+
return session
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@lru_cache()
|
|
94
|
+
def _ua_pool():
|
|
95
|
+
"""
|
|
96
|
+
Creates and caches a UserAgent rotator instance with a specified number of user agents.
|
|
97
|
+
|
|
98
|
+
:return: A UserAgent rotator instance.
|
|
99
|
+
:rtype: UserAgent
|
|
100
|
+
"""
|
|
101
|
+
software_names = [SoftwareName.CHROME.value, SoftwareName.FIREFOX.value, SoftwareName.EDGE.value]
|
|
102
|
+
operating_systems = [OperatingSystem.WINDOWS.value, OperatingSystem.MACOS.value]
|
|
103
|
+
|
|
104
|
+
user_agent_rotator = UserAgent(software_names=software_names, operating_systems=operating_systems, limit=1000)
|
|
105
|
+
return user_agent_rotator
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def get_random_ua():
|
|
109
|
+
"""
|
|
110
|
+
Retrieves a random user agent string from the cached UserAgent rotator.
|
|
111
|
+
|
|
112
|
+
:return: A random user agent string.
|
|
113
|
+
:rtype: str
|
|
114
|
+
"""
|
|
115
|
+
return _ua_pool().get_random_user_agent()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: hfutils
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.8
|
|
4
4
|
Summary: Useful utilities for huggingface
|
|
5
5
|
Home-page: https://github.com/deepghs/hfutils
|
|
6
6
|
Author: narugo1992
|
|
@@ -29,6 +29,29 @@ Requires-Dist: tzlocal
|
|
|
29
29
|
Requires-Dist: natsort
|
|
30
30
|
Requires-Dist: urlobject
|
|
31
31
|
Requires-Dist: fsspec>=2024
|
|
32
|
+
Requires-Dist: random_user_agent
|
|
33
|
+
Provides-Extra: test
|
|
34
|
+
Requires-Dist: coverage>=5; extra == "test"
|
|
35
|
+
Requires-Dist: mock>=4.0.3; extra == "test"
|
|
36
|
+
Requires-Dist: flake8~=3.5; extra == "test"
|
|
37
|
+
Requires-Dist: testfixtures>=6.18.5; extra == "test"
|
|
38
|
+
Requires-Dist: pytest~=6.2.5; extra == "test"
|
|
39
|
+
Requires-Dist: pytest-cov~=3.0.0; extra == "test"
|
|
40
|
+
Requires-Dist: pytest-mock~=3.6.1; extra == "test"
|
|
41
|
+
Requires-Dist: pytest-xdist>=1.34.0; extra == "test"
|
|
42
|
+
Requires-Dist: pytest-rerunfailures~=10.2; extra == "test"
|
|
43
|
+
Requires-Dist: pytest-timeout~=2.0.2; extra == "test"
|
|
44
|
+
Requires-Dist: pytest-benchmark~=3.4.0; extra == "test"
|
|
45
|
+
Requires-Dist: easydict<2,>=1.7; extra == "test"
|
|
46
|
+
Requires-Dist: testtools>=2; extra == "test"
|
|
47
|
+
Requires-Dist: where>=1.0.2; extra == "test"
|
|
48
|
+
Requires-Dist: responses>=0.20.0; extra == "test"
|
|
49
|
+
Requires-Dist: natsort; extra == "test"
|
|
50
|
+
Provides-Extra: rar
|
|
51
|
+
Requires-Dist: rarfile; extra == "rar"
|
|
52
|
+
Provides-Extra: build
|
|
53
|
+
Requires-Dist: pyinstaller<5,>=4.7; extra == "build"
|
|
54
|
+
Requires-Dist: setuptools<70; extra == "build"
|
|
32
55
|
Provides-Extra: doc
|
|
33
56
|
Requires-Dist: Jinja2>=3.0.0; extra == "doc"
|
|
34
57
|
Requires-Dist: sphinx>=3.2.0; extra == "doc"
|
|
@@ -49,32 +72,10 @@ Requires-Dist: ipykernel>=6.15; extra == "doc"
|
|
|
49
72
|
Requires-Dist: py-cpuinfo>=8.0.0; extra == "doc"
|
|
50
73
|
Requires-Dist: click>=7.0.0; extra == "doc"
|
|
51
74
|
Requires-Dist: pandas; extra == "doc"
|
|
52
|
-
Provides-Extra: test
|
|
53
|
-
Requires-Dist: coverage>=5; extra == "test"
|
|
54
|
-
Requires-Dist: mock>=4.0.3; extra == "test"
|
|
55
|
-
Requires-Dist: flake8~=3.5; extra == "test"
|
|
56
|
-
Requires-Dist: testfixtures>=6.18.5; extra == "test"
|
|
57
|
-
Requires-Dist: pytest~=6.2.5; extra == "test"
|
|
58
|
-
Requires-Dist: pytest-cov~=3.0.0; extra == "test"
|
|
59
|
-
Requires-Dist: pytest-mock~=3.6.1; extra == "test"
|
|
60
|
-
Requires-Dist: pytest-xdist>=1.34.0; extra == "test"
|
|
61
|
-
Requires-Dist: pytest-rerunfailures~=10.2; extra == "test"
|
|
62
|
-
Requires-Dist: pytest-timeout~=2.0.2; extra == "test"
|
|
63
|
-
Requires-Dist: pytest-benchmark~=3.4.0; extra == "test"
|
|
64
|
-
Requires-Dist: easydict<2,>=1.7; extra == "test"
|
|
65
|
-
Requires-Dist: testtools>=2; extra == "test"
|
|
66
|
-
Requires-Dist: where>=1.0.2; extra == "test"
|
|
67
|
-
Requires-Dist: responses>=0.20.0; extra == "test"
|
|
68
|
-
Requires-Dist: natsort; extra == "test"
|
|
69
75
|
Provides-Extra: transfer
|
|
70
76
|
Requires-Dist: hf-transfer; extra == "transfer"
|
|
71
77
|
Provides-Extra: 7z
|
|
72
78
|
Requires-Dist: py7zr; extra == "7z"
|
|
73
|
-
Provides-Extra: build
|
|
74
|
-
Requires-Dist: pyinstaller<5,>=4.7; extra == "build"
|
|
75
|
-
Requires-Dist: setuptools<70; extra == "build"
|
|
76
|
-
Provides-Extra: rar
|
|
77
|
-
Requires-Dist: rarfile; extra == "rar"
|
|
78
79
|
|
|
79
80
|
# hfutils
|
|
80
81
|
|
|
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
|