archae 2026.2.0__py3-none-any.whl

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.
@@ -0,0 +1,159 @@
1
+ """peazip archiver/extractor implementation."""
2
+
3
+ import subprocess
4
+ from pathlib import Path
5
+ from typing import ClassVar
6
+
7
+ from .base_archiver import BaseArchiver
8
+
9
+
10
+ class PeazipArchiver(BaseArchiver):
11
+ """Archiver implementation for peazip."""
12
+
13
+ file_extensions: ClassVar[list[str]] = [
14
+ "appinstaller",
15
+ "appx",
16
+ "appxbundle",
17
+ "gz",
18
+ "tgz",
19
+ "jar",
20
+ "ear",
21
+ "war",
22
+ "emsix",
23
+ "emsixbundle",
24
+ "msix",
25
+ "msixbundle",
26
+ "apk",
27
+ "deb",
28
+ "cab",
29
+ "chm",
30
+ "chw",
31
+ "chi",
32
+ "chq",
33
+ "pptx",
34
+ "pptm ",
35
+ "xlsx",
36
+ "xlsm",
37
+ "docx",
38
+ "docm",
39
+ "7z",
40
+ "s7z",
41
+ "ace",
42
+ "dmg",
43
+ "img",
44
+ "arc",
45
+ "pak",
46
+ "arj",
47
+ "br",
48
+ "bz2",
49
+ "tbz2",
50
+ "crx",
51
+ "z",
52
+ "taz",
53
+ "cpio",
54
+ "arc",
55
+ "pak",
56
+ "iso",
57
+ "img",
58
+ "lzma",
59
+ "wim",
60
+ "swm",
61
+ "esd",
62
+ "msi",
63
+ "msp",
64
+ "rar",
65
+ "r00",
66
+ "rpm",
67
+ "tar",
68
+ "vhd",
69
+ "vhdx",
70
+ "xar",
71
+ "pkg",
72
+ "xpi",
73
+ "xz",
74
+ "txz",
75
+ "ipa",
76
+ "zip",
77
+ "zipx",
78
+ "aar",
79
+ "zst",
80
+ ]
81
+ mime_types: ClassVar[list[str]] = [
82
+ "application/appinstaller",
83
+ "application/appx",
84
+ "application/appxbundle",
85
+ "application/gzip",
86
+ "application/java-archive",
87
+ "application/msix",
88
+ "application/msixbundle",
89
+ "application/vnd.android.package-archive",
90
+ "application/vnd.debian.binary-package",
91
+ "application/vnd.ms-cab-compressed",
92
+ "application/vnd.ms-htmlhelp",
93
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation",
94
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
95
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
96
+ "application/x-7z-compressed",
97
+ "application/x-ace-compressed",
98
+ "application/x-apple-diskimage",
99
+ "application/x-arc",
100
+ "application/x-arj",
101
+ "application/x-brotli",
102
+ "application/x-bzip2",
103
+ "application/x-chrome-extension",
104
+ "application/x-compress",
105
+ "application/x-cpio",
106
+ "application/x-freearc",
107
+ "application/x-iso9660-image",
108
+ "application/x-lzma",
109
+ "application/x-ms-wim",
110
+ "application/x-ole-storage",
111
+ "application/x-rar-compressed",
112
+ "application/x-rpm",
113
+ "application/x-tar",
114
+ "application/x-vhd",
115
+ "application/x-xar",
116
+ "application/x-xpinstall",
117
+ "application/x-xz",
118
+ "application/zip",
119
+ "application/zip",
120
+ "application/zip",
121
+ "application/zstd",
122
+ ]
123
+ archiver_name: str = "peazip"
124
+ executable_name: str = "pea"
125
+
126
+ def __init__(self, executable_path: str | Path) -> None:
127
+ """Initialize the peazip archiver.
128
+
129
+ Args:
130
+ executable_path: Path to the peazip executable.
131
+ """
132
+ self.executable_path = Path(executable_path)
133
+
134
+ def extract_archive(self, archive_path: Path, extract_dir: Path) -> None:
135
+ """Extracts an archive to a specified directory.
136
+
137
+ Args:
138
+ archive_path (Path): The path to the archive file.
139
+ extract_dir (Path): The directory to extract the archive to.
140
+
141
+ """
142
+ command: list[str] = [
143
+ str(self.executable_path),
144
+ "-ext2simple",
145
+ str(archive_path),
146
+ str(extract_dir),
147
+ ]
148
+ subprocess.run(command, check=True) # noqa: S603
149
+
150
+ def get_archive_uncompressed_size(self, archive_path: Path) -> int: # noqa: ARG002
151
+ """Get the uncompressed size of the contents.
152
+
153
+ Args:
154
+ archive_path (Path): The path to the archive file.
155
+
156
+ Returns:
157
+ int: The size of the contents
158
+ """
159
+ return -1
@@ -0,0 +1,199 @@
1
+ """7zip archiver/extractor implementation."""
2
+
3
+ import subprocess
4
+ from pathlib import Path
5
+ from typing import ClassVar
6
+
7
+ from .base_archiver import BaseArchiver
8
+
9
+
10
+ class SevenZipArchiver(BaseArchiver):
11
+ """Archiver implementation for 7zip."""
12
+
13
+ file_extensions: ClassVar[list[str]] = [
14
+ "7z",
15
+ "s7z",
16
+ "apk",
17
+ "bz2",
18
+ "tbz2",
19
+ "crx",
20
+ "xpi",
21
+ "deb",
22
+ "gz",
23
+ "tgz",
24
+ "ipa",
25
+ "jar",
26
+ "ear",
27
+ "war",
28
+ "lzma",
29
+ "cab",
30
+ "docx",
31
+ "docm",
32
+ "pptx",
33
+ "pptm",
34
+ "xlsx",
35
+ "xlsm",
36
+ "emsix",
37
+ "emsixbundle",
38
+ "msix",
39
+ "appinstaller",
40
+ "appx",
41
+ "appxbundle",
42
+ "msixbundle",
43
+ "z",
44
+ "taz",
45
+ "tar",
46
+ "zip",
47
+ "zipx",
48
+ "appimage",
49
+ "dmg ",
50
+ "img",
51
+ "arj",
52
+ "cpio",
53
+ "cramfs",
54
+ "raw",
55
+ "alz",
56
+ "ext",
57
+ "ext2",
58
+ "ext3",
59
+ "ext4",
60
+ "xar",
61
+ "pkg",
62
+ "fat",
63
+ "gpt",
64
+ "hfs",
65
+ "hfsx",
66
+ "iso",
67
+ "lha",
68
+ "lhz",
69
+ "mbr",
70
+ "chm",
71
+ "chw",
72
+ "chi",
73
+ "chq",
74
+ "msi",
75
+ "msp",
76
+ "vhd",
77
+ "vhdx",
78
+ "ntfs",
79
+ "nsi",
80
+ "exe",
81
+ "nsis",
82
+ "qcow2",
83
+ "qcow",
84
+ "qcow2c",
85
+ "rpm",
86
+ "rar",
87
+ "r00",
88
+ "sqfs",
89
+ "sfs",
90
+ "sqsh",
91
+ "squashfs",
92
+ "scap",
93
+ "uefif",
94
+ "udf",
95
+ "edb",
96
+ "edp",
97
+ "edr",
98
+ "a",
99
+ "ar",
100
+ "deb",
101
+ "lib",
102
+ "vdi",
103
+ "vmdk",
104
+ "wim",
105
+ "swm",
106
+ "esd",
107
+ "xz",
108
+ "txz",
109
+ ]
110
+ mime_types: ClassVar[list[str]] = [
111
+ "application/x-7z-compressed",
112
+ "application/vnd.android.package-archive",
113
+ "application/x-bzip2",
114
+ "application/x-chrome-extension",
115
+ "application/x-xpinstall",
116
+ "application/vnd.debian.binary-package",
117
+ "application/gzip",
118
+ "application/java-archive",
119
+ "application/x-lzma",
120
+ "application/vnd.ms-cab-compressed",
121
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
122
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation",
123
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
124
+ "application/msix",
125
+ "application/appinstaller",
126
+ "application/appx",
127
+ "application/appxbundle",
128
+ "application/msixbundle",
129
+ "application/x-compress",
130
+ "application/x-tar",
131
+ "application/zip",
132
+ "application/x-apple-diskimage",
133
+ "application/x-arj",
134
+ "application/x-cpio",
135
+ "application/vnd.efi.img",
136
+ "application/x-alz-compressed",
137
+ "application/x-xar",
138
+ "application/x-iso9660-image",
139
+ "application/x-lzh",
140
+ "application/vnd.ms-htmlhelp",
141
+ "application/x-ole-storage",
142
+ "application/x-vhd",
143
+ "text/x-nsis",
144
+ "application/x-qemu-disk",
145
+ "application/x-rpm",
146
+ "application/x-rar-compressed",
147
+ "application/vnd.squashfs",
148
+ "application/x-archive",
149
+ "application/x-virtualbox-vdi",
150
+ "application/x-vmdk-disk",
151
+ "application/x-ms-wim",
152
+ "application/x-xz",
153
+ ]
154
+ archiver_name: str = "7zip"
155
+ executable_name: str = "7z"
156
+
157
+ def __init__(self, executable_path: str | Path) -> None:
158
+ """Initialize the 7zip archiver.
159
+
160
+ Args:
161
+ executable_path: Path to the 7zip executable.
162
+ """
163
+ self.executable_path = Path(executable_path)
164
+
165
+ def extract_archive(self, archive_path: Path, extract_dir: Path) -> None:
166
+ """Extracts an archive to a specified directory.
167
+
168
+ Args:
169
+ archive_path (Path): The path to the archive file.
170
+ extract_dir (Path): The directory to extract the archive to.
171
+
172
+ """
173
+ command: list[str] = [
174
+ str(self.executable_path),
175
+ "x",
176
+ str(archive_path),
177
+ f"-o{extract_dir!s}",
178
+ ]
179
+ subprocess.run(command, check=True) # noqa: S603
180
+
181
+ def get_archive_uncompressed_size(self, archive_path: Path) -> int:
182
+ """Get the uncompressed size of the contents.
183
+
184
+ Args:
185
+ archive_path (Path): The path to the archive file.
186
+
187
+ Returns:
188
+ int: The size of the contents
189
+ """
190
+ command: list[str] = [str(self.executable_path), "l", "-slt", str(archive_path)]
191
+ result = subprocess.run(command, check=True, capture_output=True, text=True) # noqa: S603
192
+
193
+ result_lines = str(result.stdout).splitlines()
194
+ exploded_size = 0
195
+ for line in result_lines:
196
+ if line.startswith("Size = "):
197
+ exploded_size += int(line[7:])
198
+
199
+ return exploded_size
@@ -0,0 +1,158 @@
1
+ """unar archiver/extractor implementation."""
2
+
3
+ import subprocess
4
+ from pathlib import Path
5
+ from typing import ClassVar
6
+
7
+ from .base_archiver import BaseArchiver
8
+
9
+
10
+ class UnarArchiver(BaseArchiver):
11
+ """Archiver implementation for unar."""
12
+
13
+ file_extensions: ClassVar[list[str]] = [
14
+ "appinstaller",
15
+ "appx",
16
+ "appxbundle",
17
+ "gz",
18
+ "tgz",
19
+ "emsix",
20
+ "emsixbundle",
21
+ "msix",
22
+ "msixbundle",
23
+ "apk",
24
+ "deb",
25
+ "cab",
26
+ "pptx",
27
+ "pptm ",
28
+ "xlsx ",
29
+ "xlsm",
30
+ "docx",
31
+ "docm",
32
+ "7z",
33
+ "s7z",
34
+ "ace",
35
+ "alz",
36
+ "arc",
37
+ "pak",
38
+ "a",
39
+ "ar",
40
+ "deb",
41
+ "lib",
42
+ "arj",
43
+ "bz2",
44
+ "tbz2",
45
+ "crx",
46
+ "z",
47
+ "taz",
48
+ "cpio",
49
+ "arc",
50
+ "pak",
51
+ "iso",
52
+ "img",
53
+ "lha",
54
+ "lhz",
55
+ "lzma",
56
+ "msi",
57
+ "msp",
58
+ "rar",
59
+ "r00",
60
+ "sit",
61
+ "sitx",
62
+ "tar",
63
+ "xar",
64
+ "pkg",
65
+ "xpi",
66
+ "xz",
67
+ "txz",
68
+ "zoo",
69
+ "zip",
70
+ "zipx",
71
+ "aar",
72
+ "nsi",
73
+ "exe",
74
+ "nsis",
75
+ "udf",
76
+ "edb",
77
+ "edp",
78
+ "edr",
79
+ ]
80
+ mime_types: ClassVar[list[str]] = [
81
+ "application/appinstaller",
82
+ "application/appx",
83
+ "application/appxbundle",
84
+ "application/gzip",
85
+ "application/msix",
86
+ "application/msixbundle",
87
+ "application/vnd.android.package-archive",
88
+ "application/vnd.debian.binary-package",
89
+ "application/vnd.ms-cab-compressed",
90
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation",
91
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
92
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
93
+ "application/x-7z-compressed",
94
+ "application/x-ace-compressed",
95
+ "application/x-alz-compressed",
96
+ "application/x-arc",
97
+ "application/x-archive",
98
+ "application/x-arj",
99
+ "application/x-bzip2",
100
+ "application/x-chrome-extension",
101
+ "application/x-compress",
102
+ "application/x-cpio",
103
+ "application/x-freearc",
104
+ "application/x-iso9660-image",
105
+ "application/x-lzh",
106
+ "application/x-lzma",
107
+ "application/x-ole-storage",
108
+ "application/x-rar-compressed",
109
+ "application/x-stuffit",
110
+ "application/x-sit",
111
+ "application/x-stuffitx",
112
+ "application/x-sitx",
113
+ "application/x-tar",
114
+ "application/x-xar",
115
+ "application/x-xpinstall",
116
+ "application/x-xz",
117
+ "application/x-zoo",
118
+ "application/zip",
119
+ "application/zip",
120
+ "text/x-nsis",
121
+ ]
122
+ archiver_name: str = "unar"
123
+ executable_name: str = "unar"
124
+
125
+ def __init__(self, executable_path: str | Path) -> None:
126
+ """Initialize the unar archiver.
127
+
128
+ Args:
129
+ executable_path: Path to the unar executable.
130
+ """
131
+ self.executable_path = Path(executable_path)
132
+
133
+ def extract_archive(self, archive_path: Path, extract_dir: Path) -> None:
134
+ """Extracts an archive to a specified directory.
135
+
136
+ Args:
137
+ archive_path (Path): The path to the archive file.
138
+ extract_dir (Path): The directory to extract the archive to.
139
+
140
+ """
141
+ command: list[str] = [
142
+ str(self.executable_path),
143
+ "-o",
144
+ str(extract_dir),
145
+ str(archive_path),
146
+ ]
147
+ subprocess.run(command, check=True) # noqa: S603
148
+
149
+ def get_archive_uncompressed_size(self, archive_path: Path) -> int: # noqa: ARG002
150
+ """Get the uncompressed size of the contents.
151
+
152
+ Args:
153
+ archive_path (Path): The path to the archive file.
154
+
155
+ Returns:
156
+ int: The size of the contents
157
+ """
158
+ return -1
@@ -0,0 +1,77 @@
1
+ """File size conversion utilities."""
2
+
3
+ import re
4
+
5
+ from archae.util.enum.byte_scale import ByteScale
6
+
7
+
8
+ def compact_value(value: float) -> str:
9
+ """Convert a float of file size to a FileSize string.
10
+
11
+ Args:
12
+ value (float): The size to convert
13
+
14
+ Returns:
15
+ str: A string with the most collapsed exact byte size rep.
16
+
17
+ """
18
+ exponent = 0
19
+ modulo: float = 0
20
+ while modulo == 0 and exponent < int(ByteScale.PETA.value):
21
+ modulo = value % 1024
22
+ if modulo == 0:
23
+ exponent += 1
24
+ value = int(value / 1024)
25
+ return f"{value}{ByteScale(exponent).prefix_letter}" # type: ignore[call-arg]
26
+
27
+
28
+ def expand_value(value: str | int) -> int:
29
+ """Convert a FileSize string or int to an int.
30
+
31
+ Args:
32
+ value (str | int): The value to convert as necessary.
33
+
34
+ Returns:
35
+ int: Size in bytes
36
+
37
+ """
38
+ try:
39
+ return int(value)
40
+ except ValueError:
41
+ pass
42
+ except TypeError:
43
+ pass
44
+
45
+ # Regex to split number and unit
46
+ match = re.match(r"^(\d+(?:\.\d+)?)\s*([KMGTP]B?)$", str(value), re.IGNORECASE)
47
+ if not match:
48
+ msg = f"{value} is not a valid file size (e.g., 10G, 500M)"
49
+ raise ValueError(msg)
50
+
51
+ number, unit = match.groups()
52
+ number = float(number)
53
+ unit = unit[0].upper()
54
+
55
+ byte_scale = 1024 ** (ByteScale.from_prefix_letter(unit).value)
56
+
57
+ # Default to bytes if no specific unit multiplier, or assume B
58
+ return int(number * byte_scale)
59
+
60
+
61
+ def convert(value: str | int) -> int:
62
+ """Convert a FileSizeParam to an int.
63
+
64
+ Args:
65
+ value (click.Option): The value to convert as necessary.
66
+ param (str): The param we are validating.
67
+ ctx (click.Context): The click Context to fail if we can't parse it.
68
+
69
+ Returns:
70
+ int: Size in bytes
71
+
72
+ """
73
+ try:
74
+ return expand_value(value)
75
+ except ValueError as err:
76
+ msg = f"Could not convert {value} to file size: {err}"
77
+ raise ValueError(msg) from err
@@ -0,0 +1,5 @@
1
+ """Enum utilities for archae."""
2
+
3
+ from archae.util.enum.byte_scale import ByteScale
4
+
5
+ __all__ = ["ByteScale"]
@@ -0,0 +1,55 @@
1
+ """Byte scale enum for file size operations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from enum import Enum
6
+ from typing import Self
7
+
8
+
9
+ class ByteScale(Enum):
10
+ """Byte scale prefix converter."""
11
+
12
+ NONE = (0, "")
13
+ KILO = (1, "K")
14
+ MEGA = (2, "M")
15
+ GIGA = (3, "G")
16
+ TERA = (4, "T")
17
+ PETA = (5, "P")
18
+
19
+ def __new__(cls, exponent: int, prefix_letter: str) -> Self:
20
+ """Apply values to the new Enum.
21
+
22
+ __new__ is used to control how new enum members are instantiated.
23
+ It must set the `_value_` attribute and any custom attributes.
24
+
25
+ Args:
26
+ exponent (int): the exponent value for the scale
27
+ prefix_letter (str): the prefix letter for the scale
28
+
29
+ Returns:
30
+ ByteScale: A new ByteScale enum.
31
+
32
+ """
33
+ obj = object.__new__(cls)
34
+ obj._value_ = exponent
35
+ obj.prefix_letter = prefix_letter
36
+ return obj
37
+
38
+ @property
39
+ def prefix_letter(self) -> str:
40
+ """Return the prefix letter for this scale."""
41
+ return self._prefix_letter
42
+
43
+ @prefix_letter.setter
44
+ def prefix_letter(self, value: str) -> None:
45
+ """Setter for prefix letter."""
46
+ self._prefix_letter = value
47
+
48
+ @staticmethod
49
+ def from_prefix_letter(prefix_letter: str) -> Self: # type: ignore[misc]
50
+ """Static method to look up from a prefix_letter."""
51
+ for member in ByteScale:
52
+ if member.prefix_letter == prefix_letter.upper():
53
+ return member
54
+ msg = f"'{prefix_letter}' is not a valid byte scale prefix letter."
55
+ raise ValueError(msg)