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
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Company: eXonware.com
|
|
3
3
|
Author: Eng. Muhammad AlShehri
|
|
4
4
|
Email: connect@exonware.com
|
|
5
|
-
Version: 0.0.1.
|
|
5
|
+
Version: 0.0.1.411
|
|
6
6
|
Generation Date: September 04, 2025
|
|
7
7
|
|
|
8
8
|
Advanced HTTP client with HTTP/2, streaming, pluggable transports, and modern features.
|
|
@@ -13,7 +13,7 @@ import os
|
|
|
13
13
|
import ssl
|
|
14
14
|
from contextlib import asynccontextmanager
|
|
15
15
|
from dataclasses import dataclass, field
|
|
16
|
-
from typing import Any, AsyncIterator,
|
|
16
|
+
from typing import Any, AsyncIterator, Optional, Union
|
|
17
17
|
from urllib.parse import urljoin
|
|
18
18
|
|
|
19
19
|
from .contracts import Transport
|
|
@@ -28,7 +28,7 @@ from ..config.logging_setup import get_logger
|
|
|
28
28
|
from ..monitoring.error_recovery import retry_with_backoff
|
|
29
29
|
from .client import HttpError, RetryConfig
|
|
30
30
|
|
|
31
|
-
logger = get_logger("
|
|
31
|
+
logger = get_logger("xwsystem.http_client.advanced_client")
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
|
|
@@ -71,7 +71,7 @@ class AdvancedHttpConfig:
|
|
|
71
71
|
class MockTransport:
|
|
72
72
|
"""Mock transport for testing purposes."""
|
|
73
73
|
|
|
74
|
-
def __init__(self, responses:
|
|
74
|
+
def __init__(self, responses: dict[str, Any]):
|
|
75
75
|
"""
|
|
76
76
|
Initialize mock transport.
|
|
77
77
|
|
|
@@ -108,7 +108,7 @@ class MockTransport:
|
|
|
108
108
|
class MockResponse:
|
|
109
109
|
"""Mock HTTP response for testing."""
|
|
110
110
|
|
|
111
|
-
def __init__(self, status_code: int, content: bytes, headers:
|
|
111
|
+
def __init__(self, status_code: int, content: bytes, headers: dict[str, str] = None, url: str = ""):
|
|
112
112
|
self.status_code = status_code
|
|
113
113
|
self.content = content
|
|
114
114
|
self.headers = headers or {}
|
|
@@ -146,7 +146,7 @@ class AdvancedHttpClient:
|
|
|
146
146
|
timeout: float = 30.0,
|
|
147
147
|
config: Optional[AdvancedHttpConfig] = None,
|
|
148
148
|
transport: Optional[Transport] = None,
|
|
149
|
-
default_headers: Optional[
|
|
149
|
+
default_headers: Optional[dict[str, str]] = None,
|
|
150
150
|
) -> None:
|
|
151
151
|
"""
|
|
152
152
|
Initialize advanced HTTP client.
|
|
@@ -229,8 +229,8 @@ class AdvancedHttpClient:
|
|
|
229
229
|
async def get(
|
|
230
230
|
self,
|
|
231
231
|
url: str,
|
|
232
|
-
params: Optional[
|
|
233
|
-
headers: Optional[
|
|
232
|
+
params: Optional[dict[str, Any]] = None,
|
|
233
|
+
headers: Optional[dict[str, str]] = None,
|
|
234
234
|
**kwargs
|
|
235
235
|
) -> httpx.Response:
|
|
236
236
|
"""Async GET request."""
|
|
@@ -241,8 +241,8 @@ class AdvancedHttpClient:
|
|
|
241
241
|
url: str,
|
|
242
242
|
json: Optional[Any] = None,
|
|
243
243
|
data: Optional[Any] = None,
|
|
244
|
-
files: Optional[
|
|
245
|
-
headers: Optional[
|
|
244
|
+
files: Optional[dict[str, Any]] = None,
|
|
245
|
+
headers: Optional[dict[str, str]] = None,
|
|
246
246
|
**kwargs
|
|
247
247
|
) -> httpx.Response:
|
|
248
248
|
"""Async POST request."""
|
|
@@ -253,7 +253,7 @@ class AdvancedHttpClient:
|
|
|
253
253
|
url: str,
|
|
254
254
|
json: Optional[Any] = None,
|
|
255
255
|
data: Optional[Any] = None,
|
|
256
|
-
headers: Optional[
|
|
256
|
+
headers: Optional[dict[str, str]] = None,
|
|
257
257
|
**kwargs
|
|
258
258
|
) -> httpx.Response:
|
|
259
259
|
"""Async PUT request."""
|
|
@@ -264,7 +264,7 @@ class AdvancedHttpClient:
|
|
|
264
264
|
url: str,
|
|
265
265
|
json: Optional[Any] = None,
|
|
266
266
|
data: Optional[Any] = None,
|
|
267
|
-
headers: Optional[
|
|
267
|
+
headers: Optional[dict[str, str]] = None,
|
|
268
268
|
**kwargs
|
|
269
269
|
) -> httpx.Response:
|
|
270
270
|
"""Async PATCH request."""
|
|
@@ -273,7 +273,7 @@ class AdvancedHttpClient:
|
|
|
273
273
|
async def delete(
|
|
274
274
|
self,
|
|
275
275
|
url: str,
|
|
276
|
-
headers: Optional[
|
|
276
|
+
headers: Optional[dict[str, str]] = None,
|
|
277
277
|
**kwargs
|
|
278
278
|
) -> httpx.Response:
|
|
279
279
|
"""Async DELETE request."""
|
|
@@ -282,7 +282,7 @@ class AdvancedHttpClient:
|
|
|
282
282
|
async def head(
|
|
283
283
|
self,
|
|
284
284
|
url: str,
|
|
285
|
-
headers: Optional[
|
|
285
|
+
headers: Optional[dict[str, str]] = None,
|
|
286
286
|
**kwargs
|
|
287
287
|
) -> httpx.Response:
|
|
288
288
|
"""Async HEAD request."""
|
|
@@ -291,7 +291,7 @@ class AdvancedHttpClient:
|
|
|
291
291
|
async def options(
|
|
292
292
|
self,
|
|
293
293
|
url: str,
|
|
294
|
-
headers: Optional[
|
|
294
|
+
headers: Optional[dict[str, str]] = None,
|
|
295
295
|
**kwargs
|
|
296
296
|
) -> httpx.Response:
|
|
297
297
|
"""Async OPTIONS request."""
|
|
@@ -301,11 +301,11 @@ class AdvancedHttpClient:
|
|
|
301
301
|
self,
|
|
302
302
|
method: str,
|
|
303
303
|
url: str,
|
|
304
|
-
headers: Optional[
|
|
305
|
-
params: Optional[
|
|
304
|
+
headers: Optional[dict[str, str]] = None,
|
|
305
|
+
params: Optional[dict[str, Any]] = None,
|
|
306
306
|
json: Optional[Any] = None,
|
|
307
307
|
data: Optional[Any] = None,
|
|
308
|
-
files: Optional[
|
|
308
|
+
files: Optional[dict[str, Any]] = None,
|
|
309
309
|
**kwargs
|
|
310
310
|
) -> httpx.Response:
|
|
311
311
|
"""Make async HTTP request with retry logic."""
|
|
@@ -368,8 +368,8 @@ class AdvancedHttpClient:
|
|
|
368
368
|
self,
|
|
369
369
|
method: str,
|
|
370
370
|
url: str,
|
|
371
|
-
headers: Optional[
|
|
372
|
-
params: Optional[
|
|
371
|
+
headers: Optional[dict[str, str]] = None,
|
|
372
|
+
params: Optional[dict[str, Any]] = None,
|
|
373
373
|
json: Optional[Any] = None,
|
|
374
374
|
data: Optional[Any] = None,
|
|
375
375
|
**kwargs
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
#exonware/
|
|
1
|
+
#exonware/xwsystem/http/base.py
|
|
2
2
|
"""
|
|
3
3
|
Company: eXonware.com
|
|
4
4
|
Author: Eng. Muhammad AlShehri
|
|
5
5
|
Email: connect@exonware.com
|
|
6
|
-
Version: 0.0.1.
|
|
6
|
+
Version: 0.0.1.411
|
|
7
7
|
Generation Date: September 04, 2025
|
|
8
8
|
|
|
9
9
|
HTTP module base classes - abstract classes for HTTP client functionality.
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
12
|
from abc import ABC, abstractmethod
|
|
13
|
-
from typing import Any,
|
|
13
|
+
from typing import Any, Optional, Union, AsyncGenerator
|
|
14
14
|
from .contracts import HttpMethod, HttpStatus, ContentType, AuthType
|
|
15
15
|
|
|
16
16
|
|
|
@@ -28,8 +28,8 @@ class AHttpClientBase(ABC):
|
|
|
28
28
|
self.base_url = base_url
|
|
29
29
|
self.timeout = timeout
|
|
30
30
|
self._session: Optional[Any] = None
|
|
31
|
-
self._headers:
|
|
32
|
-
self._cookies:
|
|
31
|
+
self._headers: dict[str, str] = {}
|
|
32
|
+
self._cookies: dict[str, str] = {}
|
|
33
33
|
|
|
34
34
|
@abstractmethod
|
|
35
35
|
def get(self, url: str, **kwargs) -> Any:
|
|
@@ -129,7 +129,7 @@ class AAsyncHttpClientBase(ABC):
|
|
|
129
129
|
class AHttpResponseBase(ABC):
|
|
130
130
|
"""Abstract base class for HTTP response."""
|
|
131
131
|
|
|
132
|
-
def __init__(self, status_code: int, headers:
|
|
132
|
+
def __init__(self, status_code: int, headers: dict[str, str], content: Any):
|
|
133
133
|
"""
|
|
134
134
|
Initialize HTTP response.
|
|
135
135
|
|
|
@@ -143,7 +143,7 @@ class AHttpResponseBase(ABC):
|
|
|
143
143
|
self.content = content
|
|
144
144
|
|
|
145
145
|
@abstractmethod
|
|
146
|
-
def json(self) ->
|
|
146
|
+
def json(self) -> dict[str, Any]:
|
|
147
147
|
"""Parse response as JSON."""
|
|
148
148
|
pass
|
|
149
149
|
|
|
@@ -173,7 +173,7 @@ class AHttpResponseBase(ABC):
|
|
|
173
173
|
pass
|
|
174
174
|
|
|
175
175
|
@abstractmethod
|
|
176
|
-
def get_cookies(self) ->
|
|
176
|
+
def get_cookies(self) -> dict[str, str]:
|
|
177
177
|
"""Get response cookies."""
|
|
178
178
|
pass
|
|
179
179
|
|
|
@@ -187,12 +187,12 @@ class AHttpSessionBase(ABC):
|
|
|
187
187
|
pass
|
|
188
188
|
|
|
189
189
|
@abstractmethod
|
|
190
|
-
def set_headers(self, headers:
|
|
190
|
+
def set_headers(self, headers: dict[str, str]) -> None:
|
|
191
191
|
"""Set default headers."""
|
|
192
192
|
pass
|
|
193
193
|
|
|
194
194
|
@abstractmethod
|
|
195
|
-
def set_cookies(self, cookies:
|
|
195
|
+
def set_cookies(self, cookies: dict[str, str]) -> None:
|
|
196
196
|
"""Set cookies."""
|
|
197
197
|
pass
|
|
198
198
|
|
|
@@ -212,7 +212,7 @@ class AHttpSessionBase(ABC):
|
|
|
212
212
|
pass
|
|
213
213
|
|
|
214
214
|
@abstractmethod
|
|
215
|
-
def get_session_info(self) ->
|
|
215
|
+
def get_session_info(self) -> dict[str, Any]:
|
|
216
216
|
"""Get session information."""
|
|
217
217
|
pass
|
|
218
218
|
|
|
@@ -242,12 +242,12 @@ class AHttpRetryBase(ABC):
|
|
|
242
242
|
pass
|
|
243
243
|
|
|
244
244
|
@abstractmethod
|
|
245
|
-
def get_retry_status_codes(self) ->
|
|
245
|
+
def get_retry_status_codes(self) -> list[int]:
|
|
246
246
|
"""Get status codes that should trigger retry."""
|
|
247
247
|
pass
|
|
248
248
|
|
|
249
249
|
@abstractmethod
|
|
250
|
-
def set_retry_status_codes(self, status_codes:
|
|
250
|
+
def set_retry_status_codes(self, status_codes: list[int]) -> None:
|
|
251
251
|
"""Set status codes that should trigger retry."""
|
|
252
252
|
pass
|
|
253
253
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Company: eXonware.com
|
|
3
3
|
Author: Eng. Muhammad AlShehri
|
|
4
4
|
Email: connect@exonware.com
|
|
5
|
-
Version: 0.0.1.
|
|
5
|
+
Version: 0.0.1.411
|
|
6
6
|
Generation Date: September 04, 2025
|
|
7
7
|
|
|
8
8
|
HTTP client with retry mechanisms, connection pooling, and error handling.
|
|
@@ -12,7 +12,7 @@ import asyncio
|
|
|
12
12
|
import os
|
|
13
13
|
import time
|
|
14
14
|
from dataclasses import dataclass, field
|
|
15
|
-
from typing import Any,
|
|
15
|
+
from typing import Any, Optional, Union
|
|
16
16
|
from urllib.parse import urljoin
|
|
17
17
|
|
|
18
18
|
# Prevent httpx from importing rich (Python 3.8+ only, no legacy deps)
|
|
@@ -24,7 +24,7 @@ from ..config.logging_setup import get_logger
|
|
|
24
24
|
from ..monitoring.error_recovery import retry_with_backoff
|
|
25
25
|
from .errors import HttpError
|
|
26
26
|
|
|
27
|
-
logger = get_logger("
|
|
27
|
+
logger = get_logger("xwsystem.http_client.client")
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
@dataclass
|
|
@@ -35,8 +35,8 @@ class RetryConfig:
|
|
|
35
35
|
base_delay: float = 1.0
|
|
36
36
|
max_delay: float = 60.0
|
|
37
37
|
exponential_base: float = 2.0
|
|
38
|
-
retry_on_status:
|
|
39
|
-
retry_on_exceptions:
|
|
38
|
+
retry_on_status: list[int] = field(default_factory=lambda: [500, 502, 503, 504, 429])
|
|
39
|
+
retry_on_exceptions: list[type] = field(default_factory=lambda: [httpx.ConnectError, httpx.TimeoutException])
|
|
40
40
|
|
|
41
41
|
|
|
42
42
|
class HttpClient:
|
|
@@ -52,7 +52,7 @@ class HttpClient:
|
|
|
52
52
|
max_connections: int = 100,
|
|
53
53
|
max_keepalive_connections: int = 20,
|
|
54
54
|
retry_config: Optional[RetryConfig] = None,
|
|
55
|
-
default_headers: Optional[
|
|
55
|
+
default_headers: Optional[dict[str, str]] = None,
|
|
56
56
|
) -> None:
|
|
57
57
|
"""
|
|
58
58
|
Initialize HTTP client.
|
|
@@ -131,11 +131,11 @@ class HttpClient:
|
|
|
131
131
|
self,
|
|
132
132
|
method: str,
|
|
133
133
|
url: str,
|
|
134
|
-
headers: Optional[
|
|
135
|
-
params: Optional[
|
|
134
|
+
headers: Optional[dict[str, str]] = None,
|
|
135
|
+
params: Optional[dict[str, Any]] = None,
|
|
136
136
|
json_data: Optional[Any] = None,
|
|
137
137
|
data: Optional[Any] = None,
|
|
138
|
-
files: Optional[
|
|
138
|
+
files: Optional[dict[str, Any]] = None,
|
|
139
139
|
) -> httpx.Response:
|
|
140
140
|
"""Make HTTP request with retry logic."""
|
|
141
141
|
|
|
@@ -187,8 +187,8 @@ class HttpClient:
|
|
|
187
187
|
def get(
|
|
188
188
|
self,
|
|
189
189
|
url: str,
|
|
190
|
-
headers: Optional[
|
|
191
|
-
params: Optional[
|
|
190
|
+
headers: Optional[dict[str, str]] = None,
|
|
191
|
+
params: Optional[dict[str, Any]] = None,
|
|
192
192
|
) -> httpx.Response:
|
|
193
193
|
"""Make GET request."""
|
|
194
194
|
return self._make_request('GET', url, headers=headers, params=params)
|
|
@@ -196,11 +196,11 @@ class HttpClient:
|
|
|
196
196
|
def post(
|
|
197
197
|
self,
|
|
198
198
|
url: str,
|
|
199
|
-
headers: Optional[
|
|
200
|
-
params: Optional[
|
|
199
|
+
headers: Optional[dict[str, str]] = None,
|
|
200
|
+
params: Optional[dict[str, Any]] = None,
|
|
201
201
|
json_data: Optional[Any] = None,
|
|
202
202
|
data: Optional[Any] = None,
|
|
203
|
-
files: Optional[
|
|
203
|
+
files: Optional[dict[str, Any]] = None,
|
|
204
204
|
) -> httpx.Response:
|
|
205
205
|
"""Make POST request."""
|
|
206
206
|
return self._make_request(
|
|
@@ -211,8 +211,8 @@ class HttpClient:
|
|
|
211
211
|
def put(
|
|
212
212
|
self,
|
|
213
213
|
url: str,
|
|
214
|
-
headers: Optional[
|
|
215
|
-
params: Optional[
|
|
214
|
+
headers: Optional[dict[str, str]] = None,
|
|
215
|
+
params: Optional[dict[str, Any]] = None,
|
|
216
216
|
json_data: Optional[Any] = None,
|
|
217
217
|
data: Optional[Any] = None,
|
|
218
218
|
) -> httpx.Response:
|
|
@@ -225,8 +225,8 @@ class HttpClient:
|
|
|
225
225
|
def patch(
|
|
226
226
|
self,
|
|
227
227
|
url: str,
|
|
228
|
-
headers: Optional[
|
|
229
|
-
params: Optional[
|
|
228
|
+
headers: Optional[dict[str, str]] = None,
|
|
229
|
+
params: Optional[dict[str, Any]] = None,
|
|
230
230
|
json_data: Optional[Any] = None,
|
|
231
231
|
data: Optional[Any] = None,
|
|
232
232
|
) -> httpx.Response:
|
|
@@ -239,8 +239,8 @@ class HttpClient:
|
|
|
239
239
|
def delete(
|
|
240
240
|
self,
|
|
241
241
|
url: str,
|
|
242
|
-
headers: Optional[
|
|
243
|
-
params: Optional[
|
|
242
|
+
headers: Optional[dict[str, str]] = None,
|
|
243
|
+
params: Optional[dict[str, Any]] = None,
|
|
244
244
|
) -> httpx.Response:
|
|
245
245
|
"""Make DELETE request."""
|
|
246
246
|
return self._make_request('DELETE', url, headers=headers, params=params)
|
|
@@ -248,8 +248,8 @@ class HttpClient:
|
|
|
248
248
|
def head(
|
|
249
249
|
self,
|
|
250
250
|
url: str,
|
|
251
|
-
headers: Optional[
|
|
252
|
-
params: Optional[
|
|
251
|
+
headers: Optional[dict[str, str]] = None,
|
|
252
|
+
params: Optional[dict[str, Any]] = None,
|
|
253
253
|
) -> httpx.Response:
|
|
254
254
|
"""Make HEAD request."""
|
|
255
255
|
return self._make_request('HEAD', url, headers=headers, params=params)
|
|
@@ -257,8 +257,8 @@ class HttpClient:
|
|
|
257
257
|
def options(
|
|
258
258
|
self,
|
|
259
259
|
url: str,
|
|
260
|
-
headers: Optional[
|
|
261
|
-
params: Optional[
|
|
260
|
+
headers: Optional[dict[str, str]] = None,
|
|
261
|
+
params: Optional[dict[str, Any]] = None,
|
|
262
262
|
) -> httpx.Response:
|
|
263
263
|
"""Make OPTIONS request."""
|
|
264
264
|
return self._make_request('OPTIONS', url, headers=headers, params=params)
|
|
@@ -313,7 +313,7 @@ class AsyncHttpClient:
|
|
|
313
313
|
max_connections: int = 100,
|
|
314
314
|
max_keepalive_connections: int = 20,
|
|
315
315
|
retry_config: Optional[RetryConfig] = None,
|
|
316
|
-
default_headers: Optional[
|
|
316
|
+
default_headers: Optional[dict[str, str]] = None,
|
|
317
317
|
) -> None:
|
|
318
318
|
"""
|
|
319
319
|
Initialize async HTTP client.
|
|
@@ -374,11 +374,11 @@ class AsyncHttpClient:
|
|
|
374
374
|
self,
|
|
375
375
|
method: str,
|
|
376
376
|
url: str,
|
|
377
|
-
headers: Optional[
|
|
378
|
-
params: Optional[
|
|
377
|
+
headers: Optional[dict[str, str]] = None,
|
|
378
|
+
params: Optional[dict[str, Any]] = None,
|
|
379
379
|
json_data: Optional[Any] = None,
|
|
380
380
|
data: Optional[Any] = None,
|
|
381
|
-
files: Optional[
|
|
381
|
+
files: Optional[dict[str, Any]] = None,
|
|
382
382
|
) -> httpx.Response:
|
|
383
383
|
"""Make async HTTP request with retry logic."""
|
|
384
384
|
|
|
@@ -430,8 +430,8 @@ class AsyncHttpClient:
|
|
|
430
430
|
async def get(
|
|
431
431
|
self,
|
|
432
432
|
url: str,
|
|
433
|
-
headers: Optional[
|
|
434
|
-
params: Optional[
|
|
433
|
+
headers: Optional[dict[str, str]] = None,
|
|
434
|
+
params: Optional[dict[str, Any]] = None,
|
|
435
435
|
) -> httpx.Response:
|
|
436
436
|
"""Make async GET request."""
|
|
437
437
|
return await self._make_request('GET', url, headers=headers, params=params)
|
|
@@ -439,11 +439,11 @@ class AsyncHttpClient:
|
|
|
439
439
|
async def post(
|
|
440
440
|
self,
|
|
441
441
|
url: str,
|
|
442
|
-
headers: Optional[
|
|
443
|
-
params: Optional[
|
|
442
|
+
headers: Optional[dict[str, str]] = None,
|
|
443
|
+
params: Optional[dict[str, Any]] = None,
|
|
444
444
|
json_data: Optional[Any] = None,
|
|
445
445
|
data: Optional[Any] = None,
|
|
446
|
-
files: Optional[
|
|
446
|
+
files: Optional[dict[str, Any]] = None,
|
|
447
447
|
) -> httpx.Response:
|
|
448
448
|
"""Make async POST request."""
|
|
449
449
|
return await self._make_request(
|
|
@@ -454,8 +454,8 @@ class AsyncHttpClient:
|
|
|
454
454
|
async def put(
|
|
455
455
|
self,
|
|
456
456
|
url: str,
|
|
457
|
-
headers: Optional[
|
|
458
|
-
params: Optional[
|
|
457
|
+
headers: Optional[dict[str, str]] = None,
|
|
458
|
+
params: Optional[dict[str, Any]] = None,
|
|
459
459
|
json_data: Optional[Any] = None,
|
|
460
460
|
data: Optional[Any] = None,
|
|
461
461
|
) -> httpx.Response:
|
|
@@ -468,8 +468,8 @@ class AsyncHttpClient:
|
|
|
468
468
|
async def patch(
|
|
469
469
|
self,
|
|
470
470
|
url: str,
|
|
471
|
-
headers: Optional[
|
|
472
|
-
params: Optional[
|
|
471
|
+
headers: Optional[dict[str, str]] = None,
|
|
472
|
+
params: Optional[dict[str, Any]] = None,
|
|
473
473
|
json_data: Optional[Any] = None,
|
|
474
474
|
data: Optional[Any] = None,
|
|
475
475
|
) -> httpx.Response:
|
|
@@ -482,8 +482,8 @@ class AsyncHttpClient:
|
|
|
482
482
|
async def delete(
|
|
483
483
|
self,
|
|
484
484
|
url: str,
|
|
485
|
-
headers: Optional[
|
|
486
|
-
params: Optional[
|
|
485
|
+
headers: Optional[dict[str, str]] = None,
|
|
486
|
+
params: Optional[dict[str, Any]] = None,
|
|
487
487
|
) -> httpx.Response:
|
|
488
488
|
"""Make async DELETE request."""
|
|
489
489
|
return await self._make_request('DELETE', url, headers=headers, params=params)
|
|
@@ -491,8 +491,8 @@ class AsyncHttpClient:
|
|
|
491
491
|
async def head(
|
|
492
492
|
self,
|
|
493
493
|
url: str,
|
|
494
|
-
headers: Optional[
|
|
495
|
-
params: Optional[
|
|
494
|
+
headers: Optional[dict[str, str]] = None,
|
|
495
|
+
params: Optional[dict[str, Any]] = None,
|
|
496
496
|
) -> httpx.Response:
|
|
497
497
|
"""Make async HEAD request."""
|
|
498
498
|
return await self._make_request('HEAD', url, headers=headers, params=params)
|
|
@@ -500,8 +500,8 @@ class AsyncHttpClient:
|
|
|
500
500
|
async def options(
|
|
501
501
|
self,
|
|
502
502
|
url: str,
|
|
503
|
-
headers: Optional[
|
|
504
|
-
params: Optional[
|
|
503
|
+
headers: Optional[dict[str, str]] = None,
|
|
504
|
+
params: Optional[dict[str, Any]] = None,
|
|
505
505
|
) -> httpx.Response:
|
|
506
506
|
"""Make async OPTIONS request."""
|
|
507
507
|
return await self._make_request('OPTIONS', url, headers=headers, params=params)
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
Company: eXonware.com
|
|
3
3
|
Author: Eng. Muhammad AlShehri
|
|
4
4
|
Email: connect@exonware.com
|
|
5
|
-
Version: 0.0.1.
|
|
5
|
+
Version: 0.0.1.411
|
|
6
6
|
Generation Date: September 04, 2025
|
|
7
7
|
|
|
8
8
|
HTTP module contracts - interfaces and enums for HTTP client functionality.
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
11
|
from abc import ABC, abstractmethod
|
|
12
|
-
from typing import Any,
|
|
12
|
+
from typing import Any, Optional, Union, AsyncGenerator
|
|
13
13
|
from urllib.parse import ParseResult
|
|
14
14
|
|
|
15
15
|
# Import enums from types module
|
|
@@ -62,7 +62,7 @@ class IHttpResponse(ABC):
|
|
|
62
62
|
|
|
63
63
|
@property
|
|
64
64
|
@abstractmethod
|
|
65
|
-
def headers(self) ->
|
|
65
|
+
def headers(self) -> dict[str, str]:
|
|
66
66
|
"""Response headers."""
|
|
67
67
|
pass
|
|
68
68
|
|
|
@@ -108,7 +108,7 @@ class IHttpSession(ABC):
|
|
|
108
108
|
pass
|
|
109
109
|
|
|
110
110
|
@abstractmethod
|
|
111
|
-
def set_headers(self, headers:
|
|
111
|
+
def set_headers(self, headers: dict[str, str]) -> None:
|
|
112
112
|
"""Set default headers."""
|
|
113
113
|
pass
|
|
114
114
|
|
|
@@ -141,7 +141,7 @@ class IRetryConfig(ABC):
|
|
|
141
141
|
|
|
142
142
|
@property
|
|
143
143
|
@abstractmethod
|
|
144
|
-
def retry_on_status(self) ->
|
|
144
|
+
def retry_on_status(self) -> list[int]:
|
|
145
145
|
"""Status codes to retry on."""
|
|
146
146
|
pass
|
|
147
147
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
#exonware/xwsystem/
|
|
2
|
+
#exonware/xwsystem/http_client/defs.py
|
|
3
3
|
"""
|
|
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: 07-Sep-2025
|
|
9
9
|
|
|
10
10
|
HTTP types and enums for XWSystem.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
#exonware/
|
|
1
|
+
#exonware/xwsystem/http/errors.py
|
|
2
2
|
"""
|
|
3
3
|
Company: eXonware.com
|
|
4
4
|
Author: Eng. Muhammad AlShehri
|
|
5
5
|
Email: connect@exonware.com
|
|
6
|
-
Version: 0.0.1.
|
|
6
|
+
Version: 0.0.1.411
|
|
7
7
|
Generation Date: September 04, 2025
|
|
8
8
|
|
|
9
9
|
HTTP module errors - exception classes for HTTP client functionality.
|
exonware/xwsystem/io/__init__.py
CHANGED
|
@@ -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 facade using registry pattern.
|
|
@@ -19,7 +19,7 @@ Priority 5 (Extensibility): Add formats via registry!
|
|
|
19
19
|
"""
|
|
20
20
|
|
|
21
21
|
from pathlib import Path
|
|
22
|
-
from typing import
|
|
22
|
+
from typing import Optional
|
|
23
23
|
|
|
24
24
|
# IArchive removed - using IArchiver and IArchiveFile instead
|
|
25
25
|
from .formats import get_archiver_for_file, get_archiver_by_id
|
|
@@ -43,7 +43,7 @@ class Archive:
|
|
|
43
43
|
>>> archive.create([Path("file.txt")], Path("backup.7z")) # Uses 7zArchiver
|
|
44
44
|
"""
|
|
45
45
|
|
|
46
|
-
def create(self, files:
|
|
46
|
+
def create(self, files: list[Path], output: Path, format: str = 'zip', **opts) -> None:
|
|
47
47
|
"""
|
|
48
48
|
Create archive - auto-detects handler.
|
|
49
49
|
|
|
@@ -65,7 +65,7 @@ class Archive:
|
|
|
65
65
|
# Delegate to format-specific handler
|
|
66
66
|
archiver.create(files, output, **opts)
|
|
67
67
|
|
|
68
|
-
def extract(self, archive: Path, output_dir: Path, members: Optional[
|
|
68
|
+
def extract(self, archive: Path, output_dir: Path, members: Optional[list[str]] = None, **opts) -> list[Path]:
|
|
69
69
|
"""
|
|
70
70
|
Extract archive - auto-detects handler.
|
|
71
71
|
"""
|
|
@@ -78,7 +78,7 @@ class Archive:
|
|
|
78
78
|
# Delegate to format-specific handler
|
|
79
79
|
return archiver.extract(archive, output_dir, members, **opts)
|
|
80
80
|
|
|
81
|
-
def list_contents(self, archive: Path) ->
|
|
81
|
+
def list_contents(self, archive: Path) -> list[str]:
|
|
82
82
|
"""
|
|
83
83
|
List archive contents - auto-detects handler.
|
|
84
84
|
"""
|
|
@@ -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 FILES - File persistence for archives.
|
|
@@ -26,7 +26,7 @@ Priority 5 (Extensibility): Easy to add new formats
|
|
|
26
26
|
import zipfile
|
|
27
27
|
import tarfile
|
|
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 AArchiveFile
|
|
32
32
|
from ..contracts import IArchiveFile, IArchiver
|
|
@@ -68,7 +68,7 @@ class ZipFile(AArchiveFile):
|
|
|
68
68
|
super().__init__(path, archiver=ZipArchiver())
|
|
69
69
|
self._archiver = ZipArchiver() # Composition!
|
|
70
70
|
|
|
71
|
-
def add_files(self, files:
|
|
71
|
+
def add_files(self, files: list[Path], **options) -> None:
|
|
72
72
|
"""
|
|
73
73
|
Add files to zip archive.
|
|
74
74
|
|
|
@@ -93,7 +93,7 @@ class ZipFile(AArchiveFile):
|
|
|
93
93
|
except Exception as e:
|
|
94
94
|
raise ArchiveError(f"Failed to add files to zip: {e}")
|
|
95
95
|
|
|
96
|
-
def extract_to(self, dest: Path, **options) ->
|
|
96
|
+
def extract_to(self, dest: Path, **options) -> list[Path]:
|
|
97
97
|
"""
|
|
98
98
|
Extract zip archive to destination.
|
|
99
99
|
|
|
@@ -123,7 +123,7 @@ class ZipFile(AArchiveFile):
|
|
|
123
123
|
except Exception as e:
|
|
124
124
|
raise ArchiveError(f"Failed to extract zip: {e}")
|
|
125
125
|
|
|
126
|
-
def list_contents(self) ->
|
|
126
|
+
def list_contents(self) -> list[str]:
|
|
127
127
|
"""List files in zip archive."""
|
|
128
128
|
try:
|
|
129
129
|
with zipfile.ZipFile(self.file_path, 'r') as zf:
|
|
@@ -162,7 +162,7 @@ class TarFile(AArchiveFile):
|
|
|
162
162
|
self._archiver = TarArchiver() # Composition!
|
|
163
163
|
self._compression = compression
|
|
164
164
|
|
|
165
|
-
def add_files(self, files:
|
|
165
|
+
def add_files(self, files: list[Path], **options) -> None:
|
|
166
166
|
"""Add files to tar archive (uses archiver internally)."""
|
|
167
167
|
try:
|
|
168
168
|
# Read files
|
|
@@ -181,7 +181,7 @@ class TarFile(AArchiveFile):
|
|
|
181
181
|
except Exception as e:
|
|
182
182
|
raise ArchiveError(f"Failed to add files to tar: {e}")
|
|
183
183
|
|
|
184
|
-
def extract_to(self, dest: Path, **options) ->
|
|
184
|
+
def extract_to(self, dest: Path, **options) -> list[Path]:
|
|
185
185
|
"""Extract tar archive to destination (uses archiver internally)."""
|
|
186
186
|
try:
|
|
187
187
|
# Load from disk using direct read
|
|
@@ -204,7 +204,7 @@ class TarFile(AArchiveFile):
|
|
|
204
204
|
except Exception as e:
|
|
205
205
|
raise ArchiveError(f"Failed to extract tar: {e}")
|
|
206
206
|
|
|
207
|
-
def list_contents(self) ->
|
|
207
|
+
def list_contents(self) -> list[str]:
|
|
208
208
|
"""List files in tar archive."""
|
|
209
209
|
try:
|
|
210
210
|
with tarfile.open(self.file_path, 'r:*') as tf:
|