exonware-xwsystem 0.0.1.409__py3-none-any.whl → 0.0.1.411__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.
- exonware/__init__.py +2 -2
- exonware/conf.py +10 -20
- exonware/xwsystem/__init__.py +6 -16
- exonware/xwsystem/caching/__init__.py +1 -1
- exonware/xwsystem/caching/base.py +16 -16
- exonware/xwsystem/caching/bloom_cache.py +5 -5
- exonware/xwsystem/caching/cache_manager.py +2 -2
- exonware/xwsystem/caching/conditional.py +4 -4
- exonware/xwsystem/caching/contracts.py +12 -12
- exonware/xwsystem/caching/decorators.py +2 -2
- exonware/xwsystem/caching/defs.py +1 -1
- exonware/xwsystem/caching/disk_cache.py +4 -4
- exonware/xwsystem/caching/distributed.py +1 -1
- exonware/xwsystem/caching/errors.py +1 -1
- exonware/xwsystem/caching/events.py +8 -8
- exonware/xwsystem/caching/eviction_strategies.py +9 -9
- exonware/xwsystem/caching/fluent.py +1 -1
- exonware/xwsystem/caching/integrity.py +1 -1
- exonware/xwsystem/caching/lfu_cache.py +24 -9
- exonware/xwsystem/caching/lfu_optimized.py +21 -21
- exonware/xwsystem/caching/lru_cache.py +14 -7
- exonware/xwsystem/caching/memory_bounded.py +8 -8
- exonware/xwsystem/caching/metrics_exporter.py +6 -6
- exonware/xwsystem/caching/observable_cache.py +1 -1
- exonware/xwsystem/caching/pluggable_cache.py +9 -9
- exonware/xwsystem/caching/rate_limiter.py +1 -1
- exonware/xwsystem/caching/read_through.py +6 -6
- exonware/xwsystem/caching/secure_cache.py +1 -1
- exonware/xwsystem/caching/serializable.py +3 -3
- exonware/xwsystem/caching/stats.py +7 -7
- exonware/xwsystem/caching/tagging.py +11 -11
- exonware/xwsystem/caching/ttl_cache.py +21 -6
- exonware/xwsystem/caching/two_tier_cache.py +5 -5
- exonware/xwsystem/caching/utils.py +3 -3
- exonware/xwsystem/caching/validation.py +1 -1
- exonware/xwsystem/caching/warming.py +9 -9
- exonware/xwsystem/caching/write_behind.py +5 -5
- exonware/xwsystem/cli/__init__.py +1 -1
- exonware/xwsystem/cli/args.py +10 -10
- exonware/xwsystem/cli/base.py +15 -15
- exonware/xwsystem/cli/colors.py +1 -1
- exonware/xwsystem/cli/console.py +1 -1
- exonware/xwsystem/cli/contracts.py +5 -5
- exonware/xwsystem/cli/defs.py +1 -1
- exonware/xwsystem/cli/errors.py +1 -1
- exonware/xwsystem/cli/progress.py +1 -1
- exonware/xwsystem/cli/prompts.py +1 -1
- exonware/xwsystem/cli/tables.py +7 -7
- exonware/xwsystem/config/__init__.py +1 -1
- exonware/xwsystem/config/base.py +14 -14
- exonware/xwsystem/config/contracts.py +22 -22
- exonware/xwsystem/config/defaults.py +2 -2
- exonware/xwsystem/config/defs.py +1 -1
- exonware/xwsystem/config/errors.py +2 -2
- exonware/xwsystem/config/logging.py +1 -1
- exonware/xwsystem/config/logging_setup.py +2 -2
- exonware/xwsystem/config/performance.py +7 -7
- exonware/xwsystem/config/performance_modes.py +20 -20
- exonware/xwsystem/config/version_manager.py +4 -4
- exonware/xwsystem/{http → http_client}/__init__.py +1 -1
- exonware/xwsystem/{http → http_client}/advanced_client.py +20 -20
- exonware/xwsystem/{http → http_client}/base.py +13 -13
- exonware/xwsystem/{http → http_client}/client.py +43 -43
- exonware/xwsystem/{http → http_client}/contracts.py +5 -5
- exonware/xwsystem/{http → http_client}/defs.py +2 -2
- exonware/xwsystem/{http → http_client}/errors.py +2 -2
- exonware/xwsystem/io/__init__.py +1 -1
- exonware/xwsystem/io/archive/__init__.py +1 -1
- exonware/xwsystem/io/archive/archive.py +5 -5
- exonware/xwsystem/io/archive/archive_files.py +8 -8
- exonware/xwsystem/io/archive/archivers.py +3 -3
- exonware/xwsystem/io/archive/base.py +17 -17
- exonware/xwsystem/io/archive/codec_integration.py +1 -1
- exonware/xwsystem/io/archive/compression.py +1 -1
- exonware/xwsystem/io/archive/formats/__init__.py +1 -1
- exonware/xwsystem/io/archive/formats/brotli_format.py +12 -9
- exonware/xwsystem/io/archive/formats/lz4_format.py +12 -9
- exonware/xwsystem/io/archive/formats/rar.py +12 -9
- exonware/xwsystem/io/archive/formats/sevenzip.py +12 -9
- exonware/xwsystem/io/archive/formats/squashfs_format.py +7 -7
- exonware/xwsystem/io/archive/formats/tar.py +8 -8
- exonware/xwsystem/io/archive/formats/wim_format.py +12 -9
- exonware/xwsystem/io/archive/formats/zip.py +8 -8
- exonware/xwsystem/io/archive/formats/zpaq_format.py +7 -7
- exonware/xwsystem/io/archive/formats/zstandard.py +12 -9
- exonware/xwsystem/io/base.py +17 -17
- exonware/xwsystem/io/codec/__init__.py +1 -1
- exonware/xwsystem/io/codec/base.py +261 -14
- exonware/xwsystem/io/codec/contracts.py +3 -6
- exonware/xwsystem/io/codec/registry.py +29 -29
- exonware/xwsystem/io/common/__init__.py +1 -1
- exonware/xwsystem/io/common/atomic.py +2 -2
- exonware/xwsystem/io/common/base.py +1 -1
- exonware/xwsystem/io/common/lock.py +1 -1
- exonware/xwsystem/io/common/watcher.py +4 -4
- exonware/xwsystem/io/contracts.py +34 -39
- exonware/xwsystem/io/data_operations.py +480 -0
- exonware/xwsystem/io/defs.py +2 -2
- exonware/xwsystem/io/errors.py +32 -3
- exonware/xwsystem/io/facade.py +4 -4
- exonware/xwsystem/io/file/__init__.py +1 -1
- exonware/xwsystem/io/file/base.py +2 -2
- exonware/xwsystem/io/file/conversion.py +1 -1
- exonware/xwsystem/io/file/file.py +10 -8
- exonware/xwsystem/io/file/paged_source.py +8 -1
- exonware/xwsystem/io/file/paging/__init__.py +1 -1
- exonware/xwsystem/io/file/paging/byte_paging.py +1 -1
- exonware/xwsystem/io/file/paging/line_paging.py +1 -1
- exonware/xwsystem/io/file/paging/record_paging.py +1 -1
- exonware/xwsystem/io/file/paging/registry.py +5 -5
- exonware/xwsystem/io/file/source.py +22 -11
- exonware/xwsystem/io/filesystem/__init__.py +1 -1
- exonware/xwsystem/io/filesystem/base.py +1 -1
- exonware/xwsystem/io/filesystem/local.py +9 -1
- exonware/xwsystem/io/folder/__init__.py +1 -1
- exonware/xwsystem/io/folder/base.py +2 -2
- exonware/xwsystem/io/folder/folder.py +6 -6
- exonware/xwsystem/io/serialization/__init__.py +1 -1
- exonware/xwsystem/io/serialization/auto_serializer.py +53 -40
- exonware/xwsystem/io/serialization/base.py +248 -35
- exonware/xwsystem/io/serialization/contracts.py +93 -4
- exonware/xwsystem/io/serialization/defs.py +1 -1
- exonware/xwsystem/io/serialization/errors.py +1 -1
- exonware/xwsystem/io/serialization/flyweight.py +22 -22
- exonware/xwsystem/io/serialization/format_detector.py +18 -15
- exonware/xwsystem/io/serialization/formats/__init__.py +1 -1
- exonware/xwsystem/io/serialization/formats/binary/bson.py +1 -1
- exonware/xwsystem/io/serialization/formats/binary/cbor.py +1 -1
- exonware/xwsystem/io/serialization/formats/binary/marshal.py +1 -1
- exonware/xwsystem/io/serialization/formats/binary/msgpack.py +1 -1
- exonware/xwsystem/io/serialization/formats/binary/pickle.py +1 -1
- exonware/xwsystem/io/serialization/formats/binary/plistlib.py +1 -1
- exonware/xwsystem/io/serialization/formats/database/dbm.py +53 -1
- exonware/xwsystem/io/serialization/formats/database/shelve.py +48 -1
- exonware/xwsystem/io/serialization/formats/database/sqlite3.py +85 -1
- exonware/xwsystem/io/serialization/formats/text/configparser.py +2 -2
- exonware/xwsystem/io/serialization/formats/text/csv.py +2 -2
- exonware/xwsystem/io/serialization/formats/text/formdata.py +2 -2
- exonware/xwsystem/io/serialization/formats/text/json.py +23 -5
- exonware/xwsystem/io/serialization/formats/text/json5.py +98 -13
- exonware/xwsystem/io/serialization/formats/text/jsonlines.py +230 -20
- exonware/xwsystem/io/serialization/formats/text/multipart.py +2 -2
- exonware/xwsystem/io/serialization/formats/text/toml.py +65 -4
- exonware/xwsystem/io/serialization/formats/text/xml.py +451 -69
- exonware/xwsystem/io/serialization/formats/text/yaml.py +52 -2
- exonware/xwsystem/io/serialization/registry.py +5 -5
- exonware/xwsystem/io/serialization/serializer.py +184 -12
- exonware/xwsystem/io/serialization/utils/__init__.py +1 -1
- exonware/xwsystem/io/serialization/utils/path_ops.py +3 -3
- exonware/xwsystem/io/stream/__init__.py +1 -1
- exonware/xwsystem/io/stream/async_operations.py +3 -3
- exonware/xwsystem/io/stream/base.py +3 -7
- exonware/xwsystem/io/stream/codec_io.py +4 -7
- exonware/xwsystem/ipc/async_fabric.py +7 -8
- exonware/xwsystem/ipc/base.py +9 -9
- exonware/xwsystem/ipc/contracts.py +5 -5
- exonware/xwsystem/ipc/defs.py +1 -1
- exonware/xwsystem/ipc/errors.py +2 -2
- exonware/xwsystem/ipc/message_queue.py +4 -6
- exonware/xwsystem/ipc/pipes.py +2 -2
- exonware/xwsystem/ipc/process_manager.py +7 -7
- exonware/xwsystem/ipc/process_pool.py +8 -8
- exonware/xwsystem/ipc/shared_memory.py +7 -7
- exonware/xwsystem/monitoring/base.py +33 -33
- exonware/xwsystem/monitoring/contracts.py +27 -27
- exonware/xwsystem/monitoring/defs.py +1 -1
- exonware/xwsystem/monitoring/error_recovery.py +16 -16
- exonware/xwsystem/monitoring/errors.py +2 -2
- exonware/xwsystem/monitoring/memory_monitor.py +12 -12
- exonware/xwsystem/monitoring/metrics.py +8 -8
- exonware/xwsystem/monitoring/performance_manager_generic.py +20 -20
- exonware/xwsystem/monitoring/performance_monitor.py +11 -11
- exonware/xwsystem/monitoring/performance_validator.py +21 -21
- exonware/xwsystem/monitoring/system_monitor.py +17 -17
- exonware/xwsystem/monitoring/tracing.py +20 -20
- exonware/xwsystem/monitoring/tracker.py +7 -7
- exonware/xwsystem/operations/__init__.py +5 -5
- exonware/xwsystem/operations/base.py +3 -3
- exonware/xwsystem/operations/contracts.py +3 -3
- exonware/xwsystem/operations/defs.py +5 -5
- exonware/xwsystem/operations/diff.py +5 -5
- exonware/xwsystem/operations/merge.py +2 -2
- exonware/xwsystem/operations/patch.py +5 -5
- exonware/xwsystem/patterns/base.py +4 -4
- exonware/xwsystem/patterns/context_manager.py +7 -7
- exonware/xwsystem/patterns/contracts.py +29 -31
- exonware/xwsystem/patterns/defs.py +1 -1
- exonware/xwsystem/patterns/dynamic_facade.py +9 -9
- exonware/xwsystem/patterns/errors.py +10 -10
- exonware/xwsystem/patterns/handler_factory.py +15 -14
- exonware/xwsystem/patterns/import_registry.py +22 -22
- exonware/xwsystem/patterns/object_pool.py +14 -13
- exonware/xwsystem/patterns/registry.py +45 -32
- exonware/xwsystem/plugins/__init__.py +1 -1
- exonware/xwsystem/plugins/base.py +25 -25
- exonware/xwsystem/plugins/contracts.py +28 -28
- exonware/xwsystem/plugins/defs.py +1 -1
- exonware/xwsystem/plugins/errors.py +9 -9
- exonware/xwsystem/runtime/__init__.py +1 -1
- exonware/xwsystem/runtime/base.py +42 -42
- exonware/xwsystem/runtime/contracts.py +9 -9
- exonware/xwsystem/runtime/defs.py +1 -1
- exonware/xwsystem/runtime/env.py +9 -9
- exonware/xwsystem/runtime/errors.py +1 -1
- exonware/xwsystem/runtime/reflection.py +15 -15
- exonware/xwsystem/security/auth.py +47 -15
- exonware/xwsystem/security/base.py +17 -17
- exonware/xwsystem/security/contracts.py +30 -30
- exonware/xwsystem/security/crypto.py +8 -8
- exonware/xwsystem/security/defs.py +1 -1
- exonware/xwsystem/security/errors.py +2 -2
- exonware/xwsystem/security/hazmat.py +7 -7
- exonware/xwsystem/security/path_validator.py +1 -1
- exonware/xwsystem/shared/__init__.py +1 -1
- exonware/xwsystem/shared/base.py +14 -14
- exonware/xwsystem/shared/contracts.py +6 -6
- exonware/xwsystem/shared/defs.py +1 -1
- exonware/xwsystem/shared/errors.py +1 -1
- exonware/xwsystem/structures/__init__.py +1 -1
- exonware/xwsystem/structures/base.py +29 -29
- exonware/xwsystem/structures/circular_detector.py +15 -15
- exonware/xwsystem/structures/contracts.py +9 -9
- exonware/xwsystem/structures/defs.py +1 -1
- exonware/xwsystem/structures/errors.py +2 -2
- exonware/xwsystem/structures/tree_walker.py +8 -8
- exonware/xwsystem/threading/async_primitives.py +7 -7
- exonware/xwsystem/threading/base.py +19 -19
- exonware/xwsystem/threading/contracts.py +13 -13
- exonware/xwsystem/threading/defs.py +1 -1
- exonware/xwsystem/threading/errors.py +2 -2
- exonware/xwsystem/threading/safe_factory.py +13 -12
- exonware/xwsystem/utils/base.py +34 -34
- exonware/xwsystem/utils/contracts.py +9 -9
- exonware/xwsystem/utils/dt/__init__.py +1 -1
- exonware/xwsystem/utils/dt/base.py +6 -6
- exonware/xwsystem/utils/dt/contracts.py +2 -2
- exonware/xwsystem/utils/dt/defs.py +1 -1
- exonware/xwsystem/utils/dt/errors.py +2 -2
- exonware/xwsystem/utils/dt/formatting.py +3 -3
- exonware/xwsystem/utils/dt/humanize.py +2 -2
- exonware/xwsystem/utils/dt/parsing.py +2 -2
- exonware/xwsystem/utils/dt/timezone_utils.py +5 -5
- exonware/xwsystem/utils/errors.py +2 -2
- exonware/xwsystem/utils/test_runner.py +6 -6
- exonware/xwsystem/utils/utils_contracts.py +1 -1
- exonware/xwsystem/validation/__init__.py +1 -1
- exonware/xwsystem/validation/base.py +48 -48
- exonware/xwsystem/validation/contracts.py +8 -8
- exonware/xwsystem/validation/data_validator.py +10 -0
- exonware/xwsystem/validation/declarative.py +15 -15
- exonware/xwsystem/validation/defs.py +1 -1
- exonware/xwsystem/validation/errors.py +2 -2
- exonware/xwsystem/validation/fluent_validator.py +10 -10
- exonware/xwsystem/version.py +2 -2
- {exonware_xwsystem-0.0.1.409.dist-info → exonware_xwsystem-0.0.1.411.dist-info}/METADATA +9 -11
- exonware_xwsystem-0.0.1.411.dist-info/RECORD +274 -0
- {exonware_xwsystem-0.0.1.409.dist-info → exonware_xwsystem-0.0.1.411.dist-info}/WHEEL +1 -1
- exonware/xwsystem/lazy_bootstrap.py +0 -79
- exonware_xwsystem-0.0.1.409.dist-info/RECORD +0 -274
- {exonware_xwsystem-0.0.1.409.dist-info → exonware_xwsystem-0.0.1.411.dist-info}/licenses/LICENSE +0 -0
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
Company: eXonware.com
|
|
5
5
|
Author: Eng. Muhammad AlShehri
|
|
6
6
|
Email: connect@exonware.com
|
|
7
|
-
Version: 0.0.1.
|
|
7
|
+
Version: 0.0.1.411
|
|
8
8
|
Generation Date: 30-Oct-2025
|
|
9
9
|
|
|
10
10
|
Archive codecs - In-memory archive processors.
|
|
@@ -26,7 +26,7 @@ import zipfile
|
|
|
26
26
|
import tarfile
|
|
27
27
|
import io
|
|
28
28
|
from pathlib import Path
|
|
29
|
-
from typing import Any,
|
|
29
|
+
from typing import Any, Optional, Union
|
|
30
30
|
|
|
31
31
|
from ..archive.base import AArchiver
|
|
32
32
|
from ..contracts import IArchiver, EncodeOptions, DecodeOptions
|
|
@@ -117,7 +117,7 @@ class ZipArchiver(AArchiver):
|
|
|
117
117
|
|
|
118
118
|
with zipfile.ZipFile(zip_buffer, 'w', compression=compression) as zf:
|
|
119
119
|
if isinstance(value, dict):
|
|
120
|
-
#
|
|
120
|
+
# dict: keys are filenames, values are contents
|
|
121
121
|
for filename, content in value.items():
|
|
122
122
|
if isinstance(content, str):
|
|
123
123
|
zf.writestr(filename, content)
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
Company: eXonware.com
|
|
5
5
|
Author: Eng. Muhammad AlShehri
|
|
6
6
|
Email: connect@exonware.com
|
|
7
|
-
Version: 0.0.1.
|
|
7
|
+
Version: 0.0.1.411
|
|
8
8
|
Generation Date: 30-Oct-2025
|
|
9
9
|
|
|
10
10
|
Base classes and registries for archive system.
|
|
@@ -19,7 +19,7 @@ Priority 5 (Extensibility): Easy to add 7z, RAR, etc.
|
|
|
19
19
|
"""
|
|
20
20
|
|
|
21
21
|
from abc import ABC, abstractmethod
|
|
22
|
-
from typing import
|
|
22
|
+
from typing import Optional, Union, Any
|
|
23
23
|
from pathlib import Path
|
|
24
24
|
|
|
25
25
|
from ..contracts import IArchiveFormat, ICompressor, IArchiveMetadata, IArchiver, IArchiveFile, EncodeOptions, DecodeOptions
|
|
@@ -50,12 +50,12 @@ class AArchiveFormat(IArchiveFormat, ABC):
|
|
|
50
50
|
|
|
51
51
|
@property
|
|
52
52
|
@abstractmethod
|
|
53
|
-
def file_extensions(self) ->
|
|
53
|
+
def file_extensions(self) -> list[str]:
|
|
54
54
|
"""Supported file extensions."""
|
|
55
55
|
pass
|
|
56
56
|
|
|
57
57
|
@property
|
|
58
|
-
def mime_types(self) ->
|
|
58
|
+
def mime_types(self) -> list[str]:
|
|
59
59
|
"""Supported MIME types."""
|
|
60
60
|
return [] # Default: no MIME types
|
|
61
61
|
|
|
@@ -71,7 +71,7 @@ class ACompressor(ICompressor, ABC):
|
|
|
71
71
|
|
|
72
72
|
@property
|
|
73
73
|
@abstractmethod
|
|
74
|
-
def file_extensions(self) ->
|
|
74
|
+
def file_extensions(self) -> list[str]:
|
|
75
75
|
"""Supported file extensions."""
|
|
76
76
|
pass
|
|
77
77
|
|
|
@@ -210,7 +210,7 @@ class AArchiveFile(AFile, IArchiveFile, ABC):
|
|
|
210
210
|
pass
|
|
211
211
|
|
|
212
212
|
@abstractmethod
|
|
213
|
-
def add_files(self, files:
|
|
213
|
+
def add_files(self, files: list[Path], **options) -> None:
|
|
214
214
|
"""
|
|
215
215
|
Add files to archive - must implement in subclass.
|
|
216
216
|
|
|
@@ -219,7 +219,7 @@ class AArchiveFile(AFile, IArchiveFile, ABC):
|
|
|
219
219
|
pass
|
|
220
220
|
|
|
221
221
|
@abstractmethod
|
|
222
|
-
def extract_to(self, dest: Path, **options) ->
|
|
222
|
+
def extract_to(self, dest: Path, **options) -> list[Path]:
|
|
223
223
|
"""
|
|
224
224
|
Extract archive to destination - must implement in subclass.
|
|
225
225
|
|
|
@@ -228,7 +228,7 @@ class AArchiveFile(AFile, IArchiveFile, ABC):
|
|
|
228
228
|
pass
|
|
229
229
|
|
|
230
230
|
@abstractmethod
|
|
231
|
-
def list_contents(self) ->
|
|
231
|
+
def list_contents(self) -> list[str]:
|
|
232
232
|
"""List files in archive - must implement in subclass."""
|
|
233
233
|
pass
|
|
234
234
|
|
|
@@ -252,11 +252,11 @@ class ArchiveFormatRegistry:
|
|
|
252
252
|
|
|
253
253
|
def __init__(self):
|
|
254
254
|
"""Initialize registry."""
|
|
255
|
-
self._formats:
|
|
256
|
-
self._instances:
|
|
257
|
-
self._extension_map:
|
|
255
|
+
self._formats: dict[str, type[IArchiveFormat]] = {}
|
|
256
|
+
self._instances: dict[str, IArchiveFormat] = {}
|
|
257
|
+
self._extension_map: dict[str, str] = {} # .zip → "zip"
|
|
258
258
|
|
|
259
|
-
def register(self, format_class:
|
|
259
|
+
def register(self, format_class: type[IArchiveFormat]) -> None:
|
|
260
260
|
"""
|
|
261
261
|
Register an archive format.
|
|
262
262
|
|
|
@@ -312,7 +312,7 @@ class ArchiveFormatRegistry:
|
|
|
312
312
|
|
|
313
313
|
return None
|
|
314
314
|
|
|
315
|
-
def list_formats(self) ->
|
|
315
|
+
def list_formats(self) -> list[str]:
|
|
316
316
|
"""List all registered format IDs."""
|
|
317
317
|
return list(self._formats.keys())
|
|
318
318
|
|
|
@@ -326,10 +326,10 @@ class CompressionRegistry:
|
|
|
326
326
|
|
|
327
327
|
def __init__(self):
|
|
328
328
|
"""Initialize registry."""
|
|
329
|
-
self._algorithms:
|
|
330
|
-
self._instances:
|
|
329
|
+
self._algorithms: dict[str, type[ICompressor]] = {}
|
|
330
|
+
self._instances: dict[str, ICompressor] = {}
|
|
331
331
|
|
|
332
|
-
def register(self, compressor_class:
|
|
332
|
+
def register(self, compressor_class: type[ICompressor]) -> None:
|
|
333
333
|
"""Register a compression algorithm."""
|
|
334
334
|
instance = compressor_class()
|
|
335
335
|
algo_id = instance.algorithm_id
|
|
@@ -348,7 +348,7 @@ class CompressionRegistry:
|
|
|
348
348
|
return compressor
|
|
349
349
|
return None
|
|
350
350
|
|
|
351
|
-
def list_algorithms(self) ->
|
|
351
|
+
def list_algorithms(self) -> list[str]:
|
|
352
352
|
"""List all registered algorithm IDs."""
|
|
353
353
|
return list(self._algorithms.keys())
|
|
354
354
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
Company: eXonware.com
|
|
5
5
|
Author: Eng. Muhammad AlShehri
|
|
6
6
|
Email: connect@exonware.com
|
|
7
|
-
Version: 0.0.1.
|
|
7
|
+
Version: 0.0.1.411
|
|
8
8
|
Generation Date: November 1, 2025
|
|
9
9
|
|
|
10
10
|
Brotli (.br) compression format - RANK #6 WEB COMPRESSION.
|
|
@@ -20,13 +20,16 @@ Priority 5 (Extensibility): Lazy installation of brotli
|
|
|
20
20
|
|
|
21
21
|
import tarfile
|
|
22
22
|
from pathlib import Path
|
|
23
|
-
from typing import
|
|
23
|
+
from typing import Optional
|
|
24
24
|
|
|
25
25
|
from ...contracts import IArchiveFormat
|
|
26
26
|
from ...errors import ArchiveError
|
|
27
27
|
|
|
28
|
-
# Lazy import for brotli -
|
|
29
|
-
|
|
28
|
+
# Lazy import for brotli - optional dependency
|
|
29
|
+
try:
|
|
30
|
+
import brotli
|
|
31
|
+
except ImportError:
|
|
32
|
+
brotli = None # type: ignore
|
|
30
33
|
|
|
31
34
|
|
|
32
35
|
class BrotliArchiver(IArchiveFormat):
|
|
@@ -58,16 +61,16 @@ class BrotliArchiver(IArchiveFormat):
|
|
|
58
61
|
return "br"
|
|
59
62
|
|
|
60
63
|
@property
|
|
61
|
-
def file_extensions(self) ->
|
|
64
|
+
def file_extensions(self) -> list[str]:
|
|
62
65
|
"""Supported extensions."""
|
|
63
66
|
return [".br", ".tar.br", ".tbr"]
|
|
64
67
|
|
|
65
68
|
@property
|
|
66
|
-
def mime_types(self) ->
|
|
69
|
+
def mime_types(self) -> list[str]:
|
|
67
70
|
"""MIME types."""
|
|
68
71
|
return ["application/x-brotli"]
|
|
69
72
|
|
|
70
|
-
def create(self, files:
|
|
73
|
+
def create(self, files: list[Path], output: Path, **opts) -> None:
|
|
71
74
|
"""
|
|
72
75
|
Create Brotli-compressed tar archive.
|
|
73
76
|
|
|
@@ -101,7 +104,7 @@ class BrotliArchiver(IArchiveFormat):
|
|
|
101
104
|
except Exception as e:
|
|
102
105
|
raise ArchiveError(f"Failed to create brotli archive: {e}")
|
|
103
106
|
|
|
104
|
-
def extract(self, archive: Path, output_dir: Path, members: Optional[
|
|
107
|
+
def extract(self, archive: Path, output_dir: Path, members: Optional[list[str]] = None, **opts) -> list[Path]:
|
|
105
108
|
"""Extract Brotli archive."""
|
|
106
109
|
output_dir.mkdir(parents=True, exist_ok=True)
|
|
107
110
|
|
|
@@ -128,7 +131,7 @@ class BrotliArchiver(IArchiveFormat):
|
|
|
128
131
|
except Exception as e:
|
|
129
132
|
raise ArchiveError(f"Failed to extract brotli archive: {e}")
|
|
130
133
|
|
|
131
|
-
def list_contents(self, archive: Path) ->
|
|
134
|
+
def list_contents(self, archive: Path) -> list[str]:
|
|
132
135
|
"""List Brotli archive contents."""
|
|
133
136
|
try:
|
|
134
137
|
compressed = archive.read_bytes()
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
Company: eXonware.com
|
|
5
5
|
Author: Eng. Muhammad AlShehri
|
|
6
6
|
Email: connect@exonware.com
|
|
7
|
-
Version: 0.0.1.
|
|
7
|
+
Version: 0.0.1.411
|
|
8
8
|
Generation Date: November 1, 2025
|
|
9
9
|
|
|
10
10
|
LZ4 compression format - RANK #7 FASTEST COMPRESSION.
|
|
@@ -20,13 +20,16 @@ Priority 5 (Extensibility): Lazy installation of lz4
|
|
|
20
20
|
|
|
21
21
|
import tarfile
|
|
22
22
|
from pathlib import Path
|
|
23
|
-
from typing import
|
|
23
|
+
from typing import Optional
|
|
24
24
|
|
|
25
25
|
from ...contracts import IArchiveFormat
|
|
26
26
|
from ...errors import ArchiveError
|
|
27
27
|
|
|
28
|
-
# Lazy import for lz4 -
|
|
29
|
-
|
|
28
|
+
# Lazy import for lz4 - optional dependency
|
|
29
|
+
try:
|
|
30
|
+
import lz4.frame as lz4
|
|
31
|
+
except ImportError:
|
|
32
|
+
lz4 = None # type: ignore
|
|
30
33
|
|
|
31
34
|
|
|
32
35
|
class Lz4Archiver(IArchiveFormat):
|
|
@@ -58,16 +61,16 @@ class Lz4Archiver(IArchiveFormat):
|
|
|
58
61
|
return "lz4"
|
|
59
62
|
|
|
60
63
|
@property
|
|
61
|
-
def file_extensions(self) ->
|
|
64
|
+
def file_extensions(self) -> list[str]:
|
|
62
65
|
"""Supported extensions."""
|
|
63
66
|
return [".lz4", ".tar.lz4", ".tlz4"]
|
|
64
67
|
|
|
65
68
|
@property
|
|
66
|
-
def mime_types(self) ->
|
|
69
|
+
def mime_types(self) -> list[str]:
|
|
67
70
|
"""MIME types."""
|
|
68
71
|
return ["application/x-lz4"]
|
|
69
72
|
|
|
70
|
-
def create(self, files:
|
|
73
|
+
def create(self, files: list[Path], output: Path, **opts) -> None:
|
|
71
74
|
"""
|
|
72
75
|
Create LZ4-compressed tar archive.
|
|
73
76
|
|
|
@@ -100,7 +103,7 @@ class Lz4Archiver(IArchiveFormat):
|
|
|
100
103
|
except Exception as e:
|
|
101
104
|
raise ArchiveError(f"Failed to create lz4 archive: {e}")
|
|
102
105
|
|
|
103
|
-
def extract(self, archive: Path, output_dir: Path, members: Optional[
|
|
106
|
+
def extract(self, archive: Path, output_dir: Path, members: Optional[list[str]] = None, **opts) -> list[Path]:
|
|
104
107
|
"""Extract LZ4 archive."""
|
|
105
108
|
output_dir.mkdir(parents=True, exist_ok=True)
|
|
106
109
|
|
|
@@ -127,7 +130,7 @@ class Lz4Archiver(IArchiveFormat):
|
|
|
127
130
|
except Exception as e:
|
|
128
131
|
raise ArchiveError(f"Failed to extract lz4 archive: {e}")
|
|
129
132
|
|
|
130
|
-
def list_contents(self, archive: Path) ->
|
|
133
|
+
def list_contents(self, archive: Path) -> list[str]:
|
|
131
134
|
"""List LZ4 archive contents."""
|
|
132
135
|
try:
|
|
133
136
|
compressed = archive.read_bytes()
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
Company: eXonware.com
|
|
5
5
|
Author: Eng. Muhammad AlShehri
|
|
6
6
|
Email: connect@exonware.com
|
|
7
|
-
Version: 0.0.1.
|
|
7
|
+
Version: 0.0.1.411
|
|
8
8
|
Generation Date: November 1, 2025
|
|
9
9
|
|
|
10
10
|
RAR5 archive format implementation - RANK #3 PROPRIETARY COMPRESSION.
|
|
@@ -19,13 +19,16 @@ Priority 5 (Extensibility): Optional rarfile dependency
|
|
|
19
19
|
"""
|
|
20
20
|
|
|
21
21
|
from pathlib import Path
|
|
22
|
-
from typing import
|
|
22
|
+
from typing import Optional
|
|
23
23
|
|
|
24
24
|
from ...contracts import IArchiveFormat
|
|
25
25
|
from ...errors import ArchiveError
|
|
26
26
|
|
|
27
|
-
# Lazy import for rarfile -
|
|
28
|
-
|
|
27
|
+
# Lazy import for rarfile - optional dependency
|
|
28
|
+
try:
|
|
29
|
+
import rarfile
|
|
30
|
+
except ImportError:
|
|
31
|
+
rarfile = None # type: ignore
|
|
29
32
|
|
|
30
33
|
|
|
31
34
|
class RarArchiver(IArchiveFormat):
|
|
@@ -58,16 +61,16 @@ class RarArchiver(IArchiveFormat):
|
|
|
58
61
|
return "rar"
|
|
59
62
|
|
|
60
63
|
@property
|
|
61
|
-
def file_extensions(self) ->
|
|
64
|
+
def file_extensions(self) -> list[str]:
|
|
62
65
|
"""Supported extensions."""
|
|
63
66
|
return [".rar", ".r00", ".r01"]
|
|
64
67
|
|
|
65
68
|
@property
|
|
66
|
-
def mime_types(self) ->
|
|
69
|
+
def mime_types(self) -> list[str]:
|
|
67
70
|
"""MIME types."""
|
|
68
71
|
return ["application/vnd.rar", "application/x-rar-compressed"]
|
|
69
72
|
|
|
70
|
-
def create(self, files:
|
|
73
|
+
def create(self, files: list[Path], output: Path, **opts) -> None:
|
|
71
74
|
"""
|
|
72
75
|
RAR creation not supported (proprietary).
|
|
73
76
|
|
|
@@ -78,7 +81,7 @@ class RarArchiver(IArchiveFormat):
|
|
|
78
81
|
"Use SevenZipArchiver or ZstandardArchiver instead for creation."
|
|
79
82
|
)
|
|
80
83
|
|
|
81
|
-
def extract(self, archive: Path, output_dir: Path, members: Optional[
|
|
84
|
+
def extract(self, archive: Path, output_dir: Path, members: Optional[list[str]] = None, **opts) -> list[Path]:
|
|
82
85
|
"""
|
|
83
86
|
Extract RAR archive.
|
|
84
87
|
|
|
@@ -106,7 +109,7 @@ class RarArchiver(IArchiveFormat):
|
|
|
106
109
|
except Exception as e:
|
|
107
110
|
raise ArchiveError(f"Failed to extract RAR archive: {e}")
|
|
108
111
|
|
|
109
|
-
def list_contents(self, archive: Path) ->
|
|
112
|
+
def list_contents(self, archive: Path) -> list[str]:
|
|
110
113
|
"""List RAR contents."""
|
|
111
114
|
if rarfile is None:
|
|
112
115
|
raise ArchiveError("rarfile not installed. Install with: pip install rarfile")
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
Company: eXonware.com
|
|
5
5
|
Author: Eng. Muhammad AlShehri
|
|
6
6
|
Email: connect@exonware.com
|
|
7
|
-
Version: 0.0.1.
|
|
7
|
+
Version: 0.0.1.411
|
|
8
8
|
Generation Date: November 1, 2025
|
|
9
9
|
|
|
10
10
|
7z archive format implementation - RANK #1 BEST COMPRESSION.
|
|
@@ -19,13 +19,16 @@ Priority 5 (Extensibility): Lazy installation of py7zr
|
|
|
19
19
|
"""
|
|
20
20
|
|
|
21
21
|
from pathlib import Path
|
|
22
|
-
from typing import
|
|
22
|
+
from typing import Optional
|
|
23
23
|
|
|
24
24
|
from ...contracts import IArchiveFormat
|
|
25
25
|
from ...errors import ArchiveError
|
|
26
26
|
|
|
27
|
-
# Lazy import for py7zr -
|
|
28
|
-
|
|
27
|
+
# Lazy import for py7zr - optional dependency
|
|
28
|
+
try:
|
|
29
|
+
import py7zr
|
|
30
|
+
except ImportError:
|
|
31
|
+
py7zr = None # type: ignore
|
|
29
32
|
|
|
30
33
|
|
|
31
34
|
class SevenZipArchiver(IArchiveFormat):
|
|
@@ -57,16 +60,16 @@ class SevenZipArchiver(IArchiveFormat):
|
|
|
57
60
|
return "7z"
|
|
58
61
|
|
|
59
62
|
@property
|
|
60
|
-
def file_extensions(self) ->
|
|
63
|
+
def file_extensions(self) -> list[str]:
|
|
61
64
|
"""Supported extensions."""
|
|
62
65
|
return [".7z"]
|
|
63
66
|
|
|
64
67
|
@property
|
|
65
|
-
def mime_types(self) ->
|
|
68
|
+
def mime_types(self) -> list[str]:
|
|
66
69
|
"""MIME types."""
|
|
67
70
|
return ["application/x-7z-compressed"]
|
|
68
71
|
|
|
69
|
-
def create(self, files:
|
|
72
|
+
def create(self, files: list[Path], output: Path, **opts) -> None:
|
|
70
73
|
"""
|
|
71
74
|
Create 7z archive with optional encryption.
|
|
72
75
|
|
|
@@ -92,7 +95,7 @@ class SevenZipArchiver(IArchiveFormat):
|
|
|
92
95
|
except Exception as e:
|
|
93
96
|
raise ArchiveError(f"Failed to create 7z archive: {e}")
|
|
94
97
|
|
|
95
|
-
def extract(self, archive: Path, output_dir: Path, members: Optional[
|
|
98
|
+
def extract(self, archive: Path, output_dir: Path, members: Optional[list[str]] = None, **opts) -> list[Path]:
|
|
96
99
|
"""
|
|
97
100
|
Extract 7z archive.
|
|
98
101
|
|
|
@@ -114,7 +117,7 @@ class SevenZipArchiver(IArchiveFormat):
|
|
|
114
117
|
except Exception as e:
|
|
115
118
|
raise ArchiveError(f"Failed to extract 7z archive: {e}")
|
|
116
119
|
|
|
117
|
-
def list_contents(self, archive: Path) ->
|
|
120
|
+
def list_contents(self, archive: Path) -> list[str]:
|
|
118
121
|
"""List 7z contents."""
|
|
119
122
|
try:
|
|
120
123
|
with py7zr.SevenZipFile(archive, 'r') as zf:
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
Company: eXonware.com
|
|
5
5
|
Author: Eng. Muhammad AlShehri
|
|
6
6
|
Email: connect@exonware.com
|
|
7
|
-
Version: 0.0.1.
|
|
7
|
+
Version: 0.0.1.411
|
|
8
8
|
Generation Date: November 1, 2025
|
|
9
9
|
|
|
10
10
|
SquashFS filesystem format - RANK #10 EMBEDDED SYSTEMS.
|
|
@@ -19,7 +19,7 @@ Priority 5 (Extensibility): Binary tool integration
|
|
|
19
19
|
"""
|
|
20
20
|
|
|
21
21
|
from pathlib import Path
|
|
22
|
-
from typing import
|
|
22
|
+
from typing import Optional
|
|
23
23
|
import subprocess
|
|
24
24
|
import shutil
|
|
25
25
|
|
|
@@ -56,12 +56,12 @@ class SquashfsArchiver(IArchiveFormat):
|
|
|
56
56
|
return "squashfs"
|
|
57
57
|
|
|
58
58
|
@property
|
|
59
|
-
def file_extensions(self) ->
|
|
59
|
+
def file_extensions(self) -> list[str]:
|
|
60
60
|
"""Supported extensions."""
|
|
61
61
|
return [".squashfs", ".sfs", ".sqfs"]
|
|
62
62
|
|
|
63
63
|
@property
|
|
64
|
-
def mime_types(self) ->
|
|
64
|
+
def mime_types(self) -> list[str]:
|
|
65
65
|
"""MIME types."""
|
|
66
66
|
return ["application/x-squashfs"]
|
|
67
67
|
|
|
@@ -80,7 +80,7 @@ class SquashfsArchiver(IArchiveFormat):
|
|
|
80
80
|
|
|
81
81
|
return Path(mksquashfs), Path(unsquashfs)
|
|
82
82
|
|
|
83
|
-
def create(self, files:
|
|
83
|
+
def create(self, files: list[Path], output: Path, **opts) -> None:
|
|
84
84
|
"""
|
|
85
85
|
Create SquashFS filesystem.
|
|
86
86
|
|
|
@@ -111,7 +111,7 @@ class SquashfsArchiver(IArchiveFormat):
|
|
|
111
111
|
except Exception as e:
|
|
112
112
|
raise ArchiveError(f"Failed to create squashfs: {e}")
|
|
113
113
|
|
|
114
|
-
def extract(self, archive: Path, output_dir: Path, members: Optional[
|
|
114
|
+
def extract(self, archive: Path, output_dir: Path, members: Optional[list[str]] = None, **opts) -> list[Path]:
|
|
115
115
|
"""Extract SquashFS filesystem."""
|
|
116
116
|
output_dir.mkdir(parents=True, exist_ok=True)
|
|
117
117
|
_, unsquashfs = self._check_tools()
|
|
@@ -132,7 +132,7 @@ class SquashfsArchiver(IArchiveFormat):
|
|
|
132
132
|
except Exception as e:
|
|
133
133
|
raise ArchiveError(f"Failed to extract squashfs: {e}")
|
|
134
134
|
|
|
135
|
-
def list_contents(self, archive: Path) ->
|
|
135
|
+
def list_contents(self, archive: Path) -> list[str]:
|
|
136
136
|
"""List SquashFS contents."""
|
|
137
137
|
_, unsquashfs = self._check_tools()
|
|
138
138
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
Company: eXonware.com
|
|
5
5
|
Author: Eng. Muhammad AlShehri
|
|
6
6
|
Email: connect@exonware.com
|
|
7
|
-
Version: 0.0.1.
|
|
7
|
+
Version: 0.0.1.411
|
|
8
8
|
Generation Date: 30-Oct-2025
|
|
9
9
|
|
|
10
10
|
TAR archive format implementation.
|
|
@@ -18,7 +18,7 @@ Priority 5 (Extensibility): Registered via registry
|
|
|
18
18
|
|
|
19
19
|
import tarfile
|
|
20
20
|
from pathlib import Path
|
|
21
|
-
from typing import
|
|
21
|
+
from typing import Optional
|
|
22
22
|
|
|
23
23
|
from ...contracts import IArchiveFormat
|
|
24
24
|
|
|
@@ -32,12 +32,12 @@ class TarArchiver(IArchiveFormat):
|
|
|
32
32
|
return "tar"
|
|
33
33
|
|
|
34
34
|
@property
|
|
35
|
-
def file_extensions(self) ->
|
|
35
|
+
def file_extensions(self) -> list[str]:
|
|
36
36
|
"""Supported extensions."""
|
|
37
37
|
return [".tar", ".tar.gz", ".tgz", ".tar.bz2", ".tbz2", ".tar.xz", ".txz"]
|
|
38
38
|
|
|
39
39
|
@property
|
|
40
|
-
def mime_types(self) ->
|
|
40
|
+
def mime_types(self) -> list[str]:
|
|
41
41
|
"""MIME types."""
|
|
42
42
|
return [
|
|
43
43
|
"application/x-tar",
|
|
@@ -61,7 +61,7 @@ class TarArchiver(IArchiveFormat):
|
|
|
61
61
|
else:
|
|
62
62
|
return 'r:*' # Auto-detect compression on read
|
|
63
63
|
|
|
64
|
-
def create(self, files:
|
|
64
|
+
def create(self, files: list[Path], output: Path, **opts) -> None:
|
|
65
65
|
"""Create TAR archive."""
|
|
66
66
|
output.parent.mkdir(parents=True, exist_ok=True)
|
|
67
67
|
|
|
@@ -72,10 +72,10 @@ class TarArchiver(IArchiveFormat):
|
|
|
72
72
|
arcname = opts.get('arcname', file_path.name)
|
|
73
73
|
tf.add(file_path, arcname=arcname)
|
|
74
74
|
|
|
75
|
-
def extract(self, archive: Path, output_dir: Path, members: Optional[
|
|
75
|
+
def extract(self, archive: Path, output_dir: Path, members: Optional[list[str]] = None, **opts) -> list[Path]:
|
|
76
76
|
"""Extract TAR archive."""
|
|
77
77
|
output_dir.mkdir(parents=True, exist_ok=True)
|
|
78
|
-
extracted:
|
|
78
|
+
extracted: list[Path] = []
|
|
79
79
|
|
|
80
80
|
with tarfile.open(archive, 'r:*') as tf:
|
|
81
81
|
if members:
|
|
@@ -88,7 +88,7 @@ class TarArchiver(IArchiveFormat):
|
|
|
88
88
|
|
|
89
89
|
return extracted
|
|
90
90
|
|
|
91
|
-
def list_contents(self, archive: Path) ->
|
|
91
|
+
def list_contents(self, archive: Path) -> list[str]:
|
|
92
92
|
"""List TAR contents."""
|
|
93
93
|
with tarfile.open(archive, 'r:*') as tf:
|
|
94
94
|
return [member.name for member in tf.getmembers()]
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
Company: eXonware.com
|
|
5
5
|
Author: Eng. Muhammad AlShehri
|
|
6
6
|
Email: connect@exonware.com
|
|
7
|
-
Version: 0.0.1.
|
|
7
|
+
Version: 0.0.1.411
|
|
8
8
|
Generation Date: November 1, 2025
|
|
9
9
|
|
|
10
10
|
WIM (Windows Imaging) format - RANK #9 SYSTEM IMAGES.
|
|
@@ -19,13 +19,16 @@ Priority 5 (Extensibility): Lazy installation of wimlib
|
|
|
19
19
|
"""
|
|
20
20
|
|
|
21
21
|
from pathlib import Path
|
|
22
|
-
from typing import
|
|
22
|
+
from typing import Optional
|
|
23
23
|
|
|
24
24
|
from ...contracts import IArchiveFormat
|
|
25
25
|
from ...errors import ArchiveError
|
|
26
26
|
|
|
27
|
-
# Lazy import for wimlib -
|
|
28
|
-
|
|
27
|
+
# Lazy import for wimlib - optional dependency
|
|
28
|
+
try:
|
|
29
|
+
import wimlib
|
|
30
|
+
except ImportError:
|
|
31
|
+
wimlib = None # type: ignore
|
|
29
32
|
|
|
30
33
|
|
|
31
34
|
class WimArchiver(IArchiveFormat):
|
|
@@ -55,16 +58,16 @@ class WimArchiver(IArchiveFormat):
|
|
|
55
58
|
return "wim"
|
|
56
59
|
|
|
57
60
|
@property
|
|
58
|
-
def file_extensions(self) ->
|
|
61
|
+
def file_extensions(self) -> list[str]:
|
|
59
62
|
"""Supported extensions."""
|
|
60
63
|
return [".wim", ".swm", ".esd"]
|
|
61
64
|
|
|
62
65
|
@property
|
|
63
|
-
def mime_types(self) ->
|
|
66
|
+
def mime_types(self) -> list[str]:
|
|
64
67
|
"""MIME types."""
|
|
65
68
|
return ["application/x-ms-wim"]
|
|
66
69
|
|
|
67
|
-
def create(self, files:
|
|
70
|
+
def create(self, files: list[Path], output: Path, **opts) -> None:
|
|
68
71
|
"""
|
|
69
72
|
Create WIM image.
|
|
70
73
|
|
|
@@ -92,7 +95,7 @@ class WimArchiver(IArchiveFormat):
|
|
|
92
95
|
except Exception as e:
|
|
93
96
|
raise ArchiveError(f"Failed to create WIM image: {e}")
|
|
94
97
|
|
|
95
|
-
def extract(self, archive: Path, output_dir: Path, members: Optional[
|
|
98
|
+
def extract(self, archive: Path, output_dir: Path, members: Optional[list[str]] = None, **opts) -> list[Path]:
|
|
96
99
|
"""Extract WIM image."""
|
|
97
100
|
output_dir.mkdir(parents=True, exist_ok=True)
|
|
98
101
|
|
|
@@ -107,7 +110,7 @@ class WimArchiver(IArchiveFormat):
|
|
|
107
110
|
except Exception as e:
|
|
108
111
|
raise ArchiveError(f"Failed to extract WIM image: {e}")
|
|
109
112
|
|
|
110
|
-
def list_contents(self, archive: Path) ->
|
|
113
|
+
def list_contents(self, archive: Path) -> list[str]:
|
|
111
114
|
"""List WIM contents."""
|
|
112
115
|
try:
|
|
113
116
|
wim = wimlib.WIM(str(archive), 'r')
|