exonware-xwlazy 0.1.0.19__py3-none-any.whl → 0.1.0.20__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 +6 -2
- exonware/xwlazy/__init__.py +0 -1
- exonware/xwlazy/common/__init__.py +1 -1
- exonware/xwlazy/common/base.py +1 -3
- exonware/xwlazy/common/cache.py +1 -3
- exonware/xwlazy/common/logger.py +1 -12
- exonware/xwlazy/common/services/dependency_mapper.py +0 -2
- exonware/xwlazy/common/services/install_async_utils.py +1 -5
- exonware/xwlazy/common/services/install_cache_utils.py +1 -13
- exonware/xwlazy/common/services/keyword_detection.py +0 -9
- exonware/xwlazy/common/services/spec_cache.py +1 -9
- exonware/xwlazy/common/services/state_manager.py +0 -2
- exonware/xwlazy/common/strategies/__init__.py +1 -1
- exonware/xwlazy/common/strategies/caching_dict.py +1 -2
- exonware/xwlazy/common/strategies/caching_installation.py +1 -2
- exonware/xwlazy/common/strategies/caching_lfu.py +1 -2
- exonware/xwlazy/common/strategies/caching_lru.py +1 -2
- exonware/xwlazy/common/strategies/caching_multitier.py +1 -2
- exonware/xwlazy/common/strategies/caching_ttl.py +1 -2
- exonware/xwlazy/config.py +1 -3
- exonware/xwlazy/contracts.py +1 -15
- exonware/xwlazy/defs.py +0 -19
- exonware/xwlazy/errors.py +1 -9
- exonware/xwlazy/facade.py +1 -59
- exonware/xwlazy/module/base.py +1 -5
- exonware/xwlazy/module/data.py +1 -1
- exonware/xwlazy/module/facade.py +0 -1
- exonware/xwlazy/module/importer_engine.py +1 -45
- exonware/xwlazy/module/strategies/__init__.py +1 -1
- exonware/xwlazy/module/strategies/module_helper_lazy.py +1 -2
- exonware/xwlazy/module/strategies/module_helper_simple.py +1 -2
- exonware/xwlazy/module/strategies/module_manager_advanced.py +1 -2
- exonware/xwlazy/module/strategies/module_manager_simple.py +1 -2
- exonware/xwlazy/package/base.py +1 -10
- exonware/xwlazy/package/conf.py +1 -8
- exonware/xwlazy/package/data.py +1 -1
- exonware/xwlazy/package/facade.py +0 -1
- exonware/xwlazy/package/services/async_install_handle.py +1 -3
- exonware/xwlazy/package/services/config_manager.py +0 -1
- exonware/xwlazy/package/services/discovery.py +1 -5
- exonware/xwlazy/package/services/host_packages.py +0 -4
- exonware/xwlazy/package/services/install_async.py +1 -2
- exonware/xwlazy/package/services/install_cache.py +1 -2
- exonware/xwlazy/package/services/install_interactive.py +1 -2
- exonware/xwlazy/package/services/install_policy.py +1 -3
- exonware/xwlazy/package/services/install_registry.py +1 -3
- exonware/xwlazy/package/services/install_result.py +1 -1
- exonware/xwlazy/package/services/install_sbom.py +1 -2
- exonware/xwlazy/package/services/install_utils.py +1 -5
- exonware/xwlazy/package/services/installer_engine.py +1 -3
- exonware/xwlazy/package/services/lazy_installer.py +1 -3
- exonware/xwlazy/package/services/manifest.py +0 -10
- exonware/xwlazy/package/services/strategy_registry.py +1 -3
- exonware/xwlazy/package/strategies/package_discovery_file.py +1 -2
- exonware/xwlazy/package/strategies/package_discovery_hybrid.py +1 -2
- exonware/xwlazy/package/strategies/package_discovery_manifest.py +1 -2
- exonware/xwlazy/package/strategies/package_execution_async.py +1 -2
- exonware/xwlazy/package/strategies/package_execution_cached.py +1 -2
- exonware/xwlazy/package/strategies/package_execution_pip.py +1 -2
- exonware/xwlazy/package/strategies/package_execution_wheel.py +1 -2
- exonware/xwlazy/package/strategies/package_mapping_discovery_first.py +1 -2
- exonware/xwlazy/package/strategies/package_mapping_hybrid.py +1 -2
- exonware/xwlazy/package/strategies/package_mapping_manifest_first.py +1 -2
- exonware/xwlazy/package/strategies/package_policy_allow_list.py +1 -2
- exonware/xwlazy/package/strategies/package_policy_deny_list.py +1 -2
- exonware/xwlazy/package/strategies/package_policy_permissive.py +1 -2
- exonware/xwlazy/package/strategies/package_timing_clean.py +1 -2
- exonware/xwlazy/package/strategies/package_timing_full.py +1 -2
- exonware/xwlazy/package/strategies/package_timing_smart.py +1 -2
- exonware/xwlazy/package/strategies/package_timing_temporary.py +1 -2
- exonware/xwlazy/runtime/adaptive_learner.py +1 -3
- exonware/xwlazy/runtime/base.py +1 -3
- exonware/xwlazy/runtime/facade.py +0 -1
- exonware/xwlazy/runtime/intelligent_selector.py +1 -4
- exonware/xwlazy/runtime/metrics.py +0 -4
- exonware/xwlazy/runtime/performance.py +0 -2
- exonware/xwlazy/version.py +2 -2
- {exonware_xwlazy-0.1.0.19.dist-info → exonware_xwlazy-0.1.0.20.dist-info}/METADATA +4 -2
- exonware_xwlazy-0.1.0.20.dist-info/RECORD +87 -0
- exonware_xwlazy-0.1.0.19.dist-info/RECORD +0 -87
- {exonware_xwlazy-0.1.0.19.dist-info → exonware_xwlazy-0.1.0.20.dist-info}/WHEEL +0 -0
- {exonware_xwlazy-0.1.0.19.dist-info → exonware_xwlazy-0.1.0.20.dist-info}/licenses/LICENSE +0 -0
|
@@ -6,7 +6,7 @@ Import Engine - Unified engine for all import-related operations.
|
|
|
6
6
|
Company: eXonware.com
|
|
7
7
|
Author: Eng. Muhammad AlShehri
|
|
8
8
|
Email: connect@exonware.com
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
Generation Date: 15-Nov-2025
|
|
11
11
|
|
|
12
12
|
This module provides unified import engine for all import-related functionality.
|
|
@@ -86,14 +86,12 @@ from ..common.cache import MultiTierCache, BytecodeCache
|
|
|
86
86
|
from ..runtime.adaptive_learner import AdaptiveLearner
|
|
87
87
|
from ..runtime.intelligent_selector import IntelligentModeSelector, LoadLevel
|
|
88
88
|
|
|
89
|
-
|
|
90
89
|
# =============================================================================
|
|
91
90
|
# LOGGER (from common.logger)
|
|
92
91
|
# =============================================================================
|
|
93
92
|
|
|
94
93
|
logger = get_logger("xwlazy.importer_engine")
|
|
95
94
|
|
|
96
|
-
|
|
97
95
|
# =============================================================================
|
|
98
96
|
# IMPORT TRACKING (from import_tracking.py)
|
|
99
97
|
# =============================================================================
|
|
@@ -105,39 +103,32 @@ _installing = threading.local()
|
|
|
105
103
|
_installation_depth = 0
|
|
106
104
|
_installation_depth_lock = threading.Lock()
|
|
107
105
|
|
|
108
|
-
|
|
109
106
|
def _get_thread_imports() -> Set[str]:
|
|
110
107
|
"""Get thread-local import set (creates if needed)."""
|
|
111
108
|
if not hasattr(_thread_local, 'imports'):
|
|
112
109
|
_thread_local.imports = set()
|
|
113
110
|
return _thread_local.imports
|
|
114
111
|
|
|
115
|
-
|
|
116
112
|
def _is_import_in_progress(module_name: str) -> bool:
|
|
117
113
|
"""Check if a module import is currently in progress for this thread."""
|
|
118
114
|
return module_name in _get_thread_imports()
|
|
119
115
|
|
|
120
|
-
|
|
121
116
|
def _mark_import_started(module_name: str) -> None:
|
|
122
117
|
"""Mark a module import as started for this thread."""
|
|
123
118
|
_get_thread_imports().add(module_name)
|
|
124
119
|
|
|
125
|
-
|
|
126
120
|
def _mark_import_finished(module_name: str) -> None:
|
|
127
121
|
"""Mark a module import as finished for this thread."""
|
|
128
122
|
_get_thread_imports().discard(module_name)
|
|
129
123
|
|
|
130
|
-
|
|
131
124
|
def get_importing_state() -> threading.local:
|
|
132
125
|
"""Get thread-local importing state."""
|
|
133
126
|
return _importing
|
|
134
127
|
|
|
135
|
-
|
|
136
128
|
def get_installing_state() -> threading.local:
|
|
137
129
|
"""Get thread-local installing state."""
|
|
138
130
|
return _installing
|
|
139
131
|
|
|
140
|
-
|
|
141
132
|
# Thread-local storage for installation state
|
|
142
133
|
_installing_state = get_installing_state()
|
|
143
134
|
_importing_state = get_importing_state()
|
|
@@ -146,7 +137,6 @@ _importing_state = get_importing_state()
|
|
|
146
137
|
_installation_depth = 0
|
|
147
138
|
_installation_depth_lock = threading.Lock()
|
|
148
139
|
|
|
149
|
-
|
|
150
140
|
# =============================================================================
|
|
151
141
|
# PREFIX TRIE (from prefix_trie.py)
|
|
152
142
|
# =============================================================================
|
|
@@ -183,7 +173,6 @@ class _PrefixTrie:
|
|
|
183
173
|
matches.append(end_value)
|
|
184
174
|
return tuple(matches)
|
|
185
175
|
|
|
186
|
-
|
|
187
176
|
# =============================================================================
|
|
188
177
|
# WATCHED REGISTRY (from watched_registry.py)
|
|
189
178
|
# =============================================================================
|
|
@@ -315,7 +304,6 @@ class WatchedPrefixRegistry:
|
|
|
315
304
|
self._root_snapshot_dirty = False
|
|
316
305
|
return root_name in self._root_snapshot
|
|
317
306
|
|
|
318
|
-
|
|
319
307
|
# Global registry instance
|
|
320
308
|
_DEFAULT_WATCHED_PREFIXES = tuple(
|
|
321
309
|
filter(
|
|
@@ -328,12 +316,10 @@ _DEFAULT_WATCHED_PREFIXES = tuple(
|
|
|
328
316
|
)
|
|
329
317
|
_watched_registry = WatchedPrefixRegistry(list(_DEFAULT_WATCHED_PREFIXES))
|
|
330
318
|
|
|
331
|
-
|
|
332
319
|
def get_watched_registry() -> WatchedPrefixRegistry:
|
|
333
320
|
"""Get the global watched prefix registry."""
|
|
334
321
|
return _watched_registry
|
|
335
322
|
|
|
336
|
-
|
|
337
323
|
# =============================================================================
|
|
338
324
|
# DEFERRED LOADER (from deferred_loader.py)
|
|
339
325
|
# =============================================================================
|
|
@@ -350,7 +336,6 @@ class _DeferredModuleLoader(importlib.abc.Loader):
|
|
|
350
336
|
def exec_module(self, module): # noqa: D401 - nothing to execute
|
|
351
337
|
return None
|
|
352
338
|
|
|
353
|
-
|
|
354
339
|
# =============================================================================
|
|
355
340
|
# CACHE (from common.cache)
|
|
356
341
|
# =============================================================================
|
|
@@ -419,7 +404,6 @@ class ParallelLoader:
|
|
|
419
404
|
self._executor.shutdown(wait=wait)
|
|
420
405
|
self._executor = None
|
|
421
406
|
|
|
422
|
-
|
|
423
407
|
class DependencyGraph:
|
|
424
408
|
"""Manages module dependencies for optimal parallel loading."""
|
|
425
409
|
|
|
@@ -470,14 +454,12 @@ class DependencyGraph:
|
|
|
470
454
|
|
|
471
455
|
return levels
|
|
472
456
|
|
|
473
|
-
|
|
474
457
|
# =============================================================================
|
|
475
458
|
# MODULE PATCHING (from module_patching.py)
|
|
476
459
|
# =============================================================================
|
|
477
460
|
|
|
478
461
|
_original_import_module = importlib.import_module
|
|
479
462
|
|
|
480
|
-
|
|
481
463
|
def _lazy_aware_import_module(name: str, package: Optional[str] = None) -> ModuleType:
|
|
482
464
|
"""Lazy-aware version of importlib.import_module."""
|
|
483
465
|
if _is_import_in_progress(name):
|
|
@@ -489,19 +471,16 @@ def _lazy_aware_import_module(name: str, package: Optional[str] = None) -> Modul
|
|
|
489
471
|
finally:
|
|
490
472
|
_mark_import_finished(name)
|
|
491
473
|
|
|
492
|
-
|
|
493
474
|
def _patch_import_module() -> None:
|
|
494
475
|
"""Patch importlib.import_module to be lazy-aware."""
|
|
495
476
|
importlib.import_module = _lazy_aware_import_module
|
|
496
477
|
logger.debug("Patched importlib.import_module to be lazy-aware")
|
|
497
478
|
|
|
498
|
-
|
|
499
479
|
def _unpatch_import_module() -> None:
|
|
500
480
|
"""Restore original importlib.import_module."""
|
|
501
481
|
importlib.import_module = _original_import_module
|
|
502
482
|
logger.debug("Restored original importlib.import_module")
|
|
503
483
|
|
|
504
|
-
|
|
505
484
|
# =============================================================================
|
|
506
485
|
# ARCHIVE IMPORTS (from archive_imports.py)
|
|
507
486
|
# =============================================================================
|
|
@@ -509,7 +488,6 @@ def _unpatch_import_module() -> None:
|
|
|
509
488
|
_archive_path = None
|
|
510
489
|
_archive_added = False
|
|
511
490
|
|
|
512
|
-
|
|
513
491
|
def get_archive_path() -> Path:
|
|
514
492
|
"""Get the path to the _archive folder."""
|
|
515
493
|
global _archive_path
|
|
@@ -518,7 +496,6 @@ def get_archive_path() -> Path:
|
|
|
518
496
|
_archive_path = current_file.parent.parent.parent.parent.parent.parent / "_archive"
|
|
519
497
|
return _archive_path
|
|
520
498
|
|
|
521
|
-
|
|
522
499
|
def ensure_archive_in_path() -> None:
|
|
523
500
|
"""Ensure the archive folder is in sys.path for imports."""
|
|
524
501
|
global _archive_added
|
|
@@ -529,13 +506,11 @@ def ensure_archive_in_path() -> None:
|
|
|
529
506
|
sys.path.insert(0, archive_str)
|
|
530
507
|
_archive_added = True
|
|
531
508
|
|
|
532
|
-
|
|
533
509
|
def import_from_archive(module_name: str):
|
|
534
510
|
"""Import a module from the archived lazy code."""
|
|
535
511
|
ensure_archive_in_path()
|
|
536
512
|
return __import__(module_name, fromlist=[''])
|
|
537
513
|
|
|
538
|
-
|
|
539
514
|
# =============================================================================
|
|
540
515
|
# BOOTSTRAP (from bootstrap.py)
|
|
541
516
|
# =============================================================================
|
|
@@ -550,7 +525,6 @@ def _env_enabled(env_value: Optional[str]) -> Optional[bool]:
|
|
|
550
525
|
return False
|
|
551
526
|
return None
|
|
552
527
|
|
|
553
|
-
|
|
554
528
|
def bootstrap_lazy_mode(package_name: str) -> None:
|
|
555
529
|
"""Detect whether lazy mode should be enabled for ``package_name`` and bootstrap hooks."""
|
|
556
530
|
package_name = package_name.lower()
|
|
@@ -573,7 +547,6 @@ def bootstrap_lazy_mode(package_name: str) -> None:
|
|
|
573
547
|
install_hook=True,
|
|
574
548
|
)
|
|
575
549
|
|
|
576
|
-
|
|
577
550
|
def bootstrap_lazy_mode_deferred(package_name: str) -> None:
|
|
578
551
|
"""Schedule lazy mode bootstrap to run AFTER the calling package finishes importing."""
|
|
579
552
|
package_name_lower = package_name.lower()
|
|
@@ -605,7 +578,6 @@ def bootstrap_lazy_mode_deferred(package_name: str) -> None:
|
|
|
605
578
|
import builtins
|
|
606
579
|
builtins.__import__ = _import_hook
|
|
607
580
|
|
|
608
|
-
|
|
609
581
|
# =============================================================================
|
|
610
582
|
# LAZY LOADER (from loader.py)
|
|
611
583
|
# =============================================================================
|
|
@@ -668,7 +640,6 @@ class LazyLoader(AModuleHelper):
|
|
|
668
640
|
module = self.load_module()
|
|
669
641
|
return dir(module)
|
|
670
642
|
|
|
671
|
-
|
|
672
643
|
# =============================================================================
|
|
673
644
|
# LAZY MODULE REGISTRY (from registry.py)
|
|
674
645
|
# =============================================================================
|
|
@@ -739,7 +710,6 @@ class LazyModuleRegistry:
|
|
|
739
710
|
loader.unload_module(loader._module_path)
|
|
740
711
|
log_event("config", logger.info, "Cleared all cached modules")
|
|
741
712
|
|
|
742
|
-
|
|
743
713
|
# =============================================================================
|
|
744
714
|
# LAZY IMPORTER (from importer.py)
|
|
745
715
|
# =============================================================================
|
|
@@ -1306,7 +1276,6 @@ class LazyImporter:
|
|
|
1306
1276
|
'total_loaded': len(self._loaded_modules)
|
|
1307
1277
|
}
|
|
1308
1278
|
|
|
1309
|
-
|
|
1310
1279
|
# =============================================================================
|
|
1311
1280
|
# IMPORT HOOK (from import_hook.py)
|
|
1312
1281
|
# =============================================================================
|
|
@@ -1347,7 +1316,6 @@ class LazyImportHook(AModuleHelper):
|
|
|
1347
1316
|
"""Check if hook is installed."""
|
|
1348
1317
|
return is_import_hook_installed(self._package_name)
|
|
1349
1318
|
|
|
1350
|
-
|
|
1351
1319
|
# =============================================================================
|
|
1352
1320
|
# META PATH FINDER (from meta_path_finder.py)
|
|
1353
1321
|
# =============================================================================
|
|
@@ -1371,7 +1339,6 @@ _lazy_prefix_method_registry: Dict[str, Tuple[str, ...]] = {}
|
|
|
1371
1339
|
_package_class_hints: Dict[str, Tuple[str, ...]] = {}
|
|
1372
1340
|
_class_hint_lock = threading.RLock()
|
|
1373
1341
|
|
|
1374
|
-
|
|
1375
1342
|
def _set_package_class_hints(package_name: str, hints: Iterable[str]) -> None:
|
|
1376
1343
|
"""Set class hints for a package."""
|
|
1377
1344
|
normalized: Tuple[str, ...] = tuple(
|
|
@@ -1383,19 +1350,16 @@ def _set_package_class_hints(package_name: str, hints: Iterable[str]) -> None:
|
|
|
1383
1350
|
else:
|
|
1384
1351
|
_package_class_hints.pop(package_name, None)
|
|
1385
1352
|
|
|
1386
|
-
|
|
1387
1353
|
def _get_package_class_hints(package_name: str) -> Tuple[str, ...]:
|
|
1388
1354
|
"""Get class hints for a package."""
|
|
1389
1355
|
with _class_hint_lock:
|
|
1390
1356
|
return _package_class_hints.get(package_name, ())
|
|
1391
1357
|
|
|
1392
|
-
|
|
1393
1358
|
def _clear_all_package_class_hints() -> None:
|
|
1394
1359
|
"""Clear all package class hints."""
|
|
1395
1360
|
with _class_hint_lock:
|
|
1396
1361
|
_package_class_hints.clear()
|
|
1397
1362
|
|
|
1398
|
-
|
|
1399
1363
|
def register_lazy_module_methods(prefix: str, methods: Tuple[str, ...]) -> None:
|
|
1400
1364
|
"""Register method names to enhance for all classes under a module prefix."""
|
|
1401
1365
|
prefix = prefix.strip()
|
|
@@ -1408,7 +1372,6 @@ def register_lazy_module_methods(prefix: str, methods: Tuple[str, ...]) -> None:
|
|
|
1408
1372
|
_lazy_prefix_method_registry[prefix] = methods
|
|
1409
1373
|
log_event("config", logger.info, f"Registered lazy module methods for prefix {prefix}: {methods}")
|
|
1410
1374
|
|
|
1411
|
-
|
|
1412
1375
|
def _spec_for_existing_module(
|
|
1413
1376
|
fullname: str,
|
|
1414
1377
|
module: ModuleType,
|
|
@@ -1426,7 +1389,6 @@ def _spec_for_existing_module(
|
|
|
1426
1389
|
module.__spec__ = spec
|
|
1427
1390
|
return spec
|
|
1428
1391
|
|
|
1429
|
-
|
|
1430
1392
|
class LazyMetaPathFinder:
|
|
1431
1393
|
"""
|
|
1432
1394
|
Custom meta path finder that intercepts failed imports.
|
|
@@ -2037,12 +1999,10 @@ class LazyMetaPathFinder:
|
|
|
2037
1999
|
|
|
2038
2000
|
return LazyClassWrapper
|
|
2039
2001
|
|
|
2040
|
-
|
|
2041
2002
|
# Registry of installed hooks per package
|
|
2042
2003
|
_installed_hooks: Dict[str, LazyMetaPathFinder] = {}
|
|
2043
2004
|
_hook_lock = threading.RLock()
|
|
2044
2005
|
|
|
2045
|
-
|
|
2046
2006
|
def install_import_hook(package_name: str = 'default') -> None:
|
|
2047
2007
|
"""Install performant import hook for automatic lazy installation."""
|
|
2048
2008
|
global _installed_hooks
|
|
@@ -2063,7 +2023,6 @@ def install_import_hook(package_name: str = 'default') -> None:
|
|
|
2063
2023
|
|
|
2064
2024
|
log_event("hook", logger.info, f"✅ [HOOK INSTALL] Lazy import hook installed for {package_name} (now {len(sys.meta_path)} meta_path entries)")
|
|
2065
2025
|
|
|
2066
|
-
|
|
2067
2026
|
def uninstall_import_hook(package_name: str = 'default') -> None:
|
|
2068
2027
|
"""Uninstall import hook for a package."""
|
|
2069
2028
|
global _installed_hooks
|
|
@@ -2078,12 +2037,10 @@ def uninstall_import_hook(package_name: str = 'default') -> None:
|
|
|
2078
2037
|
del _installed_hooks[package_name]
|
|
2079
2038
|
log_event("hook", logger.info, f"Lazy import hook uninstalled for {package_name}")
|
|
2080
2039
|
|
|
2081
|
-
|
|
2082
2040
|
def is_import_hook_installed(package_name: str = 'default') -> bool:
|
|
2083
2041
|
"""Check if import hook is installed for a package."""
|
|
2084
2042
|
return package_name in _installed_hooks
|
|
2085
2043
|
|
|
2086
|
-
|
|
2087
2044
|
def register_lazy_module_prefix(prefix: str) -> None:
|
|
2088
2045
|
"""Register an import prefix for lazy wrapping."""
|
|
2089
2046
|
_watched_registry = get_watched_registry()
|
|
@@ -2092,7 +2049,6 @@ def register_lazy_module_prefix(prefix: str) -> None:
|
|
|
2092
2049
|
if normalized:
|
|
2093
2050
|
log_event("config", logger.info, "Registered lazy module prefix: %s", normalized)
|
|
2094
2051
|
|
|
2095
|
-
|
|
2096
2052
|
# =============================================================================
|
|
2097
2053
|
# EXPORTS
|
|
2098
2054
|
# =============================================================================
|
|
@@ -4,7 +4,7 @@ Lazy Module Helper Strategy - Deferred loading.
|
|
|
4
4
|
Company: eXonware.com
|
|
5
5
|
Author: Eng. Muhammad AlShehri
|
|
6
6
|
Email: connect@exonware.com
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
Generation Date: 15-Nov-2025
|
|
9
9
|
|
|
10
10
|
Lazy loading - loads module on first access with caching.
|
|
@@ -18,7 +18,6 @@ from typing import Any, Optional, Dict
|
|
|
18
18
|
from ...module.base import AModuleHelperStrategy
|
|
19
19
|
from ..data import ModuleData
|
|
20
20
|
|
|
21
|
-
|
|
22
21
|
class LazyHelper(AModuleHelperStrategy):
|
|
23
22
|
"""
|
|
24
23
|
Lazy helper - deferred loading with caching.
|
|
@@ -4,7 +4,7 @@ Simple Module Helper Strategy - Basic synchronous loading.
|
|
|
4
4
|
Company: eXonware.com
|
|
5
5
|
Author: Eng. Muhammad AlShehri
|
|
6
6
|
Email: connect@exonware.com
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
Generation Date: 15-Nov-2025
|
|
9
9
|
|
|
10
10
|
Simple synchronous module loading - no lazy loading.
|
|
@@ -15,7 +15,6 @@ from types import ModuleType
|
|
|
15
15
|
from typing import Any
|
|
16
16
|
from ...module.base import AModuleHelperStrategy
|
|
17
17
|
|
|
18
|
-
|
|
19
18
|
class SimpleHelper(AModuleHelperStrategy):
|
|
20
19
|
"""
|
|
21
20
|
Simple helper - standard synchronous import.
|
|
@@ -4,7 +4,7 @@ Advanced Module Manager Strategy - Full features.
|
|
|
4
4
|
Company: eXonware.com
|
|
5
5
|
Author: Eng. Muhammad AlShehri
|
|
6
6
|
Email: connect@exonware.com
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
Generation Date: 15-Nov-2025
|
|
9
9
|
|
|
10
10
|
Advanced manager - with hooks, error handling, and full features.
|
|
@@ -18,7 +18,6 @@ from ...contracts import ICachingStrategy, IModuleHelperStrategy
|
|
|
18
18
|
from ...package.base import APackageHelper
|
|
19
19
|
from ...module import importer_engine
|
|
20
20
|
|
|
21
|
-
|
|
22
21
|
class AdvancedManager(AModuleManagerStrategy):
|
|
23
22
|
"""
|
|
24
23
|
Advanced manager - full features with hooks and error handling.
|
|
@@ -4,7 +4,7 @@ Simple Module Manager Strategy - Basic operations.
|
|
|
4
4
|
Company: eXonware.com
|
|
5
5
|
Author: Eng. Muhammad AlShehri
|
|
6
6
|
Email: connect@exonware.com
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
Generation Date: 15-Nov-2025
|
|
9
9
|
|
|
10
10
|
Simple manager - basic module loading/unloading only.
|
|
@@ -15,7 +15,6 @@ from typing import Optional
|
|
|
15
15
|
from ...module.base import AModuleManagerStrategy
|
|
16
16
|
from ...contracts import ICachingStrategy, IModuleHelperStrategy
|
|
17
17
|
|
|
18
|
-
|
|
19
18
|
class SimpleManager(AModuleManagerStrategy):
|
|
20
19
|
"""
|
|
21
20
|
Simple manager - basic module operations only.
|
exonware/xwlazy/package/base.py
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
Company: eXonware.com
|
|
5
5
|
Author: Eng. Muhammad AlShehri
|
|
6
6
|
Email: connect@exonware.com
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
Generation Date: 10-Oct-2025
|
|
9
9
|
|
|
10
10
|
Abstract Base Class for Package Operations
|
|
@@ -33,7 +33,6 @@ from ..contracts import (
|
|
|
33
33
|
IMappingStrategy,
|
|
34
34
|
)
|
|
35
35
|
|
|
36
|
-
|
|
37
36
|
# =============================================================================
|
|
38
37
|
# ABSTRACT PACKAGE (Unified - Merges APackageDiscovery + APackageInstaller + APackageCache + APackageHelper)
|
|
39
38
|
# =============================================================================
|
|
@@ -604,7 +603,6 @@ class APackageHelper(IPackageHelper, ABC):
|
|
|
604
603
|
"""Get watched prefixes from manifest (from IManifestLoader)."""
|
|
605
604
|
raise NotImplementedError("Subclasses must implement get_watched_prefixes")
|
|
606
605
|
|
|
607
|
-
|
|
608
606
|
# =============================================================================
|
|
609
607
|
# DEPRECATED CLASSES (for backward compatibility)
|
|
610
608
|
# =============================================================================
|
|
@@ -641,7 +639,6 @@ class APackageHelperStrategy(IPackageHelperStrategy, ABC):
|
|
|
641
639
|
"""Get installed version."""
|
|
642
640
|
...
|
|
643
641
|
|
|
644
|
-
|
|
645
642
|
# =============================================================================
|
|
646
643
|
# ABSTRACT PACKAGE MANAGER STRATEGY
|
|
647
644
|
# =============================================================================
|
|
@@ -674,7 +671,6 @@ class APackageManagerStrategy(IPackageManagerStrategy, ABC):
|
|
|
674
671
|
"""Check security policy."""
|
|
675
672
|
...
|
|
676
673
|
|
|
677
|
-
|
|
678
674
|
# =============================================================================
|
|
679
675
|
# ABSTRACT INSTALLATION EXECUTION STRATEGY
|
|
680
676
|
# =============================================================================
|
|
@@ -696,7 +692,6 @@ class AInstallExecutionStrategy(IInstallExecutionStrategy, ABC):
|
|
|
696
692
|
"""Execute uninstallation of a package."""
|
|
697
693
|
...
|
|
698
694
|
|
|
699
|
-
|
|
700
695
|
# =============================================================================
|
|
701
696
|
# ABSTRACT INSTALLATION TIMING STRATEGY
|
|
702
697
|
# =============================================================================
|
|
@@ -723,7 +718,6 @@ class AInstallTimingStrategy(IInstallTimingStrategy, ABC):
|
|
|
723
718
|
"""Get priority order for installing packages."""
|
|
724
719
|
...
|
|
725
720
|
|
|
726
|
-
|
|
727
721
|
# =============================================================================
|
|
728
722
|
# ABSTRACT DISCOVERY STRATEGY
|
|
729
723
|
# =============================================================================
|
|
@@ -745,7 +739,6 @@ class ADiscoveryStrategy(IDiscoveryStrategy, ABC):
|
|
|
745
739
|
"""Get the source of a discovered dependency."""
|
|
746
740
|
...
|
|
747
741
|
|
|
748
|
-
|
|
749
742
|
# =============================================================================
|
|
750
743
|
# ABSTRACT POLICY STRATEGY
|
|
751
744
|
# =============================================================================
|
|
@@ -767,7 +760,6 @@ class APolicyStrategy(IPolicyStrategy, ABC):
|
|
|
767
760
|
"""Get pip arguments based on policy."""
|
|
768
761
|
...
|
|
769
762
|
|
|
770
|
-
|
|
771
763
|
# =============================================================================
|
|
772
764
|
# ABSTRACT MAPPING STRATEGY
|
|
773
765
|
# =============================================================================
|
|
@@ -789,7 +781,6 @@ class AMappingStrategy(IMappingStrategy, ABC):
|
|
|
789
781
|
"""Map package name to possible import names."""
|
|
790
782
|
...
|
|
791
783
|
|
|
792
|
-
|
|
793
784
|
# =============================================================================
|
|
794
785
|
# EXPORT ALL
|
|
795
786
|
# =============================================================================
|
exonware/xwlazy/package/conf.py
CHANGED
|
@@ -11,7 +11,7 @@ longer need to ship their own lazy bootstrap logic. Consumers import
|
|
|
11
11
|
Company: eXonware.com
|
|
12
12
|
Author: Eng. Muhammad AlShehri
|
|
13
13
|
Email: connect@exonware.com
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
Generation Date: 10-Oct-2025
|
|
16
16
|
"""
|
|
17
17
|
|
|
@@ -39,7 +39,6 @@ from .services.config_manager import LazyInstallConfig
|
|
|
39
39
|
|
|
40
40
|
__all__ = ['get_conf_module', '_PackageConfig', '_FilteredStderr', '_LazyConfModule', '_setup_global_warning_filter']
|
|
41
41
|
|
|
42
|
-
|
|
43
42
|
class _PackageConfig:
|
|
44
43
|
"""Per-package configuration wrapper."""
|
|
45
44
|
|
|
@@ -78,7 +77,6 @@ class _PackageConfig:
|
|
|
78
77
|
"""Return True if lazy install + hook are active."""
|
|
79
78
|
return self.lazy_install_status()["active"]
|
|
80
79
|
|
|
81
|
-
|
|
82
80
|
class _FilteredStderr:
|
|
83
81
|
"""Stderr wrapper that filters out specific warning messages."""
|
|
84
82
|
|
|
@@ -109,7 +107,6 @@ class _FilteredStderr:
|
|
|
109
107
|
"""Delegate all other attributes to original stderr."""
|
|
110
108
|
return getattr(self._original, name)
|
|
111
109
|
|
|
112
|
-
|
|
113
110
|
class _LazyConfModule(types.ModuleType):
|
|
114
111
|
"""Configuration module for all exonware packages."""
|
|
115
112
|
|
|
@@ -286,12 +283,10 @@ class _LazyConfModule(types.ModuleType):
|
|
|
286
283
|
return
|
|
287
284
|
super().__setattr__(name, value)
|
|
288
285
|
|
|
289
|
-
|
|
290
286
|
_CONF_INSTANCE: Optional[_LazyConfModule] = None
|
|
291
287
|
_ORIGINAL_STDERR: Optional[Any] = None
|
|
292
288
|
_FILTERED_STDERR: Optional[_FilteredStderr] = None
|
|
293
289
|
|
|
294
|
-
|
|
295
290
|
def _setup_global_warning_filter() -> None:
|
|
296
291
|
"""Set up global stderr filter for decimal module warnings (called at module import)."""
|
|
297
292
|
global _ORIGINAL_STDERR, _FILTERED_STDERR
|
|
@@ -317,12 +312,10 @@ def _setup_global_warning_filter() -> None:
|
|
|
317
312
|
if sys.stderr is not _FILTERED_STDERR:
|
|
318
313
|
sys.stderr = _FILTERED_STDERR # type: ignore[assignment]
|
|
319
314
|
|
|
320
|
-
|
|
321
315
|
# Set up warning filter immediately when module is imported (default: suppress warnings)
|
|
322
316
|
# Note: conf.py may have already set up a filter, which is fine
|
|
323
317
|
_setup_global_warning_filter()
|
|
324
318
|
|
|
325
|
-
|
|
326
319
|
def get_conf_module(name: str = "exonware.conf", doc: Optional[str] = None) -> types.ModuleType:
|
|
327
320
|
"""Return (and memoize) the shared conf module instance."""
|
|
328
321
|
global _CONF_INSTANCE
|
exonware/xwlazy/package/data.py
CHANGED
|
@@ -4,7 +4,7 @@ Async Install Handle
|
|
|
4
4
|
Company: eXonware.com
|
|
5
5
|
Author: Eng. Muhammad AlShehri
|
|
6
6
|
Email: connect@exonware.com
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
Generation Date: 15-Nov-2025
|
|
9
9
|
|
|
10
10
|
Lightweight handle for background installation jobs.
|
|
@@ -13,7 +13,6 @@ Lightweight handle for background installation jobs.
|
|
|
13
13
|
import asyncio
|
|
14
14
|
from typing import Optional, Any
|
|
15
15
|
|
|
16
|
-
|
|
17
16
|
class AsyncInstallHandle:
|
|
18
17
|
"""Lightweight handle for background installation jobs."""
|
|
19
18
|
|
|
@@ -84,6 +83,5 @@ class AsyncInstallHandle:
|
|
|
84
83
|
return self._task_or_future.done()
|
|
85
84
|
return False
|
|
86
85
|
|
|
87
|
-
|
|
88
86
|
__all__ = ['AsyncInstallHandle']
|
|
89
87
|
|
|
@@ -6,7 +6,7 @@ Package discovery implementation.
|
|
|
6
6
|
Company: eXonware.com
|
|
7
7
|
Author: Eng. Muhammad AlShehri
|
|
8
8
|
Email: connect@exonware.com
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
Generation Date: 10-Oct-2025
|
|
11
11
|
|
|
12
12
|
This module provides LazyDiscovery class that discovers dependencies from
|
|
@@ -27,7 +27,6 @@ from ...common.logger import get_logger, log_event as _log
|
|
|
27
27
|
|
|
28
28
|
logger = get_logger("xwlazy.discovery")
|
|
29
29
|
|
|
30
|
-
|
|
31
30
|
class LazyDiscovery(APackageHelper):
|
|
32
31
|
"""
|
|
33
32
|
Discovers dependencies from project configuration sources.
|
|
@@ -355,12 +354,10 @@ class LazyDiscovery(APackageHelper):
|
|
|
355
354
|
with open(file_path, 'w', encoding='utf-8') as f:
|
|
356
355
|
json.dump(data, f, indent=2, ensure_ascii=False)
|
|
357
356
|
|
|
358
|
-
|
|
359
357
|
# Global discovery instance
|
|
360
358
|
_discovery: Optional[LazyDiscovery] = None
|
|
361
359
|
_discovery_lock = threading.RLock()
|
|
362
360
|
|
|
363
|
-
|
|
364
361
|
def get_lazy_discovery(project_root: Optional[str] = None) -> LazyDiscovery:
|
|
365
362
|
"""Get or create global discovery instance."""
|
|
366
363
|
global _discovery
|
|
@@ -369,6 +366,5 @@ def get_lazy_discovery(project_root: Optional[str] = None) -> LazyDiscovery:
|
|
|
369
366
|
_discovery = LazyDiscovery(project_root)
|
|
370
367
|
return _discovery
|
|
371
368
|
|
|
372
|
-
|
|
373
369
|
__all__ = ['LazyDiscovery', 'get_lazy_discovery']
|
|
374
370
|
|
|
@@ -46,7 +46,6 @@ class LazyMetaPathFinder:
|
|
|
46
46
|
_TRUTHY = {"1", "true", "yes", "on"}
|
|
47
47
|
_REGISTERED: dict[str, dict[str, Tuple[str, ...]]] = {}
|
|
48
48
|
|
|
49
|
-
|
|
50
49
|
def _normalized(items: Iterable[str]) -> Tuple[str, ...]:
|
|
51
50
|
seen = []
|
|
52
51
|
for item in items:
|
|
@@ -54,7 +53,6 @@ def _normalized(items: Iterable[str]) -> Tuple[str, ...]:
|
|
|
54
53
|
seen.append(item)
|
|
55
54
|
return tuple(seen)
|
|
56
55
|
|
|
57
|
-
|
|
58
56
|
def register_host_package(
|
|
59
57
|
package_name: str,
|
|
60
58
|
module_prefixes: Iterable[str] = (),
|
|
@@ -114,7 +112,6 @@ def register_host_package(
|
|
|
114
112
|
# Best-effort: package import must continue even if hook installation fails
|
|
115
113
|
pass
|
|
116
114
|
|
|
117
|
-
|
|
118
115
|
def refresh_host_package(package_name: str) -> None:
|
|
119
116
|
"""Re-apply wrappers for a registered package."""
|
|
120
117
|
data = _REGISTERED.get(package_name.lower())
|
|
@@ -126,7 +123,6 @@ def refresh_host_package(package_name: str) -> None:
|
|
|
126
123
|
data["method_prefixes"],
|
|
127
124
|
)
|
|
128
125
|
|
|
129
|
-
|
|
130
126
|
def _apply_wrappers_for_loaded_modules(
|
|
131
127
|
package_name: str,
|
|
132
128
|
module_prefixes: Iterable[str],
|
|
@@ -4,7 +4,7 @@ Async Installation Mixin
|
|
|
4
4
|
Company: eXonware.com
|
|
5
5
|
Author: Eng. Muhammad AlShehri
|
|
6
6
|
Email: connect@exonware.com
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
Generation Date: 15-Nov-2025
|
|
9
9
|
|
|
10
10
|
Mixin for async installation operations.
|
|
@@ -48,7 +48,6 @@ def _ensure_logging_initialized():
|
|
|
48
48
|
if _log is None:
|
|
49
49
|
_log = _get_log_event()
|
|
50
50
|
|
|
51
|
-
|
|
52
51
|
class AsyncInstallMixin:
|
|
53
52
|
"""Mixin for async installation operations."""
|
|
54
53
|
|
|
@@ -4,7 +4,7 @@ Installation Cache Mixin
|
|
|
4
4
|
Company: eXonware.com
|
|
5
5
|
Author: Eng. Muhammad AlShehri
|
|
6
6
|
Email: connect@exonware.com
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
Generation Date: 15-Nov-2025
|
|
9
9
|
|
|
10
10
|
Mixin for cache management (wheels, install trees, known missing modules).
|
|
@@ -49,7 +49,6 @@ def _ensure_spec_cache_initialized():
|
|
|
49
49
|
if _spec_cache_clear is None:
|
|
50
50
|
_spec_cache_clear = _get_spec_cache_clear()
|
|
51
51
|
|
|
52
|
-
|
|
53
52
|
class InstallCacheMixin:
|
|
54
53
|
"""Mixin for cache management (wheels, install trees, known missing modules)."""
|
|
55
54
|
|