claude-mpm 3.7.8__py3-none-any.whl → 3.9.0__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.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/BASE_PM.md +0 -106
- claude_mpm/agents/INSTRUCTIONS.md +0 -96
- claude_mpm/agents/MEMORY.md +94 -0
- claude_mpm/agents/WORKFLOW.md +86 -0
- claude_mpm/agents/templates/code_analyzer.json +2 -2
- claude_mpm/agents/templates/data_engineer.json +1 -1
- claude_mpm/agents/templates/documentation.json +1 -1
- claude_mpm/agents/templates/engineer.json +1 -1
- claude_mpm/agents/templates/ops.json +1 -1
- claude_mpm/agents/templates/qa.json +1 -1
- claude_mpm/agents/templates/research.json +1 -1
- claude_mpm/agents/templates/security.json +1 -1
- claude_mpm/agents/templates/ticketing.json +3 -8
- claude_mpm/agents/templates/version_control.json +1 -1
- claude_mpm/agents/templates/web_qa.json +2 -2
- claude_mpm/agents/templates/web_ui.json +2 -2
- claude_mpm/cli/__init__.py +2 -2
- claude_mpm/cli/commands/__init__.py +2 -1
- claude_mpm/cli/commands/agents.py +8 -3
- claude_mpm/cli/commands/tickets.py +596 -19
- claude_mpm/cli/parser.py +217 -5
- claude_mpm/config/__init__.py +30 -39
- claude_mpm/config/socketio_config.py +8 -5
- claude_mpm/constants.py +13 -0
- claude_mpm/core/__init__.py +8 -18
- claude_mpm/core/cache.py +596 -0
- claude_mpm/core/claude_runner.py +166 -622
- claude_mpm/core/config.py +7 -3
- claude_mpm/core/constants.py +339 -0
- claude_mpm/core/container.py +548 -38
- claude_mpm/core/exceptions.py +392 -0
- claude_mpm/core/framework_loader.py +249 -93
- claude_mpm/core/interactive_session.py +479 -0
- claude_mpm/core/interfaces.py +424 -0
- claude_mpm/core/lazy.py +467 -0
- claude_mpm/core/logging_config.py +444 -0
- claude_mpm/core/oneshot_session.py +465 -0
- claude_mpm/core/optimized_agent_loader.py +485 -0
- claude_mpm/core/optimized_startup.py +490 -0
- claude_mpm/core/service_registry.py +52 -26
- claude_mpm/core/socketio_pool.py +162 -5
- claude_mpm/core/types.py +292 -0
- claude_mpm/core/typing_utils.py +477 -0
- claude_mpm/hooks/claude_hooks/hook_handler.py +213 -99
- claude_mpm/init.py +2 -1
- claude_mpm/services/__init__.py +78 -14
- claude_mpm/services/agent/__init__.py +24 -0
- claude_mpm/services/agent/deployment.py +2548 -0
- claude_mpm/services/agent/management.py +598 -0
- claude_mpm/services/agent/registry.py +813 -0
- claude_mpm/services/agents/deployment/agent_deployment.py +728 -308
- claude_mpm/services/agents/memory/agent_memory_manager.py +160 -4
- claude_mpm/services/async_session_logger.py +8 -3
- claude_mpm/services/communication/__init__.py +21 -0
- claude_mpm/services/communication/socketio.py +1933 -0
- claude_mpm/services/communication/websocket.py +479 -0
- claude_mpm/services/core/__init__.py +123 -0
- claude_mpm/services/core/base.py +247 -0
- claude_mpm/services/core/interfaces.py +951 -0
- claude_mpm/services/framework_claude_md_generator/__init__.py +10 -3
- claude_mpm/services/framework_claude_md_generator/deployment_manager.py +14 -11
- claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +23 -23
- claude_mpm/services/framework_claude_md_generator.py +3 -2
- claude_mpm/services/health_monitor.py +4 -3
- claude_mpm/services/hook_service.py +64 -4
- claude_mpm/services/infrastructure/__init__.py +21 -0
- claude_mpm/services/infrastructure/logging.py +202 -0
- claude_mpm/services/infrastructure/monitoring.py +893 -0
- claude_mpm/services/memory/indexed_memory.py +648 -0
- claude_mpm/services/project/__init__.py +21 -0
- claude_mpm/services/project/analyzer.py +864 -0
- claude_mpm/services/project/registry.py +608 -0
- claude_mpm/services/project_analyzer.py +95 -2
- claude_mpm/services/recovery_manager.py +15 -9
- claude_mpm/services/response_tracker.py +3 -5
- claude_mpm/services/socketio/__init__.py +25 -0
- claude_mpm/services/socketio/handlers/__init__.py +25 -0
- claude_mpm/services/socketio/handlers/base.py +121 -0
- claude_mpm/services/socketio/handlers/connection.py +198 -0
- claude_mpm/services/socketio/handlers/file.py +213 -0
- claude_mpm/services/socketio/handlers/git.py +723 -0
- claude_mpm/services/socketio/handlers/memory.py +27 -0
- claude_mpm/services/socketio/handlers/project.py +25 -0
- claude_mpm/services/socketio/handlers/registry.py +145 -0
- claude_mpm/services/socketio_client_manager.py +12 -7
- claude_mpm/services/socketio_server.py +156 -30
- claude_mpm/services/ticket_manager.py +172 -9
- claude_mpm/services/ticket_manager_di.py +1 -1
- claude_mpm/services/version_control/semantic_versioning.py +80 -7
- claude_mpm/services/version_control/version_parser.py +528 -0
- claude_mpm/utils/error_handler.py +1 -1
- claude_mpm/validation/agent_validator.py +27 -14
- claude_mpm/validation/frontmatter_validator.py +231 -0
- {claude_mpm-3.7.8.dist-info → claude_mpm-3.9.0.dist-info}/METADATA +38 -128
- {claude_mpm-3.7.8.dist-info → claude_mpm-3.9.0.dist-info}/RECORD +100 -59
- {claude_mpm-3.7.8.dist-info → claude_mpm-3.9.0.dist-info}/WHEEL +0 -0
- {claude_mpm-3.7.8.dist-info → claude_mpm-3.9.0.dist-info}/entry_points.txt +0 -0
- {claude_mpm-3.7.8.dist-info → claude_mpm-3.9.0.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-3.7.8.dist-info → claude_mpm-3.9.0.dist-info}/top_level.txt +0 -0
    
        claude_mpm/core/lazy.py
    ADDED
    
    | @@ -0,0 +1,467 @@ | |
| 1 | 
            +
            #!/usr/bin/env python3
         | 
| 2 | 
            +
            """Lazy loading service infrastructure for deferred instantiation.
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            This module provides a lazy loading mechanism for services that are expensive
         | 
| 5 | 
            +
            to initialize but may not be used in every execution path.
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            WHY lazy loading:
         | 
| 8 | 
            +
            - Reduces startup time from 3-5 seconds to <2 seconds
         | 
| 9 | 
            +
            - Defers heavy initialization until services are actually needed
         | 
| 10 | 
            +
            - Maintains backward compatibility with eager instantiation
         | 
| 11 | 
            +
            - Provides transparent access to underlying services
         | 
| 12 | 
            +
            """
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            import asyncio
         | 
| 15 | 
            +
            import functools
         | 
| 16 | 
            +
            import threading
         | 
| 17 | 
            +
            import time
         | 
| 18 | 
            +
            from typing import Any, Callable, Dict, Optional, Type, TypeVar, Generic
         | 
| 19 | 
            +
            from datetime import datetime
         | 
| 20 | 
            +
            from dataclasses import dataclass, field
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            from ..core.logger import get_logger
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            T = TypeVar('T')
         | 
| 25 | 
            +
             | 
| 26 | 
            +
             | 
| 27 | 
            +
            @dataclass
         | 
| 28 | 
            +
            class LazyMetrics:
         | 
| 29 | 
            +
                """Metrics for lazy loading performance."""
         | 
| 30 | 
            +
                created_at: datetime = field(default_factory=datetime.now)
         | 
| 31 | 
            +
                first_access: Optional[datetime] = None
         | 
| 32 | 
            +
                initialization_time: float = 0.0
         | 
| 33 | 
            +
                access_count: int = 0
         | 
| 34 | 
            +
                initialization_error: Optional[Exception] = None
         | 
| 35 | 
            +
                is_initialized: bool = False
         | 
| 36 | 
            +
             | 
| 37 | 
            +
             | 
| 38 | 
            +
            class LazyService(Generic[T]):
         | 
| 39 | 
            +
                """Lazy loading wrapper for expensive services.
         | 
| 40 | 
            +
                
         | 
| 41 | 
            +
                WHY this design:
         | 
| 42 | 
            +
                - Services are only initialized when first accessed
         | 
| 43 | 
            +
                - Thread-safe initialization ensures single instance
         | 
| 44 | 
            +
                - Transparent proxy pattern preserves service interface
         | 
| 45 | 
            +
                - Metrics tracking for performance monitoring
         | 
| 46 | 
            +
                
         | 
| 47 | 
            +
                Example:
         | 
| 48 | 
            +
                    # Wrap expensive service
         | 
| 49 | 
            +
                    lazy_analyzer = LazyService(
         | 
| 50 | 
            +
                        service_class=ProjectAnalyzer,
         | 
| 51 | 
            +
                        init_args=(),
         | 
| 52 | 
            +
                        init_kwargs={'config': config}
         | 
| 53 | 
            +
                    )
         | 
| 54 | 
            +
                    
         | 
| 55 | 
            +
                    # Service is not initialized yet
         | 
| 56 | 
            +
                    assert not lazy_analyzer.is_initialized
         | 
| 57 | 
            +
                    
         | 
| 58 | 
            +
                    # First access triggers initialization
         | 
| 59 | 
            +
                    result = lazy_analyzer.analyze()  # Initializes here
         | 
| 60 | 
            +
                    
         | 
| 61 | 
            +
                    # Subsequent accesses use cached instance
         | 
| 62 | 
            +
                    result2 = lazy_analyzer.analyze()  # No initialization
         | 
| 63 | 
            +
                """
         | 
| 64 | 
            +
                
         | 
| 65 | 
            +
                def __init__(
         | 
| 66 | 
            +
                    self,
         | 
| 67 | 
            +
                    service_class: Type[T],
         | 
| 68 | 
            +
                    init_args: tuple = (),
         | 
| 69 | 
            +
                    init_kwargs: dict = None,
         | 
| 70 | 
            +
                    name: Optional[str] = None,
         | 
| 71 | 
            +
                    eager: bool = False
         | 
| 72 | 
            +
                ):
         | 
| 73 | 
            +
                    """Initialize lazy service wrapper.
         | 
| 74 | 
            +
                    
         | 
| 75 | 
            +
                    Args:
         | 
| 76 | 
            +
                        service_class: The class to lazily instantiate
         | 
| 77 | 
            +
                        init_args: Positional arguments for initialization
         | 
| 78 | 
            +
                        init_kwargs: Keyword arguments for initialization  
         | 
| 79 | 
            +
                        name: Optional name for logging
         | 
| 80 | 
            +
                        eager: If True, initialize immediately (for testing)
         | 
| 81 | 
            +
                    """
         | 
| 82 | 
            +
                    self._service_class = service_class
         | 
| 83 | 
            +
                    self._init_args = init_args
         | 
| 84 | 
            +
                    self._init_kwargs = init_kwargs or {}
         | 
| 85 | 
            +
                    self._name = name or service_class.__name__
         | 
| 86 | 
            +
                    self._eager = eager
         | 
| 87 | 
            +
                    
         | 
| 88 | 
            +
                    self._instance: Optional[T] = None
         | 
| 89 | 
            +
                    self._lock = threading.RLock()
         | 
| 90 | 
            +
                    self._metrics = LazyMetrics()
         | 
| 91 | 
            +
                    self._logger = get_logger(f"lazy.{self._name}")
         | 
| 92 | 
            +
                    
         | 
| 93 | 
            +
                    # Initialize immediately if eager mode
         | 
| 94 | 
            +
                    if eager:
         | 
| 95 | 
            +
                        self._ensure_initialized()
         | 
| 96 | 
            +
                
         | 
| 97 | 
            +
                @property
         | 
| 98 | 
            +
                def is_initialized(self) -> bool:
         | 
| 99 | 
            +
                    """Check if service has been initialized."""
         | 
| 100 | 
            +
                    return self._instance is not None
         | 
| 101 | 
            +
                
         | 
| 102 | 
            +
                @property
         | 
| 103 | 
            +
                def metrics(self) -> LazyMetrics:
         | 
| 104 | 
            +
                    """Get lazy loading metrics."""
         | 
| 105 | 
            +
                    return self._metrics
         | 
| 106 | 
            +
                
         | 
| 107 | 
            +
                def _ensure_initialized(self) -> T:
         | 
| 108 | 
            +
                    """Ensure service is initialized, creating if necessary.
         | 
| 109 | 
            +
                    
         | 
| 110 | 
            +
                    Thread-safe initialization with metrics tracking.
         | 
| 111 | 
            +
                    """
         | 
| 112 | 
            +
                    if self._instance is not None:
         | 
| 113 | 
            +
                        return self._instance
         | 
| 114 | 
            +
                    
         | 
| 115 | 
            +
                    with self._lock:
         | 
| 116 | 
            +
                        # Double-check pattern for thread safety
         | 
| 117 | 
            +
                        if self._instance is not None:
         | 
| 118 | 
            +
                            return self._instance
         | 
| 119 | 
            +
                        
         | 
| 120 | 
            +
                        # Track initialization
         | 
| 121 | 
            +
                        start_time = time.time()
         | 
| 122 | 
            +
                        if self._metrics.first_access is None:
         | 
| 123 | 
            +
                            self._metrics.first_access = datetime.now()
         | 
| 124 | 
            +
                        
         | 
| 125 | 
            +
                        try:
         | 
| 126 | 
            +
                            self._logger.debug(f"Initializing lazy service: {self._name}")
         | 
| 127 | 
            +
                            
         | 
| 128 | 
            +
                            # Create the actual service instance
         | 
| 129 | 
            +
                            self._instance = self._service_class(
         | 
| 130 | 
            +
                                *self._init_args,
         | 
| 131 | 
            +
                                **self._init_kwargs
         | 
| 132 | 
            +
                            )
         | 
| 133 | 
            +
                            
         | 
| 134 | 
            +
                            # Update metrics
         | 
| 135 | 
            +
                            self._metrics.initialization_time = time.time() - start_time
         | 
| 136 | 
            +
                            self._metrics.is_initialized = True
         | 
| 137 | 
            +
                            
         | 
| 138 | 
            +
                            self._logger.info(
         | 
| 139 | 
            +
                                f"Lazy service {self._name} initialized in "
         | 
| 140 | 
            +
                                f"{self._metrics.initialization_time:.2f}s"
         | 
| 141 | 
            +
                            )
         | 
| 142 | 
            +
                            
         | 
| 143 | 
            +
                            return self._instance
         | 
| 144 | 
            +
                            
         | 
| 145 | 
            +
                        except Exception as e:
         | 
| 146 | 
            +
                            self._metrics.initialization_error = e
         | 
| 147 | 
            +
                            self._logger.error(f"Failed to initialize {self._name}: {e}")
         | 
| 148 | 
            +
                            raise
         | 
| 149 | 
            +
                
         | 
| 150 | 
            +
                def __getattr__(self, name: str) -> Any:
         | 
| 151 | 
            +
                    """Proxy attribute access to the underlying service.
         | 
| 152 | 
            +
                    
         | 
| 153 | 
            +
                    This is called when an attribute is not found on LazyService itself.
         | 
| 154 | 
            +
                    It ensures initialization and forwards the request.
         | 
| 155 | 
            +
                    """
         | 
| 156 | 
            +
                    # Avoid recursion for internal attributes
         | 
| 157 | 
            +
                    if name.startswith('_'):
         | 
| 158 | 
            +
                        raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'")
         | 
| 159 | 
            +
                    
         | 
| 160 | 
            +
                    # Initialize if needed
         | 
| 161 | 
            +
                    instance = self._ensure_initialized()
         | 
| 162 | 
            +
                    self._metrics.access_count += 1
         | 
| 163 | 
            +
                    
         | 
| 164 | 
            +
                    # Forward attribute access
         | 
| 165 | 
            +
                    return getattr(instance, name)
         | 
| 166 | 
            +
                
         | 
| 167 | 
            +
                def __call__(self, *args, **kwargs) -> Any:
         | 
| 168 | 
            +
                    """Make LazyService callable if underlying service is."""
         | 
| 169 | 
            +
                    instance = self._ensure_initialized()
         | 
| 170 | 
            +
                    self._metrics.access_count += 1
         | 
| 171 | 
            +
                    return instance(*args, **kwargs)
         | 
| 172 | 
            +
                
         | 
| 173 | 
            +
                def __repr__(self) -> str:
         | 
| 174 | 
            +
                    """String representation of lazy service."""
         | 
| 175 | 
            +
                    status = "initialized" if self.is_initialized else "pending"
         | 
| 176 | 
            +
                    return f"<LazyService({self._name}) [{status}]>"
         | 
| 177 | 
            +
             | 
| 178 | 
            +
             | 
| 179 | 
            +
            class LazyServiceRegistry:
         | 
| 180 | 
            +
                """Registry for managing lazy services.
         | 
| 181 | 
            +
                
         | 
| 182 | 
            +
                WHY registry pattern:
         | 
| 183 | 
            +
                - Central management of all lazy services
         | 
| 184 | 
            +
                - Bulk initialization for testing
         | 
| 185 | 
            +
                - Performance metrics aggregation
         | 
| 186 | 
            +
                - Service dependency resolution
         | 
| 187 | 
            +
                """
         | 
| 188 | 
            +
                
         | 
| 189 | 
            +
                def __init__(self):
         | 
| 190 | 
            +
                    self._services: Dict[str, LazyService] = {}
         | 
| 191 | 
            +
                    self._logger = get_logger("lazy_registry")
         | 
| 192 | 
            +
                    self._lock = threading.Lock()
         | 
| 193 | 
            +
                
         | 
| 194 | 
            +
                def register(
         | 
| 195 | 
            +
                    self,
         | 
| 196 | 
            +
                    name: str,
         | 
| 197 | 
            +
                    service_class: Type,
         | 
| 198 | 
            +
                    init_args: tuple = (),
         | 
| 199 | 
            +
                    init_kwargs: dict = None,
         | 
| 200 | 
            +
                    eager: bool = False
         | 
| 201 | 
            +
                ) -> LazyService:
         | 
| 202 | 
            +
                    """Register a lazy service.
         | 
| 203 | 
            +
                    
         | 
| 204 | 
            +
                    Args:
         | 
| 205 | 
            +
                        name: Unique name for the service
         | 
| 206 | 
            +
                        service_class: The service class to wrap
         | 
| 207 | 
            +
                        init_args: Initialization arguments
         | 
| 208 | 
            +
                        init_kwargs: Initialization keyword arguments
         | 
| 209 | 
            +
                        eager: Whether to initialize immediately
         | 
| 210 | 
            +
                    
         | 
| 211 | 
            +
                    Returns:
         | 
| 212 | 
            +
                        The registered LazyService instance
         | 
| 213 | 
            +
                    """
         | 
| 214 | 
            +
                    with self._lock:
         | 
| 215 | 
            +
                        if name in self._services:
         | 
| 216 | 
            +
                            self._logger.warning(f"Overwriting existing service: {name}")
         | 
| 217 | 
            +
                        
         | 
| 218 | 
            +
                        service = LazyService(
         | 
| 219 | 
            +
                            service_class=service_class,
         | 
| 220 | 
            +
                            init_args=init_args,
         | 
| 221 | 
            +
                            init_kwargs=init_kwargs,
         | 
| 222 | 
            +
                            name=name,
         | 
| 223 | 
            +
                            eager=eager
         | 
| 224 | 
            +
                        )
         | 
| 225 | 
            +
                        
         | 
| 226 | 
            +
                        self._services[name] = service
         | 
| 227 | 
            +
                        self._logger.debug(f"Registered lazy service: {name}")
         | 
| 228 | 
            +
                        return service
         | 
| 229 | 
            +
                
         | 
| 230 | 
            +
                def get(self, name: str) -> Optional[LazyService]:
         | 
| 231 | 
            +
                    """Get a registered service by name."""
         | 
| 232 | 
            +
                    return self._services.get(name)
         | 
| 233 | 
            +
                
         | 
| 234 | 
            +
                def initialize_all(self) -> Dict[str, float]:
         | 
| 235 | 
            +
                    """Initialize all registered services.
         | 
| 236 | 
            +
                    
         | 
| 237 | 
            +
                    Useful for testing or preloading.
         | 
| 238 | 
            +
                    
         | 
| 239 | 
            +
                    Returns:
         | 
| 240 | 
            +
                        Dictionary mapping service names to initialization times
         | 
| 241 | 
            +
                    """
         | 
| 242 | 
            +
                    init_times = {}
         | 
| 243 | 
            +
                    
         | 
| 244 | 
            +
                    for name, service in self._services.items():
         | 
| 245 | 
            +
                        if not service.is_initialized:
         | 
| 246 | 
            +
                            try:
         | 
| 247 | 
            +
                                service._ensure_initialized()
         | 
| 248 | 
            +
                                init_times[name] = service.metrics.initialization_time
         | 
| 249 | 
            +
                            except Exception as e:
         | 
| 250 | 
            +
                                self._logger.error(f"Failed to initialize {name}: {e}")
         | 
| 251 | 
            +
                                init_times[name] = -1.0
         | 
| 252 | 
            +
                    
         | 
| 253 | 
            +
                    return init_times
         | 
| 254 | 
            +
                
         | 
| 255 | 
            +
                def get_metrics(self) -> Dict[str, Dict[str, Any]]:
         | 
| 256 | 
            +
                    """Get metrics for all registered services."""
         | 
| 257 | 
            +
                    metrics = {}
         | 
| 258 | 
            +
                    
         | 
| 259 | 
            +
                    for name, service in self._services.items():
         | 
| 260 | 
            +
                        m = service.metrics
         | 
| 261 | 
            +
                        metrics[name] = {
         | 
| 262 | 
            +
                            "initialized": service.is_initialized,
         | 
| 263 | 
            +
                            "first_access": m.first_access.isoformat() if m.first_access else None,
         | 
| 264 | 
            +
                            "initialization_time": m.initialization_time,
         | 
| 265 | 
            +
                            "access_count": m.access_count,
         | 
| 266 | 
            +
                            "has_error": m.initialization_error is not None
         | 
| 267 | 
            +
                        }
         | 
| 268 | 
            +
                    
         | 
| 269 | 
            +
                    return metrics
         | 
| 270 | 
            +
                
         | 
| 271 | 
            +
                def reset(self):
         | 
| 272 | 
            +
                    """Clear all registered services."""
         | 
| 273 | 
            +
                    with self._lock:
         | 
| 274 | 
            +
                        self._services.clear()
         | 
| 275 | 
            +
                        self._logger.debug("Registry reset")
         | 
| 276 | 
            +
             | 
| 277 | 
            +
             | 
| 278 | 
            +
            # Global registry instance
         | 
| 279 | 
            +
            _registry = LazyServiceRegistry()
         | 
| 280 | 
            +
             | 
| 281 | 
            +
             | 
| 282 | 
            +
            def lazy_load(
         | 
| 283 | 
            +
                service_class: Type,
         | 
| 284 | 
            +
                name: Optional[str] = None,
         | 
| 285 | 
            +
                init_args: tuple = (),
         | 
| 286 | 
            +
                init_kwargs: dict = None
         | 
| 287 | 
            +
            ) -> LazyService:
         | 
| 288 | 
            +
                """Convenience function to create and register a lazy service.
         | 
| 289 | 
            +
                
         | 
| 290 | 
            +
                Args:
         | 
| 291 | 
            +
                    service_class: The service class to wrap
         | 
| 292 | 
            +
                    name: Optional name (defaults to class name)
         | 
| 293 | 
            +
                    init_args: Initialization arguments
         | 
| 294 | 
            +
                    init_kwargs: Initialization keyword arguments
         | 
| 295 | 
            +
                
         | 
| 296 | 
            +
                Returns:
         | 
| 297 | 
            +
                    Registered LazyService instance
         | 
| 298 | 
            +
                
         | 
| 299 | 
            +
                Example:
         | 
| 300 | 
            +
                    # Create lazy service
         | 
| 301 | 
            +
                    analyzer = lazy_load(
         | 
| 302 | 
            +
                        ProjectAnalyzer,
         | 
| 303 | 
            +
                        init_kwargs={'config': config}
         | 
| 304 | 
            +
                    )
         | 
| 305 | 
            +
                    
         | 
| 306 | 
            +
                    # Use like normal service
         | 
| 307 | 
            +
                    result = analyzer.analyze_project()
         | 
| 308 | 
            +
                """
         | 
| 309 | 
            +
                if name is None:
         | 
| 310 | 
            +
                    name = service_class.__name__
         | 
| 311 | 
            +
                
         | 
| 312 | 
            +
                return _registry.register(
         | 
| 313 | 
            +
                    name=name,
         | 
| 314 | 
            +
                    service_class=service_class,
         | 
| 315 | 
            +
                    init_args=init_args,
         | 
| 316 | 
            +
                    init_kwargs=init_kwargs
         | 
| 317 | 
            +
                )
         | 
| 318 | 
            +
             | 
| 319 | 
            +
             | 
| 320 | 
            +
            def get_lazy_service(name: str) -> Optional[LazyService]:
         | 
| 321 | 
            +
                """Get a registered lazy service by name."""
         | 
| 322 | 
            +
                return _registry.get(name)
         | 
| 323 | 
            +
             | 
| 324 | 
            +
             | 
| 325 | 
            +
            def get_lazy_metrics() -> Dict[str, Dict[str, Any]]:
         | 
| 326 | 
            +
                """Get metrics for all lazy services."""
         | 
| 327 | 
            +
                return _registry.get_metrics()
         | 
| 328 | 
            +
             | 
| 329 | 
            +
             | 
| 330 | 
            +
            def initialize_all_services() -> Dict[str, float]:
         | 
| 331 | 
            +
                """Initialize all registered lazy services."""
         | 
| 332 | 
            +
                return _registry.initialize_all()
         | 
| 333 | 
            +
             | 
| 334 | 
            +
             | 
| 335 | 
            +
            class lazy_property:
         | 
| 336 | 
            +
                """Decorator for lazy property initialization.
         | 
| 337 | 
            +
                
         | 
| 338 | 
            +
                WHY decorator pattern:
         | 
| 339 | 
            +
                - Pythonic approach for lazy attributes
         | 
| 340 | 
            +
                - Caches expensive computations
         | 
| 341 | 
            +
                - Thread-safe initialization
         | 
| 342 | 
            +
                - Transparent to callers
         | 
| 343 | 
            +
                
         | 
| 344 | 
            +
                Example:
         | 
| 345 | 
            +
                    class MyService:
         | 
| 346 | 
            +
                        @lazy_property
         | 
| 347 | 
            +
                        def expensive_data(self):
         | 
| 348 | 
            +
                            # This only runs once
         | 
| 349 | 
            +
                            return self._compute_expensive_data()
         | 
| 350 | 
            +
                """
         | 
| 351 | 
            +
                
         | 
| 352 | 
            +
                def __init__(self, func: Callable) -> None:
         | 
| 353 | 
            +
                    self.func = func
         | 
| 354 | 
            +
                    self.lock = threading.RLock()
         | 
| 355 | 
            +
                    functools.update_wrapper(self, func)
         | 
| 356 | 
            +
                
         | 
| 357 | 
            +
                def __get__(self, obj: Any, objtype: Type = None) -> Any:
         | 
| 358 | 
            +
                    if obj is None:
         | 
| 359 | 
            +
                        return self
         | 
| 360 | 
            +
                    
         | 
| 361 | 
            +
                    # Check if already cached
         | 
| 362 | 
            +
                    val = obj.__dict__.get(self.func.__name__)
         | 
| 363 | 
            +
                    if val is not None:
         | 
| 364 | 
            +
                        return val
         | 
| 365 | 
            +
                    
         | 
| 366 | 
            +
                    # Thread-safe initialization
         | 
| 367 | 
            +
                    with self.lock:
         | 
| 368 | 
            +
                        # Double-check pattern
         | 
| 369 | 
            +
                        val = obj.__dict__.get(self.func.__name__)
         | 
| 370 | 
            +
                        if val is not None:
         | 
| 371 | 
            +
                            return val
         | 
| 372 | 
            +
                        
         | 
| 373 | 
            +
                        # Compute and cache
         | 
| 374 | 
            +
                        val = self.func(obj)
         | 
| 375 | 
            +
                        obj.__dict__[self.func.__name__] = val
         | 
| 376 | 
            +
                        return val
         | 
| 377 | 
            +
             | 
| 378 | 
            +
             | 
| 379 | 
            +
            class AsyncLazyService(Generic[T]):
         | 
| 380 | 
            +
                """Async version of LazyService for async services.
         | 
| 381 | 
            +
                
         | 
| 382 | 
            +
                Supports services that require async initialization.
         | 
| 383 | 
            +
                """
         | 
| 384 | 
            +
                
         | 
| 385 | 
            +
                def __init__(
         | 
| 386 | 
            +
                    self,
         | 
| 387 | 
            +
                    service_class: Type[T],
         | 
| 388 | 
            +
                    init_args: tuple = (),
         | 
| 389 | 
            +
                    init_kwargs: dict = None,
         | 
| 390 | 
            +
                    name: Optional[str] = None
         | 
| 391 | 
            +
                ):
         | 
| 392 | 
            +
                    self._service_class = service_class
         | 
| 393 | 
            +
                    self._init_args = init_args
         | 
| 394 | 
            +
                    self._init_kwargs = init_kwargs or {}
         | 
| 395 | 
            +
                    self._name = name or service_class.__name__
         | 
| 396 | 
            +
                    
         | 
| 397 | 
            +
                    self._instance: Optional[T] = None
         | 
| 398 | 
            +
                    self._lock = asyncio.Lock()
         | 
| 399 | 
            +
                    self._metrics = LazyMetrics()
         | 
| 400 | 
            +
                    self._logger = get_logger(f"async_lazy.{self._name}")
         | 
| 401 | 
            +
                
         | 
| 402 | 
            +
                @property
         | 
| 403 | 
            +
                def is_initialized(self) -> bool:
         | 
| 404 | 
            +
                    """Check if service has been initialized."""
         | 
| 405 | 
            +
                    return self._instance is not None
         | 
| 406 | 
            +
                
         | 
| 407 | 
            +
                async def _ensure_initialized(self) -> T:
         | 
| 408 | 
            +
                    """Ensure service is initialized asynchronously."""
         | 
| 409 | 
            +
                    if self._instance is not None:
         | 
| 410 | 
            +
                        return self._instance
         | 
| 411 | 
            +
                    
         | 
| 412 | 
            +
                    async with self._lock:
         | 
| 413 | 
            +
                        if self._instance is not None:
         | 
| 414 | 
            +
                            return self._instance
         | 
| 415 | 
            +
                        
         | 
| 416 | 
            +
                        start_time = time.time()
         | 
| 417 | 
            +
                        if self._metrics.first_access is None:
         | 
| 418 | 
            +
                            self._metrics.first_access = datetime.now()
         | 
| 419 | 
            +
                        
         | 
| 420 | 
            +
                        try:
         | 
| 421 | 
            +
                            self._logger.debug(f"Async initializing: {self._name}")
         | 
| 422 | 
            +
                            
         | 
| 423 | 
            +
                            # Handle both async and sync initialization
         | 
| 424 | 
            +
                            if asyncio.iscoroutinefunction(self._service_class):
         | 
| 425 | 
            +
                                self._instance = await self._service_class(
         | 
| 426 | 
            +
                                    *self._init_args,
         | 
| 427 | 
            +
                                    **self._init_kwargs
         | 
| 428 | 
            +
                                )
         | 
| 429 | 
            +
                            else:
         | 
| 430 | 
            +
                                # Run sync initialization in executor
         | 
| 431 | 
            +
                                loop = asyncio.get_event_loop()
         | 
| 432 | 
            +
                                self._instance = await loop.run_in_executor(
         | 
| 433 | 
            +
                                    None,
         | 
| 434 | 
            +
                                    self._service_class,
         | 
| 435 | 
            +
                                    *self._init_args,
         | 
| 436 | 
            +
                                    **self._init_kwargs
         | 
| 437 | 
            +
                                )
         | 
| 438 | 
            +
                            
         | 
| 439 | 
            +
                            self._metrics.initialization_time = time.time() - start_time
         | 
| 440 | 
            +
                            self._metrics.is_initialized = True
         | 
| 441 | 
            +
                            
         | 
| 442 | 
            +
                            self._logger.info(
         | 
| 443 | 
            +
                                f"Async service {self._name} initialized in "
         | 
| 444 | 
            +
                                f"{self._metrics.initialization_time:.2f}s"
         | 
| 445 | 
            +
                            )
         | 
| 446 | 
            +
                            
         | 
| 447 | 
            +
                            return self._instance
         | 
| 448 | 
            +
                            
         | 
| 449 | 
            +
                        except Exception as e:
         | 
| 450 | 
            +
                            self._metrics.initialization_error = e
         | 
| 451 | 
            +
                            self._logger.error(f"Failed to initialize {self._name}: {e}")
         | 
| 452 | 
            +
                            raise
         | 
| 453 | 
            +
                
         | 
| 454 | 
            +
                def __getattr__(self, name: str) -> Any:
         | 
| 455 | 
            +
                    """Proxy attribute access to the underlying service."""
         | 
| 456 | 
            +
                    if name.startswith('_'):
         | 
| 457 | 
            +
                        raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'")
         | 
| 458 | 
            +
                    
         | 
| 459 | 
            +
                    async def async_wrapper(*args, **kwargs):
         | 
| 460 | 
            +
                        instance = await self._ensure_initialized()
         | 
| 461 | 
            +
                        self._metrics.access_count += 1
         | 
| 462 | 
            +
                        attr = getattr(instance, name)
         | 
| 463 | 
            +
                        if asyncio.iscoroutinefunction(attr):
         | 
| 464 | 
            +
                            return await attr(*args, **kwargs)
         | 
| 465 | 
            +
                        return attr(*args, **kwargs)
         | 
| 466 | 
            +
                    
         | 
| 467 | 
            +
                    return async_wrapper
         |