hfutils 0.2.8__tar.gz → 0.2.10__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. {hfutils-0.2.8/hfutils.egg-info → hfutils-0.2.10}/PKG-INFO +8 -8
  2. hfutils-0.2.10/hfutils/cache/__init__.py +7 -0
  3. hfutils-0.2.10/hfutils/cache/delete.py +157 -0
  4. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/config/meta.py +1 -1
  5. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/entry/cli.py +2 -0
  6. hfutils-0.2.10/hfutils/entry/index.py +197 -0
  7. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/utils/__init__.py +1 -0
  8. hfutils-0.2.10/hfutils/utils/logging.py +69 -0
  9. {hfutils-0.2.8 → hfutils-0.2.10/hfutils.egg-info}/PKG-INFO +8 -8
  10. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils.egg-info/SOURCES.txt +4 -0
  11. {hfutils-0.2.8 → hfutils-0.2.10}/LICENSE +0 -0
  12. {hfutils-0.2.8 → hfutils-0.2.10}/MANIFEST.in +0 -0
  13. {hfutils-0.2.8 → hfutils-0.2.10}/README.md +0 -0
  14. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/__init__.py +0 -0
  15. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/__main__.py +0 -0
  16. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/archive/__init__.py +0 -0
  17. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/archive/base.py +0 -0
  18. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/archive/rar.py +0 -0
  19. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/archive/sevenz.py +0 -0
  20. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/archive/tar.py +0 -0
  21. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/archive/zip.py +0 -0
  22. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/config/__init__.py +0 -0
  23. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/entry/__init__.py +0 -0
  24. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/entry/base.py +0 -0
  25. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/entry/dispatch.py +0 -0
  26. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/entry/download.py +0 -0
  27. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/entry/ls.py +0 -0
  28. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/entry/ls_repo.py +0 -0
  29. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/entry/upload.py +0 -0
  30. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/entry/whoami.py +0 -0
  31. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/index/__init__.py +0 -0
  32. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/index/fetch.py +0 -0
  33. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/index/hash.py +0 -0
  34. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/index/make.py +0 -0
  35. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/index/validate.py +0 -0
  36. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/operate/__init__.py +0 -0
  37. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/operate/base.py +0 -0
  38. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/operate/download.py +0 -0
  39. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/operate/upload.py +0 -0
  40. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/operate/validate.py +0 -0
  41. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/utils/binary.py +0 -0
  42. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/utils/download.py +0 -0
  43. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/utils/irregular_repo.json +0 -0
  44. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/utils/path.py +0 -0
  45. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/utils/temp.py +0 -0
  46. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/utils/tqdm_.py +0 -0
  47. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils/utils/walk.py +0 -0
  48. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils.egg-info/dependency_links.txt +0 -0
  49. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils.egg-info/entry_points.txt +0 -0
  50. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils.egg-info/requires.txt +0 -0
  51. {hfutils-0.2.8 → hfutils-0.2.10}/hfutils.egg-info/top_level.txt +0 -0
  52. {hfutils-0.2.8 → hfutils-0.2.10}/requirements-7z.txt +0 -0
  53. {hfutils-0.2.8 → hfutils-0.2.10}/requirements-build.txt +0 -0
  54. {hfutils-0.2.8 → hfutils-0.2.10}/requirements-doc.txt +0 -0
  55. {hfutils-0.2.8 → hfutils-0.2.10}/requirements-rar.txt +0 -0
  56. {hfutils-0.2.8 → hfutils-0.2.10}/requirements-test.txt +0 -0
  57. {hfutils-0.2.8 → hfutils-0.2.10}/requirements-transfer.txt +0 -0
  58. {hfutils-0.2.8 → hfutils-0.2.10}/requirements.txt +0 -0
  59. {hfutils-0.2.8 → hfutils-0.2.10}/setup.cfg +0 -0
  60. {hfutils-0.2.8 → hfutils-0.2.10}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hfutils
3
- Version: 0.2.8
3
+ Version: 0.2.10
4
4
  Summary: Useful utilities for huggingface
5
5
  Home-page: https://github.com/deepghs/hfutils
6
6
  Author: narugo1992
@@ -27,9 +27,6 @@ Requires-Dist: requests
27
27
  Requires-Dist: click>=7
28
28
  Requires-Dist: tzlocal
29
29
  Requires-Dist: natsort
30
- Provides-Extra: build
31
- Requires-Dist: pyinstaller<5,>=4.7; extra == "build"
32
- Requires-Dist: setuptools<70; extra == "build"
33
30
  Provides-Extra: doc
34
31
  Requires-Dist: Jinja2>=3.0.0; extra == "doc"
35
32
  Requires-Dist: sphinx>=3.2.0; extra == "doc"
@@ -50,10 +47,15 @@ Requires-Dist: ipykernel>=6.15; extra == "doc"
50
47
  Requires-Dist: py-cpuinfo>=8.0.0; extra == "doc"
51
48
  Requires-Dist: click>=7.0.0; extra == "doc"
52
49
  Requires-Dist: pandas; extra == "doc"
53
- Provides-Extra: 7z
54
- Requires-Dist: py7zr; extra == "7z"
55
50
  Provides-Extra: transfer
56
51
  Requires-Dist: hf-transfer; extra == "transfer"
52
+ Provides-Extra: rar
53
+ Requires-Dist: rarfile; extra == "rar"
54
+ Provides-Extra: 7z
55
+ Requires-Dist: py7zr; extra == "7z"
56
+ Provides-Extra: build
57
+ Requires-Dist: pyinstaller<5,>=4.7; extra == "build"
58
+ Requires-Dist: setuptools<70; extra == "build"
57
59
  Provides-Extra: test
58
60
  Requires-Dist: coverage>=5; extra == "test"
59
61
  Requires-Dist: mock>=4.0.3; extra == "test"
@@ -71,8 +73,6 @@ Requires-Dist: testtools>=2; extra == "test"
71
73
  Requires-Dist: where>=1.0.2; extra == "test"
72
74
  Requires-Dist: responses>=0.20.0; extra == "test"
73
75
  Requires-Dist: natsort; extra == "test"
74
- Provides-Extra: rar
75
- Requires-Dist: rarfile; extra == "rar"
76
76
 
77
77
  # hfutils
78
78
 
@@ -0,0 +1,7 @@
1
+ """
2
+ Overview:
3
+ Huggingface local cache management.
4
+
5
+ Can quickly manage the local cache and make the disk space under control.
6
+ """
7
+ from .delete import delete_detached_cache, delete_cache
@@ -0,0 +1,157 @@
1
+ import logging
2
+ from functools import partial
3
+ from typing import Optional, Callable
4
+
5
+ from huggingface_hub import scan_cache_dir, CachedRepoInfo, CachedRevisionInfo, DeleteCacheStrategy, CacheNotFound
6
+
7
+
8
+ def _collect_revisions(fn: Callable[[CachedRepoInfo, CachedRevisionInfo], bool], cache_dir: Optional[str] = None) \
9
+ -> DeleteCacheStrategy:
10
+ """
11
+ Collects revisions from the cache that match a specific condition defined by the function `fn`.
12
+
13
+ :param fn: A callable that takes a CachedRepoInfo and CachedRevisionInfo and returns a boolean.
14
+ If True, the revision matches the condition.
15
+ :type fn: Callable[[CachedRepoInfo, CachedRevisionInfo], bool]
16
+ :param cache_dir: The directory where the cache is stored. If None, uses the default directory.
17
+ :type cache_dir: Optional[str]
18
+ :return: A strategy for deleting the collected revisions.
19
+ :rtype: DeleteCacheStrategy
20
+ """
21
+ revision_hashes = set()
22
+ scan = scan_cache_dir(cache_dir=cache_dir)
23
+ for repo in scan.repos:
24
+ for revision in repo.revisions:
25
+ if fn(repo, revision):
26
+ revision_hashes.add(revision.commit_hash)
27
+ logging.info(f'Revisions to delete from huggingface cache: {sorted(revision_hashes)}')
28
+ return scan.delete_revisions(*revision_hashes)
29
+
30
+
31
+ def _is_repo_match(repo: CachedRepoInfo, repo_id: Optional[str] = None, repo_type: Optional[str] = None) -> bool:
32
+ """
33
+ Checks if a repository matches the specified ID and type.
34
+
35
+ :param repo: The repository information.
36
+ :type repo: CachedRepoInfo
37
+ :param repo_id: The ID of the repository to match. If None, matches any ID.
38
+ :type repo_id: Optional[str]
39
+ :param repo_type: The type of the repository to match. If None, matches any type.
40
+ :type repo_type: Optional[str]
41
+ :return: True if the repository matches the conditions, False otherwise.
42
+ :rtype: bool
43
+ """
44
+ if repo_id and repo_type:
45
+ return repo.repo_id == repo_id and repo.repo_type == repo_type
46
+ elif repo_id:
47
+ return repo.repo_id == repo_id
48
+ elif repo_type:
49
+ return repo.repo_type == repo_type
50
+ else:
51
+ return True
52
+
53
+
54
+ def _is_detached_revision(
55
+ repo: CachedRepoInfo, revision: CachedRevisionInfo,
56
+ repo_id: Optional[str] = None, repo_type: Optional[str] = None,
57
+ ) -> bool:
58
+ """
59
+ Determines if a revision is detached (no references) and matches the specified repository ID and type.
60
+
61
+ :param repo: The repository information.
62
+ :type repo: CachedRepoInfo
63
+ :param revision: The revision information.
64
+ :type revision: CachedRevisionInfo
65
+ :param repo_id: The repository ID to match. If None, matches any ID.
66
+ :type repo_id: Optional[str]
67
+ :param repo_type: The repository type to match. If None, matches any type.
68
+ :type repo_type: Optional[str]
69
+ :return: True if the revision is detached and matches the repository conditions, False otherwise.
70
+ :rtype: bool
71
+ """
72
+ if len(revision.refs) == 0:
73
+ return _is_repo_match(repo, repo_id, repo_type)
74
+ else:
75
+ return False
76
+
77
+
78
+ def delete_detached_cache(
79
+ repo_id: Optional[str] = None, repo_type: Optional[str] = None,
80
+ cache_dir: Optional[str] = None
81
+ ):
82
+ """
83
+ Deletes all detached revisions from the cache that match the specified repository ID and type.
84
+
85
+ :param repo_id: The repository ID to match. If None, matches any ID.
86
+ :type repo_id: Optional[str]
87
+ :param repo_type: The repository type to match. If None, matches any type.
88
+ :type repo_type: Optional[str]
89
+ :param cache_dir: The directory where the cache is stored. If None, uses the default directory.
90
+ :type cache_dir: Optional[str]
91
+ """
92
+ try:
93
+ # noinspection PyTypeChecker
94
+ strategy = _collect_revisions(
95
+ fn=partial(
96
+ _is_detached_revision,
97
+ repo_id=repo_id,
98
+ repo_type=repo_type,
99
+ ),
100
+ cache_dir=cache_dir,
101
+ )
102
+ logging.info(f'{strategy.expected_freed_size_str} space will be freed.')
103
+ strategy.execute()
104
+ except CacheNotFound:
105
+ logging.info('No cache file found.')
106
+
107
+
108
+ def _is_selected_revision(
109
+ repo: CachedRepoInfo, revision: CachedRevisionInfo,
110
+ repo_id: Optional[str] = None, repo_type: Optional[str] = None,
111
+ ) -> bool:
112
+ """
113
+ Determines if a revision matches the specified repository ID and type.
114
+
115
+ :param repo: The repository information.
116
+ :type repo: CachedRepoInfo
117
+ :param revision: The revision information.
118
+ :type revision: CachedRevisionInfo
119
+ :param repo_id: The repository ID to match. If None, matches any ID.
120
+ :type repo_id: Optional[str]
121
+ :param repo_type: The repository type to match. If None, matches any type.
122
+ :type repo_type: Optional[str]
123
+ :return: True if the revision matches the repository conditions, False otherwise.
124
+ :rtype: bool
125
+ """
126
+ _ = repo, revision
127
+ return _is_repo_match(repo, repo_id, repo_type)
128
+
129
+
130
+ def delete_cache(
131
+ repo_id: Optional[str] = None, repo_type: Optional[str] = None,
132
+ cache_dir: Optional[str] = None
133
+ ):
134
+ """
135
+ Deletes all revisions from the cache that match the specified repository ID and type.
136
+
137
+ :param repo_id: The repository ID to match. If None, matches any ID.
138
+ :type repo_id: Optional[str]
139
+ :param repo_type: The repository type to match. If None, matches any type.
140
+ :type repo_type: Optional[str]
141
+ :param cache_dir: The directory where the cache is stored. If None, uses the default directory.
142
+ :type cache_dir: Optional[str]
143
+ """
144
+ try:
145
+ # noinspection PyTypeChecker
146
+ strategy = _collect_revisions(
147
+ fn=partial(
148
+ _is_selected_revision,
149
+ repo_id=repo_id,
150
+ repo_type=repo_type,
151
+ ),
152
+ cache_dir=cache_dir,
153
+ )
154
+ logging.info(f'{strategy.expected_freed_size_str} space will be freed.')
155
+ strategy.execute()
156
+ except CacheNotFound:
157
+ logging.info('No cache file found.')
@@ -7,7 +7,7 @@ Overview:
7
7
  __TITLE__ = 'hfutils'
8
8
 
9
9
  #: Version of this project.
10
- __VERSION__ = '0.2.8'
10
+ __VERSION__ = '0.2.10'
11
11
 
12
12
  #: Short description of the project, will be included in ``setup.py``.
13
13
  __DESCRIPTION__ = 'Useful utilities for huggingface'
@@ -1,5 +1,6 @@
1
1
  from .dispatch import hfutilcli
2
2
  from .download import _add_download_subcommand
3
+ from .index import _add_index_subcommand
3
4
  from .ls import _add_ls_subcommand
4
5
  from .ls_repo import _add_ls_repo_subcommand
5
6
  from .upload import _add_upload_subcommand
@@ -11,6 +12,7 @@ _DECORATORS = [
11
12
  _add_ls_subcommand,
12
13
  _add_whoami_subcommand,
13
14
  _add_ls_repo_subcommand,
15
+ _add_index_subcommand,
14
16
  ]
15
17
 
16
18
  cli = hfutilcli
@@ -0,0 +1,197 @@
1
+ """
2
+ This module provides functionality for creating and managing index repositories for tar archives stored in Hugging Face repositories.
3
+
4
+ The main features of this module include:
5
+ - Adding an 'index' subcommand to a Click CLI application
6
+ - Creating index files for tar archives
7
+ - Uploading index files to a specified Hugging Face repository
8
+ - Managing the upload process with a minimum interval between uploads
9
+
10
+ The module uses the Hugging Face file system and client for interacting with repositories.
11
+ """
12
+
13
+ import logging
14
+ import os.path
15
+ import shutil
16
+ import time
17
+ from typing import Optional
18
+
19
+ import click
20
+ from hbutils.string import plural_word
21
+
22
+ from .base import CONTEXT_SETTINGS
23
+ from ..cache import delete_detached_cache
24
+ from ..index import hf_tar_validate, tar_create_index
25
+ from ..operate import get_hf_fs, download_file_to_file, upload_directory_as_directory
26
+ 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
+
29
+
30
+ def _add_index_subcommand(cli: click.Group) -> click.Group:
31
+ """
32
+ Add the 'index' subcommand to the CLI.
33
+
34
+ This function defines and adds the 'index' subcommand to the provided Click CLI application.
35
+ The subcommand is responsible for creating index files for tar archives in a Hugging Face repository
36
+ and uploading them to a specified index repository.
37
+
38
+ :param cli: The Click CLI application to which the 'index' subcommand will be added.
39
+ :type cli: click.Group
40
+
41
+ :return: The modified Click CLI application with the 'index' subcommand added.
42
+ :rtype: click.Group
43
+
44
+ Usage:
45
+ This function is typically called when setting up the CLI application, like this:
46
+ cli = click.Group()
47
+ cli = _add_index_subcommand(cli)
48
+ """
49
+
50
+ @cli.command('index', help='Make index repository for tar repository.\n\n'
51
+ 'Set environment $HF_TOKEN to use your own access token.',
52
+ context_settings=CONTEXT_SETTINGS)
53
+ @click.option('-r', '--repository', 'repo_id', type=str, required=True,
54
+ help='Repository with tar archives inside.')
55
+ @click.option('-x', '--index_repository', 'idx_repo_id', type=str, default=None,
56
+ help='Repository to create index files. Use the same repository as `-r` option when not given.',
57
+ show_default=True)
58
+ @click.option('-t', '--type', 'repo_type', type=click.Choice(REPO_TYPES), default='dataset',
59
+ help='Type of the HuggingFace repository.', show_default=True)
60
+ @click.option('-R', '--revision', 'revision', type=str, default='main',
61
+ help='Revision of repository.', show_default=True)
62
+ @click.option('--min_upload_interval', 'min_upload_interval', type=float, default=60,
63
+ help='Min seconds for uploading to huggingface repository.', show_default=True)
64
+ def index(repo_id: str, idx_repo_id: Optional[str], repo_type: RepoTypeTyping, revision: str,
65
+ min_upload_interval: float):
66
+ """
67
+ Create index files for tar archives in a Hugging Face repository and upload them to a specified index repository.
68
+
69
+ This function sets up logging, creates the index repository if it doesn't exist, processes tar archives
70
+ to create index files, and manages the upload process of these index files to the specified repository.
71
+
72
+ :param repo_id: The ID of the repository containing tar archives.
73
+ :type repo_id: str
74
+ :param idx_repo_id: The ID of the repository where index files will be uploaded. If None, uses repo_id.
75
+ :type idx_repo_id: Optional[str]
76
+ :param repo_type: The type of the Hugging Face repository (e.g., 'dataset', 'model').
77
+ :type repo_type: RepoTypeTyping
78
+ :param revision: The revision of the repository to use.
79
+ :type revision: str
80
+ :param min_upload_interval: The minimum time interval (in seconds) between uploads to the Hugging Face repository.
81
+ :type min_upload_interval: float
82
+
83
+ :raises: Various exceptions may be raised during file system operations or API calls.
84
+
85
+ Usage:
86
+ This function is typically invoked through the CLI interface, like:
87
+ $ python script.py index -r my_repo -x my_index_repo -t dataset -R main --min_upload_interval 120
88
+ """
89
+ logger = logging.getLogger()
90
+ logger.setLevel(logging.INFO)
91
+ console_handler = logging.StreamHandler()
92
+ console_handler.setFormatter(ColoredFormatter())
93
+ logger.addHandler(console_handler)
94
+
95
+ idx_repo_id = idx_repo_id or repo_id
96
+ delete_detached_cache(repo_id=repo_id, repo_type=repo_type)
97
+
98
+ hf_client = get_hf_client()
99
+ if not hf_client.repo_exists(repo_id=idx_repo_id, repo_type=repo_type):
100
+ logging.info(f'Creating repository {idx_repo_id!r}, type: {repo_type!r} ...')
101
+ hf_client.create_repo(repo_id=idx_repo_id, repo_type=repo_type)
102
+
103
+ hf_fs = get_hf_fs()
104
+ hf_tars = hf_fs.glob(hf_fs_path(repo_id=repo_id, repo_type=repo_type, filename='**/*.tar', revision=revision))
105
+ logging.info(f'{plural_word(len(hf_tars), "tar archive")} found in {repo_type}s/{repo_id} ...')
106
+ with TemporaryDirectory() as upload_dir:
107
+ idx_files = []
108
+ last_uploaded_at: Optional[float] = None
109
+
110
+ def _upload(force=False):
111
+ """
112
+ Upload index files to the Hugging Face repository.
113
+
114
+ This internal function manages the upload process of index files, respecting the minimum upload interval.
115
+
116
+ :param force: If True, upload regardless of the time since the last upload.
117
+ :type force: bool
118
+ """
119
+ nonlocal last_uploaded_at
120
+
121
+ if not idx_files:
122
+ return
123
+ if not force and last_uploaded_at and last_uploaded_at + min_upload_interval > time.time():
124
+ return
125
+
126
+ logging.info(f'Uploading index for {plural_word(len(idx_files), "tar archives")} ...')
127
+ upload_directory_as_directory(
128
+ repo_id=idx_repo_id,
129
+ repo_type=repo_type,
130
+ revision=revision,
131
+ local_directory=upload_dir,
132
+ path_in_repo='.',
133
+ message=f'Index for {plural_word(len(idx_files), "tar archives")} - '
134
+ f'{", ".join(map(repr, idx_files))}',
135
+ )
136
+ last_uploaded_at = time.time()
137
+
138
+ _clean_dir()
139
+
140
+ def _clean_dir():
141
+ """
142
+ Clean the temporary upload directory.
143
+
144
+ This internal function removes all files and directories in the upload directory.
145
+ """
146
+ logging.info(f'Cleaning upload temporary directory {upload_dir!r} ...')
147
+ for item in os.listdir(upload_dir):
148
+ dst_file = os.path.join(upload_dir, item)
149
+ if os.path.isfile(dst_file):
150
+ os.remove(dst_file)
151
+ elif os.path.islink(dst_file):
152
+ os.unlink(dst_file)
153
+ elif os.path.isdir(dst_file):
154
+ shutil.rmtree(dst_file)
155
+ idx_files.clear()
156
+ logging.info('Upload directory cleaned.')
157
+
158
+ for tar_path in tqdm(hf_tars, desc='Making Indices'):
159
+ tar_filename = parse_hf_fs_path(tar_path).filename
160
+ idx_filename = hf_normpath(os.path.splitext(tar_filename)[0] + '.json')
161
+ if not hf_tar_validate(
162
+ repo_id=repo_id,
163
+ repo_type=repo_type,
164
+ archive_in_repo=tar_filename,
165
+ idx_repo_id=idx_repo_id,
166
+ revision=revision,
167
+ ):
168
+ src_hf_path = hf_fs_path(repo_id=repo_id, repo_type=repo_type,
169
+ filename=tar_filename, revision=revision)
170
+ dst_hf_path = hf_fs_path(repo_id=idx_repo_id, repo_type=repo_type,
171
+ filename=idx_filename, revision=revision)
172
+ logging.info(f'Indexing {src_hf_path!r} --> {dst_hf_path!r} ...')
173
+ with TemporaryDirectory() as td:
174
+ local_tar_file = os.path.join(td, os.path.basename(tar_filename))
175
+ local_idx_file = os.path.join(upload_dir, idx_filename)
176
+ if os.path.dirname(local_idx_file):
177
+ os.makedirs(os.path.dirname(local_idx_file), exist_ok=True)
178
+
179
+ download_file_to_file(
180
+ repo_id=repo_id,
181
+ repo_type=repo_type,
182
+ file_in_repo=tar_filename,
183
+ local_file=local_tar_file,
184
+ revision=revision,
185
+ )
186
+ logging.debug(f'Creating index file {local_tar_file!r} --> {local_idx_file!r} ...')
187
+ tar_create_index(
188
+ src_tar_file=local_tar_file,
189
+ dst_index_file=local_idx_file,
190
+ )
191
+ idx_files.append(idx_filename)
192
+
193
+ _upload(force=False)
194
+
195
+ _upload(force=True)
196
+
197
+ return cli
@@ -1,5 +1,6 @@
1
1
  from .binary import is_binary_file
2
2
  from .download import download_file
3
+ from .logging import ColoredFormatter
3
4
  from .path import hf_normpath, hf_fs_path, parse_hf_fs_path, HfFileSystemPath
4
5
  from .temp import TemporaryDirectory
5
6
  from .tqdm_ import tqdm
@@ -0,0 +1,69 @@
1
+ """
2
+ Overview:
3
+ This module provides functionality to enhance logging output with colors for different log levels.
4
+ It includes a `Colors` class defining ANSI escape sequences for various colors and styles,
5
+ and a `ColoredFormatter` class to format log messages with these colors based on their severity level.
6
+ """
7
+
8
+ import logging
9
+
10
+
11
+ class Colors:
12
+ """
13
+ A collection of ANSI escape sequences for terminal text coloring and styling.
14
+ These constants can be used to format strings with various colors and text styles.
15
+ """
16
+ RESET = "\033[0m"
17
+ BOLD = "\033[1m"
18
+ UNDERLINE = "\033[4m"
19
+ BLACK = "\033[30m"
20
+ RED = "\033[31m"
21
+ GREEN = "\033[32m"
22
+ YELLOW = "\033[33m"
23
+ BLUE = "\033[34m"
24
+ MAGENTA = "\033[35m"
25
+ CYAN = "\033[36m"
26
+ WHITE = "\033[37m"
27
+ BRIGHT_BLACK = "\033[90m"
28
+ BRIGHT_RED = "\033[91m"
29
+ BRIGHT_GREEN = "\033[92m"
30
+ BRIGHT_YELLOW = "\033[93m"
31
+ BRIGHT_BLUE = "\033[94m"
32
+ BRIGHT_MAGENTA = "\033[95m"
33
+ BRIGHT_CYAN = "\033[96m"
34
+ BRIGHT_WHITE = "\033[97m"
35
+
36
+
37
+ class ColoredFormatter(logging.Formatter):
38
+ """
39
+ A logging formatter that applies colors to log messages based on their severity level.
40
+
41
+ The colors are defined in the `Colors` class and are applied to different parts of the log message
42
+ such as the timestamp, log level, logger name, and the message itself.
43
+ """
44
+ COLORS = {
45
+ 'DEBUG': Colors.BLUE,
46
+ 'INFO': Colors.GREEN,
47
+ 'WARNING': Colors.YELLOW,
48
+ 'ERROR': Colors.RED,
49
+ 'CRITICAL': Colors.BOLD + Colors.RED,
50
+ }
51
+
52
+ def format(self, record):
53
+ """
54
+ Format the specified record as text, applying color based on the log level.
55
+
56
+ :param record: The log record to be formatted.
57
+ :type record: logging.LogRecord
58
+
59
+ :return: The formatted log message with appropriate colors.
60
+ :rtype: str
61
+ """
62
+ log_color = self.COLORS.get(record.levelname, Colors.RESET)
63
+ format_str = f"{Colors.BRIGHT_BLACK}[%(asctime)s]{Colors.RESET} "
64
+ format_str += f"{log_color}%(levelname)-8s{Colors.RESET} "
65
+ format_str += f"{Colors.CYAN}%(name)s{Colors.RESET} - "
66
+ format_str += f"{Colors.WHITE}%(message)s{Colors.RESET}"
67
+
68
+ formatter = logging.Formatter(format_str, datefmt="%Y-%m-%d %H:%M:%S")
69
+ return formatter.format(record)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hfutils
3
- Version: 0.2.8
3
+ Version: 0.2.10
4
4
  Summary: Useful utilities for huggingface
5
5
  Home-page: https://github.com/deepghs/hfutils
6
6
  Author: narugo1992
@@ -27,9 +27,6 @@ Requires-Dist: requests
27
27
  Requires-Dist: click>=7
28
28
  Requires-Dist: tzlocal
29
29
  Requires-Dist: natsort
30
- Provides-Extra: build
31
- Requires-Dist: pyinstaller<5,>=4.7; extra == "build"
32
- Requires-Dist: setuptools<70; extra == "build"
33
30
  Provides-Extra: doc
34
31
  Requires-Dist: Jinja2>=3.0.0; extra == "doc"
35
32
  Requires-Dist: sphinx>=3.2.0; extra == "doc"
@@ -50,10 +47,15 @@ Requires-Dist: ipykernel>=6.15; extra == "doc"
50
47
  Requires-Dist: py-cpuinfo>=8.0.0; extra == "doc"
51
48
  Requires-Dist: click>=7.0.0; extra == "doc"
52
49
  Requires-Dist: pandas; extra == "doc"
53
- Provides-Extra: 7z
54
- Requires-Dist: py7zr; extra == "7z"
55
50
  Provides-Extra: transfer
56
51
  Requires-Dist: hf-transfer; extra == "transfer"
52
+ Provides-Extra: rar
53
+ Requires-Dist: rarfile; extra == "rar"
54
+ Provides-Extra: 7z
55
+ Requires-Dist: py7zr; extra == "7z"
56
+ Provides-Extra: build
57
+ Requires-Dist: pyinstaller<5,>=4.7; extra == "build"
58
+ Requires-Dist: setuptools<70; extra == "build"
57
59
  Provides-Extra: test
58
60
  Requires-Dist: coverage>=5; extra == "test"
59
61
  Requires-Dist: mock>=4.0.3; extra == "test"
@@ -71,8 +73,6 @@ Requires-Dist: testtools>=2; extra == "test"
71
73
  Requires-Dist: where>=1.0.2; extra == "test"
72
74
  Requires-Dist: responses>=0.20.0; extra == "test"
73
75
  Requires-Dist: natsort; extra == "test"
74
- Provides-Extra: rar
75
- Requires-Dist: rarfile; extra == "rar"
76
76
 
77
77
  # hfutils
78
78
 
@@ -23,6 +23,8 @@ hfutils/archive/rar.py
23
23
  hfutils/archive/sevenz.py
24
24
  hfutils/archive/tar.py
25
25
  hfutils/archive/zip.py
26
+ hfutils/cache/__init__.py
27
+ hfutils/cache/delete.py
26
28
  hfutils/config/__init__.py
27
29
  hfutils/config/meta.py
28
30
  hfutils/entry/__init__.py
@@ -30,6 +32,7 @@ hfutils/entry/base.py
30
32
  hfutils/entry/cli.py
31
33
  hfutils/entry/dispatch.py
32
34
  hfutils/entry/download.py
35
+ hfutils/entry/index.py
33
36
  hfutils/entry/ls.py
34
37
  hfutils/entry/ls_repo.py
35
38
  hfutils/entry/upload.py
@@ -48,6 +51,7 @@ hfutils/utils/__init__.py
48
51
  hfutils/utils/binary.py
49
52
  hfutils/utils/download.py
50
53
  hfutils/utils/irregular_repo.json
54
+ hfutils/utils/logging.py
51
55
  hfutils/utils/path.py
52
56
  hfutils/utils/temp.py
53
57
  hfutils/utils/tqdm_.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