hfutils 0.4.3__tar.gz → 0.5.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.
Files changed (83) hide show
  1. {hfutils-0.4.3/hfutils.egg-info → hfutils-0.5.0}/PKG-INFO +22 -22
  2. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/archive/base.py +56 -11
  3. hfutils-0.5.0/hfutils/archive/rar.py +61 -0
  4. hfutils-0.5.0/hfutils/archive/sevenz.py +68 -0
  5. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/archive/tar.py +45 -2
  6. hfutils-0.5.0/hfutils/archive/zip.py +73 -0
  7. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/config/meta.py +1 -1
  8. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/entry/cli.py +2 -0
  9. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/entry/download.py +34 -5
  10. hfutils-0.5.0/hfutils/entry/squash.py +71 -0
  11. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/entry/upload.py +45 -3
  12. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/index/make.py +6 -1
  13. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/operate/__init__.py +1 -0
  14. hfutils-0.5.0/hfutils/operate/duplicate.py +57 -0
  15. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/operate/upload.py +42 -10
  16. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/repository/__init__.py +1 -0
  17. hfutils-0.5.0/hfutils/repository/url.py +86 -0
  18. hfutils-0.5.0/hfutils/utils/binary.py +38 -0
  19. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/utils/number.py +12 -0
  20. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/utils/path.py +29 -1
  21. hfutils-0.5.0/hfutils/utils/walk.py +38 -0
  22. {hfutils-0.4.3 → hfutils-0.5.0/hfutils.egg-info}/PKG-INFO +22 -22
  23. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils.egg-info/SOURCES.txt +3 -0
  24. hfutils-0.4.3/hfutils/archive/rar.py +0 -28
  25. hfutils-0.4.3/hfutils/archive/sevenz.py +0 -32
  26. hfutils-0.4.3/hfutils/archive/zip.py +0 -40
  27. hfutils-0.4.3/hfutils/utils/binary.py +0 -20
  28. hfutils-0.4.3/hfutils/utils/walk.py +0 -18
  29. {hfutils-0.4.3 → hfutils-0.5.0}/LICENSE +0 -0
  30. {hfutils-0.4.3 → hfutils-0.5.0}/MANIFEST.in +0 -0
  31. {hfutils-0.4.3 → hfutils-0.5.0}/README.md +0 -0
  32. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/__init__.py +0 -0
  33. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/__main__.py +0 -0
  34. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/archive/__init__.py +0 -0
  35. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/cache/__init__.py +0 -0
  36. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/cache/delete.py +0 -0
  37. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/config/__init__.py +0 -0
  38. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/entry/__init__.py +0 -0
  39. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/entry/base.py +0 -0
  40. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/entry/clone.py +0 -0
  41. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/entry/dispatch.py +0 -0
  42. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/entry/ils.py +0 -0
  43. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/entry/index.py +0 -0
  44. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/entry/ls.py +0 -0
  45. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/entry/ls_repo.py +0 -0
  46. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/entry/rollback.py +0 -0
  47. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/entry/tree.py +0 -0
  48. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/entry/whoami.py +0 -0
  49. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/index/__init__.py +0 -0
  50. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/index/fetch.py +0 -0
  51. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/index/hash.py +0 -0
  52. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/index/local_fetch.py +0 -0
  53. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/index/validate.py +0 -0
  54. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/operate/base.py +0 -0
  55. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/operate/download.py +0 -0
  56. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/operate/validate.py +0 -0
  57. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/repository/base.py +0 -0
  58. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/repository/clone.py +0 -0
  59. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/repository/rollback.py +0 -0
  60. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/utils/__init__.py +0 -0
  61. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/utils/archive.py +0 -0
  62. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/utils/data.py +0 -0
  63. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/utils/download.py +0 -0
  64. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/utils/irregular_repo.json +0 -0
  65. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/utils/logging.py +0 -0
  66. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/utils/model.py +0 -0
  67. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/utils/session.py +0 -0
  68. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/utils/temp.py +0 -0
  69. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/utils/tqdm_.py +0 -0
  70. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils/utils/type_.py +0 -0
  71. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils.egg-info/dependency_links.txt +0 -0
  72. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils.egg-info/entry_points.txt +0 -0
  73. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils.egg-info/requires.txt +0 -0
  74. {hfutils-0.4.3 → hfutils-0.5.0}/hfutils.egg-info/top_level.txt +0 -0
  75. {hfutils-0.4.3 → hfutils-0.5.0}/requirements-7z.txt +0 -0
  76. {hfutils-0.4.3 → hfutils-0.5.0}/requirements-build.txt +0 -0
  77. {hfutils-0.4.3 → hfutils-0.5.0}/requirements-doc.txt +0 -0
  78. {hfutils-0.4.3 → hfutils-0.5.0}/requirements-rar.txt +0 -0
  79. {hfutils-0.4.3 → hfutils-0.5.0}/requirements-test.txt +0 -0
  80. {hfutils-0.4.3 → hfutils-0.5.0}/requirements-transfer.txt +0 -0
  81. {hfutils-0.4.3 → hfutils-0.5.0}/requirements.txt +0 -0
  82. {hfutils-0.4.3 → hfutils-0.5.0}/setup.cfg +0 -0
  83. {hfutils-0.4.3 → hfutils-0.5.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hfutils
3
- Version: 0.4.3
3
+ Version: 0.5.0
4
4
  Summary: Useful utilities for huggingface
5
5
  Home-page: https://github.com/deepghs/hfutils
6
6
  Author: narugo1992
@@ -30,13 +30,32 @@ Requires-Dist: natsort
30
30
  Requires-Dist: urlobject
31
31
  Requires-Dist: fsspec>=2024
32
32
  Requires-Dist: random_user_agent
33
+ Provides-Extra: rar
34
+ Requires-Dist: rarfile; extra == "rar"
33
35
  Provides-Extra: build
34
36
  Requires-Dist: pyinstaller<5,>=4.7; extra == "build"
35
37
  Requires-Dist: setuptools<70; extra == "build"
38
+ Provides-Extra: transfer
39
+ Requires-Dist: hf-transfer; extra == "transfer"
36
40
  Provides-Extra: 7z
37
41
  Requires-Dist: py7zr; extra == "7z"
38
- Provides-Extra: rar
39
- Requires-Dist: rarfile; extra == "rar"
42
+ Provides-Extra: test
43
+ Requires-Dist: coverage>=5; extra == "test"
44
+ Requires-Dist: mock>=4.0.3; extra == "test"
45
+ Requires-Dist: flake8~=3.5; extra == "test"
46
+ Requires-Dist: testfixtures>=6.18.5; extra == "test"
47
+ Requires-Dist: pytest~=6.2.5; extra == "test"
48
+ Requires-Dist: pytest-cov~=3.0.0; extra == "test"
49
+ Requires-Dist: pytest-mock~=3.6.1; extra == "test"
50
+ Requires-Dist: pytest-xdist>=1.34.0; extra == "test"
51
+ Requires-Dist: pytest-rerunfailures~=10.2; extra == "test"
52
+ Requires-Dist: pytest-timeout~=2.0.2; extra == "test"
53
+ Requires-Dist: pytest-benchmark~=3.4.0; extra == "test"
54
+ Requires-Dist: easydict<2,>=1.7; extra == "test"
55
+ Requires-Dist: testtools>=2; extra == "test"
56
+ Requires-Dist: where>=1.0.2; extra == "test"
57
+ Requires-Dist: responses>=0.20.0; extra == "test"
58
+ Requires-Dist: natsort; extra == "test"
40
59
  Provides-Extra: doc
41
60
  Requires-Dist: Jinja2>=3.0.0; extra == "doc"
42
61
  Requires-Dist: sphinx>=3.2.0; extra == "doc"
@@ -57,25 +76,6 @@ Requires-Dist: ipykernel>=6.15; extra == "doc"
57
76
  Requires-Dist: py-cpuinfo>=8.0.0; extra == "doc"
58
77
  Requires-Dist: click>=7.0.0; extra == "doc"
59
78
  Requires-Dist: pandas; extra == "doc"
60
- Provides-Extra: test
61
- Requires-Dist: coverage>=5; extra == "test"
62
- Requires-Dist: mock>=4.0.3; extra == "test"
63
- Requires-Dist: flake8~=3.5; extra == "test"
64
- Requires-Dist: testfixtures>=6.18.5; extra == "test"
65
- Requires-Dist: pytest~=6.2.5; extra == "test"
66
- Requires-Dist: pytest-cov~=3.0.0; extra == "test"
67
- Requires-Dist: pytest-mock~=3.6.1; extra == "test"
68
- Requires-Dist: pytest-xdist>=1.34.0; extra == "test"
69
- Requires-Dist: pytest-rerunfailures~=10.2; extra == "test"
70
- Requires-Dist: pytest-timeout~=2.0.2; extra == "test"
71
- Requires-Dist: pytest-benchmark~=3.4.0; extra == "test"
72
- Requires-Dist: easydict<2,>=1.7; extra == "test"
73
- Requires-Dist: testtools>=2; extra == "test"
74
- Requires-Dist: where>=1.0.2; extra == "test"
75
- Requires-Dist: responses>=0.20.0; extra == "test"
76
- Requires-Dist: natsort; extra == "test"
77
- Provides-Extra: transfer
78
- Requires-Dist: hf-transfer; extra == "transfer"
79
79
 
80
80
  # hfutils
81
81
 
@@ -1,3 +1,15 @@
1
+ """
2
+ This module provides functionality for handling archive files in various formats.
3
+
4
+ It includes functions for registering custom archive types, packing directories into archives,
5
+ unpacking archives, and determining archive types based on file extensions. The module supports
6
+ a flexible system for working with different archive formats through a registration mechanism.
7
+
8
+ .. note::
9
+ This module uses a global dictionary to store registered archive types, so it's
10
+ important to register custom types before using the packing and unpacking functions.
11
+ """
12
+
1
13
  import os.path
2
14
  import warnings
3
15
  from typing import List, Dict, Tuple, Callable, Optional
@@ -9,14 +21,27 @@ def register_archive_type(name: str, exts: List[str], fn_pack: Callable, fn_unpa
9
21
  """
10
22
  Register a custom archive type with associated file extensions and packing/unpacking functions.
11
23
 
12
- :param name: The name of the archive type.
24
+ This function allows users to add support for new archive types by providing the necessary
25
+ information and functions to handle the archive format.
26
+
27
+ :param name: The name of the archive type (e.g., 'zip', 'tar').
13
28
  :type name: str
14
- :param exts: A list of file extensions associated with the archive type.
29
+ :param exts: A list of file extensions associated with the archive type (e.g., ['.zip']).
15
30
  :type exts: List[str]
16
31
  :param fn_pack: The packing function that takes a directory and an archive filename as input and creates an archive.
17
32
  :type fn_pack: Callable
18
33
  :param fn_unpack: The unpacking function that takes an archive filename and a directory as input and extracts the archive.
19
34
  :type fn_unpack: Callable
35
+ :raises ValueError: If no file extensions are provided for the archive type.
36
+
37
+ Example:
38
+ >>> def custom_pack(directory, archive_file, **kwargs):
39
+ ... # Custom packing logic here
40
+ ... pass
41
+ >>> def custom_unpack(archive_file, directory, **kwargs):
42
+ ... # Custom unpacking logic here
43
+ ... pass
44
+ >>> register_archive_type('custom', ['.cst'], custom_pack, custom_unpack)
20
45
  """
21
46
  if len(exts) == 0:
22
47
  raise ValueError(f'At least one extension name for archive type {name!r} should be provided.')
@@ -27,12 +52,17 @@ def get_archive_extname(type_name: str) -> str:
27
52
  """
28
53
  Get the file extension associated with a registered archive type.
29
54
 
55
+ This function returns the first (primary) file extension associated with the given archive type.
56
+
30
57
  :param type_name: The name of the archive type.
31
58
  :type type_name: str
32
-
33
59
  :return: The file extension associated with the archive type.
34
60
  :rtype: str
35
61
  :raises ValueError: If the archive type is not registered.
62
+
63
+ Example:
64
+ >>> get_archive_extname('zip')
65
+ '.zip'
36
66
  """
37
67
  if type_name in _KNOWN_ARCHIVE_TYPES:
38
68
  exts, _, _ = _KNOWN_ARCHIVE_TYPES[type_name]
@@ -41,23 +71,29 @@ def get_archive_extname(type_name: str) -> str:
41
71
  raise ValueError(f'Unknown archive type - {type_name!r}.')
42
72
 
43
73
 
44
- def archive_pack(type_name: str, directory: str, archive_file: str, silent: bool = False, clear: bool = False):
74
+ def archive_pack(type_name: str, directory: str, archive_file: str,
75
+ pattern: Optional[str] = None, silent: bool = False, clear: bool = False):
45
76
  """
46
77
  Pack a directory into an archive file using the specified archive type.
47
78
 
79
+ This function creates an archive of the specified type containing the contents of the given directory.
80
+
48
81
  :param type_name: The name of the archive type.
49
82
  :type type_name: str
50
83
  :param directory: The directory to pack.
51
84
  :type directory: str
52
85
  :param archive_file: The filename of the resulting archive.
53
86
  :type archive_file: str
87
+ :param pattern: A pattern to filter files for inclusion in the archive (optional).
88
+ :type pattern: str, optional
54
89
  :param silent: If True, suppress warnings during the packing process.
55
90
  :type silent: bool
56
91
  :param clear: If True, remove existing files when packing.
57
92
  :type clear: bool
93
+ :raises ValueError: If the archive type is not registered.
58
94
 
59
- :return: The path to the created archive file.
60
- :rtype: str
95
+ Example:
96
+ >>> archive_pack('zip', '/path/to/directory', '/path/to/archive.zip', pattern='*.txt')
61
97
  """
62
98
  exts, fn_pack, _ = _KNOWN_ARCHIVE_TYPES[type_name]
63
99
  if not any(os.path.normcase(archive_file).endswith(extname) for extname in exts):
@@ -65,19 +101,25 @@ def archive_pack(type_name: str, directory: str, archive_file: str, silent: bool
65
101
  f'but file name {archive_file!r} is assigned. '
66
102
  f'We strongly recommend using a regular extension name for the archive file.')
67
103
 
68
- return fn_pack(directory, archive_file, silent=silent, clear=clear)
104
+ return fn_pack(directory, archive_file, pattern=pattern, silent=silent, clear=clear)
69
105
 
70
106
 
71
107
  def get_archive_type(archive_file: str) -> str:
72
108
  """
73
109
  Determine the archive type based on the file extension.
74
110
 
111
+ This function examines the file extension of the given archive file and returns the
112
+ corresponding archive type name.
113
+
75
114
  :param archive_file: The filename of the archive.
76
115
  :type archive_file: str
77
-
78
116
  :return: The name of the archive type.
79
117
  :rtype: str
80
118
  :raises ValueError: If the file extension is not associated with any registered archive type.
119
+
120
+ Example:
121
+ >>> get_archive_type('/path/to/archive.tar.gz')
122
+ 'gztar'
81
123
  """
82
124
  archive_file = os.path.normcase(archive_file)
83
125
  for type_name, (exts, _, _) in _KNOWN_ARCHIVE_TYPES.items():
@@ -91,17 +133,20 @@ def archive_unpack(archive_file: str, directory: str, silent: bool = False, pass
91
133
  """
92
134
  Unpack an archive file into a directory using the specified archive type.
93
135
 
136
+ This function extracts the contents of the given archive file into the specified directory.
137
+
94
138
  :param archive_file: The filename of the archive.
95
139
  :type archive_file: str
96
140
  :param directory: The directory to unpack the contents into.
97
141
  :type directory: str
98
142
  :param silent: If True, suppress warnings during the unpacking process.
99
143
  :type silent: bool
100
- :param password: The password to extract the archive file.
144
+ :param password: The password to extract the archive file (optional).
101
145
  :type password: str, optional
146
+ :raises ValueError: If the archive type is not recognized.
102
147
 
103
- :return: The path to the unpacked directory.
104
- :rtype: str
148
+ Example:
149
+ >>> archive_unpack('/path/to/archive.zip', '/path/to/extract')
105
150
  """
106
151
  type_name = get_archive_type(archive_file)
107
152
  _, _, fn_unpack = _KNOWN_ARCHIVE_TYPES[type_name]
@@ -0,0 +1,61 @@
1
+ """
2
+ This module provides functionality for handling RAR archives.
3
+
4
+ It includes functions for unpacking RAR files and a placeholder for packing (which is not supported).
5
+ The module uses the 'rarfile' library for RAR file operations.
6
+
7
+ .. note::
8
+ The 'rarfile' library is optional. If not installed, RAR functionality will be limited.
9
+ """
10
+
11
+ import os
12
+ from typing import Optional
13
+
14
+ from .base import register_archive_type
15
+
16
+ try:
17
+ import rarfile
18
+ except ImportError: # pragma: no cover
19
+ rarfile = None
20
+
21
+
22
+ def _rar_pack(directory, zip_file, pattern: Optional[str] = None, silent: bool = False, clear: bool = False):
23
+ """
24
+ Placeholder function for RAR packing (not supported).
25
+
26
+ :param directory: The directory to pack.
27
+ :param zip_file: The output RAR file.
28
+ :param pattern: Optional pattern for file selection.
29
+ :type pattern: str, optional
30
+ :param silent: If True, suppress output. Defaults to False.
31
+ :type silent: bool
32
+ :param clear: If True, clear the directory after packing. Defaults to False.
33
+ :type clear: bool
34
+ :raises RuntimeError: Always raised as RAR packing is not supported.
35
+ """
36
+ _ = directory, zip_file, pattern, silent, clear
37
+ raise RuntimeError('RAR format packing is not supported.')
38
+
39
+
40
+ def _rar_unpack(rar_file, directory, silent: bool = False, password: Optional[str] = None):
41
+ """
42
+ Unpack a RAR file to a specified directory.
43
+
44
+ :param rar_file: The RAR file to unpack.
45
+ :param directory: The directory to unpack the RAR file into.
46
+ :param silent: If True, suppress output. Defaults to False.
47
+ :type silent: bool
48
+ :param password: Optional password for encrypted RAR files.
49
+ :type password: str, optional
50
+ """
51
+ _ = silent
52
+ directory = os.fspath(directory)
53
+ os.makedirs(directory, exist_ok=True)
54
+ with rarfile.RarFile(rar_file, 'r') as zf:
55
+ if password is not None:
56
+ zf.setpassword(password)
57
+ zf.extractall(directory)
58
+
59
+
60
+ if rarfile is not None:
61
+ register_archive_type('rar', ['.rar'], _rar_pack, _rar_unpack)
@@ -0,0 +1,68 @@
1
+ """
2
+ This module provides functionality for handling 7z archive files.
3
+
4
+ It includes functions for packing and unpacking 7z archives, and registers
5
+ the 7z archive type if the py7zr library is available.
6
+
7
+ .. note::
8
+ `py7zr` is required for 7z archive operations. If not available, 7z functionality will be disabled.
9
+ """
10
+
11
+ import os
12
+ from typing import Optional
13
+
14
+ from .base import register_archive_type
15
+ from ..utils import tqdm, walk_files
16
+
17
+ try:
18
+ import py7zr
19
+ except ImportError: # pragma: no cover
20
+ py7zr = None
21
+
22
+
23
+ def _7z_pack(directory, sz_file, pattern: Optional[str] = None, silent: bool = False, clear: bool = False):
24
+ """
25
+ Pack files from a directory into a 7z archive.
26
+
27
+ :param directory: The source directory containing files to be packed.
28
+ :type directory: str
29
+ :param sz_file: The path to the output 7z file.
30
+ :type sz_file: str
31
+ :param pattern: Optional file pattern to filter files for packing.
32
+ :type pattern: str, optional
33
+ :param silent: If True, suppress progress output.
34
+ :type silent: bool, optional
35
+ :param clear: If True, remove source files after packing.
36
+ :type clear: bool, optional
37
+ """
38
+ with py7zr.SevenZipFile(sz_file, 'w') as zf:
39
+ progress = tqdm(walk_files(directory, pattern=pattern), silent=silent, desc=f'Packing {directory!r} ...')
40
+ for file in progress:
41
+ progress.set_description(file)
42
+ zf.write(os.path.join(directory, file), file)
43
+ if clear:
44
+ os.remove(os.path.join(directory, file))
45
+
46
+
47
+ def _7z_unpack(sz_file, directory, silent: bool = False, password: Optional[str] = None):
48
+ """
49
+ Unpack files from a 7z archive to a directory.
50
+
51
+ :param sz_file: The path to the 7z file to be unpacked.
52
+ :type sz_file: str
53
+ :param directory: The destination directory for unpacked files.
54
+ :type directory: str
55
+ :param silent: If True, suppress progress output (currently unused).
56
+ :type silent: bool, optional
57
+ :param password: Optional password for encrypted archives.
58
+ :type password: str, optional
59
+ """
60
+ _ = silent
61
+ directory = os.fspath(directory)
62
+ os.makedirs(directory, exist_ok=True)
63
+ with py7zr.SevenZipFile(sz_file, 'r', password=password) as zf:
64
+ zf.extractall(directory)
65
+
66
+
67
+ if py7zr is not None:
68
+ register_archive_type('7z', ['.7z'], _7z_pack, _7z_unpack)
@@ -1,3 +1,13 @@
1
+ """
2
+ This module provides functionality for working with tar archive files.
3
+
4
+ It includes functions for packing and unpacking tar archives with various compression options.
5
+ The module also registers different tar archive types based on the available compression libraries.
6
+
7
+ .. note::
8
+ Some compression methods may not be available depending on the system's installed libraries.
9
+ """
10
+
1
11
  import copy
2
12
  import os.path
3
13
  import tarfile
@@ -28,7 +38,25 @@ except ImportError:
28
38
  CompressTyping = Literal['', 'gzip', 'bzip2', 'xz']
29
39
 
30
40
 
31
- def _tarfile_pack(directory, tar_file, compress: CompressTyping = "gzip", silent: bool = False, clear: bool = False):
41
+ def _tarfile_pack(directory, tar_file, pattern: Optional[str] = None,
42
+ compress: CompressTyping = "gzip", silent: bool = False, clear: bool = False):
43
+ """
44
+ Pack a directory into a tar archive file with optional compression.
45
+
46
+ :param directory: The directory to pack.
47
+ :type directory: str
48
+ :param tar_file: The name of the tar file to create.
49
+ :type tar_file: str
50
+ :param pattern: Optional file pattern to filter files for packing.
51
+ :type pattern: str, optional
52
+ :param compress: Compression method to use ('', 'gzip', 'bzip2', 'xz').
53
+ :type compress: CompressTyping
54
+ :param silent: If True, suppress progress output.
55
+ :type silent: bool
56
+ :param clear: If True, remove packed files from the source directory.
57
+ :type clear: bool
58
+ :raises ValueError: If an unsupported compression method is specified.
59
+ """
32
60
  if compress is None:
33
61
  tar_compression = ''
34
62
  elif compress == 'gzip':
@@ -42,7 +70,7 @@ def _tarfile_pack(directory, tar_file, compress: CompressTyping = "gzip", silent
42
70
  "supported : {0}".format(compress))
43
71
 
44
72
  with tarfile.open(tar_file, f'w|{tar_compression}') as tar:
45
- progress = tqdm(walk_files(directory), silent=silent, desc=f'Packing {directory!r} ...')
73
+ progress = tqdm(walk_files(directory, pattern=pattern), silent=silent, desc=f'Packing {directory!r} ...')
46
74
  for file in progress:
47
75
  progress.set_description(file)
48
76
  tar.add(os.path.join(directory, file), file)
@@ -51,6 +79,20 @@ def _tarfile_pack(directory, tar_file, compress: CompressTyping = "gzip", silent
51
79
 
52
80
 
53
81
  def _tarfile_unpack(tar_file, directory, silent: bool = False, numeric_owner=False, password: Optional[str] = None):
82
+ """
83
+ Unpack a tar archive file into a directory.
84
+
85
+ :param tar_file: The tar file to unpack.
86
+ :type tar_file: str
87
+ :param directory: The directory to unpack the files into.
88
+ :type directory: str
89
+ :param silent: If True, suppress progress output.
90
+ :type silent: bool
91
+ :param numeric_owner: If True, use numeric owner (UID, GID) instead of names.
92
+ :type numeric_owner: bool
93
+ :param password: Ignored for tar files (included for compatibility with other archive types).
94
+ :type password: str, optional
95
+ """
54
96
  if password is not None:
55
97
  warnings.warn('Password is not supported in tar archive files.\n'
56
98
  'So assigned password will be ignored.')
@@ -82,6 +124,7 @@ def _tarfile_unpack(tar_file, directory, silent: bool = False, numeric_owner=Fal
82
124
  tar.chmod(tarinfo, dirpath)
83
125
 
84
126
 
127
+ # Register various tar archive types based on available compression libraries
85
128
  register_archive_type('tar', ['.tar'], partial(_tarfile_pack, compress=None), _tarfile_unpack)
86
129
  if _ZLIB_SUPPORTED:
87
130
  register_archive_type('gztar', ['.tar.gz', '.tgz'], partial(_tarfile_pack, compress='gzip'), _tarfile_unpack)
@@ -0,0 +1,73 @@
1
+ """
2
+ This module provides functionality for working with ZIP archives.
3
+
4
+ It includes functions for packing directories into ZIP files and unpacking ZIP files into directories.
5
+ The module also registers the ZIP archive type if zlib compression is supported.
6
+ """
7
+
8
+ import os.path
9
+ import zipfile
10
+ from typing import Optional
11
+
12
+ from .base import register_archive_type
13
+ from ..utils import tqdm, walk_files
14
+
15
+ try:
16
+ import zlib
17
+
18
+ del zlib
19
+ _ZLIB_SUPPORTED = True
20
+ except ImportError:
21
+ _ZLIB_SUPPORTED = False
22
+
23
+
24
+ def _zip_pack(directory, zip_file, pattern: Optional[str] = None, silent: bool = False, clear: bool = False):
25
+ """
26
+ Pack a directory into a ZIP file.
27
+
28
+ :param directory: The directory to pack.
29
+ :type directory: str
30
+ :param zip_file: The path to the output ZIP file.
31
+ :type zip_file: str
32
+ :param pattern: Optional file pattern to filter files for packing.
33
+ :type pattern: str, optional
34
+ :param silent: If True, suppress progress output.
35
+ :type silent: bool
36
+ :param clear: If True, remove original files after packing.
37
+ :type clear: bool
38
+ """
39
+ with zipfile.ZipFile(zip_file, "w", compression=zipfile.ZIP_DEFLATED) as zf:
40
+ progress = tqdm(walk_files(directory, pattern=pattern), silent=silent, desc=f'Packing {directory!r} ...')
41
+ for file in progress:
42
+ progress.set_description(file)
43
+ zf.write(os.path.join(directory, file), file)
44
+ if clear:
45
+ os.remove(os.path.join(directory, file))
46
+
47
+
48
+ def _zip_unpack(zip_file, directory, silent: bool = False, password: Optional[str] = None):
49
+ """
50
+ Unpack a ZIP file into a directory.
51
+
52
+ :param zip_file: The path to the ZIP file to unpack.
53
+ :type zip_file: str
54
+ :param directory: The directory to unpack the ZIP file into.
55
+ :type directory: str
56
+ :param silent: If True, suppress progress output.
57
+ :type silent: bool
58
+ :param password: Optional password for encrypted ZIP files.
59
+ :type password: str, optional
60
+ """
61
+ directory = os.fspath(directory)
62
+ os.makedirs(directory, exist_ok=True)
63
+ with zipfile.ZipFile(zip_file, 'r') as zf:
64
+ if password is not None:
65
+ zf.setpassword(password.encode(encoding='utf-8'))
66
+ progress = tqdm(zf.namelist(), silent=silent, desc=f'Unpacking {directory!r} ...')
67
+ for zipinfo in progress:
68
+ progress.set_description(zipinfo)
69
+ zf.extract(zipinfo, directory)
70
+
71
+
72
+ if _ZLIB_SUPPORTED:
73
+ register_archive_type('zip', ['.zip'], _zip_pack, _zip_unpack)
@@ -7,7 +7,7 @@ Overview:
7
7
  __TITLE__ = 'hfutils'
8
8
 
9
9
  #: Version of this project.
10
- __VERSION__ = '0.4.3'
10
+ __VERSION__ = '0.5.0'
11
11
 
12
12
  #: Short description of the project, will be included in ``setup.py``.
13
13
  __DESCRIPTION__ = 'Useful utilities for huggingface'
@@ -6,6 +6,7 @@ from .index import _add_index_subcommand
6
6
  from .ls import _add_ls_subcommand
7
7
  from .ls_repo import _add_ls_repo_subcommand
8
8
  from .rollback import _add_rollback_subcommand
9
+ from .squash import _add_squash_subcommand
9
10
  from .tree import _add_tree_subcommand
10
11
  from .upload import _add_upload_subcommand
11
12
  from .whoami import _add_whoami_subcommand
@@ -21,6 +22,7 @@ _DECORATORS = [
21
22
  _add_clone_subcommand,
22
23
  _add_tree_subcommand,
23
24
  _add_ils_subcommand,
25
+ _add_squash_subcommand,
24
26
  ]
25
27
 
26
28
  cli = hfutilcli
@@ -1,3 +1,15 @@
1
+ """
2
+ This module provides functionality for downloading data from HuggingFace repositories.
3
+
4
+ It includes a CLI command for downloading files, archives, or directories from HuggingFace,
5
+ with various options for customization. The module also defines custom exceptions and
6
+ utility functions to support the download process.
7
+
8
+ Usage:
9
+ This module is typically used as part of a larger CLI application for
10
+ interacting with HuggingFace repositories.
11
+ """
12
+
1
13
  import os
2
14
  import warnings
3
15
  from typing import Optional
@@ -14,6 +26,12 @@ from ..utils import get_requests_session
14
26
  class NoRemotePathAssignedWithDownload(ClickErrorException):
15
27
  """
16
28
  Custom exception class for indicating that no remote path in the repository is assigned.
29
+
30
+ This exception is raised when a download is attempted without specifying a file,
31
+ archive, or directory to download from the repository.
32
+
33
+ :attribute exit_code: The exit code to be used when this exception is raised.
34
+ :type exit_code: int
17
35
  """
18
36
  exit_code = 0x11
19
37
 
@@ -22,9 +40,12 @@ def _add_download_subcommand(cli: click.Group) -> click.Group:
22
40
  """
23
41
  Add the 'download' subcommand to the CLI.
24
42
 
25
- :param cli: The Click CLI application.
43
+ This function defines and adds the 'download' command to the given CLI group.
44
+ It sets up all the necessary options and implements the download functionality.
45
+
46
+ :param cli: The Click CLI application to which the download command will be added.
26
47
  :type cli: click.Group
27
- :return: The modified Click CLI application.
48
+ :return: The modified Click CLI application with the download command added.
28
49
  :rtype: click.Group
29
50
  """
30
51
 
@@ -68,6 +89,10 @@ def _add_download_subcommand(cli: click.Group) -> click.Group:
68
89
  """
69
90
  Download data from HuggingFace repositories.
70
91
 
92
+ This function implements the core functionality of the download command.
93
+ It handles downloading individual files, archives, or entire directories
94
+ from HuggingFace repositories based on the provided options.
95
+
71
96
  :param repo_id: Repository to download from.
72
97
  :type repo_id: str
73
98
  :param repo_type: Type of the HuggingFace repository.
@@ -85,13 +110,17 @@ def _add_download_subcommand(cli: click.Group) -> click.Group:
85
110
  :param max_workers: Max workers to download
86
111
  :type max_workers: int
87
112
  :param password: Password for the archive file. Only applied when -a is used.
88
- :type password: str, optional
113
+ :type password: Optional[str]
89
114
  :param wildcard: Wildcard for files to download. Only applied when -d is used.
90
- :type password: str, optional
115
+ :type wildcard: Optional[str]
91
116
  :param soft_mode_when_check: Just check the size of the expected file when enabled. Default is False.
92
117
  :type soft_mode_when_check: bool
93
118
  :param tmpdir: Use custom temporary Directory.
94
- :type tmpdir: str, optional
119
+ :type tmpdir: Optional[str]
120
+ :param show_all: Show all files, including hidden files.
121
+ :type show_all: bool
122
+
123
+ :raises NoRemotePathAssignedWithDownload: If no remote path in repository is assigned.
95
124
  """
96
125
  configure_http_backend(get_requests_session)
97
126
 
@@ -0,0 +1,71 @@
1
+ """
2
+ This module provides a command-line interface (CLI) for managing Hugging Face repositories.
3
+ It includes functionality to squash the history of a specified repository on Hugging Face.
4
+ Users can specify the repository ID, type, revision, and commit message when executing the squash command.
5
+ The module utilizes the Click library for creating the CLI and integrates with the Hugging Face Hub API.
6
+ """
7
+
8
+ from typing import Optional
9
+
10
+ import click
11
+ from huggingface_hub import configure_http_backend
12
+
13
+ from .base import CONTEXT_SETTINGS, command_wrap
14
+ from ..operate.base import REPO_TYPES, RepoTypeTyping, get_hf_client
15
+ from ..utils import get_requests_session, hf_fs_path
16
+
17
+
18
+ def _add_squash_subcommand(cli: click.Group) -> click.Group:
19
+ """
20
+ Add a 'squash' subcommand to the provided CLI group.
21
+
22
+ This subcommand allows users to squash the commit history of a specified Hugging Face repository.
23
+ Users must provide the repository ID and can optionally specify the repository type, revision, and commit message.
24
+ The command configures the HTTP backend and uses the Hugging Face client to perform the squash operation.
25
+
26
+ :param cli: The click.Group instance to which the subcommand will be added.
27
+ :type cli: click.Group
28
+
29
+ :return: The updated click.Group instance with the 'squash' subcommand added.
30
+ :rtype: click.Group
31
+ """
32
+
33
+ @cli.command('squash', help='Squash Repository from HuggingFace.\n\n'
34
+ 'Set environment $HF_TOKEN to use your own access token.',
35
+ context_settings=CONTEXT_SETTINGS)
36
+ @click.option('-r', '--repository', 'repo_id', type=str, required=True,
37
+ help='Repository to upload to.')
38
+ @click.option('-t', '--type', 'repo_type', type=click.Choice(REPO_TYPES), default='dataset',
39
+ help='Type of the HuggingFace repository.', show_default=True)
40
+ @click.option('-R', '--revision', 'revision', type=str, default='main',
41
+ help='Revision of repository.', show_default=True)
42
+ @click.option('-m', '--message', 'message', type=str, default=None,
43
+ help='Commit message for this operation.', show_default=True)
44
+ @command_wrap()
45
+ def squash(repo_id: str, repo_type: RepoTypeTyping, revision: str, message: Optional[str]):
46
+ """
47
+ Squash the commit history of the specified Hugging Face repository.
48
+
49
+ This function configures the HTTP backend, initializes the Hugging Face client,
50
+ and performs the squash operation on the repository. If no commit message is provided,
51
+ a default message is generated using the repository ID and type.
52
+
53
+ :param repo_id: The ID of the repository to squash.
54
+ :type repo_id: str
55
+ :param repo_type: The type of the Hugging Face repository (e.g., 'dataset', 'model').
56
+ :type repo_type: RepoTypeTyping
57
+ :param revision: The branch or revision of the repository to squash.
58
+ :type revision: str
59
+ :param message: Optional commit message for the squash operation.
60
+ :type message: Optional[str]
61
+ """
62
+ configure_http_backend(get_requests_session)
63
+ hf_client = get_hf_client()
64
+ hf_client.super_squash_history(
65
+ repo_id=repo_id,
66
+ repo_type=repo_type,
67
+ branch=revision,
68
+ commit_message=message or f'Squash {hf_fs_path(repo_id=repo_id, repo_type=repo_type, filename="")!r}',
69
+ )
70
+
71
+ return cli