exonware-xwlazy 0.1.0.21__py3-none-any.whl → 0.1.0.23__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. exonware/__init__.py +22 -6
  2. exonware/xwlazy/__init__.py +14 -2
  3. exonware/xwlazy/common/__init__.py +8 -0
  4. exonware/xwlazy/common/base.py +11 -2
  5. exonware/xwlazy/common/cache.py +5 -5
  6. exonware/xwlazy/common/logger.py +5 -5
  7. exonware/xwlazy/common/services/dependency_mapper.py +31 -13
  8. exonware/xwlazy/common/services/install_async_utils.py +5 -0
  9. exonware/xwlazy/common/services/install_cache_utils.py +4 -4
  10. exonware/xwlazy/common/services/spec_cache.py +2 -2
  11. exonware/xwlazy/common/services/state_manager.py +4 -4
  12. exonware/xwlazy/common/strategies/caching_dict.py +2 -2
  13. exonware/xwlazy/common/strategies/caching_lfu.py +2 -2
  14. exonware/xwlazy/common/strategies/caching_ttl.py +2 -2
  15. exonware/xwlazy/common/utils.py +142 -0
  16. exonware/xwlazy/config.py +1 -1
  17. exonware/xwlazy/contracts.py +162 -25
  18. exonware/xwlazy/defs.py +15 -15
  19. exonware/xwlazy/facade.py +175 -29
  20. exonware/xwlazy/host/__init__.py +8 -0
  21. exonware/xwlazy/host/conf.py +16 -0
  22. exonware/xwlazy/module/base.py +61 -4
  23. exonware/xwlazy/module/facade.py +1 -1
  24. exonware/xwlazy/module/importer_engine.py +1017 -170
  25. exonware/xwlazy/module/partial_module_detector.py +275 -0
  26. exonware/xwlazy/module/strategies/module_helper_lazy.py +3 -3
  27. exonware/xwlazy/package/base.py +106 -41
  28. exonware/xwlazy/package/conf.py +6 -6
  29. exonware/xwlazy/package/services/config_manager.py +20 -16
  30. exonware/xwlazy/package/services/discovery.py +81 -16
  31. exonware/xwlazy/package/services/host_packages.py +41 -6
  32. exonware/xwlazy/package/services/install_async.py +16 -2
  33. exonware/xwlazy/package/services/install_cache.py +4 -4
  34. exonware/xwlazy/package/services/install_policy.py +14 -14
  35. exonware/xwlazy/package/services/install_registry.py +3 -3
  36. exonware/xwlazy/package/services/install_sbom.py +1 -1
  37. exonware/xwlazy/package/services/installer_engine.py +3 -3
  38. exonware/xwlazy/package/services/lazy_installer.py +102 -17
  39. exonware/xwlazy/package/services/manifest.py +43 -36
  40. exonware/xwlazy/package/services/strategy_registry.py +150 -12
  41. exonware/xwlazy/package/strategies/package_discovery_file.py +2 -2
  42. exonware/xwlazy/package/strategies/package_discovery_hybrid.py +2 -2
  43. exonware/xwlazy/package/strategies/package_discovery_manifest.py +2 -2
  44. exonware/xwlazy/package/strategies/package_execution_async.py +3 -3
  45. exonware/xwlazy/package/strategies/package_execution_cached.py +2 -2
  46. exonware/xwlazy/package/strategies/package_execution_pip.py +2 -2
  47. exonware/xwlazy/package/strategies/package_execution_wheel.py +2 -2
  48. exonware/xwlazy/package/strategies/package_mapping_discovery_first.py +2 -2
  49. exonware/xwlazy/package/strategies/package_mapping_hybrid.py +2 -2
  50. exonware/xwlazy/package/strategies/package_mapping_manifest_first.py +2 -2
  51. exonware/xwlazy/package/strategies/package_policy_allow_list.py +4 -4
  52. exonware/xwlazy/package/strategies/package_policy_deny_list.py +4 -4
  53. exonware/xwlazy/package/strategies/package_policy_permissive.py +3 -3
  54. exonware/xwlazy/package/strategies/package_timing_clean.py +2 -2
  55. exonware/xwlazy/package/strategies/package_timing_full.py +2 -2
  56. exonware/xwlazy/package/strategies/package_timing_smart.py +2 -2
  57. exonware/xwlazy/package/strategies/package_timing_temporary.py +2 -2
  58. exonware/xwlazy/runtime/adaptive_learner.py +7 -7
  59. exonware/xwlazy/runtime/base.py +14 -14
  60. exonware/xwlazy/runtime/facade.py +7 -7
  61. exonware/xwlazy/runtime/intelligent_selector.py +6 -6
  62. exonware/xwlazy/runtime/metrics.py +6 -6
  63. exonware/xwlazy/runtime/performance.py +5 -5
  64. exonware/xwlazy/version.py +2 -2
  65. {exonware_xwlazy-0.1.0.21.dist-info → exonware_xwlazy-0.1.0.23.dist-info}/METADATA +2 -6
  66. exonware_xwlazy-0.1.0.23.dist-info/RECORD +93 -0
  67. xwlazy/__init__.py +14 -0
  68. xwlazy/lazy.py +30 -0
  69. exonware_xwlazy-0.1.0.21.dist-info/RECORD +0 -87
  70. {exonware_xwlazy-0.1.0.21.dist-info → exonware_xwlazy-0.1.0.23.dist-info}/WHEEL +0 -0
  71. {exonware_xwlazy-0.1.0.21.dist-info → exonware_xwlazy-0.1.0.23.dist-info}/licenses/LICENSE +0 -0
@@ -13,7 +13,7 @@ This module defines all interfaces, enums, and protocols for the lazy loading
13
13
  system following GUIDE_ARCH.md structure.
14
14
  """
15
15
 
16
- from typing import Protocol, Dict, List, Optional, Any, Tuple, runtime_checkable
16
+ from typing import Protocol, Optional, Any, runtime_checkable
17
17
  from types import ModuleType
18
18
 
19
19
  # Import enums and dataclasses from defs.py
@@ -119,7 +119,7 @@ class IPackageHelper(Protocol):
119
119
  """
120
120
  ...
121
121
 
122
- def install_and_import(self, module_name: str, package_name: Optional[str] = None) -> Tuple[Optional[ModuleType], bool]:
122
+ def install_and_import(self, module_name: str, package_name: Optional[str] = None) -> tuple[Optional[ModuleType], bool]:
123
123
  """
124
124
  Install package and import module (from IPackageInstaller).
125
125
 
@@ -152,7 +152,7 @@ class IPackageHelper(Protocol):
152
152
  # Package Discovery (from IPackageDiscovery)
153
153
  # ========================================================================
154
154
 
155
- def discover_all_dependencies(self) -> Dict[str, str]:
155
+ def discover_all_dependencies(self) -> dict[str, str]:
156
156
  """
157
157
  Discover all dependencies from all available sources.
158
158
 
@@ -175,7 +175,7 @@ class IPackageHelper(Protocol):
175
175
  """
176
176
  ...
177
177
 
178
- def get_imports_for_package(self, package_name: str) -> List[str]:
178
+ def get_imports_for_package(self, package_name: str) -> list[str]:
179
179
  """
180
180
  Get all possible import names for a package.
181
181
 
@@ -297,7 +297,7 @@ class IPackageHelper(Protocol):
297
297
  # Manifest Loading (from IManifestLoader)
298
298
  # ========================================================================
299
299
 
300
- def get_manifest_signature(self, package_name: str) -> Optional[Tuple[str, float, float]]:
300
+ def get_manifest_signature(self, package_name: str) -> Optional[tuple[str, float, float]]:
301
301
  """
302
302
  Get manifest file signature (path, mtime, size).
303
303
 
@@ -309,7 +309,7 @@ class IPackageHelper(Protocol):
309
309
  """
310
310
  ...
311
311
 
312
- def get_shared_dependencies(self, package_name: str, signature: Optional[Tuple[str, float, float]] = None) -> Dict[str, str]:
312
+ def get_shared_dependencies(self, package_name: str, signature: Optional[tuple[str, float, float]] = None) -> dict[str, str]:
313
313
  """
314
314
  Get shared dependencies from manifest.
315
315
 
@@ -322,7 +322,7 @@ class IPackageHelper(Protocol):
322
322
  """
323
323
  ...
324
324
 
325
- def get_watched_prefixes(self, package_name: str) -> Tuple[str, ...]:
325
+ def get_watched_prefixes(self, package_name: str) -> tuple[str, ...]:
326
326
  """
327
327
  Get watched prefixes from manifest.
328
328
 
@@ -353,7 +353,7 @@ class IPackageHelper(Protocol):
353
353
  """
354
354
  ...
355
355
 
356
- def get_import_names(self, package_name: str) -> List[str]:
356
+ def get_import_names(self, package_name: str) -> list[str]:
357
357
  """
358
358
  Get all import names for a package (from IDependencyMapper).
359
359
 
@@ -476,7 +476,7 @@ class IModuleHelper(Protocol):
476
476
  """
477
477
  ...
478
478
 
479
- def load(self, *module_names: str) -> List[ModuleType]:
479
+ def load(self, *module_names: str) -> list[ModuleType]:
480
480
  """
481
481
  Load one or more modules into memory.
482
482
 
@@ -509,7 +509,7 @@ class IModuleHelper(Protocol):
509
509
  # Module Installation (from IModuleInstaller)
510
510
  # ========================================================================
511
511
 
512
- def install_and_import(self, module_name: str, package_name: Optional[str] = None) -> Tuple[Optional[ModuleType], bool]:
512
+ def install_and_import(self, module_name: str, package_name: Optional[str] = None) -> tuple[Optional[ModuleType], bool]:
513
513
  """
514
514
  Install package and import module (from IModuleInstaller).
515
515
 
@@ -807,7 +807,7 @@ class IModuleHelper(Protocol):
807
807
  """
808
808
  ...
809
809
 
810
- def get_matching_prefixes(self, fullname: str) -> Tuple[str, ...]:
810
+ def get_matching_prefixes(self, fullname: str) -> tuple[str, ...]:
811
811
  """
812
812
  Get all watched prefixes that match a module name (from IWatchedRegistry).
813
813
 
@@ -945,7 +945,7 @@ class IRuntime(Protocol):
945
945
  """
946
946
  ...
947
947
 
948
- def predict_next_imports(self, current_module: str, count: int = 3) -> List[str]:
948
+ def predict_next_imports(self, current_module: str, count: int = 3) -> list[str]:
949
949
  """
950
950
  Predict next likely imports based on patterns (from IAdaptiveLearner).
951
951
 
@@ -995,7 +995,7 @@ class IRuntime(Protocol):
995
995
  """
996
996
  ...
997
997
 
998
- def get_optimal_mode(self, load_level: Any) -> Tuple[LazyLoadMode, LazyInstallMode]:
998
+ def get_optimal_mode(self, load_level: Any) -> tuple[LazyLoadMode, LazyInstallMode]:
999
999
  """
1000
1000
  Get optimal mode for a load level (from IIntelligentSelector).
1001
1001
 
@@ -1007,7 +1007,7 @@ class IRuntime(Protocol):
1007
1007
  """
1008
1008
  ...
1009
1009
 
1010
- def update_mode_map(self, mode_map: Dict[Any, Tuple[LazyLoadMode, LazyInstallMode]]) -> None:
1010
+ def update_mode_map(self, mode_map: dict[Any, tuple[LazyLoadMode, LazyInstallMode]]) -> None:
1011
1011
  """
1012
1012
  Update mode mapping with benchmark results (from IIntelligentSelector).
1013
1013
 
@@ -1031,7 +1031,7 @@ class IRuntime(Protocol):
1031
1031
  """
1032
1032
  ...
1033
1033
 
1034
- def get_metric_stats(self, name: str) -> Dict[str, Any]:
1034
+ def get_metric_stats(self, name: str) -> dict[str, Any]:
1035
1035
  """
1036
1036
  Get statistics for a metric (from IMetricsCollector).
1037
1037
 
@@ -1043,7 +1043,7 @@ class IRuntime(Protocol):
1043
1043
  """
1044
1044
  ...
1045
1045
 
1046
- def get_all_stats(self) -> Dict[str, Dict[str, Any]]:
1046
+ def get_all_stats(self) -> dict[str, dict[str, Any]]:
1047
1047
  """
1048
1048
  Get statistics for all metrics (from IMetricsCollector).
1049
1049
 
@@ -1079,7 +1079,7 @@ class IRuntime(Protocol):
1079
1079
  """
1080
1080
  ...
1081
1081
 
1082
- def get_performance_stats(self) -> Dict[str, Any]:
1082
+ def get_performance_stats(self) -> dict[str, Any]:
1083
1083
  """
1084
1084
  Get performance statistics (from IPerformanceMonitor).
1085
1085
 
@@ -1280,11 +1280,11 @@ class IPackageManagerStrategy(Protocol):
1280
1280
  """Uninstall a package."""
1281
1281
  ...
1282
1282
 
1283
- def discover_dependencies(self) -> Dict[str, str]:
1283
+ def discover_dependencies(self) -> dict[str, str]:
1284
1284
  """Discover dependencies."""
1285
1285
  ...
1286
1286
 
1287
- def check_security_policy(self, package_name: str) -> Tuple[bool, str]:
1287
+ def check_security_policy(self, package_name: str) -> tuple[bool, str]:
1288
1288
  """Check security policy."""
1289
1289
  ...
1290
1290
 
@@ -1299,7 +1299,7 @@ class IInstallExecutionStrategy(Protocol):
1299
1299
 
1300
1300
  Defines the mechanism for actually installing packages (pip, wheel, cached, async).
1301
1301
  """
1302
- def execute_install(self, package_name: str, policy_args: List[str]) -> Any:
1302
+ def execute_install(self, package_name: str, policy_args: list[str]) -> Any:
1303
1303
  """Execute installation of a package."""
1304
1304
  ...
1305
1305
 
@@ -1322,7 +1322,7 @@ class IInstallTimingStrategy(Protocol):
1322
1322
  """Determine if package should be uninstalled after use."""
1323
1323
  ...
1324
1324
 
1325
- def get_install_priority(self, packages: List[str]) -> List[str]:
1325
+ def get_install_priority(self, packages: list[str]) -> list[str]:
1326
1326
  """Get priority order for installing packages."""
1327
1327
  ...
1328
1328
 
@@ -1333,7 +1333,7 @@ class IDiscoveryStrategy(Protocol):
1333
1333
 
1334
1334
  Defines how to find dependencies (from files, manifest, auto-detect).
1335
1335
  """
1336
- def discover(self, project_root: Any) -> Dict[str, str]:
1336
+ def discover(self, project_root: Any) -> dict[str, str]:
1337
1337
  """Discover dependencies from sources."""
1338
1338
  ...
1339
1339
 
@@ -1348,11 +1348,11 @@ class IPolicyStrategy(Protocol):
1348
1348
 
1349
1349
  Defines security policies and what packages are allowed/denied.
1350
1350
  """
1351
- def is_allowed(self, package_name: str) -> Tuple[bool, str]:
1351
+ def is_allowed(self, package_name: str) -> tuple[bool, str]:
1352
1352
  """Check if package is allowed to be installed."""
1353
1353
  ...
1354
1354
 
1355
- def get_pip_args(self, package_name: str) -> List[str]:
1355
+ def get_pip_args(self, package_name: str) -> list[str]:
1356
1356
  """Get pip arguments based on policy."""
1357
1357
  ...
1358
1358
 
@@ -1367,10 +1367,143 @@ class IMappingStrategy(Protocol):
1367
1367
  """Map import name to package name."""
1368
1368
  ...
1369
1369
 
1370
- def map_package_to_imports(self, package_name: str) -> List[str]:
1370
+ def map_package_to_imports(self, package_name: str) -> list[str]:
1371
1371
  """Map package name to possible import names."""
1372
1372
  ...
1373
1373
 
1374
+ # =============================================================================
1375
+ # STRATEGY INTERFACES FOR RUNTIME SWAPPING (Enhanced)
1376
+ # =============================================================================
1377
+
1378
+ @runtime_checkable
1379
+ class IInstallStrategy(Protocol):
1380
+ """
1381
+ Installation strategy interface for swappable installation algorithms.
1382
+
1383
+ Enables runtime strategy swapping for different installation methods
1384
+ (pip, wheel, async, cached, etc.).
1385
+ """
1386
+ def install(self, package_name: str, version: Optional[str] = None) -> bool:
1387
+ """
1388
+ Install a package.
1389
+
1390
+ Args:
1391
+ package_name: Package name to install
1392
+ version: Optional version specification
1393
+
1394
+ Returns:
1395
+ True if installation successful, False otherwise
1396
+ """
1397
+ ...
1398
+
1399
+ def can_install(self, package_name: str) -> bool:
1400
+ """
1401
+ Check if this strategy can install a package.
1402
+
1403
+ Args:
1404
+ package_name: Package name to check
1405
+
1406
+ Returns:
1407
+ True if can install, False otherwise
1408
+ """
1409
+ ...
1410
+
1411
+ def uninstall(self, package_name: str) -> bool:
1412
+ """
1413
+ Uninstall a package.
1414
+
1415
+ Args:
1416
+ package_name: Package name to uninstall
1417
+
1418
+ Returns:
1419
+ True if uninstallation successful, False otherwise
1420
+ """
1421
+ ...
1422
+
1423
+ @runtime_checkable
1424
+ class ILoadStrategy(Protocol):
1425
+ """
1426
+ Module loading strategy interface for swappable loading algorithms.
1427
+
1428
+ Enables runtime strategy swapping for different loading methods
1429
+ (lazy, simple, advanced, etc.).
1430
+ """
1431
+ def load(self, module_name: str) -> ModuleType:
1432
+ """
1433
+ Load a module.
1434
+
1435
+ Args:
1436
+ module_name: Module name to load
1437
+
1438
+ Returns:
1439
+ Loaded module
1440
+ """
1441
+ ...
1442
+
1443
+ def should_lazy_load(self, module_name: str) -> bool:
1444
+ """
1445
+ Determine if module should be lazy loaded.
1446
+
1447
+ Args:
1448
+ module_name: Module name to check
1449
+
1450
+ Returns:
1451
+ True if should lazy load, False otherwise
1452
+ """
1453
+ ...
1454
+
1455
+ def unload(self, module_name: str) -> None:
1456
+ """
1457
+ Unload a module.
1458
+
1459
+ Args:
1460
+ module_name: Module name to unload
1461
+ """
1462
+ ...
1463
+
1464
+ @runtime_checkable
1465
+ class ICacheStrategy(Protocol):
1466
+ """
1467
+ Caching strategy interface for swappable caching algorithms.
1468
+
1469
+ Enables runtime strategy swapping for different caching methods
1470
+ (LRU, LFU, TTL, multi-tier, etc.).
1471
+ """
1472
+ def get(self, key: str) -> Optional[Any]:
1473
+ """
1474
+ Get value from cache.
1475
+
1476
+ Args:
1477
+ key: Cache key
1478
+
1479
+ Returns:
1480
+ Cached value or None if not found
1481
+ """
1482
+ ...
1483
+
1484
+ def put(self, key: str, value: Any) -> None:
1485
+ """
1486
+ Put value in cache.
1487
+
1488
+ Args:
1489
+ key: Cache key
1490
+ value: Value to cache
1491
+ """
1492
+ ...
1493
+
1494
+ def invalidate(self, key: str) -> None:
1495
+ """
1496
+ Invalidate cached value.
1497
+
1498
+ Args:
1499
+ key: Cache key to invalidate
1500
+ """
1501
+ ...
1502
+
1503
+ def clear(self) -> None:
1504
+ """Clear all cached values."""
1505
+ ...
1506
+
1374
1507
  # =============================================================================
1375
1508
  # EXPORT ALL
1376
1509
  # =============================================================================
@@ -1392,5 +1525,9 @@ __all__ = [
1392
1525
  'IDiscoveryStrategy',
1393
1526
  'IPolicyStrategy',
1394
1527
  'IMappingStrategy',
1528
+ # Enhanced Strategy Interfaces for Runtime Swapping
1529
+ 'IInstallStrategy',
1530
+ 'ILoadStrategy',
1531
+ 'ICacheStrategy',
1395
1532
  ]
1396
1533
 
exonware/xwlazy/defs.py CHANGED
@@ -13,7 +13,7 @@ for the lazy loading system following GUIDE_ARCH.md structure.
13
13
  """
14
14
 
15
15
  from enum import Enum
16
- from typing import TypedDict, Dict, List, Optional, Any, Tuple
16
+ from typing import TypedDict, Optional, Any
17
17
  from dataclasses import dataclass, field
18
18
  from types import ModuleType
19
19
 
@@ -95,7 +95,7 @@ class LazyModeConfig:
95
95
  # Additional configuration options
96
96
  auto_uninstall_large: bool = False # For AUTO_MODE behavior
97
97
  large_package_threshold_mb: float = 50.0 # Size threshold for SIZE_AWARE mode
98
- preload_priority: List[str] = field(default_factory=list) # Priority modules for PRELOAD
98
+ preload_priority: list[str] = field(default_factory=list) # Priority modules for PRELOAD
99
99
  background_workers: int = 2 # Workers for BACKGROUND mode
100
100
 
101
101
  def __post_init__(self):
@@ -118,7 +118,7 @@ class InstallResult:
118
118
  @dataclass
119
119
  class LazyConfig:
120
120
  """Bridge configuration settings with the lazy package implementation."""
121
- packages: Tuple[str, ...] = field(
121
+ packages: tuple[str, ...] = field(
122
122
  default_factory=lambda: ("default",)
123
123
  )
124
124
 
@@ -129,12 +129,12 @@ class LazyConfig:
129
129
  class PackageManifest:
130
130
  """Resolved manifest data for a single package."""
131
131
  package: str
132
- dependencies: Dict[str, str] = field(default_factory=dict)
133
- watched_prefixes: Tuple[str, ...] = ()
132
+ dependencies: dict[str, str] = field(default_factory=dict)
133
+ watched_prefixes: tuple[str, ...] = ()
134
134
  async_installs: bool = False
135
135
  async_workers: int = 1
136
- class_wrap_prefixes: Tuple[str, ...] = ()
137
- metadata: Dict[str, Any] = field(default_factory=dict)
136
+ class_wrap_prefixes: tuple[str, ...] = ()
137
+ metadata: dict[str, Any] = field(default_factory=dict)
138
138
 
139
139
  def get_dependency(self, import_name: str) -> Optional[str]:
140
140
  """Return the declared package for the given import name."""
@@ -160,7 +160,7 @@ class PackageData:
160
160
  access_count: int = 0
161
161
  install_mode: Optional['LazyInstallMode'] = None
162
162
  error: Optional[Exception] = None
163
- metadata: Dict[str, Any] = field(default_factory=dict)
163
+ metadata: dict[str, Any] = field(default_factory=dict)
164
164
 
165
165
  @dataclass(frozen=True)
166
166
  class ModuleData:
@@ -175,7 +175,7 @@ class ModuleData:
175
175
  load_time: Optional[float] = None
176
176
  access_count: int = 0
177
177
  error: Optional[Exception] = None
178
- metadata: Dict[str, Any] = field(default_factory=dict)
178
+ metadata: dict[str, Any] = field(default_factory=dict)
179
179
 
180
180
  # =============================================================================
181
181
  # TYPE DEFINITIONS
@@ -194,8 +194,8 @@ class PackageStats(TypedDict, total=False):
194
194
  enabled: bool
195
195
  mode: str
196
196
  package_name: str
197
- installed_packages: List[str]
198
- failed_packages: List[str]
197
+ installed_packages: list[str]
198
+ failed_packages: list[str]
199
199
  total_installed: int
200
200
  total_failed: int
201
201
 
@@ -214,10 +214,10 @@ class LazyStatus(TypedDict, total=False):
214
214
  # Default configuration values
215
215
  DEFAULT_LARGE_PACKAGE_THRESHOLD_MB: float = 50.0
216
216
  DEFAULT_BACKGROUND_WORKERS: int = 2
217
- DEFAULT_PRELOAD_PRIORITY: List[str] = []
217
+ DEFAULT_PRELOAD_PRIORITY: list[str] = []
218
218
 
219
219
  # Common import -> package mappings (will be populated from discovery)
220
- COMMON_IMPORT_MAPPINGS: Dict[str, str] = {
220
+ COMMON_IMPORT_MAPPINGS: dict[str, str] = {
221
221
  # Common mappings that are frequently used
222
222
  'cv2': 'opencv-python',
223
223
  'PIL': 'Pillow',
@@ -262,7 +262,7 @@ DISCOVERY_SOURCE_PIPFILE = "Pipfile"
262
262
  DISCOVERY_SOURCE_MANIFEST = "manifest.json"
263
263
 
264
264
  # Installation mode aliases
265
- INSTALL_MODE_ALIASES: Dict[str, str] = {
265
+ INSTALL_MODE_ALIASES: dict[str, str] = {
266
266
  'auto': 'smart',
267
267
  'on_demand': 'smart',
268
268
  'on-demand': 'smart',
@@ -287,7 +287,7 @@ PIPFILE_PATTERN = "Pipfile"
287
287
  # =============================================================================
288
288
 
289
289
  # Preset mode combinations for convenience
290
- PRESET_MODES: Dict[str, LazyModeConfig] = {
290
+ PRESET_MODES: dict[str, LazyModeConfig] = {
291
291
  "none": LazyModeConfig(
292
292
  load_mode=LazyLoadMode.NONE,
293
293
  install_mode=LazyInstallMode.NONE