exonware-xwlazy 0.1.0.1__py3-none-any.whl → 0.1.0.8__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.
Files changed (95) hide show
  1. exonware/xwlazy/__init__.py +0 -0
  2. exonware/xwlazy/version.py +2 -2
  3. exonware_xwlazy-0.1.0.8.dist-info/METADATA +0 -0
  4. exonware_xwlazy-0.1.0.8.dist-info/RECORD +6 -0
  5. exonware/__init__.py +0 -42
  6. exonware/xwlazy/common/__init__.py +0 -55
  7. exonware/xwlazy/common/base.py +0 -65
  8. exonware/xwlazy/common/cache.py +0 -504
  9. exonware/xwlazy/common/logger.py +0 -257
  10. exonware/xwlazy/common/services/__init__.py +0 -72
  11. exonware/xwlazy/common/services/dependency_mapper.py +0 -250
  12. exonware/xwlazy/common/services/install_async_utils.py +0 -170
  13. exonware/xwlazy/common/services/install_cache_utils.py +0 -245
  14. exonware/xwlazy/common/services/keyword_detection.py +0 -283
  15. exonware/xwlazy/common/services/spec_cache.py +0 -165
  16. exonware/xwlazy/common/services/state_manager.py +0 -84
  17. exonware/xwlazy/common/strategies/__init__.py +0 -28
  18. exonware/xwlazy/common/strategies/caching_dict.py +0 -44
  19. exonware/xwlazy/common/strategies/caching_installation.py +0 -88
  20. exonware/xwlazy/common/strategies/caching_lfu.py +0 -66
  21. exonware/xwlazy/common/strategies/caching_lru.py +0 -63
  22. exonware/xwlazy/common/strategies/caching_multitier.py +0 -59
  23. exonware/xwlazy/common/strategies/caching_ttl.py +0 -59
  24. exonware/xwlazy/common/utils.py +0 -142
  25. exonware/xwlazy/config.py +0 -193
  26. exonware/xwlazy/contracts.py +0 -1533
  27. exonware/xwlazy/defs.py +0 -378
  28. exonware/xwlazy/errors.py +0 -276
  29. exonware/xwlazy/facade.py +0 -1137
  30. exonware/xwlazy/host/__init__.py +0 -8
  31. exonware/xwlazy/host/conf.py +0 -16
  32. exonware/xwlazy/module/__init__.py +0 -18
  33. exonware/xwlazy/module/base.py +0 -643
  34. exonware/xwlazy/module/data.py +0 -17
  35. exonware/xwlazy/module/facade.py +0 -246
  36. exonware/xwlazy/module/importer_engine.py +0 -2964
  37. exonware/xwlazy/module/partial_module_detector.py +0 -275
  38. exonware/xwlazy/module/strategies/__init__.py +0 -22
  39. exonware/xwlazy/module/strategies/module_helper_lazy.py +0 -93
  40. exonware/xwlazy/module/strategies/module_helper_simple.py +0 -65
  41. exonware/xwlazy/module/strategies/module_manager_advanced.py +0 -111
  42. exonware/xwlazy/module/strategies/module_manager_simple.py +0 -95
  43. exonware/xwlazy/package/__init__.py +0 -18
  44. exonware/xwlazy/package/base.py +0 -877
  45. exonware/xwlazy/package/conf.py +0 -324
  46. exonware/xwlazy/package/data.py +0 -17
  47. exonware/xwlazy/package/facade.py +0 -480
  48. exonware/xwlazy/package/services/__init__.py +0 -84
  49. exonware/xwlazy/package/services/async_install_handle.py +0 -87
  50. exonware/xwlazy/package/services/config_manager.py +0 -249
  51. exonware/xwlazy/package/services/discovery.py +0 -435
  52. exonware/xwlazy/package/services/host_packages.py +0 -180
  53. exonware/xwlazy/package/services/install_async.py +0 -291
  54. exonware/xwlazy/package/services/install_cache.py +0 -145
  55. exonware/xwlazy/package/services/install_interactive.py +0 -59
  56. exonware/xwlazy/package/services/install_policy.py +0 -156
  57. exonware/xwlazy/package/services/install_registry.py +0 -54
  58. exonware/xwlazy/package/services/install_result.py +0 -17
  59. exonware/xwlazy/package/services/install_sbom.py +0 -153
  60. exonware/xwlazy/package/services/install_utils.py +0 -79
  61. exonware/xwlazy/package/services/installer_engine.py +0 -406
  62. exonware/xwlazy/package/services/lazy_installer.py +0 -803
  63. exonware/xwlazy/package/services/manifest.py +0 -503
  64. exonware/xwlazy/package/services/strategy_registry.py +0 -324
  65. exonware/xwlazy/package/strategies/__init__.py +0 -57
  66. exonware/xwlazy/package/strategies/package_discovery_file.py +0 -129
  67. exonware/xwlazy/package/strategies/package_discovery_hybrid.py +0 -84
  68. exonware/xwlazy/package/strategies/package_discovery_manifest.py +0 -101
  69. exonware/xwlazy/package/strategies/package_execution_async.py +0 -113
  70. exonware/xwlazy/package/strategies/package_execution_cached.py +0 -90
  71. exonware/xwlazy/package/strategies/package_execution_pip.py +0 -99
  72. exonware/xwlazy/package/strategies/package_execution_wheel.py +0 -106
  73. exonware/xwlazy/package/strategies/package_mapping_discovery_first.py +0 -100
  74. exonware/xwlazy/package/strategies/package_mapping_hybrid.py +0 -105
  75. exonware/xwlazy/package/strategies/package_mapping_manifest_first.py +0 -100
  76. exonware/xwlazy/package/strategies/package_policy_allow_list.py +0 -57
  77. exonware/xwlazy/package/strategies/package_policy_deny_list.py +0 -57
  78. exonware/xwlazy/package/strategies/package_policy_permissive.py +0 -46
  79. exonware/xwlazy/package/strategies/package_timing_clean.py +0 -67
  80. exonware/xwlazy/package/strategies/package_timing_full.py +0 -66
  81. exonware/xwlazy/package/strategies/package_timing_smart.py +0 -68
  82. exonware/xwlazy/package/strategies/package_timing_temporary.py +0 -66
  83. exonware/xwlazy/runtime/__init__.py +0 -18
  84. exonware/xwlazy/runtime/adaptive_learner.py +0 -129
  85. exonware/xwlazy/runtime/base.py +0 -274
  86. exonware/xwlazy/runtime/facade.py +0 -94
  87. exonware/xwlazy/runtime/intelligent_selector.py +0 -170
  88. exonware/xwlazy/runtime/metrics.py +0 -60
  89. exonware/xwlazy/runtime/performance.py +0 -37
  90. exonware_xwlazy-0.1.0.1.dist-info/METADATA +0 -454
  91. exonware_xwlazy-0.1.0.1.dist-info/RECORD +0 -93
  92. xwlazy/__init__.py +0 -14
  93. xwlazy/lazy.py +0 -30
  94. {exonware_xwlazy-0.1.0.1.dist-info → exonware_xwlazy-0.1.0.8.dist-info}/WHEEL +0 -0
  95. {exonware_xwlazy-0.1.0.1.dist-info → exonware_xwlazy-0.1.0.8.dist-info}/licenses/LICENSE +0 -0
@@ -1,165 +0,0 @@
1
- """
2
- #exonware/xwlazy/src/exonware/xwlazy/discovery/spec_cache.py
3
-
4
- Spec cache utilities for module specification caching.
5
-
6
- Company: eXonware.com
7
- Author: Eng. Muhammad AlShehri
8
- Email: connect@exonware.com
9
-
10
- Generation Date: 10-Oct-2025
11
-
12
- This module provides multi-level caching (L1: memory, L2: disk) for module specs
13
- to optimize import performance.
14
- """
15
-
16
- import os
17
- import sys
18
- import time
19
- import threading
20
- import importlib
21
- import importlib.machinery
22
- import importlib.util
23
- from pathlib import Path
24
- from typing import Optional
25
- from collections import OrderedDict
26
- from functools import lru_cache
27
-
28
- # Environment variables
29
- _SPEC_CACHE_MAX = int(os.environ.get("XWLAZY_SPEC_CACHE_MAX", "512") or 512)
30
- _SPEC_CACHE_TTL = float(os.environ.get("XWLAZY_SPEC_CACHE_TTL", "60") or 60.0)
31
-
32
- # Cache storage
33
- _spec_cache_lock = threading.RLock()
34
- _spec_cache: OrderedDict[str, tuple[importlib.machinery.ModuleSpec, float]] = OrderedDict()
35
-
36
- # Multi-level cache: L1 (in-memory) + L2 (disk)
37
- _CACHE_L2_DIR = Path(
38
- os.environ.get(
39
- "XWLAZY_CACHE_DIR",
40
- os.path.join(os.path.expanduser("~"), ".xwlazy", "cache"),
41
- )
42
- )
43
- _CACHE_L2_DIR.mkdir(parents=True, exist_ok=True)
44
-
45
- # Stdlib module set
46
- try:
47
- _STDLIB_MODULE_SET: set[str] = set(sys.stdlib_module_names) # type: ignore[attr-defined]
48
- except AttributeError:
49
- _STDLIB_MODULE_SET = set()
50
- _STDLIB_MODULE_SET.update(sys.builtin_module_names)
51
-
52
- @lru_cache(maxsize=1024)
53
- def _cached_stdlib_check(module_name: str) -> bool:
54
- """Check if module is part of stdlib or built-in modules."""
55
- try:
56
- spec = importlib.util.find_spec(module_name)
57
- if spec is None:
58
- return False
59
- if spec.origin in ("built-in", None):
60
- return True
61
- origin = spec.origin or ""
62
- return (
63
- "python" in origin.lower()
64
- and "site-packages" not in origin.lower()
65
- and "dist-packages" not in origin.lower()
66
- )
67
- except Exception:
68
- return False
69
-
70
- def _spec_cache_prune_locked(now: Optional[float] = None) -> None:
71
- """Prune expired entries from spec cache (must be called with lock held)."""
72
- if not _spec_cache:
73
- return
74
- current = now or time.monotonic()
75
- while _spec_cache:
76
- fullname, (_, ts) = next(iter(_spec_cache.items()))
77
- if current - ts <= _SPEC_CACHE_TTL and len(_spec_cache) <= _SPEC_CACHE_MAX:
78
- break
79
- _spec_cache.popitem(last=False)
80
-
81
- def _spec_cache_get(fullname: str) -> Optional[importlib.machinery.ModuleSpec]:
82
- """Get spec from multi-level cache (L1: memory, L2: disk)."""
83
- with _spec_cache_lock:
84
- _spec_cache_prune_locked()
85
- entry = _spec_cache.get(fullname)
86
- if entry is not None:
87
- spec, _ = entry
88
- _spec_cache.move_to_end(fullname)
89
- return spec
90
-
91
- # L2 cache: Check disk cache
92
- try:
93
- cache_file = _CACHE_L2_DIR / f"{fullname.replace('.', '_')}.spec"
94
- if cache_file.exists():
95
- mtime = cache_file.stat().st_mtime
96
- age = time.time() - mtime
97
- if age < _SPEC_CACHE_TTL:
98
- try:
99
- import pickle
100
- with open(cache_file, 'rb') as f:
101
- spec = pickle.load(f)
102
- # Promote to L1 cache
103
- _spec_cache[fullname] = (spec, time.monotonic())
104
- _spec_cache.move_to_end(fullname)
105
- return spec
106
- except Exception:
107
- pass
108
- except Exception:
109
- pass
110
-
111
- return None
112
-
113
- def _spec_cache_put(fullname: str, spec: Optional[importlib.machinery.ModuleSpec]) -> None:
114
- """Put spec in multi-level cache (L1: memory, L2: disk)."""
115
- if spec is None:
116
- return
117
- with _spec_cache_lock:
118
- # L1 cache: In-memory
119
- _spec_cache[fullname] = (spec, time.monotonic())
120
- _spec_cache.move_to_end(fullname)
121
- _spec_cache_prune_locked()
122
-
123
- # L2 cache: Disk (async, non-blocking)
124
- try:
125
- cache_file = _CACHE_L2_DIR / f"{fullname.replace('.', '_')}.spec"
126
- import pickle
127
- # Use protocol 5 for better performance
128
- with open(cache_file, 'wb') as f:
129
- pickle.dump(spec, f, protocol=5)
130
- except Exception:
131
- pass # Fail silently for disk cache
132
-
133
- def _spec_cache_clear(fullname: Optional[str] = None) -> None:
134
- """Clear spec cache entries."""
135
- with _spec_cache_lock:
136
- if fullname is None:
137
- _spec_cache.clear()
138
- else:
139
- _spec_cache.pop(fullname, None)
140
-
141
- def _cache_spec_if_missing(fullname: str) -> None:
142
- """Ensure a ModuleSpec is cached for a known-good module."""
143
- if _spec_cache_get(fullname):
144
- return
145
- try:
146
- spec = importlib.util.find_spec(fullname)
147
- except Exception:
148
- spec = None
149
- if spec is not None:
150
- _spec_cache_put(fullname, spec)
151
-
152
- def get_stdlib_module_set() -> set[str]:
153
- """Get the set of stdlib module names."""
154
- return _STDLIB_MODULE_SET.copy()
155
-
156
- __all__ = [
157
- '_cached_stdlib_check',
158
- '_spec_cache_get',
159
- '_spec_cache_put',
160
- '_spec_cache_clear',
161
- '_spec_cache_prune_locked',
162
- '_cache_spec_if_missing',
163
- 'get_stdlib_module_set',
164
- ]
165
-
@@ -1,84 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import json
4
- import os
5
- from pathlib import Path
6
- from typing import Optional
7
-
8
- def _get_base_config_dir() -> Path:
9
- """Determine a cross-platform directory for storing lazy configuration."""
10
- if os.name == "nt":
11
- appdata = os.getenv("APPDATA")
12
- if appdata:
13
- return Path(appdata) / "exonware" / "lazy"
14
- return Path.home() / "AppData" / "Roaming" / "exonware" / "lazy"
15
-
16
- # POSIX-style
17
- xdg_config = os.getenv("XDG_CONFIG_HOME")
18
- if xdg_config:
19
- return Path(xdg_config) / "exonware" / "lazy"
20
- return Path.home() / ".config" / "exonware" / "lazy"
21
-
22
- class LazyStateManager:
23
- """Persist and retrieve lazy installation state."""
24
-
25
- def __init__(self, package_name: str) -> None:
26
- self._package = package_name.lower()
27
- self._state_path = _get_base_config_dir() / "state.json"
28
- self._state: dict[str, dict[str, bool]] = self._load_state()
29
-
30
- # --------------------------------------------------------------------- #
31
- # Persistence helpers
32
- # --------------------------------------------------------------------- #
33
- def _load_state(self) -> dict[str, dict[str, bool]]:
34
- if not self._state_path.exists():
35
- return {}
36
- try:
37
- with self._state_path.open("r", encoding="utf-8") as fh:
38
- data = json.load(fh)
39
- if isinstance(data, dict):
40
- return data
41
- except Exception:
42
- pass
43
- return {}
44
-
45
- def _save_state(self) -> None:
46
- self._state_path.parent.mkdir(parents=True, exist_ok=True)
47
- with self._state_path.open("w", encoding="utf-8") as fh:
48
- json.dump(self._state, fh, indent=2, sort_keys=True)
49
-
50
- def _ensure_entry(self) -> dict[str, bool]:
51
- return self._state.setdefault(self._package, {})
52
-
53
- # --------------------------------------------------------------------- #
54
- # Manual state management
55
- # --------------------------------------------------------------------- #
56
- def get_manual_state(self) -> Optional[bool]:
57
- entry = self._state.get(self._package, {})
58
- value = entry.get("manual")
59
- return bool(value) if isinstance(value, bool) else None
60
-
61
- def set_manual_state(self, value: Optional[bool]) -> None:
62
- entry = self._ensure_entry()
63
- if value is None:
64
- entry.pop("manual", None)
65
- else:
66
- entry["manual"] = bool(value)
67
- self._save_state()
68
-
69
- # --------------------------------------------------------------------- #
70
- # Auto detection cache
71
- # --------------------------------------------------------------------- #
72
- def get_cached_auto_state(self) -> Optional[bool]:
73
- entry = self._state.get(self._package, {})
74
- value = entry.get("auto")
75
- return bool(value) if isinstance(value, bool) else None
76
-
77
- def set_auto_state(self, value: Optional[bool]) -> None:
78
- entry = self._ensure_entry()
79
- if value is None:
80
- entry.pop("auto", None)
81
- else:
82
- entry["auto"] = bool(value)
83
- self._save_state()
84
-
@@ -1,28 +0,0 @@
1
- """
2
- Common Caching Strategies - Shared by modules and packages.
3
-
4
- Company: eXonware.com
5
- Author: Eng. Muhammad AlShehri
6
- Email: connect@exonware.com
7
-
8
- Generation Date: 15-Nov-2025
9
-
10
- Generic caching strategies that work with ANY data type.
11
- """
12
-
13
- from .caching_dict import DictCache
14
- from .caching_lru import LRUCache
15
- from .caching_lfu import LFUCache
16
- from .caching_ttl import TTLCache
17
- from .caching_multitier import MultiTierCacheStrategy
18
- from .caching_installation import InstallationCacheWrapper
19
-
20
- __all__ = [
21
- 'DictCache',
22
- 'LRUCache',
23
- 'LFUCache',
24
- 'TTLCache',
25
- 'MultiTierCacheStrategy',
26
- 'InstallationCacheWrapper',
27
- ]
28
-
@@ -1,44 +0,0 @@
1
- """
2
- Dict Cache Strategy - Simple dictionary-based caching.
3
-
4
- Company: eXonware.com
5
- Author: Eng. Muhammad AlShehri
6
- Email: connect@exonware.com
7
-
8
- Generation Date: 15-Nov-2025
9
-
10
- Simple dict-based cache implementation.
11
- Works with ANY data type (modules, packages, etc.).
12
- """
13
-
14
- from typing import Optional, Any
15
- from ...common.base import ACachingStrategy
16
-
17
- class DictCache(ACachingStrategy):
18
- """
19
- Simple dictionary-based cache.
20
-
21
- No eviction policy - grows unbounded.
22
- Use for small applications or when memory is not a concern.
23
- """
24
-
25
- def __init__(self):
26
- """Initialize dict cache."""
27
- self._cache: dict[str, Any] = {}
28
-
29
- def get(self, key: str) -> Optional[Any]:
30
- """Get value from cache."""
31
- return self._cache.get(key)
32
-
33
- def set(self, key: str, value: Any) -> None:
34
- """Set value in cache."""
35
- self._cache[key] = value
36
-
37
- def invalidate(self, key: str) -> None:
38
- """Invalidate cached value."""
39
- self._cache.pop(key, None)
40
-
41
- def clear(self) -> None:
42
- """Clear all cached values."""
43
- self._cache.clear()
44
-
@@ -1,88 +0,0 @@
1
- """
2
- Installation Cache Strategy - Wrapper for existing InstallationCache.
3
-
4
- Company: eXonware.com
5
- Author: Eng. Muhammad AlShehri
6
- Email: connect@exonware.com
7
-
8
- Generation Date: 15-Nov-2025
9
-
10
- Wraps existing InstallationCache to implement ICachingStrategy interface.
11
- """
12
-
13
- from typing import Optional, Any
14
- from pathlib import Path
15
- from ..cache import InstallationCache
16
- from ..base import ACachingStrategy
17
- from ...package.data import PackageData
18
-
19
- class InstallationCacheWrapper(ACachingStrategy):
20
- """
21
- Installation cache strategy wrapper.
22
-
23
- Wraps existing InstallationCache to implement ICachingStrategy interface.
24
- Used for package installation status caching.
25
- """
26
-
27
- def __init__(self, cache_file: Optional[Path] = None):
28
- """
29
- Initialize installation cache wrapper.
30
-
31
- Args:
32
- cache_file: Optional path to cache file
33
- """
34
- self._cache = InstallationCache(cache_file)
35
-
36
- def get(self, key: str) -> Optional[Any]:
37
- """
38
- Get package from cache.
39
-
40
- Args:
41
- key: Package name
42
-
43
- Returns:
44
- PackageData if found, None otherwise
45
- """
46
- if self._cache.is_installed(key):
47
- version = self._cache.get_version(key)
48
- return PackageData(
49
- name=key,
50
- installed=True,
51
- version=version
52
- )
53
- return None
54
-
55
- def set(self, key: str, value: Any) -> None:
56
- """
57
- Cache a package.
58
-
59
- Args:
60
- key: Package name
61
- value: PackageData or dict with installed/version info
62
- """
63
- if isinstance(value, PackageData):
64
- if value.installed:
65
- self._cache.mark_installed(key, value.version)
66
- else:
67
- self._cache.mark_uninstalled(key)
68
- elif isinstance(value, dict):
69
- if value.get('installed', False):
70
- self._cache.mark_installed(key, value.get('version'))
71
- else:
72
- self._cache.mark_uninstalled(key)
73
-
74
- def invalidate(self, key: str) -> None:
75
- """
76
- Invalidate cached package.
77
-
78
- Args:
79
- key: Package name
80
- """
81
- self._cache.mark_uninstalled(key)
82
-
83
- def clear(self) -> None:
84
- """Clear all cached packages."""
85
- # InstallationCache doesn't have clear, so we'd need to extend it
86
- # For now, just mark all as uninstalled (would need cache iteration)
87
- pass
88
-
@@ -1,66 +0,0 @@
1
- """
2
- LFU Cache Strategy - Least Frequently Used eviction.
3
-
4
- Company: eXonware.com
5
- Author: Eng. Muhammad AlShehri
6
- Email: connect@exonware.com
7
-
8
- Generation Date: 15-Nov-2025
9
-
10
- LFU 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 Counter
16
- from ...common.base import ACachingStrategy
17
-
18
- class LFUCache(ACachingStrategy):
19
- """
20
- LFU (Least Frequently Used) cache with size limit.
21
-
22
- Evicts least frequently accessed items when cache is full.
23
- Good for access pattern-based caching.
24
- """
25
-
26
- def __init__(self, max_size: int = 1000):
27
- """
28
- Initialize LFU cache.
29
-
30
- Args:
31
- max_size: Maximum number of items in cache
32
- """
33
- self._cache: dict[str, Any] = {}
34
- self._freq: Counter[str] = Counter()
35
- self._max_size = max_size
36
-
37
- def get(self, key: str) -> Optional[Any]:
38
- """Get value from cache (increments frequency)."""
39
- if key in self._cache:
40
- self._freq[key] += 1
41
- return self._cache[key]
42
- return None
43
-
44
- def set(self, key: str, value: Any) -> None:
45
- """Set value in cache (evicts least frequent if full)."""
46
- if key not in self._cache and len(self._cache) >= self._max_size:
47
- # Evict least frequent
48
- if self._freq:
49
- least_frequent = min(self._freq.items(), key=lambda x: x[1])[0]
50
- self._cache.pop(least_frequent, None)
51
- self._freq.pop(least_frequent, None)
52
-
53
- self._cache[key] = value
54
- if key not in self._freq:
55
- self._freq[key] = 0
56
-
57
- def invalidate(self, key: str) -> None:
58
- """Invalidate cached value."""
59
- self._cache.pop(key, None)
60
- self._freq.pop(key, None)
61
-
62
- def clear(self) -> None:
63
- """Clear all cached values."""
64
- self._cache.clear()
65
- self._freq.clear()
66
-
@@ -1,63 +0,0 @@
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
-
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
- class LRUCache(ACachingStrategy):
19
- """
20
- LRU (Least Recently Used) cache with size limit.
21
-
22
- Evicts least recently used items when cache is full.
23
- Good for general-purpose caching.
24
- """
25
-
26
- def __init__(self, max_size: int = 1000):
27
- """
28
- Initialize LRU cache.
29
-
30
- Args:
31
- max_size: Maximum number of items in cache
32
- """
33
- self._cache: OrderedDict[str, Any] = OrderedDict()
34
- self._max_size = max_size
35
-
36
- def get(self, key: str) -> Optional[Any]:
37
- """Get value from cache (moves to end for LRU)."""
38
- if key in self._cache:
39
- # Move to end (most recently used)
40
- self._cache.move_to_end(key)
41
- return self._cache[key]
42
- return None
43
-
44
- def set(self, key: str, value: Any) -> None:
45
- """Set value in cache (evicts oldest if full)."""
46
- if key in self._cache:
47
- # Update existing - move to end
48
- self._cache.move_to_end(key)
49
- else:
50
- # New entry - check size limit
51
- if len(self._cache) >= self._max_size:
52
- # Remove oldest (first item)
53
- self._cache.popitem(last=False)
54
- self._cache[key] = value
55
-
56
- def invalidate(self, key: str) -> None:
57
- """Invalidate cached value."""
58
- self._cache.pop(key, None)
59
-
60
- def clear(self) -> None:
61
- """Clear all cached values."""
62
- self._cache.clear()
63
-
@@ -1,59 +0,0 @@
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
-
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
- class MultiTierCacheStrategy(ACachingStrategy):
20
- """
21
- Multi-tier cache strategy (L1 memory + L2 disk + L3 predictive).
22
-
23
- Wraps existing MultiTierCache to implement ICachingStrategy interface.
24
- High-performance caching with multiple tiers.
25
- """
26
-
27
- def __init__(self, l1_size: int = 1000, l2_dir: Optional[Path] = None, enable_l3: bool = True):
28
- """
29
- Initialize multi-tier cache.
30
-
31
- Args:
32
- l1_size: Maximum size of L1 (memory) cache
33
- l2_dir: Directory for L2 (disk) cache
34
- enable_l3: Enable L3 (predictive) cache
35
- """
36
- self._cache = MultiTierCache(l1_size=l1_size, l2_dir=l2_dir, enable_l3=enable_l3)
37
-
38
- def get(self, key: str) -> Optional[Any]:
39
- """Get value from cache (L1 -> L2 -> L3)."""
40
- return self._cache.get(key)
41
-
42
- def set(self, key: str, value: Any) -> None:
43
- """Set value in cache (L1 + L2 batched)."""
44
- self._cache.set(key, value)
45
-
46
- def invalidate(self, key: str) -> None:
47
- """Invalidate cached value."""
48
- # MultiTierCache doesn't have invalidate, so we set to None
49
- # Or we could extend MultiTierCache to add invalidate
50
- self._cache.set(key, None)
51
-
52
- def clear(self) -> None:
53
- """Clear all cached values."""
54
- self._cache.clear()
55
-
56
- def shutdown(self) -> None:
57
- """Shutdown cache (flush L2, cleanup threads)."""
58
- self._cache.shutdown()
59
-
@@ -1,59 +0,0 @@
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
-
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 Optional, Any
16
- from ...common.base import ACachingStrategy
17
-
18
- class TTLCache(ACachingStrategy):
19
- """
20
- TTL (Time-To-Live) cache with expiration.
21
-
22
- Automatically expires entries after TTL seconds.
23
- Good for time-sensitive data.
24
- """
25
-
26
- def __init__(self, ttl_seconds: float = 3600.0):
27
- """
28
- Initialize TTL cache.
29
-
30
- Args:
31
- ttl_seconds: Time-to-live in seconds (default: 1 hour)
32
- """
33
- self._cache: dict[str, tuple[Any, float]] = {} # (value, expiry_time)
34
- self._ttl = ttl_seconds
35
-
36
- def get(self, key: str) -> Optional[Any]:
37
- """Get value from cache (returns None if expired)."""
38
- if key in self._cache:
39
- value, expiry = self._cache[key]
40
- if time.time() < expiry:
41
- return value
42
- else:
43
- # Expired - remove
44
- del self._cache[key]
45
- return None
46
-
47
- def set(self, key: str, value: Any) -> None:
48
- """Set value in cache with TTL."""
49
- expiry = time.time() + self._ttl
50
- self._cache[key] = (value, expiry)
51
-
52
- def invalidate(self, key: str) -> None:
53
- """Invalidate cached value."""
54
- self._cache.pop(key, None)
55
-
56
- def clear(self) -> None:
57
- """Clear all cached values."""
58
- self._cache.clear()
59
-