exonware-xwlazy 0.1.0.22__py3-none-any.whl → 1.0.1.2__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 +86 -16
- exonware/xwlazy/version.py +5 -5
- exonware/xwlazy.py +2546 -0
- exonware/xwlazy_external_libs.toml +716 -0
- {exonware_xwlazy-0.1.0.22.dist-info → exonware_xwlazy-1.0.1.2.dist-info}/METADATA +6 -6
- exonware_xwlazy-1.0.1.2.dist-info/RECORD +8 -0
- exonware/xwlazy/__init__.py +0 -367
- exonware/xwlazy/common/__init__.py +0 -47
- exonware/xwlazy/common/base.py +0 -56
- exonware/xwlazy/common/cache.py +0 -504
- exonware/xwlazy/common/logger.py +0 -257
- exonware/xwlazy/common/services/__init__.py +0 -72
- exonware/xwlazy/common/services/dependency_mapper.py +0 -232
- exonware/xwlazy/common/services/install_async_utils.py +0 -165
- exonware/xwlazy/common/services/install_cache_utils.py +0 -245
- exonware/xwlazy/common/services/keyword_detection.py +0 -283
- exonware/xwlazy/common/services/spec_cache.py +0 -165
- exonware/xwlazy/common/services/state_manager.py +0 -84
- exonware/xwlazy/common/strategies/__init__.py +0 -28
- exonware/xwlazy/common/strategies/caching_dict.py +0 -44
- exonware/xwlazy/common/strategies/caching_installation.py +0 -88
- exonware/xwlazy/common/strategies/caching_lfu.py +0 -66
- exonware/xwlazy/common/strategies/caching_lru.py +0 -63
- exonware/xwlazy/common/strategies/caching_multitier.py +0 -59
- exonware/xwlazy/common/strategies/caching_ttl.py +0 -59
- exonware/xwlazy/config.py +0 -193
- exonware/xwlazy/contracts.py +0 -1396
- exonware/xwlazy/defs.py +0 -378
- exonware/xwlazy/errors.py +0 -276
- exonware/xwlazy/facade.py +0 -991
- exonware/xwlazy/module/__init__.py +0 -18
- exonware/xwlazy/module/base.py +0 -565
- exonware/xwlazy/module/data.py +0 -17
- exonware/xwlazy/module/facade.py +0 -246
- exonware/xwlazy/module/importer_engine.py +0 -2117
- exonware/xwlazy/module/strategies/__init__.py +0 -22
- exonware/xwlazy/module/strategies/module_helper_lazy.py +0 -93
- exonware/xwlazy/module/strategies/module_helper_simple.py +0 -65
- exonware/xwlazy/module/strategies/module_manager_advanced.py +0 -111
- exonware/xwlazy/module/strategies/module_manager_simple.py +0 -95
- exonware/xwlazy/package/__init__.py +0 -18
- exonware/xwlazy/package/base.py +0 -798
- exonware/xwlazy/package/conf.py +0 -324
- exonware/xwlazy/package/data.py +0 -17
- exonware/xwlazy/package/facade.py +0 -480
- exonware/xwlazy/package/services/__init__.py +0 -84
- exonware/xwlazy/package/services/async_install_handle.py +0 -87
- exonware/xwlazy/package/services/config_manager.py +0 -245
- exonware/xwlazy/package/services/discovery.py +0 -370
- exonware/xwlazy/package/services/host_packages.py +0 -145
- exonware/xwlazy/package/services/install_async.py +0 -277
- exonware/xwlazy/package/services/install_cache.py +0 -145
- exonware/xwlazy/package/services/install_interactive.py +0 -59
- exonware/xwlazy/package/services/install_policy.py +0 -156
- exonware/xwlazy/package/services/install_registry.py +0 -54
- exonware/xwlazy/package/services/install_result.py +0 -17
- exonware/xwlazy/package/services/install_sbom.py +0 -153
- exonware/xwlazy/package/services/install_utils.py +0 -79
- exonware/xwlazy/package/services/installer_engine.py +0 -406
- exonware/xwlazy/package/services/lazy_installer.py +0 -718
- exonware/xwlazy/package/services/manifest.py +0 -496
- exonware/xwlazy/package/services/strategy_registry.py +0 -186
- exonware/xwlazy/package/strategies/__init__.py +0 -57
- exonware/xwlazy/package/strategies/package_discovery_file.py +0 -129
- exonware/xwlazy/package/strategies/package_discovery_hybrid.py +0 -84
- exonware/xwlazy/package/strategies/package_discovery_manifest.py +0 -101
- exonware/xwlazy/package/strategies/package_execution_async.py +0 -113
- exonware/xwlazy/package/strategies/package_execution_cached.py +0 -90
- exonware/xwlazy/package/strategies/package_execution_pip.py +0 -99
- exonware/xwlazy/package/strategies/package_execution_wheel.py +0 -106
- exonware/xwlazy/package/strategies/package_mapping_discovery_first.py +0 -100
- exonware/xwlazy/package/strategies/package_mapping_hybrid.py +0 -105
- exonware/xwlazy/package/strategies/package_mapping_manifest_first.py +0 -100
- exonware/xwlazy/package/strategies/package_policy_allow_list.py +0 -57
- exonware/xwlazy/package/strategies/package_policy_deny_list.py +0 -57
- exonware/xwlazy/package/strategies/package_policy_permissive.py +0 -46
- exonware/xwlazy/package/strategies/package_timing_clean.py +0 -67
- exonware/xwlazy/package/strategies/package_timing_full.py +0 -66
- exonware/xwlazy/package/strategies/package_timing_smart.py +0 -68
- exonware/xwlazy/package/strategies/package_timing_temporary.py +0 -66
- exonware/xwlazy/runtime/__init__.py +0 -18
- exonware/xwlazy/runtime/adaptive_learner.py +0 -129
- exonware/xwlazy/runtime/base.py +0 -274
- exonware/xwlazy/runtime/facade.py +0 -94
- exonware/xwlazy/runtime/intelligent_selector.py +0 -170
- exonware/xwlazy/runtime/metrics.py +0 -60
- exonware/xwlazy/runtime/performance.py +0 -37
- exonware_xwlazy-0.1.0.22.dist-info/RECORD +0 -87
- {exonware_xwlazy-0.1.0.22.dist-info → exonware_xwlazy-1.0.1.2.dist-info}/WHEEL +0 -0
- {exonware_xwlazy-0.1.0.22.dist-info → exonware_xwlazy-1.0.1.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Wheel Execution Strategy
|
|
3
|
-
|
|
4
|
-
Company: eXonware.com
|
|
5
|
-
Author: Eng. Muhammad AlShehri
|
|
6
|
-
Email: connect@exonware.com
|
|
7
|
-
|
|
8
|
-
Generation Date: 15-Nov-2025
|
|
9
|
-
|
|
10
|
-
Wheel execution strategy - install from wheel files.
|
|
11
|
-
Uses shared utilities from common/services/install_cache_utils.
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
import sys
|
|
15
|
-
import subprocess
|
|
16
|
-
from pathlib import Path
|
|
17
|
-
from typing import List, Any, Optional
|
|
18
|
-
from ...package.base import AInstallExecutionStrategy
|
|
19
|
-
from ...package.services.install_result import InstallResult, InstallStatus
|
|
20
|
-
from ...common.services.install_cache_utils import (
|
|
21
|
-
get_wheel_path,
|
|
22
|
-
ensure_cached_wheel,
|
|
23
|
-
pip_install_from_path,
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
class WheelExecution(AInstallExecutionStrategy):
|
|
27
|
-
"""
|
|
28
|
-
Wheel execution strategy - installs packages from wheel files.
|
|
29
|
-
|
|
30
|
-
Downloads wheel first, then installs from local wheel file.
|
|
31
|
-
Uses shared utilities from common/services/install_cache_utils.
|
|
32
|
-
"""
|
|
33
|
-
|
|
34
|
-
def __init__(self, cache_dir: Optional[Path] = None):
|
|
35
|
-
"""
|
|
36
|
-
Initialize wheel execution strategy.
|
|
37
|
-
|
|
38
|
-
Args:
|
|
39
|
-
cache_dir: Optional cache directory for wheels
|
|
40
|
-
"""
|
|
41
|
-
self._cache_dir = cache_dir
|
|
42
|
-
|
|
43
|
-
def execute_install(self, package_name: str, policy_args: List[str]) -> Any:
|
|
44
|
-
"""
|
|
45
|
-
Execute installation from wheel file.
|
|
46
|
-
|
|
47
|
-
Args:
|
|
48
|
-
package_name: Package name to install
|
|
49
|
-
policy_args: Policy arguments
|
|
50
|
-
|
|
51
|
-
Returns:
|
|
52
|
-
InstallResult with success status
|
|
53
|
-
"""
|
|
54
|
-
# Check if wheel already exists
|
|
55
|
-
wheel_path = get_wheel_path(package_name, self._cache_dir)
|
|
56
|
-
|
|
57
|
-
if not wheel_path.exists():
|
|
58
|
-
# Download wheel first
|
|
59
|
-
wheel_path = ensure_cached_wheel(package_name, policy_args, self._cache_dir)
|
|
60
|
-
if wheel_path is None:
|
|
61
|
-
return InstallResult(
|
|
62
|
-
package_name=package_name,
|
|
63
|
-
success=False,
|
|
64
|
-
status=InstallStatus.FAILED,
|
|
65
|
-
error="Failed to download wheel"
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
# Install from wheel
|
|
69
|
-
success = pip_install_from_path(wheel_path, policy_args)
|
|
70
|
-
|
|
71
|
-
if success:
|
|
72
|
-
return InstallResult(
|
|
73
|
-
package_name=package_name,
|
|
74
|
-
success=True,
|
|
75
|
-
status=InstallStatus.SUCCESS,
|
|
76
|
-
source="wheel"
|
|
77
|
-
)
|
|
78
|
-
else:
|
|
79
|
-
return InstallResult(
|
|
80
|
-
package_name=package_name,
|
|
81
|
-
success=False,
|
|
82
|
-
status=InstallStatus.FAILED,
|
|
83
|
-
error="Failed to install from wheel"
|
|
84
|
-
)
|
|
85
|
-
|
|
86
|
-
def execute_uninstall(self, package_name: str) -> bool:
|
|
87
|
-
"""
|
|
88
|
-
Execute uninstallation using pip.
|
|
89
|
-
|
|
90
|
-
Args:
|
|
91
|
-
package_name: Package name to uninstall
|
|
92
|
-
|
|
93
|
-
Returns:
|
|
94
|
-
True if successful, False otherwise
|
|
95
|
-
"""
|
|
96
|
-
try:
|
|
97
|
-
result = subprocess.run(
|
|
98
|
-
[sys.executable, '-m', 'pip', 'uninstall', '-y', package_name],
|
|
99
|
-
capture_output=True,
|
|
100
|
-
text=True,
|
|
101
|
-
check=True
|
|
102
|
-
)
|
|
103
|
-
return result.returncode == 0
|
|
104
|
-
except Exception:
|
|
105
|
-
return False
|
|
106
|
-
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Discovery-First Mapping Strategy
|
|
3
|
-
|
|
4
|
-
Company: eXonware.com
|
|
5
|
-
Author: Eng. Muhammad AlShehri
|
|
6
|
-
Email: connect@exonware.com
|
|
7
|
-
|
|
8
|
-
Generation Date: 15-Nov-2025
|
|
9
|
-
|
|
10
|
-
Discovery-first mapping strategy - discovery takes precedence over manifest.
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
from typing import Optional, List
|
|
14
|
-
from ...package.base import AMappingStrategy
|
|
15
|
-
from ...package.services.manifest import get_manifest_loader
|
|
16
|
-
|
|
17
|
-
class DiscoveryFirstMapping(AMappingStrategy):
|
|
18
|
-
"""
|
|
19
|
-
Discovery-first mapping strategy.
|
|
20
|
-
|
|
21
|
-
Priority order:
|
|
22
|
-
1. Discovery mappings (automatic discovery - highest priority)
|
|
23
|
-
2. Manifest dependencies (explicit user configuration)
|
|
24
|
-
3. Common mappings (fallback)
|
|
25
|
-
"""
|
|
26
|
-
|
|
27
|
-
def __init__(self, package_name: str = 'default'):
|
|
28
|
-
"""
|
|
29
|
-
Initialize discovery-first mapping strategy.
|
|
30
|
-
|
|
31
|
-
Args:
|
|
32
|
-
package_name: Package name for isolation
|
|
33
|
-
"""
|
|
34
|
-
self._package_name = package_name
|
|
35
|
-
self._discovery = None # Lazy init
|
|
36
|
-
|
|
37
|
-
def _get_discovery(self):
|
|
38
|
-
"""Get discovery instance (lazy init)."""
|
|
39
|
-
if self._discovery is None:
|
|
40
|
-
from ...package.services.discovery import LazyDiscovery
|
|
41
|
-
self._discovery = LazyDiscovery(self._package_name)
|
|
42
|
-
return self._discovery
|
|
43
|
-
|
|
44
|
-
def map_import_to_package(self, import_name: str) -> Optional[str]:
|
|
45
|
-
"""
|
|
46
|
-
Map import name to package name.
|
|
47
|
-
|
|
48
|
-
Priority: Discovery > Manifest > Common mappings
|
|
49
|
-
|
|
50
|
-
Args:
|
|
51
|
-
import_name: Import name (e.g., 'cv2')
|
|
52
|
-
|
|
53
|
-
Returns:
|
|
54
|
-
Package name (e.g., 'opencv-python') or None
|
|
55
|
-
"""
|
|
56
|
-
# Check discovery mappings FIRST
|
|
57
|
-
discovery = self._get_discovery()
|
|
58
|
-
discovery_mapping = discovery.get_import_package_mapping()
|
|
59
|
-
package = discovery_mapping.get(import_name)
|
|
60
|
-
if package:
|
|
61
|
-
return package
|
|
62
|
-
|
|
63
|
-
# Check manifest (fallback)
|
|
64
|
-
loader = get_manifest_loader()
|
|
65
|
-
manifest = loader.get_manifest(self._package_name)
|
|
66
|
-
if manifest:
|
|
67
|
-
package = manifest.get_dependency(import_name)
|
|
68
|
-
if package:
|
|
69
|
-
return package
|
|
70
|
-
|
|
71
|
-
# Fallback to common mappings
|
|
72
|
-
common_mappings = discovery.COMMON_MAPPINGS
|
|
73
|
-
return common_mappings.get(import_name)
|
|
74
|
-
|
|
75
|
-
def map_package_to_imports(self, package_name: str) -> List[str]:
|
|
76
|
-
"""
|
|
77
|
-
Map package name to possible import names.
|
|
78
|
-
|
|
79
|
-
Args:
|
|
80
|
-
package_name: Package name (e.g., 'opencv-python')
|
|
81
|
-
|
|
82
|
-
Returns:
|
|
83
|
-
List of possible import names (e.g., ['cv2'])
|
|
84
|
-
"""
|
|
85
|
-
# Check discovery mappings FIRST
|
|
86
|
-
discovery = self._get_discovery()
|
|
87
|
-
package_mapping = discovery.get_package_import_mapping()
|
|
88
|
-
imports = package_mapping.get(package_name, [])
|
|
89
|
-
|
|
90
|
-
# Also check manifest (reverse lookup)
|
|
91
|
-
loader = get_manifest_loader()
|
|
92
|
-
manifest = loader.get_manifest(self._package_name)
|
|
93
|
-
if manifest:
|
|
94
|
-
for import_name, pkg in manifest.dependencies.items():
|
|
95
|
-
if pkg.lower() == package_name.lower():
|
|
96
|
-
if import_name not in imports:
|
|
97
|
-
imports.append(import_name)
|
|
98
|
-
|
|
99
|
-
return imports if imports else [package_name]
|
|
100
|
-
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Hybrid Mapping Strategy
|
|
3
|
-
|
|
4
|
-
Company: eXonware.com
|
|
5
|
-
Author: Eng. Muhammad AlShehri
|
|
6
|
-
Email: connect@exonware.com
|
|
7
|
-
|
|
8
|
-
Generation Date: 15-Nov-2025
|
|
9
|
-
|
|
10
|
-
Hybrid mapping strategy - tries both manifest and discovery, uses best match.
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
from typing import Optional, List
|
|
14
|
-
from ...package.base import AMappingStrategy
|
|
15
|
-
from ...package.services.manifest import get_manifest_loader
|
|
16
|
-
|
|
17
|
-
class HybridMapping(AMappingStrategy):
|
|
18
|
-
"""
|
|
19
|
-
Hybrid mapping strategy.
|
|
20
|
-
|
|
21
|
-
Tries both manifest and discovery, uses the best match.
|
|
22
|
-
If both exist, prefers the one that's more specific.
|
|
23
|
-
"""
|
|
24
|
-
|
|
25
|
-
def __init__(self, package_name: str = 'default'):
|
|
26
|
-
"""
|
|
27
|
-
Initialize hybrid mapping strategy.
|
|
28
|
-
|
|
29
|
-
Args:
|
|
30
|
-
package_name: Package name for isolation
|
|
31
|
-
"""
|
|
32
|
-
self._package_name = package_name
|
|
33
|
-
self._discovery = None # Lazy init
|
|
34
|
-
|
|
35
|
-
def _get_discovery(self):
|
|
36
|
-
"""Get discovery instance (lazy init)."""
|
|
37
|
-
if self._discovery is None:
|
|
38
|
-
from ...package.services.discovery import LazyDiscovery
|
|
39
|
-
self._discovery = LazyDiscovery(self._package_name)
|
|
40
|
-
return self._discovery
|
|
41
|
-
|
|
42
|
-
def map_import_to_package(self, import_name: str) -> Optional[str]:
|
|
43
|
-
"""
|
|
44
|
-
Map import name to package name.
|
|
45
|
-
|
|
46
|
-
Tries both manifest and discovery, prefers more specific match.
|
|
47
|
-
|
|
48
|
-
Args:
|
|
49
|
-
import_name: Import name (e.g., 'cv2')
|
|
50
|
-
|
|
51
|
-
Returns:
|
|
52
|
-
Package name (e.g., 'opencv-python') or None
|
|
53
|
-
"""
|
|
54
|
-
# Try manifest first
|
|
55
|
-
loader = get_manifest_loader()
|
|
56
|
-
manifest = loader.get_manifest(self._package_name)
|
|
57
|
-
manifest_package = None
|
|
58
|
-
if manifest:
|
|
59
|
-
manifest_package = manifest.get_dependency(import_name)
|
|
60
|
-
|
|
61
|
-
# Try discovery
|
|
62
|
-
discovery = self._get_discovery()
|
|
63
|
-
discovery_mapping = discovery.get_import_package_mapping()
|
|
64
|
-
discovery_package = discovery_mapping.get(import_name)
|
|
65
|
-
|
|
66
|
-
# Prefer manifest if both exist (more explicit)
|
|
67
|
-
if manifest_package:
|
|
68
|
-
return manifest_package
|
|
69
|
-
|
|
70
|
-
if discovery_package:
|
|
71
|
-
return discovery_package
|
|
72
|
-
|
|
73
|
-
# Fallback to common mappings
|
|
74
|
-
common_mappings = discovery.COMMON_MAPPINGS
|
|
75
|
-
return common_mappings.get(import_name)
|
|
76
|
-
|
|
77
|
-
def map_package_to_imports(self, package_name: str) -> List[str]:
|
|
78
|
-
"""
|
|
79
|
-
Map package name to possible import names.
|
|
80
|
-
|
|
81
|
-
Args:
|
|
82
|
-
package_name: Package name (e.g., 'opencv-python')
|
|
83
|
-
|
|
84
|
-
Returns:
|
|
85
|
-
List of possible import names (e.g., ['cv2'])
|
|
86
|
-
"""
|
|
87
|
-
imports = []
|
|
88
|
-
|
|
89
|
-
# Check discovery mappings
|
|
90
|
-
discovery = self._get_discovery()
|
|
91
|
-
package_mapping = discovery.get_package_import_mapping()
|
|
92
|
-
discovery_imports = package_mapping.get(package_name, [])
|
|
93
|
-
imports.extend(discovery_imports)
|
|
94
|
-
|
|
95
|
-
# Check manifest (reverse lookup)
|
|
96
|
-
loader = get_manifest_loader()
|
|
97
|
-
manifest = loader.get_manifest(self._package_name)
|
|
98
|
-
if manifest:
|
|
99
|
-
for import_name, pkg in manifest.dependencies.items():
|
|
100
|
-
if pkg.lower() == package_name.lower():
|
|
101
|
-
if import_name not in imports:
|
|
102
|
-
imports.append(import_name)
|
|
103
|
-
|
|
104
|
-
return imports if imports else [package_name]
|
|
105
|
-
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Manifest-First Mapping Strategy
|
|
3
|
-
|
|
4
|
-
Company: eXonware.com
|
|
5
|
-
Author: Eng. Muhammad AlShehri
|
|
6
|
-
Email: connect@exonware.com
|
|
7
|
-
|
|
8
|
-
Generation Date: 15-Nov-2025
|
|
9
|
-
|
|
10
|
-
Manifest-first mapping strategy - manifest takes precedence over discovery.
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
from typing import Optional, List
|
|
14
|
-
from ...package.base import AMappingStrategy
|
|
15
|
-
from ...package.services.manifest import get_manifest_loader
|
|
16
|
-
|
|
17
|
-
class ManifestFirstMapping(AMappingStrategy):
|
|
18
|
-
"""
|
|
19
|
-
Manifest-first mapping strategy.
|
|
20
|
-
|
|
21
|
-
Priority order:
|
|
22
|
-
1. Manifest dependencies (explicit user configuration - highest priority)
|
|
23
|
-
2. Discovery mappings (automatic discovery)
|
|
24
|
-
3. Common mappings (fallback)
|
|
25
|
-
"""
|
|
26
|
-
|
|
27
|
-
def __init__(self, package_name: str = 'default'):
|
|
28
|
-
"""
|
|
29
|
-
Initialize manifest-first mapping strategy.
|
|
30
|
-
|
|
31
|
-
Args:
|
|
32
|
-
package_name: Package name for isolation
|
|
33
|
-
"""
|
|
34
|
-
self._package_name = package_name
|
|
35
|
-
self._discovery = None # Lazy init
|
|
36
|
-
|
|
37
|
-
def _get_discovery(self):
|
|
38
|
-
"""Get discovery instance (lazy init)."""
|
|
39
|
-
if self._discovery is None:
|
|
40
|
-
from ...package.services.discovery import LazyDiscovery
|
|
41
|
-
self._discovery = LazyDiscovery(self._package_name)
|
|
42
|
-
return self._discovery
|
|
43
|
-
|
|
44
|
-
def map_import_to_package(self, import_name: str) -> Optional[str]:
|
|
45
|
-
"""
|
|
46
|
-
Map import name to package name.
|
|
47
|
-
|
|
48
|
-
Priority: Manifest > Discovery > Common mappings
|
|
49
|
-
|
|
50
|
-
Args:
|
|
51
|
-
import_name: Import name (e.g., 'cv2')
|
|
52
|
-
|
|
53
|
-
Returns:
|
|
54
|
-
Package name (e.g., 'opencv-python') or None
|
|
55
|
-
"""
|
|
56
|
-
# Check manifest FIRST - explicit user configuration takes precedence
|
|
57
|
-
loader = get_manifest_loader()
|
|
58
|
-
manifest = loader.get_manifest(self._package_name)
|
|
59
|
-
if manifest:
|
|
60
|
-
package = manifest.get_dependency(import_name)
|
|
61
|
-
if package:
|
|
62
|
-
return package
|
|
63
|
-
|
|
64
|
-
# Check discovery mappings
|
|
65
|
-
discovery = self._get_discovery()
|
|
66
|
-
discovery_mapping = discovery.get_import_package_mapping()
|
|
67
|
-
package = discovery_mapping.get(import_name)
|
|
68
|
-
if package:
|
|
69
|
-
return package
|
|
70
|
-
|
|
71
|
-
# Fallback to common mappings
|
|
72
|
-
common_mappings = discovery.COMMON_MAPPINGS
|
|
73
|
-
return common_mappings.get(import_name)
|
|
74
|
-
|
|
75
|
-
def map_package_to_imports(self, package_name: str) -> List[str]:
|
|
76
|
-
"""
|
|
77
|
-
Map package name to possible import names.
|
|
78
|
-
|
|
79
|
-
Args:
|
|
80
|
-
package_name: Package name (e.g., 'opencv-python')
|
|
81
|
-
|
|
82
|
-
Returns:
|
|
83
|
-
List of possible import names (e.g., ['cv2'])
|
|
84
|
-
"""
|
|
85
|
-
# Check discovery mappings
|
|
86
|
-
discovery = self._get_discovery()
|
|
87
|
-
package_mapping = discovery.get_package_import_mapping()
|
|
88
|
-
imports = package_mapping.get(package_name, [])
|
|
89
|
-
|
|
90
|
-
# Also check manifest (reverse lookup)
|
|
91
|
-
loader = get_manifest_loader()
|
|
92
|
-
manifest = loader.get_manifest(self._package_name)
|
|
93
|
-
if manifest:
|
|
94
|
-
for import_name, pkg in manifest.dependencies.items():
|
|
95
|
-
if pkg.lower() == package_name.lower():
|
|
96
|
-
if import_name not in imports:
|
|
97
|
-
imports.append(import_name)
|
|
98
|
-
|
|
99
|
-
return imports if imports else [package_name]
|
|
100
|
-
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Allow List Policy Strategy
|
|
3
|
-
|
|
4
|
-
Company: eXonware.com
|
|
5
|
-
Author: Eng. Muhammad AlShehri
|
|
6
|
-
Email: connect@exonware.com
|
|
7
|
-
|
|
8
|
-
Generation Date: 15-Nov-2025
|
|
9
|
-
|
|
10
|
-
Allow list policy - only allows packages in the allow list.
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
from typing import Tuple, List, Set
|
|
14
|
-
from ...package.base import APolicyStrategy
|
|
15
|
-
|
|
16
|
-
class AllowListPolicy(APolicyStrategy):
|
|
17
|
-
"""
|
|
18
|
-
Allow list policy strategy - only allows packages in the allow list.
|
|
19
|
-
|
|
20
|
-
Only packages explicitly in the allow list can be installed.
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
def __init__(self, allowed_packages: Set[str]):
|
|
24
|
-
"""
|
|
25
|
-
Initialize allow list policy.
|
|
26
|
-
|
|
27
|
-
Args:
|
|
28
|
-
allowed_packages: Set of allowed package names
|
|
29
|
-
"""
|
|
30
|
-
self._allowed = {pkg.lower() for pkg in allowed_packages}
|
|
31
|
-
|
|
32
|
-
def is_allowed(self, package_name: str) -> Tuple[bool, str]:
|
|
33
|
-
"""
|
|
34
|
-
Check if package is allowed to be installed.
|
|
35
|
-
|
|
36
|
-
Args:
|
|
37
|
-
package_name: Package name to check
|
|
38
|
-
|
|
39
|
-
Returns:
|
|
40
|
-
Tuple of (allowed: bool, reason: str)
|
|
41
|
-
"""
|
|
42
|
-
if package_name.lower() in self._allowed:
|
|
43
|
-
return (True, f"Package '{package_name}' is in allow list")
|
|
44
|
-
return (False, f"Package '{package_name}' is not in allow list")
|
|
45
|
-
|
|
46
|
-
def get_pip_args(self, package_name: str) -> List[str]:
|
|
47
|
-
"""
|
|
48
|
-
Get pip arguments based on policy.
|
|
49
|
-
|
|
50
|
-
Args:
|
|
51
|
-
package_name: Package name
|
|
52
|
-
|
|
53
|
-
Returns:
|
|
54
|
-
List of pip arguments (empty for allow list policy)
|
|
55
|
-
"""
|
|
56
|
-
return []
|
|
57
|
-
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Deny List Policy Strategy
|
|
3
|
-
|
|
4
|
-
Company: eXonware.com
|
|
5
|
-
Author: Eng. Muhammad AlShehri
|
|
6
|
-
Email: connect@exonware.com
|
|
7
|
-
|
|
8
|
-
Generation Date: 15-Nov-2025
|
|
9
|
-
|
|
10
|
-
Deny list policy - blocks packages in the deny list.
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
from typing import Tuple, List, Set
|
|
14
|
-
from ...package.base import APolicyStrategy
|
|
15
|
-
|
|
16
|
-
class DenyListPolicy(APolicyStrategy):
|
|
17
|
-
"""
|
|
18
|
-
Deny list policy strategy - blocks packages in the deny list.
|
|
19
|
-
|
|
20
|
-
Packages in the deny list cannot be installed.
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
def __init__(self, denied_packages: Set[str]):
|
|
24
|
-
"""
|
|
25
|
-
Initialize deny list policy.
|
|
26
|
-
|
|
27
|
-
Args:
|
|
28
|
-
denied_packages: Set of denied package names
|
|
29
|
-
"""
|
|
30
|
-
self._denied = {pkg.lower() for pkg in denied_packages}
|
|
31
|
-
|
|
32
|
-
def is_allowed(self, package_name: str) -> Tuple[bool, str]:
|
|
33
|
-
"""
|
|
34
|
-
Check if package is allowed to be installed.
|
|
35
|
-
|
|
36
|
-
Args:
|
|
37
|
-
package_name: Package name to check
|
|
38
|
-
|
|
39
|
-
Returns:
|
|
40
|
-
Tuple of (allowed: bool, reason: str)
|
|
41
|
-
"""
|
|
42
|
-
if package_name.lower() in self._denied:
|
|
43
|
-
return (False, f"Package '{package_name}' is in deny list")
|
|
44
|
-
return (True, f"Package '{package_name}' is not in deny list")
|
|
45
|
-
|
|
46
|
-
def get_pip_args(self, package_name: str) -> List[str]:
|
|
47
|
-
"""
|
|
48
|
-
Get pip arguments based on policy.
|
|
49
|
-
|
|
50
|
-
Args:
|
|
51
|
-
package_name: Package name
|
|
52
|
-
|
|
53
|
-
Returns:
|
|
54
|
-
List of pip arguments (empty for deny list policy)
|
|
55
|
-
"""
|
|
56
|
-
return []
|
|
57
|
-
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Permissive Policy Strategy
|
|
3
|
-
|
|
4
|
-
Company: eXonware.com
|
|
5
|
-
Author: Eng. Muhammad AlShehri
|
|
6
|
-
Email: connect@exonware.com
|
|
7
|
-
|
|
8
|
-
Generation Date: 15-Nov-2025
|
|
9
|
-
|
|
10
|
-
Permissive policy - allows all packages (default).
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
from typing import Tuple, List
|
|
14
|
-
from ...package.base import APolicyStrategy
|
|
15
|
-
|
|
16
|
-
class PermissivePolicy(APolicyStrategy):
|
|
17
|
-
"""
|
|
18
|
-
Permissive policy strategy - allows all packages.
|
|
19
|
-
|
|
20
|
-
This is the default policy that doesn't restrict any packages.
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
def is_allowed(self, package_name: str) -> Tuple[bool, str]:
|
|
24
|
-
"""
|
|
25
|
-
Check if package is allowed to be installed.
|
|
26
|
-
|
|
27
|
-
Args:
|
|
28
|
-
package_name: Package name to check
|
|
29
|
-
|
|
30
|
-
Returns:
|
|
31
|
-
Tuple of (allowed: bool, reason: str)
|
|
32
|
-
"""
|
|
33
|
-
return (True, "Permissive policy allows all packages")
|
|
34
|
-
|
|
35
|
-
def get_pip_args(self, package_name: str) -> List[str]:
|
|
36
|
-
"""
|
|
37
|
-
Get pip arguments based on policy.
|
|
38
|
-
|
|
39
|
-
Args:
|
|
40
|
-
package_name: Package name
|
|
41
|
-
|
|
42
|
-
Returns:
|
|
43
|
-
List of pip arguments (empty for permissive policy)
|
|
44
|
-
"""
|
|
45
|
-
return []
|
|
46
|
-
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Clean Timing Strategy
|
|
3
|
-
|
|
4
|
-
Company: eXonware.com
|
|
5
|
-
Author: Eng. Muhammad AlShehri
|
|
6
|
-
Email: connect@exonware.com
|
|
7
|
-
|
|
8
|
-
Generation Date: 15-Nov-2025
|
|
9
|
-
|
|
10
|
-
Clean timing - install on usage + uninstall after completion.
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
from typing import List, Any
|
|
14
|
-
from ...package.base import AInstallTimingStrategy
|
|
15
|
-
|
|
16
|
-
class CleanTiming(AInstallTimingStrategy):
|
|
17
|
-
"""
|
|
18
|
-
Clean timing strategy - installs on usage + uninstalls after completion (LazyInstallMode.CLEAN).
|
|
19
|
-
|
|
20
|
-
Installs package when needed, then uninstalls after use to keep environment clean.
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
def should_install_now(self, package_name: str, context: Any) -> bool:
|
|
24
|
-
"""
|
|
25
|
-
Determine if package should be installed now.
|
|
26
|
-
|
|
27
|
-
Clean mode: Install when first needed.
|
|
28
|
-
|
|
29
|
-
Args:
|
|
30
|
-
package_name: Package name to check
|
|
31
|
-
context: Context information (e.g., import error)
|
|
32
|
-
|
|
33
|
-
Returns:
|
|
34
|
-
True if should install now
|
|
35
|
-
"""
|
|
36
|
-
# In clean mode, install when first needed
|
|
37
|
-
return context is not None
|
|
38
|
-
|
|
39
|
-
def should_uninstall_after(self, package_name: str, context: Any) -> bool:
|
|
40
|
-
"""
|
|
41
|
-
Determine if package should be uninstalled after use.
|
|
42
|
-
|
|
43
|
-
Clean mode: Uninstall after use.
|
|
44
|
-
|
|
45
|
-
Args:
|
|
46
|
-
package_name: Package name to check
|
|
47
|
-
context: Context information
|
|
48
|
-
|
|
49
|
-
Returns:
|
|
50
|
-
True (uninstall after use)
|
|
51
|
-
"""
|
|
52
|
-
return True
|
|
53
|
-
|
|
54
|
-
def get_install_priority(self, packages: List[str]) -> List[str]:
|
|
55
|
-
"""
|
|
56
|
-
Get priority order for installing packages.
|
|
57
|
-
|
|
58
|
-
Clean mode: Install in order requested.
|
|
59
|
-
|
|
60
|
-
Args:
|
|
61
|
-
packages: List of package names
|
|
62
|
-
|
|
63
|
-
Returns:
|
|
64
|
-
Priority-ordered list
|
|
65
|
-
"""
|
|
66
|
-
return packages
|
|
67
|
-
|