hfutils 0.3.9__tar.gz → 0.4.0__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.9/hfutils.egg-info → hfutils-0.4.0}/PKG-INFO +1 -1
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/config/meta.py +1 -1
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/entry/cli.py +2 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/entry/download.py +6 -2
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/entry/ls.py +8 -61
- hfutils-0.4.0/hfutils/entry/tree.py +239 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/utils/__init__.py +3 -0
- hfutils-0.4.0/hfutils/utils/archive.py +157 -0
- hfutils-0.4.0/hfutils/utils/data.py +87 -0
- hfutils-0.4.0/hfutils/utils/model.py +140 -0
- hfutils-0.4.0/hfutils/utils/type_.py +121 -0
- {hfutils-0.3.9 → hfutils-0.4.0/hfutils.egg-info}/PKG-INFO +1 -1
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils.egg-info/SOURCES.txt +5 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/LICENSE +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/MANIFEST.in +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/README.md +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/__init__.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/__main__.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/archive/__init__.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/archive/base.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/archive/rar.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/archive/sevenz.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/archive/tar.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/archive/zip.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/cache/__init__.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/cache/delete.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/config/__init__.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/entry/__init__.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/entry/base.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/entry/clone.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/entry/dispatch.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/entry/index.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/entry/ls_repo.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/entry/rollback.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/entry/upload.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/entry/whoami.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/index/__init__.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/index/fetch.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/index/hash.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/index/local_fetch.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/index/make.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/index/validate.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/operate/__init__.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/operate/base.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/operate/download.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/operate/upload.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/operate/validate.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/repository/__init__.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/repository/base.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/repository/clone.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/repository/rollback.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/utils/binary.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/utils/download.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/utils/irregular_repo.json +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/utils/logging.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/utils/number.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/utils/path.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/utils/session.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/utils/temp.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/utils/tqdm_.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils/utils/walk.py +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils.egg-info/dependency_links.txt +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils.egg-info/entry_points.txt +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils.egg-info/requires.txt +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/hfutils.egg-info/top_level.txt +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/requirements-7z.txt +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/requirements-build.txt +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/requirements-doc.txt +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/requirements-rar.txt +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/requirements-test.txt +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/requirements-transfer.txt +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/requirements.txt +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/setup.cfg +0 -0
- {hfutils-0.3.9 → hfutils-0.4.0}/setup.py +0 -0
|
@@ -5,6 +5,7 @@ from .index import _add_index_subcommand
|
|
|
5
5
|
from .ls import _add_ls_subcommand
|
|
6
6
|
from .ls_repo import _add_ls_repo_subcommand
|
|
7
7
|
from .rollback import _add_rollback_subcommand
|
|
8
|
+
from .tree import _add_tree_subcommand
|
|
8
9
|
from .upload import _add_upload_subcommand
|
|
9
10
|
from .whoami import _add_whoami_subcommand
|
|
10
11
|
|
|
@@ -17,6 +18,7 @@ _DECORATORS = [
|
|
|
17
18
|
_add_index_subcommand,
|
|
18
19
|
_add_rollback_subcommand,
|
|
19
20
|
_add_clone_subcommand,
|
|
21
|
+
_add_tree_subcommand,
|
|
20
22
|
]
|
|
21
23
|
|
|
22
24
|
cli = hfutilcli
|
|
@@ -7,7 +7,7 @@ from huggingface_hub import configure_http_backend
|
|
|
7
7
|
|
|
8
8
|
from .base import CONTEXT_SETTINGS, command_wrap, ClickErrorException
|
|
9
9
|
from ..operate import download_file_to_file, download_archive_as_directory, download_directory_as_directory
|
|
10
|
-
from ..operate.base import REPO_TYPES, RepoTypeTyping
|
|
10
|
+
from ..operate.base import REPO_TYPES, RepoTypeTyping, _IGNORE_PATTERN_UNSET
|
|
11
11
|
from ..utils import get_requests_session
|
|
12
12
|
|
|
13
13
|
|
|
@@ -55,12 +55,15 @@ def _add_download_subcommand(cli: click.Group) -> click.Group:
|
|
|
55
55
|
help='Just check the file size when validating the downloaded files.', show_default=True)
|
|
56
56
|
@click.option('--tmpdir', 'tmpdir', type=str, default=None,
|
|
57
57
|
help='Use custom temporary Directory.', show_default=True)
|
|
58
|
+
@click.option('--all', 'show_all', is_flag=True, type=bool, default=False,
|
|
59
|
+
help='Show all files, including hidden files.', show_default=True)
|
|
58
60
|
@command_wrap()
|
|
59
61
|
def download(
|
|
60
62
|
repo_id: str, repo_type: RepoTypeTyping,
|
|
61
63
|
file_in_repo: Optional[str], archive_in_repo: Optional[str], dir_in_repo: Optional[str],
|
|
62
64
|
output_path: str, revision: str, max_workers: int,
|
|
63
|
-
password: Optional[str], wildcard: Optional[str], soft_mode_when_check: bool, tmpdir: Optional[str]
|
|
65
|
+
password: Optional[str], wildcard: Optional[str], soft_mode_when_check: bool, tmpdir: Optional[str],
|
|
66
|
+
show_all: bool = False,
|
|
64
67
|
):
|
|
65
68
|
"""
|
|
66
69
|
Download data from HuggingFace repositories.
|
|
@@ -135,6 +138,7 @@ def _add_download_subcommand(cli: click.Group) -> click.Group:
|
|
|
135
138
|
silent=False,
|
|
136
139
|
max_workers=max_workers,
|
|
137
140
|
soft_mode_when_check=soft_mode_when_check,
|
|
141
|
+
ignore_patterns=_IGNORE_PATTERN_UNSET if not show_all else [],
|
|
138
142
|
)
|
|
139
143
|
|
|
140
144
|
else:
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import mimetypes
|
|
2
1
|
import os.path
|
|
3
|
-
|
|
2
|
+
import os.path
|
|
4
3
|
from typing import Union, List
|
|
5
4
|
|
|
6
5
|
import click
|
|
@@ -10,46 +9,7 @@ from huggingface_hub.hf_api import RepoFolder, RepoFile
|
|
|
10
9
|
|
|
11
10
|
from .base import CONTEXT_SETTINGS
|
|
12
11
|
from ..operate.base import REPO_TYPES, get_hf_client
|
|
13
|
-
from ..utils import get_requests_session
|
|
14
|
-
|
|
15
|
-
mimetypes.add_type('image/webp', '.webp')
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
@unique
|
|
19
|
-
class ListItemType(Enum):
|
|
20
|
-
"""
|
|
21
|
-
Enum class representing different types of list items.
|
|
22
|
-
"""
|
|
23
|
-
|
|
24
|
-
FILE = 0x1
|
|
25
|
-
FOLDER = 0x2
|
|
26
|
-
IMAGE = 0x3
|
|
27
|
-
ARCHIVE = 0x4
|
|
28
|
-
MODEL = 0x5
|
|
29
|
-
DATA = 0x6
|
|
30
|
-
|
|
31
|
-
@property
|
|
32
|
-
def render_color(self):
|
|
33
|
-
"""
|
|
34
|
-
Get the render color based on the item type.
|
|
35
|
-
|
|
36
|
-
:return: The render color for the item type.
|
|
37
|
-
:rtype: str
|
|
38
|
-
"""
|
|
39
|
-
if self == self.FILE:
|
|
40
|
-
return None
|
|
41
|
-
elif self == self.FOLDER:
|
|
42
|
-
return 'blue'
|
|
43
|
-
elif self == self.IMAGE:
|
|
44
|
-
return 'magenta'
|
|
45
|
-
elif self == self.ARCHIVE:
|
|
46
|
-
return 'red'
|
|
47
|
-
elif self == self.MODEL:
|
|
48
|
-
return 'green'
|
|
49
|
-
elif self == self.DATA:
|
|
50
|
-
return 'yellow'
|
|
51
|
-
else:
|
|
52
|
-
raise ValueError(f'Unknown type - {self!r}') # pragma: no cover
|
|
12
|
+
from ..utils import get_requests_session, FileItemType, get_file_type
|
|
53
13
|
|
|
54
14
|
|
|
55
15
|
class ListItem:
|
|
@@ -66,22 +26,9 @@ class ListItem:
|
|
|
66
26
|
self.item = item
|
|
67
27
|
self.base_dir = base_dir
|
|
68
28
|
if isinstance(item, RepoFolder):
|
|
69
|
-
self.type =
|
|
29
|
+
self.type = FileItemType.FOLDER
|
|
70
30
|
else:
|
|
71
|
-
|
|
72
|
-
_, ext = os.path.splitext(item.path)
|
|
73
|
-
self.type = ListItemType.FILE
|
|
74
|
-
if ext in {'.ckpt', '.pt', '.safetensors', '.onnx', '.model', '.h5', '.mlmodel',
|
|
75
|
-
'.ftz', '.pb', '.pth', '.tflite'}:
|
|
76
|
-
self.type = ListItemType.MODEL
|
|
77
|
-
elif ext in {'.json', '.csv', '.tsv', '.arrow', '.bin', '.msgpack', '.npy', '.npz',
|
|
78
|
-
'.parquet', '.pickle', '.pkl', '.wasm'}:
|
|
79
|
-
self.type = ListItemType.DATA
|
|
80
|
-
elif mimetype:
|
|
81
|
-
if 'image' in mimetype:
|
|
82
|
-
self.type = ListItemType.IMAGE
|
|
83
|
-
elif mimetype.split('/', maxsplit=1)[-1] in {'zip', 'rar', 'x-tar', 'x-7z-compressed'}:
|
|
84
|
-
self.type = ListItemType.ARCHIVE
|
|
31
|
+
self.type = get_file_type(item.path)
|
|
85
32
|
|
|
86
33
|
|
|
87
34
|
def _add_ls_subcommand(cli: click.Group) -> click.Group:
|
|
@@ -154,7 +101,7 @@ def _add_ls_subcommand(cli: click.Group) -> click.Group:
|
|
|
154
101
|
max_size_length = 0
|
|
155
102
|
max_commit_info_length = 0
|
|
156
103
|
for item in items:
|
|
157
|
-
if item.type ==
|
|
104
|
+
if item.type == FileItemType.FOLDER:
|
|
158
105
|
size_text = '-'
|
|
159
106
|
else:
|
|
160
107
|
size_text = str(item.item.size)
|
|
@@ -164,8 +111,8 @@ def _add_ls_subcommand(cli: click.Group) -> click.Group:
|
|
|
164
111
|
max_commit_info_length = max(max_commit_info_length, len(commit_text))
|
|
165
112
|
|
|
166
113
|
for item in items:
|
|
167
|
-
print('d' if item.type ==
|
|
168
|
-
print('L' if item.type !=
|
|
114
|
+
print('d' if item.type == FileItemType.FOLDER else '-', end='')
|
|
115
|
+
print('L' if item.type != FileItemType.FOLDER and item.item.lfs else '-', end='')
|
|
169
116
|
|
|
170
117
|
commit_text = (item.item.last_commit.title or '').splitlines(keepends=False)[0]
|
|
171
118
|
print(
|
|
@@ -174,7 +121,7 @@ def _add_ls_subcommand(cli: click.Group) -> click.Group:
|
|
|
174
121
|
end=''
|
|
175
122
|
)
|
|
176
123
|
|
|
177
|
-
if item.type ==
|
|
124
|
+
if item.type == FileItemType.FOLDER:
|
|
178
125
|
size_text = '-'
|
|
179
126
|
else:
|
|
180
127
|
size_text = str(item.item.size)
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module provides functionality for listing and displaying files from a HuggingFace repository in a tree-like structure.
|
|
3
|
+
|
|
4
|
+
It includes functions for parsing repository paths, retrieving file information, and formatting the output as a tree.
|
|
5
|
+
The module also defines a CLI command for easy interaction with the tree functionality.
|
|
6
|
+
|
|
7
|
+
Key components:
|
|
8
|
+
|
|
9
|
+
- TreeItem: A dataclass representing an item (file or folder) in the tree structure.
|
|
10
|
+
- _get_tree: Function to retrieve the tree structure of files in a HuggingFace repository.
|
|
11
|
+
- _add_tree_subcommand: Function to add the 'tree' subcommand to a Click CLI group.
|
|
12
|
+
|
|
13
|
+
Usage:
|
|
14
|
+
This module is typically used as part of a larger CLI application for interacting with HuggingFace repositories.
|
|
15
|
+
The 'tree' command can be used to visualize the structure of files in a repository.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import dataclasses
|
|
19
|
+
import os
|
|
20
|
+
import re
|
|
21
|
+
from typing import Optional, List, Union
|
|
22
|
+
|
|
23
|
+
import click
|
|
24
|
+
from hbutils.string import format_tree
|
|
25
|
+
from huggingface_hub import configure_http_backend
|
|
26
|
+
from huggingface_hub.hf_api import RepoFile
|
|
27
|
+
from natsort import natsorted
|
|
28
|
+
|
|
29
|
+
from .base import CONTEXT_SETTINGS
|
|
30
|
+
from ..operate.base import REPO_TYPES, list_files_in_repository, RepoTypeTyping, get_hf_client
|
|
31
|
+
from ..utils import get_requests_session, hf_normpath, get_file_type, hf_fs_path, FileItemType
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclasses.dataclass
|
|
35
|
+
class TreeItem:
|
|
36
|
+
"""
|
|
37
|
+
Represents an item (file or folder) in the tree structure.
|
|
38
|
+
|
|
39
|
+
:param name: The name of the item.
|
|
40
|
+
:type name: str
|
|
41
|
+
:param type_: The type of the item (file or folder).
|
|
42
|
+
:type type_: FileItemType
|
|
43
|
+
:param children: List of child items if this is a folder.
|
|
44
|
+
:type children: Optional[List[TreeItem]]
|
|
45
|
+
:param exist: Whether the item exists in the repository.
|
|
46
|
+
:type exist: bool
|
|
47
|
+
|
|
48
|
+
:ivar name: The name of the item.
|
|
49
|
+
:ivar type_: The type of the item.
|
|
50
|
+
:ivar children: List of child items.
|
|
51
|
+
:ivar exist: Existence status of the item.
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
name: str
|
|
55
|
+
type_: FileItemType
|
|
56
|
+
children: Optional[List['TreeItem']]
|
|
57
|
+
exist: bool = True
|
|
58
|
+
|
|
59
|
+
def get_name(self):
|
|
60
|
+
"""
|
|
61
|
+
Get the formatted name of the item for display.
|
|
62
|
+
|
|
63
|
+
:return: Formatted name string with color and strike-through if applicable.
|
|
64
|
+
:rtype: str
|
|
65
|
+
"""
|
|
66
|
+
return click.style(
|
|
67
|
+
self.name,
|
|
68
|
+
fg=self.type_.render_color if self.exist else None,
|
|
69
|
+
strikethrough=not self.exist,
|
|
70
|
+
) + ('' if self.exist else ' <NOT EXIST>')
|
|
71
|
+
|
|
72
|
+
def get_children(self):
|
|
73
|
+
"""
|
|
74
|
+
Get the children of this item if it's a folder.
|
|
75
|
+
|
|
76
|
+
:return: List of child items if folder, empty list otherwise.
|
|
77
|
+
:rtype: List[TreeItem]
|
|
78
|
+
"""
|
|
79
|
+
return self.children if self.type_ == FileItemType.FOLDER else []
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _get_tree(repo_id: str, repo_type: RepoTypeTyping, dir_in_repo: str,
|
|
83
|
+
revision: Optional[str] = None, show_all: bool = False) -> TreeItem:
|
|
84
|
+
"""
|
|
85
|
+
Retrieve the tree structure of files in a HuggingFace repository.
|
|
86
|
+
|
|
87
|
+
:param repo_id: The ID of the repository.
|
|
88
|
+
:type repo_id: str
|
|
89
|
+
:param repo_type: The type of the repository.
|
|
90
|
+
:type repo_type: RepoTypeTyping
|
|
91
|
+
:param dir_in_repo: The directory in the repository to start from.
|
|
92
|
+
:type dir_in_repo: str
|
|
93
|
+
:param revision: The revision of the repository to use.
|
|
94
|
+
:type revision: Optional[str]
|
|
95
|
+
:param show_all: Whether to show hidden files.
|
|
96
|
+
:type show_all: bool
|
|
97
|
+
|
|
98
|
+
:return: The root TreeItem representing the directory structure.
|
|
99
|
+
:rtype: TreeItem
|
|
100
|
+
"""
|
|
101
|
+
root = {}
|
|
102
|
+
for filepath in list_files_in_repository(
|
|
103
|
+
repo_id=repo_id,
|
|
104
|
+
repo_type=repo_type,
|
|
105
|
+
subdir=dir_in_repo,
|
|
106
|
+
revision=revision,
|
|
107
|
+
ignore_patterns=[],
|
|
108
|
+
):
|
|
109
|
+
filename = hf_normpath(os.path.relpath(filepath, dir_in_repo))
|
|
110
|
+
segments = re.split(r'[\\/]+', filename)
|
|
111
|
+
if any(segment.startswith('.') and segment != '.' for segment in segments) and not show_all:
|
|
112
|
+
continue
|
|
113
|
+
|
|
114
|
+
current_node = root
|
|
115
|
+
for i, segment in enumerate(segments):
|
|
116
|
+
if segment not in current_node:
|
|
117
|
+
if i == (len(segments) - 1):
|
|
118
|
+
current_node[segment] = get_file_type(segment)
|
|
119
|
+
else:
|
|
120
|
+
current_node[segment] = {}
|
|
121
|
+
current_node = current_node[segment]
|
|
122
|
+
|
|
123
|
+
root_name = hf_fs_path(
|
|
124
|
+
repo_id=repo_id,
|
|
125
|
+
repo_type=repo_type,
|
|
126
|
+
filename=dir_in_repo,
|
|
127
|
+
revision=revision,
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
def _recursion(cur_node: Union[dict, FileItemType], parent_name: str, is_exist: bool = False):
|
|
131
|
+
if isinstance(cur_node, dict):
|
|
132
|
+
return TreeItem(
|
|
133
|
+
name=parent_name,
|
|
134
|
+
type_=FileItemType.FOLDER,
|
|
135
|
+
children=[
|
|
136
|
+
_recursion(cur_node=value, parent_name=name, is_exist=is_exist)
|
|
137
|
+
for name, value in natsorted(cur_node.items())
|
|
138
|
+
],
|
|
139
|
+
exist=is_exist,
|
|
140
|
+
)
|
|
141
|
+
else:
|
|
142
|
+
return TreeItem(
|
|
143
|
+
name=parent_name,
|
|
144
|
+
type_=cur_node,
|
|
145
|
+
children=[],
|
|
146
|
+
exist=is_exist,
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
exist = True
|
|
150
|
+
if not root:
|
|
151
|
+
hf_client = get_hf_client()
|
|
152
|
+
paths = hf_client.get_paths_info(
|
|
153
|
+
repo_id=repo_id,
|
|
154
|
+
repo_type=repo_type,
|
|
155
|
+
revision=revision,
|
|
156
|
+
paths=[dir_in_repo],
|
|
157
|
+
)
|
|
158
|
+
if len(paths) == 0:
|
|
159
|
+
exist = False
|
|
160
|
+
elif len(paths) == 1:
|
|
161
|
+
pathobj = paths[0]
|
|
162
|
+
if isinstance(pathobj, RepoFile): # the subdir is a file
|
|
163
|
+
root = get_file_type(dir_in_repo)
|
|
164
|
+
else:
|
|
165
|
+
assert len(paths) == 1, \
|
|
166
|
+
f'Multiple path {dir_in_repo!r} found in repo {root_name!r}, ' \
|
|
167
|
+
f'this must be caused by HuggingFace API.' # pragma: no cover
|
|
168
|
+
|
|
169
|
+
return _recursion(
|
|
170
|
+
cur_node=root,
|
|
171
|
+
parent_name=root_name,
|
|
172
|
+
is_exist=exist,
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def _add_tree_subcommand(cli: click.Group) -> click.Group:
|
|
177
|
+
"""
|
|
178
|
+
Add the 'tree' subcommand to a Click CLI group.
|
|
179
|
+
|
|
180
|
+
This function defines a new 'tree' command that lists files from a HuggingFace repository
|
|
181
|
+
in a tree-like structure.
|
|
182
|
+
|
|
183
|
+
:param cli: The Click CLI group to add the command to.
|
|
184
|
+
:type cli: click.Group
|
|
185
|
+
|
|
186
|
+
:return: The modified CLI group with the 'tree' command added.
|
|
187
|
+
:rtype: click.Group
|
|
188
|
+
|
|
189
|
+
Usage:
|
|
190
|
+
This function is typically called when setting up a CLI application:
|
|
191
|
+
|
|
192
|
+
cli = click.Group()
|
|
193
|
+
cli = _add_tree_subcommand(cli)
|
|
194
|
+
"""
|
|
195
|
+
|
|
196
|
+
@cli.command('tree', help='List files as a tree from HuggingFace repository.\n\n'
|
|
197
|
+
'Set environment $HF_TOKEN to use your own access token.',
|
|
198
|
+
context_settings=CONTEXT_SETTINGS)
|
|
199
|
+
@click.option('-r', '--repository', 'repo_id', type=str, required=True,
|
|
200
|
+
help='Repository to download from.')
|
|
201
|
+
@click.option('-t', '--type', 'repo_type', type=click.Choice(REPO_TYPES), default='dataset',
|
|
202
|
+
help='Type of the HuggingFace repository.', show_default=True)
|
|
203
|
+
@click.option('-d', '--directory', 'dir_in_repo', type=str, default=None,
|
|
204
|
+
help='Directory in repository to download the full directory tree.')
|
|
205
|
+
@click.option('-R', '--revision', 'revision', type=str, default='main',
|
|
206
|
+
help='Revision of repository.', show_default=True)
|
|
207
|
+
@click.option('-a', '--all', 'show_all', is_flag=True, type=bool, default=False,
|
|
208
|
+
help='Show all files, including hidden files.', show_default=True)
|
|
209
|
+
def tree(repo_id: str, repo_type: RepoTypeTyping, dir_in_repo, revision: str, show_all: bool):
|
|
210
|
+
"""
|
|
211
|
+
List files as a tree from a HuggingFace repository in a tree-like structure.
|
|
212
|
+
|
|
213
|
+
:param repo_id: The ID of the repository.
|
|
214
|
+
:type repo_id: str
|
|
215
|
+
:param repo_type: The type of the repository.
|
|
216
|
+
:type repo_type: RepoTypeTyping
|
|
217
|
+
:param dir_in_repo: The directory in the repository to start from.
|
|
218
|
+
:type dir_in_repo: str
|
|
219
|
+
:param revision: The revision of the repository to use.
|
|
220
|
+
:type revision: str
|
|
221
|
+
:param show_all: Whether to show hidden files.
|
|
222
|
+
:type show_all: bool
|
|
223
|
+
"""
|
|
224
|
+
configure_http_backend(get_requests_session)
|
|
225
|
+
|
|
226
|
+
_tree = _get_tree(
|
|
227
|
+
repo_id=repo_id,
|
|
228
|
+
repo_type=repo_type,
|
|
229
|
+
dir_in_repo=dir_in_repo or '.',
|
|
230
|
+
revision=revision,
|
|
231
|
+
show_all=show_all,
|
|
232
|
+
)
|
|
233
|
+
print(format_tree(
|
|
234
|
+
_tree,
|
|
235
|
+
format_node=TreeItem.get_name,
|
|
236
|
+
get_children=TreeItem.get_children,
|
|
237
|
+
))
|
|
238
|
+
|
|
239
|
+
return cli
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
from .archive import is_archive_or_compressed
|
|
1
2
|
from .binary import is_binary_file
|
|
3
|
+
from .data import is_data_file
|
|
2
4
|
from .download import download_file
|
|
3
5
|
from .logging import ColoredFormatter
|
|
4
6
|
from .number import number_to_tag
|
|
@@ -6,4 +8,5 @@ from .path import hf_normpath, hf_fs_path, parse_hf_fs_path, HfFileSystemPath
|
|
|
6
8
|
from .session import TimeoutHTTPAdapter, get_requests_session, get_random_ua
|
|
7
9
|
from .temp import TemporaryDirectory
|
|
8
10
|
from .tqdm_ import tqdm
|
|
11
|
+
from .type_ import FileItemType, get_file_type
|
|
9
12
|
from .walk import walk_files
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module provides functionality for identifying archive and compressed files based on their filenames.
|
|
3
|
+
|
|
4
|
+
It includes a comprehensive list of known archive and compressed file extensions, as well as patterns for
|
|
5
|
+
identifying split archives and other generic compressed file formats. The main
|
|
6
|
+
function :func:`is_archive_or_compressed` can be used to determine if a given filename
|
|
7
|
+
represents an archive or compressed file.
|
|
8
|
+
|
|
9
|
+
The module is useful for file handling operations where it's necessary to distinguish between regular files
|
|
10
|
+
and archives or compressed files.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import os.path
|
|
14
|
+
import re
|
|
15
|
+
from typing import Union
|
|
16
|
+
|
|
17
|
+
_ARCHIVE_KNOWN_EXTS = {
|
|
18
|
+
'.tar', # Tape Archive
|
|
19
|
+
'.rar', # Roshal Archive
|
|
20
|
+
'.rar5', # RAR version 5
|
|
21
|
+
'.zip', # ZIP archive
|
|
22
|
+
'.7z', # 7-Zip archive
|
|
23
|
+
'.7zip', # Alternative extension for 7-Zip
|
|
24
|
+
'.gz', # Gzip compressed file
|
|
25
|
+
'.bz2', # Bzip2 compressed file
|
|
26
|
+
'.xz', # XZ compressed file
|
|
27
|
+
'.ace', # ACE archive
|
|
28
|
+
'.lz', # Lzip compressed file
|
|
29
|
+
'.lzma', # LZMA compressed file
|
|
30
|
+
'.z', # Compress (Unix) file
|
|
31
|
+
'.cab', # Microsoft Cabinet file
|
|
32
|
+
'.arj', # ARJ archive
|
|
33
|
+
'.iso', # ISO disk image
|
|
34
|
+
'.lzh', # LZH archive
|
|
35
|
+
'.sit', # StuffIt archive
|
|
36
|
+
'.sitx', # StuffIt X archive
|
|
37
|
+
'.sea', # Self-Extracting Archive
|
|
38
|
+
'.alz', # ALZip archive
|
|
39
|
+
'.egg', # Python Egg
|
|
40
|
+
'.whl', # Python Wheel
|
|
41
|
+
'.deb', # Debian package
|
|
42
|
+
'.rpm', # Red Hat Package Manager
|
|
43
|
+
'.pkg', # macOS Installer Package
|
|
44
|
+
'.dmg', # Apple Disk Image
|
|
45
|
+
'.msi', # Microsoft Installer
|
|
46
|
+
'.tgz', # Gzipped tar archive
|
|
47
|
+
'.tbz2', # Bzip2 compressed tar archive
|
|
48
|
+
'.lzw', # LZW compressed file
|
|
49
|
+
'.rz', # RZip compressed file
|
|
50
|
+
'.lzo', # Lempel-Ziv-Oberhumer compressed file
|
|
51
|
+
'.zst', # Zstandard compressed file
|
|
52
|
+
'.tar.gz', # Gzipped tar archive
|
|
53
|
+
'.tar.bz2', # Bzip2 compressed tar archive
|
|
54
|
+
'.tar.xz', # XZ compressed tar archive
|
|
55
|
+
'.tar.lz', # Lzip compressed tar archive
|
|
56
|
+
'.tar.lzma', # LZMA compressed tar archive
|
|
57
|
+
'.zipx', # Extended ZIP archive
|
|
58
|
+
'.arc', # ARC archive
|
|
59
|
+
'.ark', # ARC archive (alternative extension)
|
|
60
|
+
'.lha', # LHA archive
|
|
61
|
+
'.zoo', # ZOO archive
|
|
62
|
+
'.gca', # GCA archive
|
|
63
|
+
'.uc2', # UC2 archive
|
|
64
|
+
'.uha', # UHarc archive
|
|
65
|
+
'.war', # Web Application Archive
|
|
66
|
+
'.ear', # Enterprise Application aRchive
|
|
67
|
+
'.sar', # SAR archive
|
|
68
|
+
'.jar', # Java Archive
|
|
69
|
+
'.apk', # Android Package Kit
|
|
70
|
+
'.xpi', # XPInstall (Mozilla browser extension)
|
|
71
|
+
'.snap', # Snap package (Ubuntu)
|
|
72
|
+
'.appimage', # AppImage package
|
|
73
|
+
'.squashfs', # Squashfs filesystem
|
|
74
|
+
'.cpio', # CPIO archive
|
|
75
|
+
'.shar', # Shell archive
|
|
76
|
+
'.lbr', # LBR archive
|
|
77
|
+
'.mar', # Mozilla Archive
|
|
78
|
+
'.sbx', # Sandbox file
|
|
79
|
+
'.qcow2', # QEMU Copy On Write 2
|
|
80
|
+
'.vdi', # VirtualBox Disk Image
|
|
81
|
+
'.vhd', # Virtual Hard Disk
|
|
82
|
+
'.vmdk', # Virtual Machine Disk
|
|
83
|
+
'.ova', # Open Virtual Appliance
|
|
84
|
+
'.xar', # eXtensible ARchive
|
|
85
|
+
'.mpq', # MoPaQ archive (Blizzard games)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
# Additional generic patterns
|
|
89
|
+
_EXTERNAL_PATTERNS = [
|
|
90
|
+
r'\.tar(?:\.(?:gz|bz2|xz|lz|lzma|Z))?$', # Tar and compressed tar archives
|
|
91
|
+
r'\.t\.(?:gz|bz2|xz|lz|lzma|Z)$', # Compressed files with .t.XX extension
|
|
92
|
+
r'\.(?:zip|z)$', # ZIP archives and Z compressed files
|
|
93
|
+
r'\.rar$', # RAR archives
|
|
94
|
+
r'\.7z$', # 7-Zip archives
|
|
95
|
+
r'\.(?:ar|a)$', # AR archives
|
|
96
|
+
r'\.(?:lz|lzma?)$', # LZ and LZMA compressed files
|
|
97
|
+
r'\.gz(?:ip)?$', # Gzip compressed files
|
|
98
|
+
r'\.bz(?:ip)?2?$', # Bzip and Bzip2 compressed files
|
|
99
|
+
r'\.(?:xz|lzh|lha)$', # XZ, LZH, and LHA archives
|
|
100
|
+
r'\.(?:iso|img|dmg|pkg|msi)$', # Disk images and installers
|
|
101
|
+
r'\.(?:deb|rpm|apk|ipa)$', # Package formats
|
|
102
|
+
]
|
|
103
|
+
|
|
104
|
+
_ARCHIVE_SPLIT_PATTERNS = [
|
|
105
|
+
r'^(.+\.(?:zip|rar|7z|tar|tar\.gz|tar\.bz2|tar\.xz))\.\d+$', # Split archives (e.g., .zip.001)
|
|
106
|
+
r'^(.+\.t)\.[a-z0-9]{2,4}$', # Split archives with .t.XX extension
|
|
107
|
+
r'^(.+\.part\d+)\.rar$', # Split RAR archives
|
|
108
|
+
r'^(.+)\.r\d{2}$', # Old-style split RAR archives
|
|
109
|
+
]
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def is_archive_or_compressed(filename: Union[str, os.PathLike]) -> bool:
|
|
113
|
+
"""
|
|
114
|
+
Determine if the given filename represents an archive or compressed file.
|
|
115
|
+
|
|
116
|
+
This function checks the filename against a list of known archive and compressed file extensions,
|
|
117
|
+
as well as patterns for split archives and other generic compressed file formats.
|
|
118
|
+
|
|
119
|
+
:param filename: The name of the file to check. Can be a string or a path-like object.
|
|
120
|
+
:type filename: Union[str, os.PathLike]
|
|
121
|
+
|
|
122
|
+
:return: True if the filename represents an archive or compressed file, False otherwise.
|
|
123
|
+
:rtype: bool
|
|
124
|
+
|
|
125
|
+
:raises TypeError: If the filename is not a string or path-like object.
|
|
126
|
+
|
|
127
|
+
Usage:
|
|
128
|
+
>>> is_archive_or_compressed('example.zip')
|
|
129
|
+
True
|
|
130
|
+
>>> is_archive_or_compressed('document.txt')
|
|
131
|
+
False
|
|
132
|
+
>>> is_archive_or_compressed('archive.tar.gz')
|
|
133
|
+
True
|
|
134
|
+
>>> is_archive_or_compressed('split_archive.zip.001')
|
|
135
|
+
True
|
|
136
|
+
"""
|
|
137
|
+
if not isinstance(filename, (str, os.PathLike)):
|
|
138
|
+
raise TypeError(f'Unknown file name type - {filename!r}')
|
|
139
|
+
filename = os.path.basename(os.path.normcase(str(filename)))
|
|
140
|
+
|
|
141
|
+
# Check for known extensions
|
|
142
|
+
for ext in _ARCHIVE_KNOWN_EXTS:
|
|
143
|
+
if filename.lower().endswith(ext):
|
|
144
|
+
return True
|
|
145
|
+
|
|
146
|
+
# Check for split archives
|
|
147
|
+
for pattern in _ARCHIVE_SPLIT_PATTERNS:
|
|
148
|
+
match = re.match(pattern, filename.lower())
|
|
149
|
+
if match:
|
|
150
|
+
return True
|
|
151
|
+
|
|
152
|
+
# Check for external patterns
|
|
153
|
+
for pattern in _EXTERNAL_PATTERNS:
|
|
154
|
+
if re.search(pattern, filename.lower()):
|
|
155
|
+
return True
|
|
156
|
+
|
|
157
|
+
return False
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module provides functionality for identifying data files based on their file extensions.
|
|
3
|
+
|
|
4
|
+
It includes a comprehensive set of data file extensions and a function to check if a given
|
|
5
|
+
filename corresponds to a known data file format. This can be useful in various data processing
|
|
6
|
+
and file handling scenarios where it's necessary to distinguish data files from other types of files.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import os
|
|
10
|
+
from typing import Union
|
|
11
|
+
|
|
12
|
+
_DATA_EXTS = {
|
|
13
|
+
'.json', # JavaScript Object Notation
|
|
14
|
+
'.csv', # Comma-Separated Values
|
|
15
|
+
'.tsv', # Tab-Separated Values
|
|
16
|
+
'.arrow', # Apache Arrow file format
|
|
17
|
+
'.feather', # Feather file format (fast, language-agnostic columnar format)
|
|
18
|
+
'.parquet', # Apache Parquet file format
|
|
19
|
+
'.avro', # Apache Avro file format
|
|
20
|
+
'.orc', # Optimized Row Columnar file format
|
|
21
|
+
'.npy', # NumPy array file
|
|
22
|
+
'.npz', # NumPy compressed archive file
|
|
23
|
+
'.hdf5', # Hierarchical Data Format version 5
|
|
24
|
+
'.h5', # Alternative extension for HDF5
|
|
25
|
+
'.mat', # MATLAB file format
|
|
26
|
+
'.sav', # SPSS data file
|
|
27
|
+
'.dta', # Stata data file
|
|
28
|
+
'.sas7bdat', # SAS data file
|
|
29
|
+
'.xpt', # SAS transport file
|
|
30
|
+
'.xlsx', # Microsoft Excel Open XML Spreadsheet
|
|
31
|
+
'.xls', # Microsoft Excel Binary File Format
|
|
32
|
+
'.ods', # OpenDocument Spreadsheet
|
|
33
|
+
'.db', # Generic database file
|
|
34
|
+
'.sqlite', # SQLite database file
|
|
35
|
+
'.mdb', # Microsoft Access database file
|
|
36
|
+
'.accdb', # Microsoft Access database file (newer version)
|
|
37
|
+
'.dbf', # dBase database file
|
|
38
|
+
'.ftr', # Feather file format (alternative extension)
|
|
39
|
+
'.geojson', # GeoJSON file (for geographical data)
|
|
40
|
+
'.shp', # Shapefile (for geographical data)
|
|
41
|
+
'.kml', # Keyhole Markup Language (for geographical data)
|
|
42
|
+
'.gpx', # GPS Exchange Format
|
|
43
|
+
'.nc', # NetCDF (Network Common Data Form) file
|
|
44
|
+
'.grib', # GRIdded Binary or General Regularly-distributed Information in Binary form
|
|
45
|
+
'.hdf', # Hierarchical Data Format (older version)
|
|
46
|
+
'.zarr', # Zarr array storage format
|
|
47
|
+
'.bin', # Generic Binary File
|
|
48
|
+
'.pickle', # Pickle dumped file
|
|
49
|
+
'.pkl', # Shortcut of .pickle
|
|
50
|
+
'.wasm', # WASM
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def is_data_file(filename: Union[str, os.PathLike]) -> bool:
|
|
55
|
+
"""
|
|
56
|
+
Determine if a given filename corresponds to a known data file format.
|
|
57
|
+
|
|
58
|
+
This function checks if the file extension of the provided filename matches
|
|
59
|
+
any of the known data file extensions defined in the `_DATA_EXTS` set.
|
|
60
|
+
|
|
61
|
+
:param filename: The name of the file to check. Can be a string or a path-like object.
|
|
62
|
+
:type filename: Union[str, os.PathLike]
|
|
63
|
+
|
|
64
|
+
:return: True if the file extension matches a known data file format, False otherwise.
|
|
65
|
+
:rtype: bool
|
|
66
|
+
|
|
67
|
+
:raises TypeError: If the provided filename is not a string or path-like object.
|
|
68
|
+
|
|
69
|
+
Usage:
|
|
70
|
+
>>> is_data_file('data.csv')
|
|
71
|
+
True
|
|
72
|
+
>>> is_data_file('script.py')
|
|
73
|
+
False
|
|
74
|
+
>>> is_data_file(Path('/path/to/data.json'))
|
|
75
|
+
True
|
|
76
|
+
|
|
77
|
+
.. note::
|
|
78
|
+
The function is case-insensitive and works with both file names and full paths.
|
|
79
|
+
It normalizes the filename and extracts only the extension for comparison.
|
|
80
|
+
"""
|
|
81
|
+
if not isinstance(filename, (str, os.PathLike)):
|
|
82
|
+
raise TypeError(f'Unknown file name type - {filename!r}')
|
|
83
|
+
|
|
84
|
+
# Normalize the filename and get the extension
|
|
85
|
+
filename = os.path.basename(os.path.normcase(str(filename)))
|
|
86
|
+
_, ext = os.path.splitext(filename.lower())
|
|
87
|
+
return ext in _DATA_EXTS
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module provides functionality for identifying model files based on their extensions and naming patterns.
|
|
3
|
+
|
|
4
|
+
It includes a comprehensive list of model file extensions, patterns for sharded model files, and specific patterns
|
|
5
|
+
for Hugging Face model files. The main function, :func:`is_model_file`, determines whether a given filename corresponds
|
|
6
|
+
to a model file based on these predefined patterns and extensions.
|
|
7
|
+
|
|
8
|
+
This module can be useful in various scenarios, such as:
|
|
9
|
+
|
|
10
|
+
- Automated model file detection in directories
|
|
11
|
+
- Validation of uploaded files in machine learning platforms
|
|
12
|
+
- Preprocessing steps in model loading pipelines
|
|
13
|
+
|
|
14
|
+
Usage:
|
|
15
|
+
.. code:: python
|
|
16
|
+
|
|
17
|
+
from model_file_identifier import is_model_file
|
|
18
|
+
|
|
19
|
+
filename = "model.pt"
|
|
20
|
+
if is_model_file(filename):
|
|
21
|
+
print(f"{filename} is a model file")
|
|
22
|
+
else:
|
|
23
|
+
print(f"{filename} is not a model file")
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
import os
|
|
27
|
+
import re
|
|
28
|
+
from typing import Union
|
|
29
|
+
|
|
30
|
+
_MODEL_EXTS = {
|
|
31
|
+
'.ckpt', # Checkpoint file
|
|
32
|
+
'.pt', # PyTorch model file
|
|
33
|
+
'.pth', # PyTorch model file (alternative extension)
|
|
34
|
+
'.safetensors', # SafeTensors model file
|
|
35
|
+
'.onnx', # Open Neural Network Exchange model file
|
|
36
|
+
'.model', # Generic model file
|
|
37
|
+
'.h5', # Hierarchical Data Format version 5
|
|
38
|
+
'.hdf5', # Hierarchical Data Format version 5 (alternative extension)
|
|
39
|
+
'.mlmodel', # Core ML model file
|
|
40
|
+
'.ftz', # FastText model file
|
|
41
|
+
'.pb', # Protocol Buffer file (often used for TensorFlow models)
|
|
42
|
+
'.tflite', # TensorFlow Lite model file
|
|
43
|
+
'.pkl', # Pickle file (often used for scikit-learn models)
|
|
44
|
+
'.joblib', # Joblib file (often used for scikit-learn models)
|
|
45
|
+
'.bin', # Binary file (generic)
|
|
46
|
+
'.meta', # Meta file (often associated with TensorFlow checkpoints)
|
|
47
|
+
'.params', # Parameters file (often used in MXNet)
|
|
48
|
+
'.pdparams', # PaddlePaddle parameters file
|
|
49
|
+
'.pdmodel', # PaddlePaddle model file
|
|
50
|
+
'.ot', # OpenVINO model file
|
|
51
|
+
'.nnet', # Neural network file
|
|
52
|
+
'.dnn', # Deep neural network file
|
|
53
|
+
'.mar', # MXNet Archive
|
|
54
|
+
'.tf', # TensorFlow SavedModel file
|
|
55
|
+
'.keras', # Keras model file
|
|
56
|
+
'.weights', # Weights file (generic)
|
|
57
|
+
'.pmml', # Predictive Model Markup Language file
|
|
58
|
+
'.gguf', # GGUF (GPT-Generated Unified Format) file
|
|
59
|
+
'.ggml', # GGML (GPT-Generated Model Language) file
|
|
60
|
+
'.q4_0', # 4-bit quantized model (type 0)
|
|
61
|
+
'.q4_1', # 4-bit quantized model (type 1)
|
|
62
|
+
'.q5_0', # 5-bit quantized model (type 0)
|
|
63
|
+
'.q5_1', # 5-bit quantized model (type 1)
|
|
64
|
+
'.q8_0', # 8-bit quantized model
|
|
65
|
+
'.qnt', # Quantized model (generic)
|
|
66
|
+
'.int8', # 8-bit integer quantized model
|
|
67
|
+
'.fp16', # 16-bit floating point model
|
|
68
|
+
'.bk', # Backup file (often used for model checkpoints)
|
|
69
|
+
'.engine', # TensorRT engine file
|
|
70
|
+
'.plan', # TensorRT plan file
|
|
71
|
+
'.trt', # TensorRT model file
|
|
72
|
+
'.torchscript', # TorchScript model file
|
|
73
|
+
'.pdiparams', # PaddlePaddle inference parameters file
|
|
74
|
+
'.pdopt', # PaddlePaddle optimizer file
|
|
75
|
+
'.nb', # Neural network binary file
|
|
76
|
+
'.mnn', # MNN (Mobile Neural Network) model file
|
|
77
|
+
'.ncnn', # NCNN model file
|
|
78
|
+
'.om', # CANN (Compute Architecture for Neural Networks) offline model
|
|
79
|
+
'.rknn', # Rockchip Neural Network model file
|
|
80
|
+
'.xmodel', # Vitis AI model file
|
|
81
|
+
'.kmodel', # Kendryte model file
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
_MODEL_SHARD_PATTERNS = [
|
|
85
|
+
r'.*-\d{5}-of-\d{5}', # Pattern for sharded files like "model-00001-of-00005"
|
|
86
|
+
r'.*\.bin\.\d+', # Pattern for binary shards like "model.bin.1"
|
|
87
|
+
r'.*\.part\.\d+', # Pattern for part files like "model.part.0"
|
|
88
|
+
r'.*_part_\d+', # Alternative pattern for part files like "model_part_0"
|
|
89
|
+
r'.*-shard\d+', # Pattern for shard files like "model-shard1"
|
|
90
|
+
]
|
|
91
|
+
|
|
92
|
+
_HF_MODEL_PATTERNS = [
|
|
93
|
+
r'pytorch_model.*\.bin', # Hugging Face PyTorch model file
|
|
94
|
+
r'tf_model.*\.h5', # Hugging Face TensorFlow model file
|
|
95
|
+
r'model.*\.ckpt', # Hugging Face checkpoint file
|
|
96
|
+
r'flax_model.*\.msgpack', # Hugging Face Flax model file
|
|
97
|
+
r'.*\.safetensors', # SafeTensors file (often used in Hugging Face models)
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def is_model_file(filename: Union[str, os.PathLike]) -> bool:
|
|
102
|
+
"""
|
|
103
|
+
Determine if a given filename corresponds to a model file.
|
|
104
|
+
|
|
105
|
+
This function checks if the provided filename matches any of the known model file extensions
|
|
106
|
+
or patterns, including sharded model files and Hugging Face specific patterns.
|
|
107
|
+
|
|
108
|
+
:param filename: The name of the file to check. Can be a full path or just the filename.
|
|
109
|
+
:type filename: Union[str, os.PathLike]
|
|
110
|
+
|
|
111
|
+
:return: True if the filename corresponds to a model file, False otherwise.
|
|
112
|
+
:rtype: bool
|
|
113
|
+
|
|
114
|
+
:raises TypeError: If the filename is not a string or os.PathLike object.
|
|
115
|
+
|
|
116
|
+
Usage:
|
|
117
|
+
>>> is_model_file("model.pt")
|
|
118
|
+
True
|
|
119
|
+
>>> is_model_file("data.csv")
|
|
120
|
+
False
|
|
121
|
+
>>> is_model_file("model-00001-of-00005")
|
|
122
|
+
True
|
|
123
|
+
>>> is_model_file("pytorch_model.bin")
|
|
124
|
+
True
|
|
125
|
+
|
|
126
|
+
.. note::
|
|
127
|
+
This function is case-insensitive and works with both file names and full paths.
|
|
128
|
+
"""
|
|
129
|
+
if not isinstance(filename, (str, os.PathLike)):
|
|
130
|
+
raise TypeError(f'Unknown file name type - {filename!r}')
|
|
131
|
+
filename = os.path.basename(os.path.normcase(str(filename)))
|
|
132
|
+
|
|
133
|
+
if any(filename.lower().endswith(ext) for ext in _MODEL_EXTS):
|
|
134
|
+
return True
|
|
135
|
+
if any(re.match(pattern, filename.lower()) for pattern in _MODEL_SHARD_PATTERNS):
|
|
136
|
+
return True
|
|
137
|
+
if any(re.match(pattern, filename.lower()) for pattern in _HF_MODEL_PATTERNS):
|
|
138
|
+
return True
|
|
139
|
+
|
|
140
|
+
return False
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module provides functionality for determining file types and managing list item types.
|
|
3
|
+
|
|
4
|
+
It includes an enumeration class for different types of list items, and a function to determine
|
|
5
|
+
the type of a given file. The module also adds support for the WebP image format.
|
|
6
|
+
|
|
7
|
+
The module uses the ``mimetypes`` library for MIME type detection and imports custom functions
|
|
8
|
+
for identifying archive, model, and data files.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import mimetypes
|
|
12
|
+
import os
|
|
13
|
+
from enum import Enum, unique
|
|
14
|
+
from typing import Union
|
|
15
|
+
|
|
16
|
+
from .archive import is_archive_or_compressed
|
|
17
|
+
from .data import is_data_file
|
|
18
|
+
from .model import is_model_file
|
|
19
|
+
|
|
20
|
+
mimetypes.add_type('image/webp', '.webp')
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@unique
|
|
24
|
+
class FileItemType(Enum):
|
|
25
|
+
"""
|
|
26
|
+
Enum class representing different types of list items.
|
|
27
|
+
|
|
28
|
+
This enumeration defines various file and folder types that can be encountered
|
|
29
|
+
in a file system or list of items. Each type is associated with a unique integer value.
|
|
30
|
+
|
|
31
|
+
Usage:
|
|
32
|
+
>>> item_type = FileItemType.FILE
|
|
33
|
+
>>> print(item_type)
|
|
34
|
+
FileItemType.FILE
|
|
35
|
+
>>> print(item_type.value)
|
|
36
|
+
1
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
FILE = 0x1
|
|
40
|
+
FOLDER = 0x2
|
|
41
|
+
IMAGE = 0x3
|
|
42
|
+
ARCHIVE = 0x4
|
|
43
|
+
MODEL = 0x5
|
|
44
|
+
DATA = 0x6
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def render_color(self):
|
|
48
|
+
"""
|
|
49
|
+
Get the render color based on the item type.
|
|
50
|
+
|
|
51
|
+
This property returns a color string associated with each item type,
|
|
52
|
+
which can be used for rendering or display purposes.
|
|
53
|
+
|
|
54
|
+
:return: The render color for the item type.
|
|
55
|
+
:rtype: str or None
|
|
56
|
+
|
|
57
|
+
:raises ValueError: If an unknown item type is encountered.
|
|
58
|
+
|
|
59
|
+
Usage:
|
|
60
|
+
>>> item_type = FileItemType.FOLDER
|
|
61
|
+
>>> print(item_type.render_color)
|
|
62
|
+
blue
|
|
63
|
+
"""
|
|
64
|
+
if self == FileItemType.FILE:
|
|
65
|
+
return None
|
|
66
|
+
elif self == FileItemType.FOLDER:
|
|
67
|
+
return 'blue'
|
|
68
|
+
elif self == FileItemType.IMAGE:
|
|
69
|
+
return 'magenta'
|
|
70
|
+
elif self == FileItemType.ARCHIVE:
|
|
71
|
+
return 'red'
|
|
72
|
+
elif self == FileItemType.MODEL:
|
|
73
|
+
return 'green'
|
|
74
|
+
elif self == FileItemType.DATA:
|
|
75
|
+
return 'yellow'
|
|
76
|
+
else:
|
|
77
|
+
raise ValueError(f'Unknown type - {self!r}') # pragma: no cover
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def get_file_type(filename: Union[str, os.PathLike]) -> FileItemType:
|
|
81
|
+
"""
|
|
82
|
+
Determine the type of a given file.
|
|
83
|
+
|
|
84
|
+
This function analyzes the provided filename and returns the corresponding FileItemType.
|
|
85
|
+
It uses various methods to determine the file type, including checking for archives,
|
|
86
|
+
model files, data files, and image files based on MIME types.
|
|
87
|
+
|
|
88
|
+
:param filename: The name or path of the file to analyze.
|
|
89
|
+
:type filename: Union[str, os.PathLike]
|
|
90
|
+
|
|
91
|
+
:return: The determined FileItemType for the given file.
|
|
92
|
+
:rtype: FileItemType
|
|
93
|
+
|
|
94
|
+
:raises TypeError: If the provided filename is not a string or PathLike object.
|
|
95
|
+
|
|
96
|
+
Usage:
|
|
97
|
+
>>> file_type = get_file_type('image.jpg')
|
|
98
|
+
>>> print(file_type)
|
|
99
|
+
FileItemType.IMAGE
|
|
100
|
+
|
|
101
|
+
>>> file_type = get_file_type('data.csv')
|
|
102
|
+
>>> print(file_type)
|
|
103
|
+
FileItemType.DATA
|
|
104
|
+
"""
|
|
105
|
+
if not isinstance(filename, (str, os.PathLike)):
|
|
106
|
+
raise TypeError(f'Unknown file name type - {filename!r}')
|
|
107
|
+
filename = os.path.basename(os.path.normcase(str(filename)))
|
|
108
|
+
|
|
109
|
+
mimetype, _ = mimetypes.guess_type(filename)
|
|
110
|
+
type_ = FileItemType.FILE
|
|
111
|
+
if is_archive_or_compressed(filename):
|
|
112
|
+
type_ = FileItemType.ARCHIVE
|
|
113
|
+
elif is_model_file(filename):
|
|
114
|
+
type_ = FileItemType.MODEL
|
|
115
|
+
elif is_data_file(filename):
|
|
116
|
+
type_ = FileItemType.DATA
|
|
117
|
+
elif mimetype:
|
|
118
|
+
if 'image' in mimetype:
|
|
119
|
+
type_ = FileItemType.IMAGE
|
|
120
|
+
|
|
121
|
+
return type_
|
|
@@ -37,6 +37,7 @@ hfutils/entry/index.py
|
|
|
37
37
|
hfutils/entry/ls.py
|
|
38
38
|
hfutils/entry/ls_repo.py
|
|
39
39
|
hfutils/entry/rollback.py
|
|
40
|
+
hfutils/entry/tree.py
|
|
40
41
|
hfutils/entry/upload.py
|
|
41
42
|
hfutils/entry/whoami.py
|
|
42
43
|
hfutils/index/__init__.py
|
|
@@ -55,13 +56,17 @@ hfutils/repository/base.py
|
|
|
55
56
|
hfutils/repository/clone.py
|
|
56
57
|
hfutils/repository/rollback.py
|
|
57
58
|
hfutils/utils/__init__.py
|
|
59
|
+
hfutils/utils/archive.py
|
|
58
60
|
hfutils/utils/binary.py
|
|
61
|
+
hfutils/utils/data.py
|
|
59
62
|
hfutils/utils/download.py
|
|
60
63
|
hfutils/utils/irregular_repo.json
|
|
61
64
|
hfutils/utils/logging.py
|
|
65
|
+
hfutils/utils/model.py
|
|
62
66
|
hfutils/utils/number.py
|
|
63
67
|
hfutils/utils/path.py
|
|
64
68
|
hfutils/utils/session.py
|
|
65
69
|
hfutils/utils/temp.py
|
|
66
70
|
hfutils/utils/tqdm_.py
|
|
71
|
+
hfutils/utils/type_.py
|
|
67
72
|
hfutils/utils/walk.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
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
|