hfutils 0.3.6__tar.gz → 0.3.7__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.7}/PKG-INFO +24 -23
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/config/meta.py +1 -1
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/entry/download.py +10 -1
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/entry/index.py +5 -1
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/entry/ls.py +4 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/entry/ls_repo.py +4 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/entry/upload.py +4 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/entry/whoami.py +4 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/operate/download.py +4 -1
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/operate/validate.py +11 -3
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/utils/__init__.py +1 -0
- hfutils-0.3.7/hfutils/utils/session.py +115 -0
- {hfutils-0.3.6 → hfutils-0.3.7/hfutils.egg-info}/PKG-INFO +24 -23
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils.egg-info/SOURCES.txt +1 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils.egg-info/requires.txt +1 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/requirements.txt +2 -1
- {hfutils-0.3.6 → hfutils-0.3.7}/LICENSE +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/MANIFEST.in +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/README.md +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/__init__.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/__main__.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/archive/__init__.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/archive/base.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/archive/rar.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/archive/sevenz.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/archive/tar.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/archive/zip.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/cache/__init__.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/cache/delete.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/config/__init__.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/entry/__init__.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/entry/base.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/entry/cli.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/entry/clone.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/entry/dispatch.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/entry/rollback.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/index/__init__.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/index/fetch.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/index/hash.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/index/local_fetch.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/index/make.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/index/validate.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/operate/__init__.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/operate/base.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/operate/upload.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/repository/__init__.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/repository/base.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/repository/clone.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/repository/rollback.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/utils/binary.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/utils/download.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/utils/irregular_repo.json +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/utils/logging.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/utils/number.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/utils/path.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/utils/temp.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/utils/tqdm_.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils/utils/walk.py +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils.egg-info/dependency_links.txt +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils.egg-info/entry_points.txt +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/hfutils.egg-info/top_level.txt +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/requirements-7z.txt +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/requirements-build.txt +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/requirements-doc.txt +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/requirements-rar.txt +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/requirements-test.txt +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/requirements-transfer.txt +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/setup.cfg +0 -0
- {hfutils-0.3.6 → hfutils-0.3.7}/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.7
|
|
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()
|
|
@@ -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.7
|
|
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
|
|
File without changes
|
|
File without changes
|