exonware-xwlazy 0.1.0.22__tar.gz → 1.0.1.2__tar.gz
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_xwlazy-0.1.0.22 → exonware_xwlazy-1.0.1.2}/.gitignore +4 -0
- {exonware_xwlazy-0.1.0.22 → exonware_xwlazy-1.0.1.2}/PKG-INFO +6 -6
- {exonware_xwlazy-0.1.0.22 → exonware_xwlazy-1.0.1.2}/README.md +4 -0
- {exonware_xwlazy-0.1.0.22 → exonware_xwlazy-1.0.1.2}/pyproject.toml +4 -5
- exonware_xwlazy-1.0.1.2/src/_old/exonware/__init__.py +42 -0
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/__init__.py +14 -3
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/common/__init__.py +8 -1
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/common/base.py +11 -3
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/common/cache.py +24 -24
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/common/logger.py +5 -6
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/common/services/__init__.py +0 -1
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/common/services/dependency_mapper.py +31 -14
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/common/services/install_async_utils.py +9 -3
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/common/services/install_cache_utils.py +4 -5
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/common/services/keyword_detection.py +0 -1
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/common/services/spec_cache.py +2 -3
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/common/services/state_manager.py +12 -12
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/common/strategies/__init__.py +0 -1
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/common/strategies/caching_dict.py +2 -3
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/common/strategies/caching_installation.py +0 -1
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/common/strategies/caching_lfu.py +2 -3
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/common/strategies/caching_lru.py +0 -1
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/common/strategies/caching_multitier.py +0 -1
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/common/strategies/caching_ttl.py +2 -3
- exonware_xwlazy-1.0.1.2/src/_old/exonware/xwlazy/common/utils.py +141 -0
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/config.py +1 -2
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/contracts.py +162 -26
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/defs.py +19 -18
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/errors.py +0 -1
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/facade.py +175 -29
- exonware_xwlazy-1.0.1.2/src/_old/exonware/xwlazy/host/__init__.py +7 -0
- exonware_xwlazy-1.0.1.2/src/_old/exonware/xwlazy/host/conf.py +15 -0
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/module/base.py +103 -26
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/module/data.py +0 -1
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/module/facade.py +4 -5
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/module/importer_engine.py +1017 -171
- exonware_xwlazy-1.0.1.2/src/_old/exonware/xwlazy/module/partial_module_detector.py +274 -0
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/module/strategies/__init__.py +0 -1
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/module/strategies/module_helper_lazy.py +3 -4
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/module/strategies/module_helper_simple.py +0 -1
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/module/strategies/module_manager_advanced.py +0 -1
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/module/strategies/module_manager_simple.py +0 -1
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/base.py +131 -53
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/conf.py +6 -6
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/data.py +0 -1
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/facade.py +0 -1
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/services/__init__.py +0 -1
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/services/async_install_handle.py +0 -1
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/services/config_manager.py +20 -17
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/services/discovery.py +89 -51
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/services/host_packages.py +41 -6
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/services/install_async.py +16 -3
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/services/install_cache.py +4 -5
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/services/install_interactive.py +0 -1
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/services/install_policy.py +14 -15
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/services/install_registry.py +6 -5
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/services/install_result.py +0 -1
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/services/install_sbom.py +6 -10
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/services/install_utils.py +0 -1
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/services/installer_engine.py +3 -4
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/services/lazy_installer.py +181 -19
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/services/manifest.py +55 -53
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/services/strategy_registry.py +152 -13
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/strategies/package_discovery_file.py +2 -3
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/strategies/package_discovery_hybrid.py +2 -3
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/strategies/package_discovery_manifest.py +2 -3
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/strategies/package_execution_async.py +3 -4
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/strategies/package_execution_cached.py +2 -3
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/strategies/package_execution_pip.py +2 -3
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/strategies/package_execution_wheel.py +2 -3
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/strategies/package_mapping_discovery_first.py +2 -3
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/strategies/package_mapping_hybrid.py +2 -3
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/strategies/package_mapping_manifest_first.py +2 -3
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/strategies/package_policy_allow_list.py +4 -5
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/strategies/package_policy_deny_list.py +4 -5
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/strategies/package_policy_permissive.py +3 -4
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/strategies/package_timing_clean.py +2 -3
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/strategies/package_timing_full.py +2 -3
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/strategies/package_timing_smart.py +2 -3
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/strategies/package_timing_temporary.py +2 -3
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/runtime/adaptive_learner.py +7 -8
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/runtime/base.py +14 -15
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/runtime/facade.py +7 -8
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/runtime/intelligent_selector.py +6 -7
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/runtime/metrics.py +6 -7
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/runtime/performance.py +5 -6
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/version.py +2 -2
- exonware_xwlazy-1.0.1.2/src/_old/xwlazy/__init__.py +13 -0
- exonware_xwlazy-1.0.1.2/src/_old/xwlazy/lazy.py +29 -0
- exonware_xwlazy-1.0.1.2/src/exonware/__init__.py +93 -0
- exonware_xwlazy-1.0.1.2/src/exonware/xwlazy/version.py +77 -0
- exonware_xwlazy-1.0.1.2/src/exonware/xwlazy.py +2546 -0
- exonware_xwlazy-1.0.1.2/src/exonware/xwlazy_external_libs.toml +716 -0
- {exonware_xwlazy-0.1.0.22 → exonware_xwlazy-1.0.1.2}/src/xwlazy.py +3 -16
- {exonware_xwlazy-0.1.0.22 → exonware_xwlazy-1.0.1.2}/src/xwlazy_wrapper.py +0 -1
- exonware_xwlazy-0.1.0.22/src/exonware/__init__.py +0 -23
- {exonware_xwlazy-0.1.0.22 → exonware_xwlazy-1.0.1.2}/LICENSE +0 -0
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/module/__init__.py +0 -0
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/__init__.py +0 -0
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/package/strategies/__init__.py +0 -0
- {exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/runtime/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: exonware-xwlazy
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 1.0.1.2
|
|
4
4
|
Summary: Marker package that enables lazy install features across the eXonware suite.
|
|
5
5
|
Project-URL: Homepage, https://exonware.com
|
|
6
6
|
Project-URL: Repository, https://github.com/exonware/xwlazy
|
|
@@ -15,13 +15,9 @@ Classifier: Intended Audience :: Developers
|
|
|
15
15
|
Classifier: License :: OSI Approved :: MIT License
|
|
16
16
|
Classifier: Operating System :: OS Independent
|
|
17
17
|
Classifier: Programming Language :: Python :: 3
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
22
18
|
Classifier: Programming Language :: Python :: 3.12
|
|
23
19
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
-
Requires-Python: >=3.
|
|
20
|
+
Requires-Python: >=3.12
|
|
25
21
|
Requires-Dist: tomli>=2.0.1; python_version < '3.11'
|
|
26
22
|
Description-Content-Type: text/markdown
|
|
27
23
|
|
|
@@ -178,6 +174,10 @@ After `pip install -e .`, xwlazy automatically enables lazy loading for your pac
|
|
|
178
174
|
## 📖 Documentation
|
|
179
175
|
|
|
180
176
|
- **[Architecture Reference](docs/REF_ARCH.md)** - System design, patterns, and structure
|
|
177
|
+
- **[Integration Guide](docs/INTEGRATION_GUIDE.md)** - Integration with xw libraries
|
|
178
|
+
- **[Best Practices](docs/BEST_PRACTICES.md)** - Usage guidelines and recommendations
|
|
179
|
+
- **[Troubleshooting Guide](docs/TROUBLESHOOTING.md)** - Common issues and solutions
|
|
180
|
+
- **[Production Deployment](docs/PRODUCTION_DEPLOYMENT.md)** - Production deployment guide
|
|
181
181
|
- **[Keyword Detection Guide](docs/KEYWORD_DETECTION.md)** - Zero-code integration
|
|
182
182
|
- **[Competition Benchmarks](benchmarks/competition_tests/)** - Performance comparisons
|
|
183
183
|
- **[Performance Analysis](benchmarks/competition_tests/PERFORMANCE_ANALYSIS.md)** - Optimization recommendations
|
|
@@ -151,6 +151,10 @@ After `pip install -e .`, xwlazy automatically enables lazy loading for your pac
|
|
|
151
151
|
## 📖 Documentation
|
|
152
152
|
|
|
153
153
|
- **[Architecture Reference](docs/REF_ARCH.md)** - System design, patterns, and structure
|
|
154
|
+
- **[Integration Guide](docs/INTEGRATION_GUIDE.md)** - Integration with xw libraries
|
|
155
|
+
- **[Best Practices](docs/BEST_PRACTICES.md)** - Usage guidelines and recommendations
|
|
156
|
+
- **[Troubleshooting Guide](docs/TROUBLESHOOTING.md)** - Common issues and solutions
|
|
157
|
+
- **[Production Deployment](docs/PRODUCTION_DEPLOYMENT.md)** - Production deployment guide
|
|
154
158
|
- **[Keyword Detection Guide](docs/KEYWORD_DETECTION.md)** - Zero-code integration
|
|
155
159
|
- **[Competition Benchmarks](benchmarks/competition_tests/)** - Performance comparisons
|
|
156
160
|
- **[Performance Analysis](benchmarks/competition_tests/PERFORMANCE_ANALYSIS.md)** - Optimization recommendations
|
|
@@ -7,7 +7,7 @@ name = "exonware-xwlazy"
|
|
|
7
7
|
dynamic = ["version"]
|
|
8
8
|
description = "Marker package that enables lazy install features across the eXonware suite."
|
|
9
9
|
readme = "README.md"
|
|
10
|
-
requires-python = ">=3.
|
|
10
|
+
requires-python = ">=3.12"
|
|
11
11
|
keywords = ["lazy", "exonware", "xwlazy"]
|
|
12
12
|
classifiers = [
|
|
13
13
|
"Development Status :: 4 - Beta",
|
|
@@ -15,10 +15,6 @@ classifiers = [
|
|
|
15
15
|
"License :: OSI Approved :: MIT License",
|
|
16
16
|
"Operating System :: OS Independent",
|
|
17
17
|
"Programming Language :: Python :: 3",
|
|
18
|
-
"Programming Language :: Python :: 3.8",
|
|
19
|
-
"Programming Language :: Python :: 3.9",
|
|
20
|
-
"Programming Language :: Python :: 3.10",
|
|
21
|
-
"Programming Language :: Python :: 3.11",
|
|
22
18
|
"Programming Language :: Python :: 3.12",
|
|
23
19
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
24
20
|
]
|
|
@@ -42,6 +38,9 @@ Subtree = "https://github.com/Exonware/XWLazy.git"
|
|
|
42
38
|
[tool.hatch.version]
|
|
43
39
|
path = "src/exonware/xwlazy/version.py"
|
|
44
40
|
|
|
41
|
+
# Fallback: use static version if version.py doesn't exist
|
|
42
|
+
# __version__ = "1.0.1"
|
|
43
|
+
|
|
45
44
|
[tool.hatch.build.targets.wheel]
|
|
46
45
|
packages = ["src/exonware", "src/xwlazy"]
|
|
47
46
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""
|
|
2
|
+
exonware package - Enterprise-grade Python framework ecosystem
|
|
3
|
+
|
|
4
|
+
Company: eXonware.com
|
|
5
|
+
Author: Eng. Muhammad AlShehri
|
|
6
|
+
Email: connect@exonware.com
|
|
7
|
+
Generation Date: 2025-01-03
|
|
8
|
+
|
|
9
|
+
This is a namespace package allowing multiple exonware subpackages
|
|
10
|
+
to coexist (xwsystem, xwnode, xwdata, xwlazy, etc.)
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
# Make this a namespace package FIRST
|
|
14
|
+
# This allows both exonware.xwsystem and exonware.xwlazy to coexist
|
|
15
|
+
__path__ = __import__('pkgutil').extend_path(__path__, __name__)
|
|
16
|
+
|
|
17
|
+
# Import version from xwlazy - required, no fallback
|
|
18
|
+
from exonware.xwlazy.version import __version__
|
|
19
|
+
|
|
20
|
+
__author__ = 'Eng. Muhammad AlShehri'
|
|
21
|
+
__email__ = 'connect@exonware.com'
|
|
22
|
+
__company__ = 'eXonware.com'
|
|
23
|
+
|
|
24
|
+
# NOW enable lazy mode (after namespace package is set up)
|
|
25
|
+
import sys
|
|
26
|
+
import importlib
|
|
27
|
+
try:
|
|
28
|
+
# Use importlib to import after namespace is ready
|
|
29
|
+
if 'exonware.xwlazy' not in sys.modules:
|
|
30
|
+
xwlazy_module = importlib.import_module('exonware.xwlazy')
|
|
31
|
+
auto_enable_lazy = getattr(xwlazy_module, 'auto_enable_lazy', None)
|
|
32
|
+
if auto_enable_lazy:
|
|
33
|
+
auto_enable_lazy("xwsystem", mode="smart")
|
|
34
|
+
print("✅ Lazy mode enabled for xwsystem")
|
|
35
|
+
else:
|
|
36
|
+
# Module already loaded, use it directly
|
|
37
|
+
from exonware.xwlazy import auto_enable_lazy
|
|
38
|
+
auto_enable_lazy("xwsystem", mode="smart")
|
|
39
|
+
print("✅ Lazy mode enabled for xwsystem")
|
|
40
|
+
except (ImportError, AttributeError):
|
|
41
|
+
print("❌ Lazy mode not enabled for xwsystem (xwlazy not installed)")
|
|
42
|
+
pass # xwlazy not installed - silently continue
|
{exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/__init__.py
RENAMED
|
@@ -63,6 +63,10 @@ from .facade import (
|
|
|
63
63
|
configure_lazy_mode,
|
|
64
64
|
preload_modules,
|
|
65
65
|
optimize_lazy_mode,
|
|
66
|
+
# One-line activation API
|
|
67
|
+
auto_enable_lazy,
|
|
68
|
+
# Lazy-loader compatible API
|
|
69
|
+
attach,
|
|
66
70
|
# Public API functions
|
|
67
71
|
enable_lazy_install,
|
|
68
72
|
disable_lazy_install,
|
|
@@ -167,6 +171,10 @@ def __getattr__(name: str) -> Any:
|
|
|
167
171
|
elif name == "XWRuntimeHelper":
|
|
168
172
|
from .runtime import XWRuntimeHelper
|
|
169
173
|
return XWRuntimeHelper
|
|
174
|
+
elif name == "manifest":
|
|
175
|
+
# Import manifest module for lazy access
|
|
176
|
+
from .package.services import manifest
|
|
177
|
+
return manifest
|
|
170
178
|
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
171
179
|
|
|
172
180
|
# Import core classes for advanced usage
|
|
@@ -210,7 +218,7 @@ from .module.importer_engine import (
|
|
|
210
218
|
_mark_import_started,
|
|
211
219
|
_mark_import_finished,
|
|
212
220
|
_lazy_aware_import_module,
|
|
213
|
-
_patch_import_module,
|
|
221
|
+
# _patch_import_module removed - deprecated, use sys.meta_path hooks instead
|
|
214
222
|
_unpatch_import_module,
|
|
215
223
|
)
|
|
216
224
|
|
|
@@ -245,6 +253,10 @@ __all__ = [
|
|
|
245
253
|
"configure_lazy_mode",
|
|
246
254
|
"preload_modules",
|
|
247
255
|
"optimize_lazy_mode",
|
|
256
|
+
# One-line activation API
|
|
257
|
+
"auto_enable_lazy",
|
|
258
|
+
# Lazy-loader compatible API
|
|
259
|
+
"attach",
|
|
248
260
|
# Public API functions
|
|
249
261
|
"enable_lazy_install",
|
|
250
262
|
"disable_lazy_install",
|
|
@@ -361,7 +373,6 @@ __all__ = [
|
|
|
361
373
|
"_mark_import_started",
|
|
362
374
|
"_mark_import_finished",
|
|
363
375
|
"_lazy_aware_import_module",
|
|
364
|
-
"_patch_import_module",
|
|
376
|
+
# "_patch_import_module", # Removed - deprecated, use sys.meta_path hooks instead
|
|
365
377
|
"_unpatch_import_module",
|
|
366
378
|
]
|
|
367
|
-
|
{exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/common/__init__.py
RENAMED
|
@@ -28,6 +28,11 @@ from .cache import (
|
|
|
28
28
|
InstallationCache,
|
|
29
29
|
)
|
|
30
30
|
|
|
31
|
+
from .utils import (
|
|
32
|
+
find_project_root,
|
|
33
|
+
find_config_file,
|
|
34
|
+
)
|
|
35
|
+
|
|
31
36
|
__all__ = [
|
|
32
37
|
# Logger
|
|
33
38
|
'get_logger',
|
|
@@ -43,5 +48,7 @@ __all__ = [
|
|
|
43
48
|
'MultiTierCache',
|
|
44
49
|
'BytecodeCache',
|
|
45
50
|
'InstallationCache',
|
|
51
|
+
# Utils
|
|
52
|
+
'find_project_root',
|
|
53
|
+
'find_config_file',
|
|
46
54
|
]
|
|
47
|
-
|
{exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/common/base.py
RENAMED
|
@@ -12,13 +12,21 @@ Abstract base classes for shared/common strategies.
|
|
|
12
12
|
|
|
13
13
|
from abc import ABC, abstractmethod
|
|
14
14
|
from typing import Optional, Any
|
|
15
|
-
from ..contracts import ICachingStrategy
|
|
15
|
+
from ..contracts import ICachingStrategy, ICacheStrategy
|
|
16
16
|
|
|
17
17
|
# =============================================================================
|
|
18
18
|
# ABSTRACT CACHING STRATEGY
|
|
19
19
|
# =============================================================================
|
|
20
20
|
|
|
21
21
|
class ACachingStrategy(ICachingStrategy, ABC):
|
|
22
|
+
"""
|
|
23
|
+
Abstract base class for caching strategies (legacy name).
|
|
24
|
+
|
|
25
|
+
Note: Use ACacheStrategy for new code (ICacheStrategy interface).
|
|
26
|
+
"""
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
class ACacheStrategy(ICacheStrategy, ABC):
|
|
22
30
|
"""
|
|
23
31
|
Abstract base class for caching strategies.
|
|
24
32
|
|
|
@@ -51,6 +59,6 @@ class ACachingStrategy(ICachingStrategy, ABC):
|
|
|
51
59
|
# =============================================================================
|
|
52
60
|
|
|
53
61
|
__all__ = [
|
|
54
|
-
'ACachingStrategy',
|
|
62
|
+
'ACachingStrategy', # Legacy name
|
|
63
|
+
'ACacheStrategy', # New name for ICacheStrategy interface
|
|
55
64
|
]
|
|
56
|
-
|
{exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/common/cache.py
RENAMED
|
@@ -15,7 +15,6 @@ All cache code is centralized here to avoid duplication.
|
|
|
15
15
|
|
|
16
16
|
import os
|
|
17
17
|
import sys
|
|
18
|
-
import json
|
|
19
18
|
import time
|
|
20
19
|
import pickle
|
|
21
20
|
import struct
|
|
@@ -23,10 +22,11 @@ import importlib
|
|
|
23
22
|
import importlib.util
|
|
24
23
|
import threading
|
|
25
24
|
from pathlib import Path
|
|
26
|
-
from typing import
|
|
25
|
+
from typing import Optional, Any
|
|
27
26
|
from collections import OrderedDict
|
|
28
27
|
from queue import Queue
|
|
29
28
|
|
|
29
|
+
from exonware.xwsystem.io.serialization.auto_serializer import AutoSerializer
|
|
30
30
|
from .logger import get_logger
|
|
31
31
|
|
|
32
32
|
logger = get_logger("xwlazy.cache")
|
|
@@ -59,7 +59,7 @@ class MultiTierCache:
|
|
|
59
59
|
self._l2_dir = l2_dir or Path.home() / ".xwlazy_cache"
|
|
60
60
|
self._l2_dir.mkdir(parents=True, exist_ok=True)
|
|
61
61
|
self._enable_l3 = enable_l3
|
|
62
|
-
self._l3_patterns:
|
|
62
|
+
self._l3_patterns: dict[str, tuple[int, float]] = {}
|
|
63
63
|
self._lock = threading.RLock()
|
|
64
64
|
|
|
65
65
|
self._l2_write_queue: Queue = Queue()
|
|
@@ -192,7 +192,7 @@ class MultiTierCache:
|
|
|
192
192
|
for old_key, _ in sorted_patterns[:1000]:
|
|
193
193
|
del self._l3_patterns[old_key]
|
|
194
194
|
|
|
195
|
-
def get_predictive_keys(self, limit: int = 10) ->
|
|
195
|
+
def get_predictive_keys(self, limit: int = 10) -> list[str]:
|
|
196
196
|
"""
|
|
197
197
|
Get keys likely to be accessed soon (for preloading).
|
|
198
198
|
|
|
@@ -370,7 +370,7 @@ class InstallationCache:
|
|
|
370
370
|
|
|
371
371
|
self._cache_file = cache_file
|
|
372
372
|
self._lock = threading.RLock()
|
|
373
|
-
self._cache:
|
|
373
|
+
self._cache: dict[str, dict[str, Any]] = {}
|
|
374
374
|
self._dirty = False
|
|
375
375
|
|
|
376
376
|
# Load cache on init
|
|
@@ -384,15 +384,15 @@ class InstallationCache:
|
|
|
384
384
|
|
|
385
385
|
try:
|
|
386
386
|
with self._lock:
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
except
|
|
387
|
+
auto_serializer = AutoSerializer()
|
|
388
|
+
data = auto_serializer.auto_load_file(self._cache_file, format_hint='json')
|
|
389
|
+
# Validate format
|
|
390
|
+
if isinstance(data, dict):
|
|
391
|
+
self._cache = {k: v for k, v in data.items()
|
|
392
|
+
if isinstance(v, dict) and 'installed' in v}
|
|
393
|
+
else:
|
|
394
|
+
self._cache = {}
|
|
395
|
+
except Exception as e:
|
|
396
396
|
logger.debug(f"Failed to load installation cache: {e}")
|
|
397
397
|
self._cache = {}
|
|
398
398
|
|
|
@@ -406,15 +406,16 @@ class InstallationCache:
|
|
|
406
406
|
# Create parent directory if needed
|
|
407
407
|
self._cache_file.parent.mkdir(parents=True, exist_ok=True)
|
|
408
408
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
409
|
+
auto_serializer = AutoSerializer()
|
|
410
|
+
auto_serializer.auto_save_file(
|
|
411
|
+
self._cache,
|
|
412
|
+
self._cache_file,
|
|
413
|
+
format_hint='json',
|
|
414
|
+
indent=2,
|
|
415
|
+
sort_keys=True
|
|
416
|
+
)
|
|
416
417
|
self._dirty = False
|
|
417
|
-
except
|
|
418
|
+
except Exception as e:
|
|
418
419
|
logger.warning(f"Failed to save installation cache: {e}")
|
|
419
420
|
|
|
420
421
|
def is_installed(self, package_name: str) -> bool:
|
|
@@ -487,7 +488,7 @@ class InstallationCache:
|
|
|
487
488
|
self._dirty = True
|
|
488
489
|
self._save_cache()
|
|
489
490
|
|
|
490
|
-
def get_all_installed(self) ->
|
|
491
|
+
def get_all_installed(self) -> set[str]:
|
|
491
492
|
"""
|
|
492
493
|
Get set of all packages marked as installed.
|
|
493
494
|
|
|
@@ -501,4 +502,3 @@ class InstallationCache:
|
|
|
501
502
|
def __len__(self) -> int:
|
|
502
503
|
"""Return number of cached packages."""
|
|
503
504
|
return len(self._cache)
|
|
504
|
-
|
{exonware_xwlazy-0.1.0.22/src → exonware_xwlazy-1.0.1.2/src/_old}/exonware/xwlazy/common/logger.py
RENAMED
|
@@ -17,7 +17,7 @@ import os
|
|
|
17
17
|
import sys
|
|
18
18
|
import logging
|
|
19
19
|
import io
|
|
20
|
-
from typing import
|
|
20
|
+
from typing import Optional
|
|
21
21
|
from datetime import datetime
|
|
22
22
|
|
|
23
23
|
# =============================================================================
|
|
@@ -37,7 +37,7 @@ _EMOJI_MAP = {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
# Default log category states
|
|
40
|
-
_CATEGORY_DEFAULTS:
|
|
40
|
+
_CATEGORY_DEFAULTS: dict[str, bool] = {
|
|
41
41
|
"install": True,
|
|
42
42
|
"hook": False,
|
|
43
43
|
"enhance": False,
|
|
@@ -52,7 +52,7 @@ _CATEGORY_DEFAULTS: Dict[str, bool] = {
|
|
|
52
52
|
# =============================================================================
|
|
53
53
|
|
|
54
54
|
_configured = False
|
|
55
|
-
_category_overrides:
|
|
55
|
+
_category_overrides: dict[str, bool] = {}
|
|
56
56
|
|
|
57
57
|
# =============================================================================
|
|
58
58
|
# HELPER FUNCTIONS
|
|
@@ -186,7 +186,7 @@ def set_log_category(category: str, enabled: bool) -> None:
|
|
|
186
186
|
"""
|
|
187
187
|
_category_overrides[_normalize_category(category)] = bool(enabled)
|
|
188
188
|
|
|
189
|
-
def set_log_categories(overrides:
|
|
189
|
+
def set_log_categories(overrides: dict[str, bool]) -> None:
|
|
190
190
|
"""
|
|
191
191
|
Bulk update multiple log categories.
|
|
192
192
|
|
|
@@ -196,7 +196,7 @@ def set_log_categories(overrides: Dict[str, bool]) -> None:
|
|
|
196
196
|
for category, enabled in overrides.items():
|
|
197
197
|
set_log_category(category, enabled)
|
|
198
198
|
|
|
199
|
-
def get_log_categories() ->
|
|
199
|
+
def get_log_categories() -> dict[str, bool]:
|
|
200
200
|
"""
|
|
201
201
|
Return the effective state for each built-in log category.
|
|
202
202
|
|
|
@@ -254,4 +254,3 @@ def print_formatted(flag: str, message: str, same_line: bool = False) -> None:
|
|
|
254
254
|
sys.stdout.flush()
|
|
255
255
|
else:
|
|
256
256
|
print(formatted)
|
|
257
|
-
|
|
@@ -5,7 +5,7 @@ This module contains DependencyMapper class extracted from lazy_core.py Section
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import threading
|
|
8
|
-
from typing import
|
|
8
|
+
from typing import Optional
|
|
9
9
|
|
|
10
10
|
# Lazy import to avoid circular dependency
|
|
11
11
|
def _get_logger():
|
|
@@ -59,14 +59,14 @@ class DependencyMapper:
|
|
|
59
59
|
def __init__(self, package_name: str = 'default'):
|
|
60
60
|
"""Initialize dependency mapper."""
|
|
61
61
|
self._discovery = None # Lazy init to avoid circular imports
|
|
62
|
-
self._package_import_mapping:
|
|
63
|
-
self._import_package_mapping:
|
|
62
|
+
self._package_import_mapping: dict[str, list[str]] = {}
|
|
63
|
+
self._import_package_mapping: dict[str, str] = {}
|
|
64
64
|
self._cached = False
|
|
65
65
|
self._lock = threading.RLock()
|
|
66
66
|
self._package_name = package_name
|
|
67
67
|
self._manifest_generation = -1
|
|
68
|
-
self._manifest_dependencies:
|
|
69
|
-
self._manifest_signature: Optional[
|
|
68
|
+
self._manifest_dependencies: dict[str, str] = {}
|
|
69
|
+
self._manifest_signature: Optional[tuple[str, float, float]] = None
|
|
70
70
|
self._manifest_empty = False
|
|
71
71
|
|
|
72
72
|
def set_package_name(self, package_name: str) -> None:
|
|
@@ -115,7 +115,7 @@ class DependencyMapper:
|
|
|
115
115
|
manifest = loader.get_manifest(self._package_name)
|
|
116
116
|
current_generation = loader.generation
|
|
117
117
|
|
|
118
|
-
dependencies:
|
|
118
|
+
dependencies: dict[str, str] = {}
|
|
119
119
|
manifest_empty = True
|
|
120
120
|
if manifest and manifest.dependencies:
|
|
121
121
|
dependencies = {
|
|
@@ -143,7 +143,7 @@ class DependencyMapper:
|
|
|
143
143
|
_cache_spec_if_missing(module_name)
|
|
144
144
|
return needs_cache
|
|
145
145
|
|
|
146
|
-
DENY_LIST:
|
|
146
|
+
DENY_LIST: set[str] = {
|
|
147
147
|
# POSIX-only modules that don't exist on Windows but try to auto-install
|
|
148
148
|
"pwd",
|
|
149
149
|
"grp",
|
|
@@ -191,7 +191,9 @@ class DependencyMapper:
|
|
|
191
191
|
1. Skip checks (stdlib, deny list)
|
|
192
192
|
2. Manifest dependencies (explicit user configuration - highest priority)
|
|
193
193
|
3. Spec cache (module already exists - skip auto-install)
|
|
194
|
-
4. Discovery mappings (automatic discovery)
|
|
194
|
+
4. Discovery mappings (automatic discovery from project configs)
|
|
195
|
+
5. Common mappings (quick access list - works without project configs)
|
|
196
|
+
6. Fallback to import_name itself
|
|
195
197
|
"""
|
|
196
198
|
if self._should_skip_auto_install(import_name):
|
|
197
199
|
return None
|
|
@@ -206,27 +208,42 @@ class DependencyMapper:
|
|
|
206
208
|
if manifest_hit:
|
|
207
209
|
return manifest_hit
|
|
208
210
|
|
|
209
|
-
# Check
|
|
211
|
+
# Check common mappings BEFORE spec cache (common mappings are reliable)
|
|
212
|
+
# This is important for exonware projects to work immediately
|
|
213
|
+
# Common mappings take precedence over spec cache because spec cache can be stale
|
|
214
|
+
discovery = self._get_discovery()
|
|
215
|
+
common_mappings = getattr(discovery, 'COMMON_MAPPINGS', {})
|
|
216
|
+
common_hit = common_mappings.get(import_name)
|
|
217
|
+
if common_hit:
|
|
218
|
+
return common_hit
|
|
219
|
+
|
|
220
|
+
# Check spec cache - if module already exists AND we don't have a common mapping, skip auto-install
|
|
221
|
+
# Note: We check this AFTER common mappings because spec cache can be stale after uninstallation
|
|
210
222
|
if _spec_cache_get(import_name):
|
|
211
223
|
return None
|
|
212
224
|
|
|
225
|
+
# Try discovery mappings (from project configs)
|
|
213
226
|
self._ensure_mappings_cached()
|
|
214
|
-
|
|
227
|
+
discovery_hit = self._import_package_mapping.get(import_name)
|
|
228
|
+
if discovery_hit:
|
|
229
|
+
return discovery_hit
|
|
230
|
+
|
|
231
|
+
# Fallback: assume import name matches package name
|
|
232
|
+
return import_name
|
|
215
233
|
|
|
216
|
-
def get_import_names(self, package_name: str) ->
|
|
234
|
+
def get_import_names(self, package_name: str) -> list[str]:
|
|
217
235
|
"""Get all possible import names for a package."""
|
|
218
236
|
self._ensure_mappings_cached()
|
|
219
237
|
return self._package_import_mapping.get(package_name, [package_name])
|
|
220
238
|
|
|
221
|
-
def get_package_import_mapping(self) ->
|
|
239
|
+
def get_package_import_mapping(self) -> dict[str, list[str]]:
|
|
222
240
|
"""Get complete package to import names mapping."""
|
|
223
241
|
self._ensure_mappings_cached()
|
|
224
242
|
return self._package_import_mapping.copy()
|
|
225
243
|
|
|
226
|
-
def get_import_package_mapping(self) ->
|
|
244
|
+
def get_import_package_mapping(self) -> dict[str, str]:
|
|
227
245
|
"""Get complete import to package name mapping."""
|
|
228
246
|
self._ensure_mappings_cached()
|
|
229
247
|
return self._import_package_mapping.copy()
|
|
230
248
|
|
|
231
249
|
__all__ = ['DependencyMapper']
|
|
232
|
-
|
|
@@ -13,11 +13,12 @@ Used by both execution strategies and LazyInstaller.
|
|
|
13
13
|
|
|
14
14
|
import os
|
|
15
15
|
import sys
|
|
16
|
-
import json
|
|
17
16
|
import asyncio
|
|
18
17
|
import subprocess
|
|
19
18
|
from typing import Optional
|
|
20
19
|
|
|
20
|
+
from exonware.xwsystem.io.serialization.auto_serializer import AutoSerializer
|
|
21
|
+
|
|
21
22
|
# Lazy imports
|
|
22
23
|
def _get_logger():
|
|
23
24
|
"""Get logger (lazy import to avoid circular dependency)."""
|
|
@@ -31,6 +32,11 @@ def _ensure_logging_initialized():
|
|
|
31
32
|
global logger
|
|
32
33
|
if logger is None:
|
|
33
34
|
logger = _get_logger()
|
|
35
|
+
# Fallback if get_logger returns None (should not happen but safety first)
|
|
36
|
+
if logger is None:
|
|
37
|
+
import logging
|
|
38
|
+
logger = logging.getLogger("xwlazy.install_async_utils.fallback")
|
|
39
|
+
logger.addHandler(logging.NullHandler())
|
|
34
40
|
|
|
35
41
|
async def get_package_size_mb(package_name: str) -> Optional[float]:
|
|
36
42
|
"""
|
|
@@ -73,7 +79,8 @@ async def get_package_size_mb(package_name: str) -> Optional[float]:
|
|
|
73
79
|
import urllib.request
|
|
74
80
|
url = f"https://pypi.org/pypi/{package_name}/json"
|
|
75
81
|
with urllib.request.urlopen(url, timeout=5) as response:
|
|
76
|
-
|
|
82
|
+
auto_serializer = AutoSerializer()
|
|
83
|
+
data = auto_serializer.detect_and_deserialize(response.read(), format_hint='json')
|
|
77
84
|
if 'urls' in data and data['urls']:
|
|
78
85
|
latest = data['urls'][0]
|
|
79
86
|
if 'size' in latest:
|
|
@@ -162,4 +169,3 @@ __all__ = [
|
|
|
162
169
|
'async_install_package',
|
|
163
170
|
'async_uninstall_package',
|
|
164
171
|
]
|
|
165
|
-
|
|
@@ -19,7 +19,7 @@ import tempfile
|
|
|
19
19
|
import subprocess
|
|
20
20
|
import zipfile
|
|
21
21
|
from pathlib import Path
|
|
22
|
-
from typing import Optional
|
|
22
|
+
from typing import Optional
|
|
23
23
|
from contextlib import suppress
|
|
24
24
|
|
|
25
25
|
# Lazy imports
|
|
@@ -77,7 +77,7 @@ def get_site_packages_dir() -> Path:
|
|
|
77
77
|
path.mkdir(parents=True, exist_ok=True)
|
|
78
78
|
return path
|
|
79
79
|
|
|
80
|
-
def pip_install_from_path(wheel_path: Path, policy_args: Optional[
|
|
80
|
+
def pip_install_from_path(wheel_path: Path, policy_args: Optional[list[str]] = None) -> bool:
|
|
81
81
|
"""Install a wheel file using pip."""
|
|
82
82
|
try:
|
|
83
83
|
pip_args = [
|
|
@@ -104,7 +104,7 @@ def pip_install_from_path(wheel_path: Path, policy_args: Optional[List[str]] = N
|
|
|
104
104
|
|
|
105
105
|
def ensure_cached_wheel(
|
|
106
106
|
package_name: str,
|
|
107
|
-
policy_args: Optional[
|
|
107
|
+
policy_args: Optional[list[str]] = None,
|
|
108
108
|
cache_dir: Optional[Path] = None
|
|
109
109
|
) -> Optional[Path]:
|
|
110
110
|
"""Ensure a wheel is cached, downloading it if necessary."""
|
|
@@ -220,7 +220,7 @@ def has_cached_install_tree(
|
|
|
220
220
|
|
|
221
221
|
def install_from_cached_wheel(
|
|
222
222
|
package_name: str,
|
|
223
|
-
policy_args: Optional[
|
|
223
|
+
policy_args: Optional[list[str]] = None,
|
|
224
224
|
cache_dir: Optional[Path] = None
|
|
225
225
|
) -> bool:
|
|
226
226
|
"""Install from a cached wheel file."""
|
|
@@ -242,4 +242,3 @@ __all__ = [
|
|
|
242
242
|
'has_cached_install_tree',
|
|
243
243
|
'install_from_cached_wheel',
|
|
244
244
|
]
|
|
245
|
-
|
|
@@ -21,7 +21,7 @@ import importlib
|
|
|
21
21
|
import importlib.machinery
|
|
22
22
|
import importlib.util
|
|
23
23
|
from pathlib import Path
|
|
24
|
-
from typing import Optional
|
|
24
|
+
from typing import Optional
|
|
25
25
|
from collections import OrderedDict
|
|
26
26
|
from functools import lru_cache
|
|
27
27
|
|
|
@@ -31,7 +31,7 @@ _SPEC_CACHE_TTL = float(os.environ.get("XWLAZY_SPEC_CACHE_TTL", "60") or 60.0)
|
|
|
31
31
|
|
|
32
32
|
# Cache storage
|
|
33
33
|
_spec_cache_lock = threading.RLock()
|
|
34
|
-
_spec_cache: OrderedDict[str,
|
|
34
|
+
_spec_cache: OrderedDict[str, tuple[importlib.machinery.ModuleSpec, float]] = OrderedDict()
|
|
35
35
|
|
|
36
36
|
# Multi-level cache: L1 (in-memory) + L2 (disk)
|
|
37
37
|
_CACHE_L2_DIR = Path(
|
|
@@ -162,4 +162,3 @@ __all__ = [
|
|
|
162
162
|
'_cache_spec_if_missing',
|
|
163
163
|
'get_stdlib_module_set',
|
|
164
164
|
]
|
|
165
|
-
|