exonware-xwlazy 0.1.0.11__py3-none-any.whl → 0.1.0.19__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 +22 -0
- exonware/xwlazy/__init__.py +0 -0
- exonware/xwlazy/common/__init__.py +47 -0
- exonware/xwlazy/common/base.py +58 -0
- exonware/xwlazy/common/cache.py +506 -0
- exonware/xwlazy/common/logger.py +268 -0
- exonware/xwlazy/common/services/__init__.py +72 -0
- exonware/xwlazy/common/services/dependency_mapper.py +234 -0
- exonware/xwlazy/common/services/install_async_utils.py +169 -0
- exonware/xwlazy/common/services/install_cache_utils.py +257 -0
- exonware/xwlazy/common/services/keyword_detection.py +292 -0
- exonware/xwlazy/common/services/spec_cache.py +173 -0
- exonware/xwlazy/common/strategies/__init__.py +28 -0
- exonware/xwlazy/common/strategies/caching_dict.py +45 -0
- exonware/xwlazy/common/strategies/caching_installation.py +89 -0
- exonware/xwlazy/common/strategies/caching_lfu.py +67 -0
- exonware/xwlazy/common/strategies/caching_lru.py +64 -0
- exonware/xwlazy/common/strategies/caching_multitier.py +60 -0
- exonware/xwlazy/common/strategies/caching_ttl.py +60 -0
- {xwlazy/lazy → exonware/xwlazy}/config.py +52 -20
- exonware/xwlazy/contracts.py +1410 -0
- exonware/xwlazy/defs.py +397 -0
- xwlazy/lazy/lazy_errors.py → exonware/xwlazy/errors.py +21 -8
- exonware/xwlazy/facade.py +1049 -0
- exonware/xwlazy/module/__init__.py +18 -0
- exonware/xwlazy/module/base.py +569 -0
- exonware/xwlazy/module/data.py +17 -0
- exonware/xwlazy/module/facade.py +247 -0
- exonware/xwlazy/module/importer_engine.py +2161 -0
- exonware/xwlazy/module/strategies/__init__.py +22 -0
- exonware/xwlazy/module/strategies/module_helper_lazy.py +94 -0
- exonware/xwlazy/module/strategies/module_helper_simple.py +66 -0
- exonware/xwlazy/module/strategies/module_manager_advanced.py +112 -0
- exonware/xwlazy/module/strategies/module_manager_simple.py +96 -0
- exonware/xwlazy/package/__init__.py +18 -0
- exonware/xwlazy/package/base.py +807 -0
- xwlazy/lazy/host_conf.py → exonware/xwlazy/package/conf.py +62 -10
- exonware/xwlazy/package/data.py +17 -0
- exonware/xwlazy/package/facade.py +481 -0
- exonware/xwlazy/package/services/__init__.py +84 -0
- exonware/xwlazy/package/services/async_install_handle.py +89 -0
- exonware/xwlazy/package/services/config_manager.py +246 -0
- exonware/xwlazy/package/services/discovery.py +374 -0
- {xwlazy/lazy → exonware/xwlazy/package/services}/host_packages.py +43 -16
- exonware/xwlazy/package/services/install_async.py +278 -0
- exonware/xwlazy/package/services/install_cache.py +146 -0
- exonware/xwlazy/package/services/install_interactive.py +60 -0
- exonware/xwlazy/package/services/install_policy.py +158 -0
- exonware/xwlazy/package/services/install_registry.py +56 -0
- exonware/xwlazy/package/services/install_result.py +17 -0
- exonware/xwlazy/package/services/install_sbom.py +154 -0
- exonware/xwlazy/package/services/install_utils.py +83 -0
- exonware/xwlazy/package/services/installer_engine.py +408 -0
- exonware/xwlazy/package/services/lazy_installer.py +720 -0
- {xwlazy/lazy → exonware/xwlazy/package/services}/manifest.py +42 -25
- exonware/xwlazy/package/services/strategy_registry.py +188 -0
- exonware/xwlazy/package/strategies/__init__.py +57 -0
- exonware/xwlazy/package/strategies/package_discovery_file.py +130 -0
- exonware/xwlazy/package/strategies/package_discovery_hybrid.py +85 -0
- exonware/xwlazy/package/strategies/package_discovery_manifest.py +102 -0
- exonware/xwlazy/package/strategies/package_execution_async.py +114 -0
- exonware/xwlazy/package/strategies/package_execution_cached.py +91 -0
- exonware/xwlazy/package/strategies/package_execution_pip.py +100 -0
- exonware/xwlazy/package/strategies/package_execution_wheel.py +107 -0
- exonware/xwlazy/package/strategies/package_mapping_discovery_first.py +101 -0
- exonware/xwlazy/package/strategies/package_mapping_hybrid.py +106 -0
- exonware/xwlazy/package/strategies/package_mapping_manifest_first.py +101 -0
- exonware/xwlazy/package/strategies/package_policy_allow_list.py +58 -0
- exonware/xwlazy/package/strategies/package_policy_deny_list.py +58 -0
- exonware/xwlazy/package/strategies/package_policy_permissive.py +47 -0
- exonware/xwlazy/package/strategies/package_timing_clean.py +68 -0
- exonware/xwlazy/package/strategies/package_timing_full.py +67 -0
- exonware/xwlazy/package/strategies/package_timing_smart.py +69 -0
- exonware/xwlazy/package/strategies/package_timing_temporary.py +67 -0
- exonware/xwlazy/runtime/__init__.py +18 -0
- exonware/xwlazy/runtime/adaptive_learner.py +131 -0
- exonware/xwlazy/runtime/base.py +276 -0
- exonware/xwlazy/runtime/facade.py +95 -0
- exonware/xwlazy/runtime/intelligent_selector.py +173 -0
- exonware/xwlazy/runtime/metrics.py +64 -0
- exonware/xwlazy/runtime/performance.py +39 -0
- exonware/xwlazy/version.py +2 -2
- {exonware_xwlazy-0.1.0.11.dist-info → exonware_xwlazy-0.1.0.19.dist-info}/METADATA +86 -10
- exonware_xwlazy-0.1.0.19.dist-info/RECORD +87 -0
- exonware_xwlazy-0.1.0.11.dist-info/RECORD +0 -20
- xwlazy/__init__.py +0 -34
- xwlazy/lazy/__init__.py +0 -301
- xwlazy/lazy/bootstrap.py +0 -106
- xwlazy/lazy/lazy_base.py +0 -465
- xwlazy/lazy/lazy_contracts.py +0 -290
- xwlazy/lazy/lazy_core.py +0 -3727
- xwlazy/lazy/logging_utils.py +0 -194
- xwlazy/version.py +0 -77
- /xwlazy/lazy/lazy_state.py → /exonware/xwlazy/common/services/state_manager.py +0 -0
- {exonware_xwlazy-0.1.0.11.dist-info → exonware_xwlazy-0.1.0.19.dist-info}/WHEEL +0 -0
- {exonware_xwlazy-0.1.0.11.dist-info → exonware_xwlazy-0.1.0.19.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""
|
|
2
|
+
LRU Cache Strategy - Least Recently Used eviction.
|
|
3
|
+
|
|
4
|
+
Company: eXonware.com
|
|
5
|
+
Author: Eng. Muhammad AlShehri
|
|
6
|
+
Email: connect@exonware.com
|
|
7
|
+
Version: 0.1.0.19
|
|
8
|
+
Generation Date: 15-Nov-2025
|
|
9
|
+
|
|
10
|
+
LRU cache implementation with size limit.
|
|
11
|
+
Works with ANY data type (modules, packages, etc.).
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from typing import Optional, Any
|
|
15
|
+
from collections import OrderedDict
|
|
16
|
+
from ...common.base import ACachingStrategy
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class LRUCache(ACachingStrategy):
|
|
20
|
+
"""
|
|
21
|
+
LRU (Least Recently Used) cache with size limit.
|
|
22
|
+
|
|
23
|
+
Evicts least recently used items when cache is full.
|
|
24
|
+
Good for general-purpose caching.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, max_size: int = 1000):
|
|
28
|
+
"""
|
|
29
|
+
Initialize LRU cache.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
max_size: Maximum number of items in cache
|
|
33
|
+
"""
|
|
34
|
+
self._cache: OrderedDict[str, Any] = OrderedDict()
|
|
35
|
+
self._max_size = max_size
|
|
36
|
+
|
|
37
|
+
def get(self, key: str) -> Optional[Any]:
|
|
38
|
+
"""Get value from cache (moves to end for LRU)."""
|
|
39
|
+
if key in self._cache:
|
|
40
|
+
# Move to end (most recently used)
|
|
41
|
+
self._cache.move_to_end(key)
|
|
42
|
+
return self._cache[key]
|
|
43
|
+
return None
|
|
44
|
+
|
|
45
|
+
def set(self, key: str, value: Any) -> None:
|
|
46
|
+
"""Set value in cache (evicts oldest if full)."""
|
|
47
|
+
if key in self._cache:
|
|
48
|
+
# Update existing - move to end
|
|
49
|
+
self._cache.move_to_end(key)
|
|
50
|
+
else:
|
|
51
|
+
# New entry - check size limit
|
|
52
|
+
if len(self._cache) >= self._max_size:
|
|
53
|
+
# Remove oldest (first item)
|
|
54
|
+
self._cache.popitem(last=False)
|
|
55
|
+
self._cache[key] = value
|
|
56
|
+
|
|
57
|
+
def invalidate(self, key: str) -> None:
|
|
58
|
+
"""Invalidate cached value."""
|
|
59
|
+
self._cache.pop(key, None)
|
|
60
|
+
|
|
61
|
+
def clear(self) -> None:
|
|
62
|
+
"""Clear all cached values."""
|
|
63
|
+
self._cache.clear()
|
|
64
|
+
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Multi-Tier Cache Strategy - Wrapper for existing MultiTierCache.
|
|
3
|
+
|
|
4
|
+
Company: eXonware.com
|
|
5
|
+
Author: Eng. Muhammad AlShehri
|
|
6
|
+
Email: connect@exonware.com
|
|
7
|
+
Version: 0.1.0.19
|
|
8
|
+
Generation Date: 15-Nov-2025
|
|
9
|
+
|
|
10
|
+
Wraps existing MultiTierCache to implement ICaching interface.
|
|
11
|
+
Works with ANY data type (modules, packages, etc.).
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from typing import Optional, Any
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
from ...common.cache import MultiTierCache
|
|
17
|
+
from ...common.base import ACachingStrategy
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class MultiTierCacheStrategy(ACachingStrategy):
|
|
21
|
+
"""
|
|
22
|
+
Multi-tier cache strategy (L1 memory + L2 disk + L3 predictive).
|
|
23
|
+
|
|
24
|
+
Wraps existing MultiTierCache to implement ICachingStrategy interface.
|
|
25
|
+
High-performance caching with multiple tiers.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, l1_size: int = 1000, l2_dir: Optional[Path] = None, enable_l3: bool = True):
|
|
29
|
+
"""
|
|
30
|
+
Initialize multi-tier cache.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
l1_size: Maximum size of L1 (memory) cache
|
|
34
|
+
l2_dir: Directory for L2 (disk) cache
|
|
35
|
+
enable_l3: Enable L3 (predictive) cache
|
|
36
|
+
"""
|
|
37
|
+
self._cache = MultiTierCache(l1_size=l1_size, l2_dir=l2_dir, enable_l3=enable_l3)
|
|
38
|
+
|
|
39
|
+
def get(self, key: str) -> Optional[Any]:
|
|
40
|
+
"""Get value from cache (L1 -> L2 -> L3)."""
|
|
41
|
+
return self._cache.get(key)
|
|
42
|
+
|
|
43
|
+
def set(self, key: str, value: Any) -> None:
|
|
44
|
+
"""Set value in cache (L1 + L2 batched)."""
|
|
45
|
+
self._cache.set(key, value)
|
|
46
|
+
|
|
47
|
+
def invalidate(self, key: str) -> None:
|
|
48
|
+
"""Invalidate cached value."""
|
|
49
|
+
# MultiTierCache doesn't have invalidate, so we set to None
|
|
50
|
+
# Or we could extend MultiTierCache to add invalidate
|
|
51
|
+
self._cache.set(key, None)
|
|
52
|
+
|
|
53
|
+
def clear(self) -> None:
|
|
54
|
+
"""Clear all cached values."""
|
|
55
|
+
self._cache.clear()
|
|
56
|
+
|
|
57
|
+
def shutdown(self) -> None:
|
|
58
|
+
"""Shutdown cache (flush L2, cleanup threads)."""
|
|
59
|
+
self._cache.shutdown()
|
|
60
|
+
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TTL Cache Strategy - Time-To-Live expiration.
|
|
3
|
+
|
|
4
|
+
Company: eXonware.com
|
|
5
|
+
Author: Eng. Muhammad AlShehri
|
|
6
|
+
Email: connect@exonware.com
|
|
7
|
+
Version: 0.1.0.19
|
|
8
|
+
Generation Date: 15-Nov-2025
|
|
9
|
+
|
|
10
|
+
TTL cache implementation with expiration.
|
|
11
|
+
Works with ANY data type (modules, packages, etc.).
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import time
|
|
15
|
+
from typing import Dict, Optional, Any, Tuple
|
|
16
|
+
from ...common.base import ACachingStrategy
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class TTLCache(ACachingStrategy):
|
|
20
|
+
"""
|
|
21
|
+
TTL (Time-To-Live) cache with expiration.
|
|
22
|
+
|
|
23
|
+
Automatically expires entries after TTL seconds.
|
|
24
|
+
Good for time-sensitive data.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, ttl_seconds: float = 3600.0):
|
|
28
|
+
"""
|
|
29
|
+
Initialize TTL cache.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
ttl_seconds: Time-to-live in seconds (default: 1 hour)
|
|
33
|
+
"""
|
|
34
|
+
self._cache: Dict[str, Tuple[Any, float]] = {} # (value, expiry_time)
|
|
35
|
+
self._ttl = ttl_seconds
|
|
36
|
+
|
|
37
|
+
def get(self, key: str) -> Optional[Any]:
|
|
38
|
+
"""Get value from cache (returns None if expired)."""
|
|
39
|
+
if key in self._cache:
|
|
40
|
+
value, expiry = self._cache[key]
|
|
41
|
+
if time.time() < expiry:
|
|
42
|
+
return value
|
|
43
|
+
else:
|
|
44
|
+
# Expired - remove
|
|
45
|
+
del self._cache[key]
|
|
46
|
+
return None
|
|
47
|
+
|
|
48
|
+
def set(self, key: str, value: Any) -> None:
|
|
49
|
+
"""Set value in cache with TTL."""
|
|
50
|
+
expiry = time.time() + self._ttl
|
|
51
|
+
self._cache[key] = (value, expiry)
|
|
52
|
+
|
|
53
|
+
def invalidate(self, key: str) -> None:
|
|
54
|
+
"""Invalidate cached value."""
|
|
55
|
+
self._cache.pop(key, None)
|
|
56
|
+
|
|
57
|
+
def clear(self) -> None:
|
|
58
|
+
"""Clear all cached values."""
|
|
59
|
+
self._cache.clear()
|
|
60
|
+
|
|
@@ -1,36 +1,40 @@
|
|
|
1
|
-
|
|
1
|
+
"""
|
|
2
|
+
#exonware/xwlazy/src/exonware/xwlazy/config.py
|
|
3
|
+
|
|
4
|
+
Company: eXonware.com
|
|
5
|
+
Author: Eng. Muhammad AlShehri
|
|
6
|
+
Email: connect@exonware.com
|
|
7
|
+
Version: 0.1.0.19
|
|
8
|
+
Generation Date: 10-Oct-2025
|
|
2
9
|
|
|
3
|
-
|
|
10
|
+
Configuration for Lazy Loading System
|
|
4
11
|
|
|
5
|
-
|
|
6
|
-
|
|
12
|
+
This module defines configuration classes for the lazy loading system
|
|
13
|
+
following GUIDE_ARCH.md structure.
|
|
14
|
+
"""
|
|
7
15
|
|
|
8
|
-
from
|
|
9
|
-
config_package_lazy_install_enabled,
|
|
10
|
-
disable_lazy_mode,
|
|
11
|
-
enable_lazy_mode,
|
|
12
|
-
is_import_hook_installed,
|
|
13
|
-
is_lazy_install_enabled,
|
|
14
|
-
is_lazy_mode_enabled,
|
|
15
|
-
install_import_hook,
|
|
16
|
-
)
|
|
16
|
+
from __future__ import annotations
|
|
17
17
|
|
|
18
|
+
from typing import Optional, Any, Dict
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"""Bridge configuration settings with the lazy package implementation."""
|
|
20
|
+
# Import LazyConfig dataclass from defs.py
|
|
21
|
+
from .defs import LazyConfig as _LazyConfigBase
|
|
22
22
|
|
|
23
|
-
packages: Tuple[str, ...] = field(
|
|
24
|
-
default_factory=lambda: ("default",)
|
|
25
|
-
)
|
|
26
23
|
|
|
24
|
+
# Extend LazyConfig with methods (dataclass is in defs.py)
|
|
25
|
+
class LazyConfig(_LazyConfigBase):
|
|
26
|
+
"""Bridge configuration settings with the lazy package implementation."""
|
|
27
|
+
|
|
27
28
|
def __post_init__(self) -> None:
|
|
28
|
-
|
|
29
|
+
"""Normalize package names."""
|
|
30
|
+
super().__post_init__()
|
|
29
31
|
|
|
30
32
|
# High-level API -----------------------------------------------------
|
|
31
33
|
@property
|
|
32
34
|
def lazy_import(self) -> bool:
|
|
33
35
|
"""Return whether lazy mode is currently active."""
|
|
36
|
+
# Import from facade
|
|
37
|
+
from .facade import is_lazy_mode_enabled
|
|
34
38
|
return is_lazy_mode_enabled()
|
|
35
39
|
|
|
36
40
|
@lazy_import.setter
|
|
@@ -52,6 +56,15 @@ class LazyConfig:
|
|
|
52
56
|
Includes re-hooking support: If lazy is enabled and install_hook is True,
|
|
53
57
|
ensures the import hook is installed even if it wasn't installed initially.
|
|
54
58
|
"""
|
|
59
|
+
# Import from facade
|
|
60
|
+
from .facade import (
|
|
61
|
+
config_package_lazy_install_enabled,
|
|
62
|
+
disable_lazy_mode,
|
|
63
|
+
enable_lazy_mode,
|
|
64
|
+
is_import_hook_installed,
|
|
65
|
+
install_import_hook,
|
|
66
|
+
)
|
|
67
|
+
|
|
55
68
|
if enabled:
|
|
56
69
|
self._configure_packages(True, mode=mode, install_hook=install_hook)
|
|
57
70
|
enable_lazy_mode(
|
|
@@ -99,6 +112,12 @@ class LazyConfig:
|
|
|
99
112
|
Returns:
|
|
100
113
|
Dictionary with lazy mode status information
|
|
101
114
|
"""
|
|
115
|
+
# Import from facade
|
|
116
|
+
from .facade import (
|
|
117
|
+
is_import_hook_installed,
|
|
118
|
+
is_lazy_install_enabled,
|
|
119
|
+
)
|
|
120
|
+
|
|
102
121
|
try:
|
|
103
122
|
primary_package = self.packages[0] if self.packages else "default"
|
|
104
123
|
return {
|
|
@@ -123,6 +142,9 @@ class LazyConfig:
|
|
|
123
142
|
Returns:
|
|
124
143
|
True if lazy mode is enabled and hook is installed
|
|
125
144
|
"""
|
|
145
|
+
# Import from facade
|
|
146
|
+
from .facade import is_import_hook_installed
|
|
147
|
+
|
|
126
148
|
try:
|
|
127
149
|
primary_package = self.packages[0] if self.packages else "default"
|
|
128
150
|
return self.lazy_import and is_import_hook_installed(primary_package)
|
|
@@ -137,6 +159,9 @@ class LazyConfig:
|
|
|
137
159
|
mode: str = "auto",
|
|
138
160
|
install_hook: bool = True,
|
|
139
161
|
) -> None:
|
|
162
|
+
# Import from facade
|
|
163
|
+
from .facade import config_package_lazy_install_enabled
|
|
164
|
+
|
|
140
165
|
for package in self.packages:
|
|
141
166
|
config_package_lazy_install_enabled(
|
|
142
167
|
package,
|
|
@@ -151,6 +176,12 @@ class LazyConfig:
|
|
|
151
176
|
|
|
152
177
|
Re-hooking support: Install hook if not already installed.
|
|
153
178
|
"""
|
|
179
|
+
# Import from facade
|
|
180
|
+
from .facade import (
|
|
181
|
+
is_import_hook_installed,
|
|
182
|
+
install_import_hook,
|
|
183
|
+
)
|
|
184
|
+
|
|
154
185
|
try:
|
|
155
186
|
primary_package = self.packages[0] if self.packages else "default"
|
|
156
187
|
if not is_import_hook_installed(primary_package):
|
|
@@ -161,3 +192,4 @@ class LazyConfig:
|
|
|
161
192
|
|
|
162
193
|
|
|
163
194
|
DEFAULT_LAZY_CONFIG = LazyConfig()
|
|
195
|
+
|