unrealon 1.1.5__py3-none-any.whl → 2.0.4__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 (146) hide show
  1. {unrealon-1.1.5.dist-info/licenses → unrealon-2.0.4.dist-info}/LICENSE +1 -1
  2. unrealon-2.0.4.dist-info/METADATA +491 -0
  3. unrealon-2.0.4.dist-info/RECORD +129 -0
  4. {unrealon-1.1.5.dist-info → unrealon-2.0.4.dist-info}/WHEEL +2 -1
  5. unrealon-2.0.4.dist-info/entry_points.txt +3 -0
  6. unrealon-2.0.4.dist-info/top_level.txt +3 -0
  7. unrealon_browser/__init__.py +5 -2
  8. unrealon_browser/cli/browser_cli.py +18 -9
  9. unrealon_browser/cli/interactive_mode.py +18 -7
  10. unrealon_browser/core/browser_manager.py +76 -13
  11. unrealon_browser/dto/__init__.py +21 -0
  12. unrealon_browser/dto/bot_detection.py +175 -0
  13. unrealon_browser/dto/models/config.py +14 -1
  14. unrealon_browser/managers/__init__.py +4 -1
  15. unrealon_browser/managers/logger_bridge.py +3 -6
  16. unrealon_browser/managers/page_wait_manager.py +198 -0
  17. unrealon_browser/stealth/__init__.py +27 -0
  18. unrealon_browser/stealth/bypass_techniques.pyc +0 -0
  19. unrealon_browser/stealth/manager.pyc +0 -0
  20. unrealon_browser/stealth/nodriver_stealth.pyc +0 -0
  21. unrealon_browser/stealth/playwright_stealth.pyc +0 -0
  22. unrealon_browser/stealth/scanner_tester.pyc +0 -0
  23. unrealon_browser/stealth/undetected_chrome.pyc +0 -0
  24. unrealon_core/__init__.py +160 -0
  25. unrealon_core/config/__init__.py +16 -0
  26. unrealon_core/config/environment.py +98 -0
  27. unrealon_core/config/urls.py +93 -0
  28. unrealon_core/enums/__init__.py +24 -0
  29. unrealon_core/enums/status.py +216 -0
  30. unrealon_core/enums/types.py +240 -0
  31. unrealon_core/error_handling/__init__.py +45 -0
  32. unrealon_core/error_handling/circuit_breaker.py +292 -0
  33. unrealon_core/error_handling/error_context.py +324 -0
  34. unrealon_core/error_handling/recovery.py +371 -0
  35. unrealon_core/error_handling/retry.py +268 -0
  36. unrealon_core/exceptions/__init__.py +46 -0
  37. unrealon_core/exceptions/base.py +292 -0
  38. unrealon_core/exceptions/communication.py +22 -0
  39. unrealon_core/exceptions/driver.py +11 -0
  40. unrealon_core/exceptions/proxy.py +11 -0
  41. unrealon_core/exceptions/task.py +12 -0
  42. unrealon_core/exceptions/validation.py +17 -0
  43. unrealon_core/models/__init__.py +98 -0
  44. unrealon_core/models/arq_context.py +252 -0
  45. unrealon_core/models/arq_responses.py +125 -0
  46. unrealon_core/models/base.py +291 -0
  47. unrealon_core/models/bridge_stats.py +58 -0
  48. unrealon_core/models/communication.py +39 -0
  49. unrealon_core/models/config.py +47 -0
  50. unrealon_core/models/connection_stats.py +47 -0
  51. unrealon_core/models/driver.py +30 -0
  52. unrealon_core/models/driver_details.py +98 -0
  53. unrealon_core/models/logging.py +28 -0
  54. unrealon_core/models/task.py +21 -0
  55. unrealon_core/models/typed_responses.py +210 -0
  56. unrealon_core/models/websocket/__init__.py +91 -0
  57. unrealon_core/models/websocket/base.py +49 -0
  58. unrealon_core/models/websocket/config.py +200 -0
  59. unrealon_core/models/websocket/driver.py +215 -0
  60. unrealon_core/models/websocket/errors.py +138 -0
  61. unrealon_core/models/websocket/heartbeat.py +100 -0
  62. unrealon_core/models/websocket/logging.py +261 -0
  63. unrealon_core/models/websocket/proxy.py +496 -0
  64. unrealon_core/models/websocket/tasks.py +275 -0
  65. unrealon_core/models/websocket/utils.py +153 -0
  66. unrealon_core/models/websocket_session.py +144 -0
  67. unrealon_core/monitoring/__init__.py +43 -0
  68. unrealon_core/monitoring/alerts.py +398 -0
  69. unrealon_core/monitoring/dashboard.py +307 -0
  70. unrealon_core/monitoring/health_check.py +354 -0
  71. unrealon_core/monitoring/metrics.py +352 -0
  72. unrealon_core/utils/__init__.py +11 -0
  73. unrealon_core/utils/time.py +61 -0
  74. unrealon_core/version.py +219 -0
  75. unrealon_driver/__init__.py +88 -50
  76. unrealon_driver/core_module/__init__.py +34 -0
  77. unrealon_driver/core_module/base.py +184 -0
  78. unrealon_driver/core_module/config.py +30 -0
  79. unrealon_driver/core_module/event_manager.py +127 -0
  80. unrealon_driver/core_module/protocols.py +98 -0
  81. unrealon_driver/core_module/registry.py +146 -0
  82. unrealon_driver/decorators/__init__.py +15 -0
  83. unrealon_driver/decorators/retry.py +117 -0
  84. unrealon_driver/decorators/schedule.py +137 -0
  85. unrealon_driver/decorators/task.py +61 -0
  86. unrealon_driver/decorators/timing.py +132 -0
  87. unrealon_driver/driver/__init__.py +20 -0
  88. unrealon_driver/driver/communication/__init__.py +10 -0
  89. unrealon_driver/driver/communication/session.py +203 -0
  90. unrealon_driver/driver/communication/websocket_client.py +197 -0
  91. unrealon_driver/driver/core/__init__.py +10 -0
  92. unrealon_driver/driver/core/config.py +85 -0
  93. unrealon_driver/driver/core/driver.py +221 -0
  94. unrealon_driver/driver/factory/__init__.py +9 -0
  95. unrealon_driver/driver/factory/manager_factory.py +130 -0
  96. unrealon_driver/driver/lifecycle/__init__.py +11 -0
  97. unrealon_driver/driver/lifecycle/daemon.py +76 -0
  98. unrealon_driver/driver/lifecycle/initialization.py +97 -0
  99. unrealon_driver/driver/lifecycle/shutdown.py +48 -0
  100. unrealon_driver/driver/monitoring/__init__.py +9 -0
  101. unrealon_driver/driver/monitoring/health.py +63 -0
  102. unrealon_driver/driver/utilities/__init__.py +10 -0
  103. unrealon_driver/driver/utilities/logging.py +51 -0
  104. unrealon_driver/driver/utilities/serialization.py +61 -0
  105. unrealon_driver/managers/__init__.py +32 -0
  106. unrealon_driver/managers/base.py +174 -0
  107. unrealon_driver/managers/browser.py +98 -0
  108. unrealon_driver/managers/cache.py +116 -0
  109. unrealon_driver/managers/http.py +107 -0
  110. unrealon_driver/managers/logger.py +286 -0
  111. unrealon_driver/managers/proxy.py +99 -0
  112. unrealon_driver/managers/registry.py +87 -0
  113. unrealon_driver/managers/threading.py +54 -0
  114. unrealon_driver/managers/update.py +107 -0
  115. unrealon_driver/utils/__init__.py +9 -0
  116. unrealon_driver/utils/time.py +10 -0
  117. unrealon/__init__.py +0 -40
  118. unrealon-1.1.5.dist-info/METADATA +0 -621
  119. unrealon-1.1.5.dist-info/RECORD +0 -54
  120. unrealon-1.1.5.dist-info/entry_points.txt +0 -9
  121. unrealon_browser/managers/stealth.py +0 -388
  122. unrealon_driver/exceptions.py +0 -33
  123. unrealon_driver/html_analyzer/__init__.py +0 -32
  124. unrealon_driver/html_analyzer/cleaner.py +0 -657
  125. unrealon_driver/html_analyzer/config.py +0 -64
  126. unrealon_driver/html_analyzer/manager.py +0 -247
  127. unrealon_driver/html_analyzer/models.py +0 -115
  128. unrealon_driver/html_analyzer/websocket_analyzer.py +0 -157
  129. unrealon_driver/models/__init__.py +0 -31
  130. unrealon_driver/models/websocket.py +0 -98
  131. unrealon_driver/parser/__init__.py +0 -36
  132. unrealon_driver/parser/cli_manager.py +0 -142
  133. unrealon_driver/parser/daemon_manager.py +0 -403
  134. unrealon_driver/parser/managers/__init__.py +0 -25
  135. unrealon_driver/parser/managers/config.py +0 -293
  136. unrealon_driver/parser/managers/error.py +0 -412
  137. unrealon_driver/parser/managers/result.py +0 -321
  138. unrealon_driver/parser/parser_manager.py +0 -458
  139. unrealon_driver/smart_logging/__init__.py +0 -24
  140. unrealon_driver/smart_logging/models.py +0 -44
  141. unrealon_driver/smart_logging/smart_logger.py +0 -406
  142. unrealon_driver/smart_logging/unified_logger.py +0 -525
  143. unrealon_driver/websocket/__init__.py +0 -31
  144. unrealon_driver/websocket/client.py +0 -249
  145. unrealon_driver/websocket/config.py +0 -188
  146. unrealon_driver/websocket/manager.py +0 -90
@@ -0,0 +1,11 @@
1
+ """
2
+ Utility functions for UnrealOn Core.
3
+ """
4
+
5
+ from .time import utc_now, utc_timestamp, datetime_to_iso
6
+
7
+ __all__ = [
8
+ "utc_now",
9
+ "utc_timestamp",
10
+ "datetime_to_iso",
11
+ ]
@@ -0,0 +1,61 @@
1
+ """
2
+ Time utilities for UnrealOn.
3
+
4
+ Provides timezone-aware datetime functions to replace deprecated datetime.utc_now().
5
+ """
6
+
7
+ from datetime import datetime, timezone
8
+ from typing import Optional
9
+
10
+
11
+ def utc_now() -> datetime:
12
+ """
13
+ Get current UTC time as timezone-aware datetime.
14
+
15
+ Replacement for deprecated datetime.utc_now().
16
+
17
+ Returns:
18
+ datetime: Current UTC time with timezone info
19
+ """
20
+ return datetime.now(timezone.utc)
21
+
22
+
23
+ def utc_timestamp() -> str:
24
+ """
25
+ Get current UTC time as ISO format string.
26
+
27
+ Returns:
28
+ str: Current UTC time in ISO format
29
+ """
30
+ return utc_now().isoformat()
31
+
32
+
33
+ def datetime_to_iso(dt: Optional[datetime]) -> Optional[str]:
34
+ """
35
+ Convert datetime to ISO format string.
36
+
37
+ Args:
38
+ dt: Datetime to convert (can be None)
39
+
40
+ Returns:
41
+ str or None: ISO format string or None if input was None
42
+ """
43
+ if dt is None:
44
+ return None
45
+ return dt.isoformat()
46
+
47
+
48
+ def ensure_utc(dt: datetime) -> datetime:
49
+ """
50
+ Ensure datetime is timezone-aware and in UTC.
51
+
52
+ Args:
53
+ dt: Datetime to convert
54
+
55
+ Returns:
56
+ datetime: UTC timezone-aware datetime
57
+ """
58
+ if dt.tzinfo is None:
59
+ # Assume naive datetime is UTC
60
+ return dt.replace(tzinfo=timezone.utc)
61
+ return dt.astimezone(timezone.utc)
@@ -0,0 +1,219 @@
1
+ """
2
+ 🔄 UnrealOn Version Management
3
+
4
+ Unified version system for all UnrealOn packages.
5
+ This ensures version synchronization between driver, RPC server, and core components.
6
+ """
7
+
8
+ import tomlkit
9
+ from typing import Dict, Any
10
+ from pathlib import Path
11
+ from unrealon_core.utils.time import utc_timestamp
12
+
13
+
14
+ def _get_version_from_pyproject() -> str:
15
+ """Get version from main pyproject.toml."""
16
+ try:
17
+ # Go up from unrealon-core/src/unrealon_core to project root
18
+ project_root = Path(__file__).parent.parent.parent.parent
19
+ pyproject_path = project_root / "pyproject.toml"
20
+
21
+ if pyproject_path.exists():
22
+ with open(pyproject_path, "r") as f:
23
+ pyproject = tomlkit.parse(f.read())
24
+
25
+ # Try PEP 621 format first
26
+ if "project" in pyproject and "version" in pyproject["project"]:
27
+ return str(pyproject["project"]["version"])
28
+ # Fallback to Poetry format
29
+ elif "tool" in pyproject and "poetry" in pyproject["tool"] and "version" in pyproject["tool"]["poetry"]:
30
+ return str(pyproject["tool"]["poetry"]["version"])
31
+ except Exception:
32
+ pass
33
+
34
+ # Fallback version if can't read from pyproject.toml
35
+ return "2.0.0"
36
+
37
+
38
+ # 🎯 UNIFIED VERSION - Automatically synced from main pyproject.toml
39
+ __version__ = _get_version_from_pyproject()
40
+
41
+ # 📅 Release Information
42
+ __release_date__ = "2024-12-19"
43
+ __build_number__ = "20241219001"
44
+
45
+ # 🏷️ Version Components
46
+ VERSION_MAJOR = 4
47
+ VERSION_MINOR = 0
48
+ VERSION_PATCH = 0
49
+ VERSION_BUILD = "stable"
50
+
51
+ # 🔧 Package Compatibility Matrix
52
+ COMPATIBILITY_MATRIX = {
53
+ "unrealon_core": __version__,
54
+ "unrealon_rpc": __version__,
55
+ "unrealon_driver": __version__,
56
+ "unrealon_browser": __version__
57
+ }
58
+
59
+ # 📊 Version Metadata
60
+ VERSION_INFO = {
61
+ "version": __version__,
62
+ "major": VERSION_MAJOR,
63
+ "minor": VERSION_MINOR,
64
+ "patch": VERSION_PATCH,
65
+ "build": VERSION_BUILD,
66
+ "release_date": __release_date__,
67
+ "build_number": __build_number__,
68
+ "compatibility": COMPATIBILITY_MATRIX
69
+ }
70
+
71
+
72
+ def get_version() -> str:
73
+ """
74
+ Get the current UnrealOn version.
75
+
76
+ Returns:
77
+ str: Version string (e.g., "4.0.0")
78
+ """
79
+ return __version__
80
+
81
+
82
+ def get_version_info() -> Dict[str, Any]:
83
+ """
84
+ Get detailed version information.
85
+
86
+ Returns:
87
+ Dict[str, Any]: Complete version metadata
88
+ """
89
+ return VERSION_INFO.copy()
90
+
91
+
92
+ def get_build_info() -> Dict[str, Any]:
93
+ """
94
+ Get build information.
95
+
96
+ Returns:
97
+ Dict[str, Any]: Build metadata
98
+ """
99
+ return {
100
+ "version": __version__,
101
+ "build_number": __build_number__,
102
+ "release_date": __release_date__,
103
+ "build_type": VERSION_BUILD,
104
+ "timestamp": utc_timestamp()
105
+ }
106
+
107
+
108
+ def is_compatible_version(other_version: str) -> bool:
109
+ """
110
+ Check if another version is compatible with current version.
111
+
112
+ Args:
113
+ other_version: Version string to check
114
+
115
+ Returns:
116
+ bool: True if versions are compatible
117
+ """
118
+ try:
119
+ # For now, require exact match for stability
120
+ return other_version == __version__
121
+ except Exception:
122
+ return False
123
+
124
+
125
+ def get_compatibility_status(package_versions: Dict[str, str]) -> Dict[str, Any]:
126
+ """
127
+ Check compatibility status of multiple packages.
128
+
129
+ Args:
130
+ package_versions: Dict of package names to versions
131
+
132
+ Returns:
133
+ Dict[str, Any]: Compatibility report
134
+ """
135
+ compatible_packages = []
136
+ incompatible_packages = []
137
+
138
+ for package, version in package_versions.items():
139
+ expected_version = COMPATIBILITY_MATRIX.get(package)
140
+ if expected_version and version == expected_version:
141
+ compatible_packages.append(package)
142
+ else:
143
+ incompatible_packages.append({
144
+ "package": package,
145
+ "current": version,
146
+ "expected": expected_version
147
+ })
148
+
149
+ return {
150
+ "overall_compatible": len(incompatible_packages) == 0,
151
+ "compatible_packages": compatible_packages,
152
+ "incompatible_packages": incompatible_packages,
153
+ "total_packages": len(package_versions),
154
+ "compatibility_score": len(compatible_packages) / len(package_versions) if package_versions else 1.0
155
+ }
156
+
157
+
158
+ # 🎯 Convenience functions for specific packages
159
+ def get_core_version() -> str:
160
+ """Get unrealon_core version."""
161
+ return COMPATIBILITY_MATRIX["unrealon_core"]
162
+
163
+
164
+ def get_rpc_version() -> str:
165
+ """Get unrealon_rpc version."""
166
+ return COMPATIBILITY_MATRIX["unrealon_rpc"]
167
+
168
+
169
+ def get_driver_version() -> str:
170
+ """Get unrealon_driver version."""
171
+ return COMPATIBILITY_MATRIX["unrealon_driver"]
172
+
173
+
174
+ def get_browser_version() -> str:
175
+ """Get unrealon_browser version."""
176
+ return COMPATIBILITY_MATRIX["unrealon_browser"]
177
+
178
+
179
+ # 🔍 Version validation
180
+ def validate_version_format(version: str) -> bool:
181
+ """
182
+ Validate version string format.
183
+
184
+ Args:
185
+ version: Version string to validate
186
+
187
+ Returns:
188
+ bool: True if format is valid
189
+ """
190
+ try:
191
+ parts = version.split(".")
192
+ if len(parts) != 3:
193
+ return False
194
+
195
+ # Check if all parts are integers
196
+ for part in parts:
197
+ int(part)
198
+
199
+ return True
200
+ except (ValueError, AttributeError):
201
+ return False
202
+
203
+
204
+ # 📋 Export all version functions
205
+ __all__ = [
206
+ "__version__",
207
+ "VERSION_INFO",
208
+ "COMPATIBILITY_MATRIX",
209
+ "get_version",
210
+ "get_version_info",
211
+ "get_build_info",
212
+ "is_compatible_version",
213
+ "get_compatibility_status",
214
+ "get_core_version",
215
+ "get_rpc_version",
216
+ "get_driver_version",
217
+ "get_browser_version",
218
+ "validate_version_format"
219
+ ]
@@ -1,67 +1,105 @@
1
1
  """
2
- 🚀 UnrealOn Driver v4.0 - Modern Parser Framework
2
+ UnrealOn Driver SDK - Refactored
3
3
 
4
- Revolutionary parser framework with specialized managers and zero configuration.
5
- Built on unrealon-rpc bridge with full Pydantic v2 compliance.
4
+ Clean, simple, powerful API for parser development.
5
+ Simplified architecture with all original functionality.
6
6
 
7
7
  Key Features:
8
- - 🎯 Zero Configuration: Everything works out of the box
9
- - 🏗️ Manager Architecture: Specialized managers for different concerns
10
- - 🌐 Smart Browser: Intelligent automation with stealth
11
- - 🧹 HTML Cleaning: Optimized for LLM analysis
12
- - 🔌 Bridge Integration: Built on unrealon-rpc bridge
13
- - 📊 Built-in Monitoring: Enterprise observability
14
- - 🛡️ Type Safety: Full Pydantic v2 compliance
8
+ - UniversalDriver - Simple unified API
9
+ - All managers integrated cleanly
10
+ - WebSocket communication with RPC
11
+ - Module system for extensibility
12
+ - Clean decorator system
13
+ - No complex inheritance chains
15
14
  """
16
15
 
17
- from unrealon import VersionInfo
18
-
19
- __version__ = VersionInfo().version
16
+ # Version info
17
+ from unrealon_core.version import get_driver_version
20
18
 
19
+ # Core API - Simple and clean
20
+ from .driver import (
21
+ UniversalDriver,
22
+ DriverConfig,
23
+ DriverMode
24
+ )
21
25
 
22
- from .parser import (
23
- ParserManager,
24
- ParserManagerConfig,
25
- ParserStats,
26
- get_parser_manager,
27
- quick_parse,
28
- ConfigManager,
29
- ParserConfig,
30
- ResultManager,
31
- ParseResult,
32
- ParseMetrics,
33
- ErrorManager,
34
- RetryConfig,
35
- ErrorInfo,
26
+ from .driver.communication import (
27
+ DriverSession,
28
+ WebSocketClient
29
+ )
36
30
 
31
+ # Managers - Clean resource management
32
+ from .managers import (
33
+ LoggerManager,
34
+ HttpManager,
35
+ BrowserManager,
36
+ CacheManager,
37
+ ProxyManager,
38
+ ThreadManager,
39
+ UpdateManager,
40
+ ManagerRegistry
41
+ )
37
42
 
43
+ # Module system - Extensible architecture
44
+ from .core_module import (
45
+ BaseModule,
46
+ DriverModule,
47
+ ModuleConfig,
48
+ EventManager,
49
+ ModuleRegistry,
50
+ ModuleStatus,
51
+ EventType,
52
+ HealthStatus
38
53
  )
39
- from .exceptions import ParserError, BrowserError
40
54
 
41
- __all__ = [
42
- "__version__",
43
- # Main Parser Manager
44
- "ParserManager",
45
- "ParserManagerConfig",
46
- "ParserStats",
47
- "get_parser_manager",
48
- "quick_parse",
49
- # Individual Managers
50
- "ConfigManager",
51
- "ParserConfig",
52
- "ResultManager",
53
- "ParseResult",
54
- "ParseMetrics",
55
- "ErrorManager",
56
- "RetryConfig",
57
- "ErrorInfo",
55
+ # Decorators - Clean task management
56
+ from .decorators import (
57
+ task,
58
+ retry,
59
+ schedule,
60
+ timing
61
+ )
58
62
 
63
+ __version__ = get_driver_version()
64
+ __author__ = "UnrealOn Team"
65
+ __phase__ = "Phase 3.8: Clean Refactor"
59
66
 
60
- # Exceptions
61
- "ParserError",
62
- "BrowserError",
67
+ __all__ = [
63
68
  # Version
64
69
  "__version__",
70
+ "__author__",
71
+ "__phase__",
72
+
73
+ # Core API
74
+ "UniversalDriver",
75
+ "DriverConfig",
76
+ "DriverMode",
77
+ "DriverSession",
78
+ "WebSocketClient",
79
+
80
+ # Managers
81
+ "LoggerManager",
82
+ "HttpManager",
83
+ "BrowserManager",
84
+ "CacheManager",
85
+ "ProxyManager",
86
+ "ThreadManager",
87
+ "UpdateManager",
88
+ "ManagerRegistry",
89
+
90
+ # Module system
91
+ "BaseModule",
92
+ "DriverModule",
93
+ "ModuleConfig",
94
+ "EventManager",
95
+ "ModuleRegistry",
96
+ "ModuleStatus",
97
+ "EventType",
98
+ "HealthStatus",
99
+
100
+ # Decorators
101
+ "task",
102
+ "retry",
103
+ "schedule",
104
+ "timing",
65
105
  ]
66
- # Convenience aliases for backward compatibility
67
- Parser = ParserManager
@@ -0,0 +1,34 @@
1
+ """
2
+ Clean module system for UnrealOn Driver.
3
+ """
4
+
5
+ from .protocols import (
6
+ BaseModule,
7
+ ModuleStatus,
8
+ EventType,
9
+ HealthStatus,
10
+ ModuleEvent,
11
+ HealthCheckResult
12
+ )
13
+ from .config import ModuleConfig
14
+ from .base import DriverModule
15
+ from .event_manager import EventManager
16
+ from .registry import ModuleRegistry
17
+
18
+ __all__ = [
19
+ # Protocols and enums
20
+ "BaseModule",
21
+ "ModuleStatus",
22
+ "EventType",
23
+ "HealthStatus",
24
+ "ModuleEvent",
25
+ "HealthCheckResult",
26
+
27
+ # Base classes
28
+ "ModuleConfig",
29
+ "DriverModule",
30
+
31
+ # System components
32
+ "EventManager",
33
+ "ModuleRegistry",
34
+ ]
@@ -0,0 +1,184 @@
1
+ """
2
+ Clean base module implementation.
3
+ """
4
+
5
+ import asyncio
6
+ import logging
7
+ from abc import ABC, abstractmethod
8
+ from typing import Optional, Dict, Any
9
+
10
+ from .protocols import ModuleStatus, HealthStatus, HealthCheckResult, ModuleEvent, EventType
11
+ from .config import ModuleConfig
12
+ from ..utils.time import utc_now
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ class DriverModule(ABC):
18
+ """
19
+ Clean base module implementation.
20
+
21
+ Provides common functionality for all driver modules.
22
+ """
23
+
24
+ def __init__(self, config: ModuleConfig, driver_id: str):
25
+ self.config = config
26
+ self.driver_id = driver_id
27
+ self.name = config.module_name
28
+ self.status = ModuleStatus.UNINITIALIZED
29
+ self.logger = logging.getLogger(f"{__name__}.{self.name}")
30
+
31
+ # Event system
32
+ self.event_manager: Optional[Any] = None
33
+
34
+ async def initialize(self) -> bool:
35
+ """Initialize module."""
36
+ if not self.config.enabled:
37
+ self.logger.info(f"Module {self.name} is disabled")
38
+ self.status = ModuleStatus.STOPPED
39
+ return True
40
+
41
+ try:
42
+ self.status = ModuleStatus.INITIALIZING
43
+ self.logger.info(f"Initializing module: {self.name}")
44
+
45
+ success = await self._initialize()
46
+
47
+ if success:
48
+ self.status = ModuleStatus.INITIALIZED
49
+ self.logger.info(f"Module {self.name} initialized successfully")
50
+
51
+ # Emit event
52
+ await self._emit_event(EventType.MODULE_INITIALIZED)
53
+ else:
54
+ self.status = ModuleStatus.ERROR
55
+ self.logger.error(f"Module {self.name} initialization failed")
56
+
57
+ return success
58
+
59
+ except Exception as e:
60
+ self.status = ModuleStatus.ERROR
61
+ self.logger.error(f"Module {self.name} initialization error: {e}")
62
+ await self._emit_event(EventType.MODULE_ERROR, error=str(e))
63
+ return False
64
+
65
+ async def start(self) -> bool:
66
+ """Start module."""
67
+ if self.status != ModuleStatus.INITIALIZED:
68
+ self.logger.error(f"Cannot start module {self.name} - not initialized")
69
+ return False
70
+
71
+ try:
72
+ self.status = ModuleStatus.STARTING
73
+ self.logger.info(f"Starting module: {self.name}")
74
+
75
+ success = await self._start()
76
+
77
+ if success:
78
+ self.status = ModuleStatus.RUNNING
79
+ self.logger.info(f"Module {self.name} started successfully")
80
+
81
+ # Emit event
82
+ await self._emit_event(EventType.MODULE_STARTED)
83
+ else:
84
+ self.status = ModuleStatus.ERROR
85
+ self.logger.error(f"Module {self.name} start failed")
86
+
87
+ return success
88
+
89
+ except Exception as e:
90
+ self.status = ModuleStatus.ERROR
91
+ self.logger.error(f"Module {self.name} start error: {e}")
92
+ await self._emit_event(EventType.MODULE_ERROR, error=str(e))
93
+ return False
94
+
95
+ async def stop(self) -> None:
96
+ """Stop module."""
97
+ try:
98
+ self.status = ModuleStatus.STOPPING
99
+ self.logger.info(f"Stopping module: {self.name}")
100
+
101
+ await self._stop()
102
+
103
+ self.status = ModuleStatus.STOPPED
104
+ self.logger.info(f"Module {self.name} stopped successfully")
105
+
106
+ # Emit event
107
+ await self._emit_event(EventType.MODULE_STOPPED)
108
+
109
+ except Exception as e:
110
+ self.status = ModuleStatus.ERROR
111
+ self.logger.error(f"Module {self.name} stop error: {e}")
112
+ await self._emit_event(EventType.MODULE_ERROR, error=str(e))
113
+
114
+ async def health_check(self) -> HealthCheckResult:
115
+ """Perform health check."""
116
+ start_time = asyncio.get_event_loop().time()
117
+
118
+ try:
119
+ health_data = await self._health_check()
120
+
121
+ response_time = (asyncio.get_event_loop().time() - start_time) * 1000
122
+
123
+ return HealthCheckResult(
124
+ status=HealthStatus.HEALTHY,
125
+ timestamp=utc_now(),
126
+ details=health_data,
127
+ response_time_ms=response_time
128
+ )
129
+
130
+ except Exception as e:
131
+ response_time = (asyncio.get_event_loop().time() - start_time) * 1000
132
+
133
+ return HealthCheckResult(
134
+ status=HealthStatus.UNHEALTHY,
135
+ timestamp=utc_now(),
136
+ error=str(e),
137
+ response_time_ms=response_time
138
+ )
139
+
140
+ def set_event_manager(self, event_manager):
141
+ """Set event manager for event emission."""
142
+ self.event_manager = event_manager
143
+
144
+ async def _emit_event(self, event_type: EventType, data: Optional[Dict[str, Any]] = None, error: Optional[str] = None):
145
+ """Emit module event."""
146
+ if not self.event_manager:
147
+ return
148
+
149
+ try:
150
+ event = ModuleEvent(
151
+ event_type=event_type,
152
+ module_name=self.name,
153
+ timestamp=utc_now(),
154
+ data=data or {},
155
+ error=error
156
+ )
157
+
158
+ await self.event_manager.emit(event)
159
+
160
+ except Exception as e:
161
+ self.logger.error(f"Failed to emit event: {e}")
162
+
163
+ @abstractmethod
164
+ async def _initialize(self) -> bool:
165
+ """Module-specific initialization."""
166
+ pass
167
+
168
+ @abstractmethod
169
+ async def _start(self) -> bool:
170
+ """Module-specific start logic."""
171
+ pass
172
+
173
+ @abstractmethod
174
+ async def _stop(self) -> None:
175
+ """Module-specific stop logic."""
176
+ pass
177
+
178
+ async def _health_check(self) -> Dict[str, Any]:
179
+ """Module-specific health check."""
180
+ return {
181
+ "status": "ok",
182
+ "module": self.name,
183
+ "version": self.config.version
184
+ }
@@ -0,0 +1,30 @@
1
+ """
2
+ Clean module configuration.
3
+ """
4
+
5
+ from typing import Optional, Dict, Any
6
+ from pydantic import BaseModel, Field
7
+
8
+
9
+ class ModuleConfig(BaseModel):
10
+ """Base configuration for all modules."""
11
+
12
+ # Module identification
13
+ module_name: str = Field(..., description="Unique module name")
14
+ version: str = Field(default="1.0.0", description="Module version")
15
+
16
+ # Module behavior
17
+ enabled: bool = Field(default=True, description="Whether module is enabled")
18
+ auto_start: bool = Field(default=True, description="Auto-start on driver init")
19
+
20
+ # Performance
21
+ timeout_seconds: float = Field(default=30.0, description="Operation timeout")
22
+ retry_count: int = Field(default=3, description="Retry attempts")
23
+
24
+ # Health checks
25
+ health_check_interval: int = Field(default=60, description="Health check interval")
26
+
27
+ # Custom settings
28
+ custom_settings: Dict[str, Any] = Field(default_factory=dict, description="Module-specific settings")
29
+
30
+ model_config = {"extra": "forbid"}