unrealon 1.1.6__py3-none-any.whl → 2.0.5__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 (144) hide show
  1. {unrealon-1.1.6.dist-info/licenses → unrealon-2.0.5.dist-info}/LICENSE +1 -1
  2. unrealon-2.0.5.dist-info/METADATA +491 -0
  3. unrealon-2.0.5.dist-info/RECORD +128 -0
  4. {unrealon-1.1.6.dist-info → unrealon-2.0.5.dist-info}/WHEEL +2 -1
  5. unrealon-2.0.5.dist-info/entry_points.txt +3 -0
  6. unrealon-2.0.5.dist-info/top_level.txt +3 -0
  7. unrealon_browser/__init__.py +5 -6
  8. unrealon_browser/cli/browser_cli.py +18 -9
  9. unrealon_browser/cli/interactive_mode.py +13 -4
  10. unrealon_browser/core/browser_manager.py +29 -16
  11. unrealon_browser/dto/__init__.py +21 -0
  12. unrealon_browser/dto/bot_detection.py +175 -0
  13. unrealon_browser/dto/models/config.py +9 -3
  14. unrealon_browser/managers/__init__.py +1 -1
  15. unrealon_browser/managers/logger_bridge.py +1 -4
  16. unrealon_browser/stealth/__init__.py +27 -0
  17. unrealon_browser/stealth/bypass_techniques.pyc +0 -0
  18. unrealon_browser/stealth/manager.pyc +0 -0
  19. unrealon_browser/stealth/nodriver_stealth.pyc +0 -0
  20. unrealon_browser/stealth/playwright_stealth.pyc +0 -0
  21. unrealon_browser/stealth/scanner_tester.pyc +0 -0
  22. unrealon_browser/stealth/undetected_chrome.pyc +0 -0
  23. unrealon_core/__init__.py +172 -0
  24. unrealon_core/config/__init__.py +16 -0
  25. unrealon_core/config/environment.py +151 -0
  26. unrealon_core/config/urls.py +94 -0
  27. unrealon_core/enums/__init__.py +24 -0
  28. unrealon_core/enums/status.py +216 -0
  29. unrealon_core/enums/types.py +240 -0
  30. unrealon_core/error_handling/__init__.py +45 -0
  31. unrealon_core/error_handling/circuit_breaker.py +292 -0
  32. unrealon_core/error_handling/error_context.py +324 -0
  33. unrealon_core/error_handling/recovery.py +371 -0
  34. unrealon_core/error_handling/retry.py +268 -0
  35. unrealon_core/exceptions/__init__.py +46 -0
  36. unrealon_core/exceptions/base.py +292 -0
  37. unrealon_core/exceptions/communication.py +22 -0
  38. unrealon_core/exceptions/driver.py +11 -0
  39. unrealon_core/exceptions/proxy.py +11 -0
  40. unrealon_core/exceptions/task.py +12 -0
  41. unrealon_core/exceptions/validation.py +17 -0
  42. unrealon_core/models/__init__.py +79 -0
  43. unrealon_core/models/arq_context.py +252 -0
  44. unrealon_core/models/arq_responses.py +125 -0
  45. unrealon_core/models/base.py +291 -0
  46. unrealon_core/models/bridge_stats.py +58 -0
  47. unrealon_core/models/communication.py +39 -0
  48. unrealon_core/models/connection_stats.py +47 -0
  49. unrealon_core/models/driver.py +30 -0
  50. unrealon_core/models/driver_details.py +98 -0
  51. unrealon_core/models/logging.py +28 -0
  52. unrealon_core/models/task.py +21 -0
  53. unrealon_core/models/typed_responses.py +210 -0
  54. unrealon_core/models/websocket/__init__.py +91 -0
  55. unrealon_core/models/websocket/base.py +49 -0
  56. unrealon_core/models/websocket/config.py +200 -0
  57. unrealon_core/models/websocket/driver.py +215 -0
  58. unrealon_core/models/websocket/errors.py +138 -0
  59. unrealon_core/models/websocket/heartbeat.py +100 -0
  60. unrealon_core/models/websocket/logging.py +261 -0
  61. unrealon_core/models/websocket/proxy.py +496 -0
  62. unrealon_core/models/websocket/tasks.py +275 -0
  63. unrealon_core/models/websocket/utils.py +153 -0
  64. unrealon_core/models/websocket_session.py +144 -0
  65. unrealon_core/monitoring/__init__.py +43 -0
  66. unrealon_core/monitoring/alerts.py +398 -0
  67. unrealon_core/monitoring/dashboard.py +307 -0
  68. unrealon_core/monitoring/health_check.py +354 -0
  69. unrealon_core/monitoring/metrics.py +352 -0
  70. unrealon_core/utils/__init__.py +11 -0
  71. unrealon_core/utils/time.py +61 -0
  72. unrealon_core/version.py +219 -0
  73. unrealon_driver/__init__.py +90 -51
  74. unrealon_driver/core_module/__init__.py +34 -0
  75. unrealon_driver/core_module/base.py +184 -0
  76. unrealon_driver/core_module/config.py +30 -0
  77. unrealon_driver/core_module/event_manager.py +127 -0
  78. unrealon_driver/core_module/protocols.py +98 -0
  79. unrealon_driver/core_module/registry.py +146 -0
  80. unrealon_driver/decorators/__init__.py +15 -0
  81. unrealon_driver/decorators/retry.py +117 -0
  82. unrealon_driver/decorators/schedule.py +137 -0
  83. unrealon_driver/decorators/task.py +61 -0
  84. unrealon_driver/decorators/timing.py +132 -0
  85. unrealon_driver/driver/__init__.py +20 -0
  86. unrealon_driver/driver/communication/__init__.py +10 -0
  87. unrealon_driver/driver/communication/session.py +203 -0
  88. unrealon_driver/driver/communication/websocket_client.py +205 -0
  89. unrealon_driver/driver/core/__init__.py +10 -0
  90. unrealon_driver/driver/core/config.py +175 -0
  91. unrealon_driver/driver/core/driver.py +221 -0
  92. unrealon_driver/driver/factory/__init__.py +9 -0
  93. unrealon_driver/driver/factory/manager_factory.py +130 -0
  94. unrealon_driver/driver/lifecycle/__init__.py +11 -0
  95. unrealon_driver/driver/lifecycle/daemon.py +76 -0
  96. unrealon_driver/driver/lifecycle/initialization.py +97 -0
  97. unrealon_driver/driver/lifecycle/shutdown.py +48 -0
  98. unrealon_driver/driver/monitoring/__init__.py +9 -0
  99. unrealon_driver/driver/monitoring/health.py +63 -0
  100. unrealon_driver/driver/utilities/__init__.py +10 -0
  101. unrealon_driver/driver/utilities/logging.py +51 -0
  102. unrealon_driver/driver/utilities/serialization.py +61 -0
  103. unrealon_driver/managers/__init__.py +32 -0
  104. unrealon_driver/managers/base.py +174 -0
  105. unrealon_driver/managers/browser.py +98 -0
  106. unrealon_driver/managers/cache.py +116 -0
  107. unrealon_driver/managers/http.py +107 -0
  108. unrealon_driver/managers/logger.py +286 -0
  109. unrealon_driver/managers/proxy.py +99 -0
  110. unrealon_driver/managers/registry.py +87 -0
  111. unrealon_driver/managers/threading.py +54 -0
  112. unrealon_driver/managers/update.py +107 -0
  113. unrealon_driver/utils/__init__.py +9 -0
  114. unrealon_driver/utils/time.py +10 -0
  115. unrealon-1.1.6.dist-info/METADATA +0 -625
  116. unrealon-1.1.6.dist-info/RECORD +0 -55
  117. unrealon-1.1.6.dist-info/entry_points.txt +0 -9
  118. unrealon_browser/managers/stealth.py +0 -388
  119. unrealon_driver/README.md +0 -0
  120. unrealon_driver/exceptions.py +0 -33
  121. unrealon_driver/html_analyzer/__init__.py +0 -32
  122. unrealon_driver/html_analyzer/cleaner.py +0 -657
  123. unrealon_driver/html_analyzer/config.py +0 -64
  124. unrealon_driver/html_analyzer/manager.py +0 -247
  125. unrealon_driver/html_analyzer/models.py +0 -115
  126. unrealon_driver/html_analyzer/websocket_analyzer.py +0 -157
  127. unrealon_driver/models/__init__.py +0 -31
  128. unrealon_driver/models/websocket.py +0 -98
  129. unrealon_driver/parser/__init__.py +0 -36
  130. unrealon_driver/parser/cli_manager.py +0 -142
  131. unrealon_driver/parser/daemon_manager.py +0 -403
  132. unrealon_driver/parser/managers/__init__.py +0 -25
  133. unrealon_driver/parser/managers/config.py +0 -293
  134. unrealon_driver/parser/managers/error.py +0 -412
  135. unrealon_driver/parser/managers/result.py +0 -321
  136. unrealon_driver/parser/parser_manager.py +0 -458
  137. unrealon_driver/smart_logging/__init__.py +0 -24
  138. unrealon_driver/smart_logging/models.py +0 -44
  139. unrealon_driver/smart_logging/smart_logger.py +0 -406
  140. unrealon_driver/smart_logging/unified_logger.py +0 -525
  141. unrealon_driver/websocket/__init__.py +0 -31
  142. unrealon_driver/websocket/client.py +0 -249
  143. unrealon_driver/websocket/config.py +0 -188
  144. unrealon_driver/websocket/manager.py +0 -90
@@ -0,0 +1,175 @@
1
+ """
2
+ Clean driver configuration without hardcoded values.
3
+ """
4
+
5
+ import os
6
+ from enum import Enum
7
+ from typing import Optional
8
+ from pydantic import BaseModel, Field, computed_field
9
+
10
+ try:
11
+ from unrealon_core.config.environment import get_environment_config
12
+ UNREALON_CORE_AVAILABLE = True
13
+ except ImportError:
14
+ UNREALON_CORE_AVAILABLE = False
15
+
16
+
17
+ class DriverMode(str, Enum):
18
+ """Driver operation modes."""
19
+ STANDALONE = "standalone"
20
+ DAEMON = "daemon"
21
+
22
+
23
+ class DriverConfig(BaseModel):
24
+ """
25
+ Clean driver configuration.
26
+ No hardcoded presets - user configures everything explicitly.
27
+ """
28
+
29
+ # Basic settings
30
+ name: str = Field(..., description="Driver name")
31
+ mode: DriverMode = Field(default=DriverMode.STANDALONE, description="Operation mode")
32
+
33
+ # WebSocket connection (auto-detected)
34
+ websocket_url: Optional[str] = Field(default=None, description="Manual WebSocket URL override")
35
+ websocket_timeout: int = Field(default=30, description="WebSocket timeout seconds")
36
+
37
+ @computed_field
38
+ @property
39
+ def effective_websocket_url(self) -> Optional[str]:
40
+ """
41
+ Auto-detect WebSocket URL from multiple sources.
42
+
43
+ Priority:
44
+ 1. Explicit websocket_url field
45
+ 2. Environment variables (UNREALON_WEBSOCKET_URL, UNREALON_WS_URL, WS_URL)
46
+ 3. UnrealOn core environment config (if available)
47
+ 4. No default - return None if nothing configured
48
+ """
49
+ # 1. Explicit override
50
+ if self.websocket_url:
51
+ return self.websocket_url
52
+
53
+ # 2. Environment variables
54
+ env_url = (
55
+ os.getenv('UNREALON_WEBSOCKET_URL') or
56
+ os.getenv('UNREALON_WS_URL') or
57
+ os.getenv('WS_URL')
58
+ )
59
+ if env_url:
60
+ return env_url
61
+
62
+ # 3. Try unrealon_core environment config
63
+ if UNREALON_CORE_AVAILABLE:
64
+ try:
65
+ env_config = get_environment_config()
66
+ return env_config.websocket_url
67
+ except Exception:
68
+ pass # Fallback gracefully if core config fails
69
+
70
+ # 4. No default - return None if nothing is configured
71
+ return None
72
+
73
+ # Logging
74
+ log_level: str = Field(default="INFO", description="Logging level")
75
+ log_file: Optional[str] = Field(default=None, description="Log file path")
76
+
77
+ # HTTP settings
78
+ http_timeout: int = Field(default=30, description="HTTP timeout seconds")
79
+ max_retries: int = Field(default=3, description="Max HTTP retries")
80
+
81
+ # Browser settings
82
+ browser_headless: bool = Field(default=True, description="Run browser headless")
83
+ browser_timeout: int = Field(default=30, description="Browser timeout seconds")
84
+
85
+ # Proxy settings
86
+ proxy_enabled: bool = Field(default=False, description="Enable proxy rotation")
87
+ proxy_rotation_interval: int = Field(default=300, description="Proxy rotation seconds")
88
+
89
+ # Cache settings
90
+ cache_enabled: bool = Field(default=True, description="Enable response caching")
91
+ cache_ttl: int = Field(default=3600, description="Cache TTL seconds")
92
+
93
+ # Threading
94
+ max_workers: int = Field(default=4, description="Max thread workers")
95
+
96
+ # Performance
97
+ batch_size: int = Field(default=10, description="Batch processing size")
98
+
99
+ model_config = {"extra": "forbid"}
100
+
101
+ @classmethod
102
+ def for_development(cls, name: str, **kwargs) -> "DriverConfig":
103
+ """
104
+ Create development configuration with sensible defaults.
105
+
106
+ Args:
107
+ name: Driver name
108
+ **kwargs: Additional configuration overrides
109
+ """
110
+ defaults = {
111
+ "name": name,
112
+ "mode": DriverMode.STANDALONE,
113
+ "log_level": "DEBUG",
114
+ "browser_headless": False,
115
+ "proxy_enabled": False,
116
+ "cache_enabled": True,
117
+ "max_workers": 2,
118
+ }
119
+ defaults.update(kwargs)
120
+ return cls(**defaults)
121
+
122
+ @classmethod
123
+ def for_production(cls, name: str, **kwargs) -> "DriverConfig":
124
+ """
125
+ Create production configuration with performance and reliability defaults.
126
+
127
+ Args:
128
+ name: Driver name
129
+ **kwargs: Additional configuration overrides
130
+ """
131
+ defaults = {
132
+ "name": name,
133
+ "mode": DriverMode.DAEMON,
134
+ "log_level": "INFO",
135
+ "browser_headless": True,
136
+ "proxy_enabled": True,
137
+ "cache_enabled": True,
138
+ "max_workers": 4,
139
+ "max_retries": 5,
140
+ "http_timeout": 60,
141
+ "browser_timeout": 60,
142
+ }
143
+ defaults.update(kwargs)
144
+ return cls(**defaults)
145
+
146
+ @classmethod
147
+ def auto_detect(cls, name: str, **kwargs) -> "DriverConfig":
148
+ """
149
+ Auto-detect environment and create appropriate configuration.
150
+
151
+ Uses UNREALON_ENV environment variable or unrealon_core config to determine environment.
152
+
153
+ Args:
154
+ name: Driver name
155
+ **kwargs: Additional configuration overrides
156
+ """
157
+ # Try to detect environment
158
+ env_name = os.getenv("UNREALON_ENV", "development").lower()
159
+
160
+ # Try unrealon_core if available
161
+ if UNREALON_CORE_AVAILABLE:
162
+ try:
163
+ env_config = get_environment_config()
164
+ if env_config.is_production:
165
+ return cls.for_production(name, **kwargs)
166
+ elif env_config.is_development:
167
+ return cls.for_development(name, **kwargs)
168
+ except Exception:
169
+ pass # Fallback to env variable
170
+
171
+ # Fallback to environment variable
172
+ if env_name in ("prod", "production"):
173
+ return cls.for_production(name, **kwargs)
174
+ else:
175
+ return cls.for_development(name, **kwargs)
@@ -0,0 +1,221 @@
1
+ """
2
+ UniversalDriver - Clean, modular driver orchestrator.
3
+
4
+ The main driver class that coordinates all components through a clean,
5
+ organized architecture with separated concerns.
6
+ """
7
+
8
+ import logging
9
+ from pathlib import Path
10
+ from typing import Optional, List, Dict, Any, Callable
11
+
12
+ from .config import DriverConfig
13
+ from ..communication.websocket_client import WebSocketClient
14
+ from ..communication.session import DriverSession
15
+ from ..factory.manager_factory import ManagerFactory
16
+ from ..lifecycle.initialization import DriverInitializer
17
+ from ..lifecycle.shutdown import DriverShutdown
18
+ from ..lifecycle.daemon import DaemonManager
19
+ from ..monitoring.health import HealthMonitor
20
+ from ..utilities.logging import LoggingUtility
21
+ from ..utilities.serialization import SerializationUtility
22
+
23
+ from ...managers import (
24
+ LoggerManager, HttpManager, BrowserManager, CacheManager,
25
+ ProxyManager, ThreadManager, UpdateManager, ManagerRegistry
26
+ )
27
+
28
+ from ...core_module import (
29
+ EventManager,
30
+ ModuleRegistry
31
+ )
32
+
33
+ from ...decorators import task, retry, schedule, timing
34
+
35
+ logger = logging.getLogger(__name__)
36
+
37
+
38
+ class UniversalDriver:
39
+ """
40
+ Universal Driver - Clean orchestrator for all parsing operations.
41
+
42
+ Key Features:
43
+ - Zero-config initialization with sensible defaults
44
+ - Modular manager system (HTTP, Browser, Cache, etc.)
45
+ - WebSocket communication for RPC and logging
46
+ - Graceful shutdown with signal handling
47
+ - Built-in utilities for common operations
48
+ - Decorator-based task registration
49
+
50
+ Usage:
51
+ # Basic usage
52
+ config = DriverConfig.for_development("my_parser")
53
+ driver = UniversalDriver(config)
54
+ await driver.initialize()
55
+
56
+ # Daemon mode with RPC
57
+ await driver.run_daemon_mode()
58
+
59
+ # Standalone mode
60
+ await driver.initialize()
61
+ # ... your parsing logic
62
+ await driver.shutdown()
63
+ """
64
+
65
+ def __init__(self, config: DriverConfig):
66
+ """Initialize UniversalDriver with configuration."""
67
+ self.config = config
68
+ self.driver_id = config.name
69
+ self.is_initialized = False
70
+ self.capabilities: List[str] = []
71
+
72
+ # Core components
73
+ self.websocket_client: Optional[WebSocketClient] = None
74
+ self.session: Optional[DriverSession] = None
75
+
76
+ # Manager system (initialized by factory)
77
+ self.manager_registry: Optional[ManagerRegistry] = None
78
+ self.logger_manager: Optional[LoggerManager] = None
79
+ self.http: Optional[HttpManager] = None
80
+ self.browser: Optional[BrowserManager] = None
81
+ self.cache: Optional[CacheManager] = None
82
+ self.proxy: Optional[ProxyManager] = None
83
+ self.threading: Optional[ThreadManager] = None
84
+ self.update: Optional[UpdateManager] = None
85
+
86
+ # Module system
87
+ self.event_manager = EventManager()
88
+ self.module_registry = ModuleRegistry(self.event_manager)
89
+
90
+ # Utilities
91
+ self._logging_util = LoggingUtility(self.driver_id)
92
+
93
+ # Decorators (exposed as instance methods for convenience)
94
+ self.task = task
95
+ self.retry = retry
96
+ self.schedule = schedule
97
+ self.timing = timing
98
+
99
+ # Setup managers using factory
100
+ self._setup_components()
101
+
102
+ def _setup_components(self):
103
+ """Setup all driver components."""
104
+ # Initialize managers using factory
105
+ self.manager_registry = ManagerFactory.setup_managers(self)
106
+
107
+ # Update logging utility with manager
108
+ self._logging_util.logger_manager = self.logger_manager
109
+
110
+ logger.debug(f"UniversalDriver components initialized: {self.driver_id}")
111
+
112
+ # === Lifecycle Management ===
113
+
114
+ async def initialize(self, capabilities: List[str] = []) -> bool:
115
+ """
116
+ Initialize driver with all components.
117
+
118
+ Args:
119
+ capabilities: List of driver capabilities
120
+
121
+ Returns:
122
+ True if initialization successful
123
+ """
124
+ return await DriverInitializer.initialize_driver(self, capabilities)
125
+
126
+ async def shutdown(self):
127
+ """Shutdown driver cleanly."""
128
+ await DriverShutdown.shutdown_driver(self)
129
+
130
+ async def run_daemon_mode(self, on_start_message: str = "Driver initialized, waiting for RPC tasks..."):
131
+ """
132
+ Run driver in daemon mode with graceful shutdown handling.
133
+
134
+ Args:
135
+ on_start_message: Message to display when daemon starts
136
+ """
137
+ await DaemonManager.run_daemon_mode(self, on_start_message)
138
+
139
+ # === Task Registration ===
140
+
141
+ def register_task_handler(self, task_type: str, handler: Callable):
142
+ """Register task handler for RPC tasks."""
143
+ if self.session:
144
+ self.session.register_task_handler(task_type, handler)
145
+ else:
146
+ logger.warning("No session available for task handler registration")
147
+
148
+ # === Health & Monitoring ===
149
+
150
+ async def health_check(self) -> Dict[str, Any]:
151
+ """Get comprehensive health status."""
152
+ return await HealthMonitor.get_health_status(self)
153
+
154
+ def get_status(self) -> Dict[str, Any]:
155
+ """Get basic driver status (synchronous)."""
156
+ return HealthMonitor.get_basic_status(self)
157
+
158
+ # === Utilities ===
159
+
160
+ def save_results_to_file(self, data: dict, filename: str, results_dir: Optional[str] = None) -> Path:
161
+ """
162
+ Save parsing results to JSON file with automatic serialization.
163
+
164
+ Args:
165
+ data: Data to save (can contain Pydantic models)
166
+ filename: Base filename (without extension)
167
+ results_dir: Directory to save to (default: ./data/results)
168
+
169
+ Returns:
170
+ Path to saved file
171
+ """
172
+ return SerializationUtility.save_results_to_file(data, filename, results_dir)
173
+
174
+ # === Logging Methods ===
175
+
176
+ def log(self, level: str, message: str, context: Optional[Dict[str, Any]] = None):
177
+ """Log message through logger manager."""
178
+ self._logging_util.log(level, message, context)
179
+
180
+ def debug(self, message: str, context: Optional[Dict[str, Any]] = None):
181
+ """Log debug message."""
182
+ self._logging_util.debug(message, context)
183
+
184
+ def info(self, message: str, context: Optional[Dict[str, Any]] = None):
185
+ """Log info message."""
186
+ self._logging_util.info(message, context)
187
+
188
+ def warning(self, message: str, context: Optional[Dict[str, Any]] = None):
189
+ """Log warning message."""
190
+ self._logging_util.warning(message, context)
191
+
192
+ def error(self, message: str, context: Optional[Dict[str, Any]] = None):
193
+ """Log error message."""
194
+ self._logging_util.error(message, context)
195
+
196
+ def critical(self, message: str, context: Optional[Dict[str, Any]] = None):
197
+ """Log critical message."""
198
+ self._logging_util.critical(message, context)
199
+
200
+ # === Convenience Properties ===
201
+
202
+ @property
203
+ def is_daemon_mode(self) -> bool:
204
+ """Check if driver is running in daemon mode."""
205
+ return self.session is not None
206
+
207
+ @property
208
+ def is_connected(self) -> bool:
209
+ """Check if WebSocket is connected."""
210
+ return self.websocket_client is not None and self.websocket_client.is_connected
211
+
212
+ @property
213
+ def manager_count(self) -> int:
214
+ """Get number of active managers."""
215
+ return len(self.manager_registry.managers) if self.manager_registry else 0
216
+
217
+ def __repr__(self) -> str:
218
+ """String representation of driver."""
219
+ status = "initialized" if self.is_initialized else "not initialized"
220
+ mode = "daemon" if self.is_daemon_mode else "standalone"
221
+ return f"UniversalDriver(id='{self.driver_id}', status='{status}', mode='{mode}')"
@@ -0,0 +1,9 @@
1
+ """
2
+ Factory pattern for driver components.
3
+
4
+ Handles setup and configuration of managers and other components.
5
+ """
6
+
7
+ from .manager_factory import ManagerFactory
8
+
9
+ __all__ = ["ManagerFactory"]
@@ -0,0 +1,130 @@
1
+ """
2
+ Manager Factory - Setup and configuration of all managers.
3
+
4
+ Handles the creation and configuration of manager components.
5
+ """
6
+
7
+ import logging
8
+ from typing import TYPE_CHECKING
9
+
10
+ from ...managers import (
11
+ LoggerManager, HttpManager, BrowserManager, CacheManager,
12
+ ProxyManager, ThreadManager, UpdateManager, ManagerRegistry
13
+ )
14
+ from ...managers.logger import LoggerManagerConfig
15
+ from ...managers.http import HttpManagerConfig
16
+ from ...managers.browser import BrowserManagerConfig
17
+ from ...managers.cache import CacheManagerConfig
18
+ from ...managers.proxy import ProxyManagerConfig
19
+ from ...managers.threading import ThreadManagerConfig
20
+ from ...managers.update import UpdateManagerConfig
21
+
22
+ if TYPE_CHECKING:
23
+ from ..core.driver import UniversalDriver
24
+
25
+ logger = logging.getLogger(__name__)
26
+
27
+
28
+ class ManagerFactory:
29
+ """Factory for creating and configuring manager components."""
30
+
31
+ @staticmethod
32
+ def setup_managers(driver: 'UniversalDriver') -> ManagerRegistry:
33
+ """
34
+ Setup all managers with configurations.
35
+
36
+ Args:
37
+ driver: UniversalDriver instance
38
+
39
+ Returns:
40
+ Configured ManagerRegistry
41
+ """
42
+ # Create registry
43
+ manager_registry = ManagerRegistry()
44
+
45
+ # Setup each manager
46
+ ManagerFactory._setup_logger_manager(driver, manager_registry)
47
+ ManagerFactory._setup_http_manager(driver, manager_registry)
48
+ ManagerFactory._setup_browser_manager(driver, manager_registry)
49
+ ManagerFactory._setup_cache_manager(driver, manager_registry)
50
+ ManagerFactory._setup_proxy_manager(driver, manager_registry)
51
+ ManagerFactory._setup_threading_manager(driver, manager_registry)
52
+ ManagerFactory._setup_update_manager(driver, manager_registry)
53
+
54
+ logger.debug(f"Managers setup complete for driver: {driver.driver_id}")
55
+ return manager_registry
56
+
57
+ @staticmethod
58
+ def _setup_logger_manager(driver: 'UniversalDriver', registry: ManagerRegistry):
59
+ """Setup logger manager."""
60
+ logger_config = LoggerManagerConfig(
61
+ enabled=True,
62
+ log_file=driver.config.log_file,
63
+ log_level=driver.config.log_level,
64
+ driver_id=driver.driver_id,
65
+ timeout=driver.config.websocket_timeout
66
+ )
67
+ driver.logger_manager = LoggerManager(logger_config)
68
+ registry.register(driver.logger_manager)
69
+
70
+ @staticmethod
71
+ def _setup_http_manager(driver: 'UniversalDriver', registry: ManagerRegistry):
72
+ """Setup HTTP manager."""
73
+ http_config = HttpManagerConfig(
74
+ enabled=True,
75
+ timeout=driver.config.http_timeout,
76
+ max_retries=driver.config.max_retries
77
+ )
78
+ driver.http = HttpManager(http_config)
79
+ registry.register(driver.http)
80
+
81
+ @staticmethod
82
+ def _setup_browser_manager(driver: 'UniversalDriver', registry: ManagerRegistry):
83
+ """Setup browser manager."""
84
+ browser_config = BrowserManagerConfig(
85
+ enabled=True,
86
+ headless=driver.config.browser_headless,
87
+ timeout=driver.config.browser_timeout,
88
+ parser_name=driver.driver_id
89
+ )
90
+ driver.browser = BrowserManager(browser_config)
91
+ registry.register(driver.browser)
92
+
93
+ @staticmethod
94
+ def _setup_cache_manager(driver: 'UniversalDriver', registry: ManagerRegistry):
95
+ """Setup cache manager."""
96
+ cache_config = CacheManagerConfig(
97
+ enabled=driver.config.cache_enabled,
98
+ default_ttl=driver.config.cache_ttl
99
+ )
100
+ driver.cache = CacheManager(cache_config)
101
+ registry.register(driver.cache)
102
+
103
+ @staticmethod
104
+ def _setup_proxy_manager(driver: 'UniversalDriver', registry: ManagerRegistry):
105
+ """Setup proxy manager."""
106
+ proxy_config = ProxyManagerConfig(
107
+ enabled=driver.config.proxy_enabled,
108
+ rotation_interval=driver.config.proxy_rotation_interval
109
+ )
110
+ driver.proxy = ProxyManager(proxy_config)
111
+ registry.register(driver.proxy)
112
+
113
+ @staticmethod
114
+ def _setup_threading_manager(driver: 'UniversalDriver', registry: ManagerRegistry):
115
+ """Setup threading manager."""
116
+ threading_config = ThreadManagerConfig(
117
+ enabled=True,
118
+ max_workers=driver.config.max_workers
119
+ )
120
+ driver.threading = ThreadManager(threading_config)
121
+ registry.register(driver.threading)
122
+
123
+ @staticmethod
124
+ def _setup_update_manager(driver: 'UniversalDriver', registry: ManagerRegistry):
125
+ """Setup update manager."""
126
+ update_config = UpdateManagerConfig(
127
+ enabled=True
128
+ )
129
+ driver.update = UpdateManager(update_config)
130
+ registry.register(driver.update)
@@ -0,0 +1,11 @@
1
+ """
2
+ Driver lifecycle management.
3
+
4
+ Handles initialization, shutdown, and daemon mode operations.
5
+ """
6
+
7
+ from .initialization import DriverInitializer
8
+ from .shutdown import DriverShutdown
9
+ from .daemon import DaemonManager
10
+
11
+ __all__ = ["DriverInitializer", "DriverShutdown", "DaemonManager"]
@@ -0,0 +1,76 @@
1
+ """
2
+ Daemon mode management.
3
+
4
+ Handles running the driver in daemon mode with graceful shutdown.
5
+ """
6
+
7
+ import asyncio
8
+ import logging
9
+ import signal
10
+ import sys
11
+ from typing import TYPE_CHECKING
12
+
13
+ from .initialization import DriverInitializer
14
+ from .shutdown import DriverShutdown
15
+
16
+ if TYPE_CHECKING:
17
+ from ..core.driver import UniversalDriver
18
+
19
+ logger = logging.getLogger(__name__)
20
+
21
+
22
+ class DaemonManager:
23
+ """Manages daemon mode operations."""
24
+
25
+ @staticmethod
26
+ async def run_daemon_mode(driver: 'UniversalDriver', on_start_message: str = "Driver initialized, waiting for RPC tasks..."):
27
+ """
28
+ Run driver in daemon mode with graceful shutdown handling.
29
+
30
+ Args:
31
+ driver: UniversalDriver instance
32
+ on_start_message: Message to display when daemon starts
33
+ """
34
+ # Flag for graceful shutdown
35
+ shutdown_event = asyncio.Event()
36
+
37
+ def signal_handler():
38
+ """Handle shutdown signals gracefully."""
39
+ logger.info("Shutdown signal received")
40
+ shutdown_event.set()
41
+
42
+ # Register signal handlers
43
+ if sys.platform != "win32":
44
+ loop = asyncio.get_running_loop()
45
+ for sig in (signal.SIGTERM, signal.SIGINT):
46
+ loop.add_signal_handler(sig, signal_handler)
47
+
48
+ try:
49
+ # Initialize driver with capabilities
50
+ success = await DriverInitializer.initialize_driver(driver, driver.capabilities)
51
+ if not success:
52
+ raise RuntimeError("Driver initialization failed")
53
+
54
+ # Call on_start hook if available
55
+ if hasattr(driver, 'on_start') and callable(driver.on_start):
56
+ await driver.on_start()
57
+
58
+ logger.info(on_start_message)
59
+
60
+ # Keep running until shutdown signal
61
+ await shutdown_event.wait()
62
+
63
+ except Exception as e:
64
+ logger.error(f"Daemon mode error: {e}")
65
+ raise
66
+ finally:
67
+ # Always shutdown cleanly
68
+ try:
69
+ # Call on_shutdown hook if available
70
+ if hasattr(driver, 'on_shutdown') and callable(driver.on_shutdown):
71
+ await driver.on_shutdown()
72
+
73
+ await DriverShutdown.shutdown_driver(driver)
74
+ logger.info("Driver shutdown complete")
75
+ except Exception as e:
76
+ logger.error(f"Error during shutdown: {e}")