unrealon 1.0.9__py3-none-any.whl → 1.1.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.
Files changed (302) hide show
  1. unrealon/__init__.py +23 -21
  2. unrealon-1.1.0.dist-info/METADATA +164 -0
  3. unrealon-1.1.0.dist-info/RECORD +82 -0
  4. {unrealon-1.0.9.dist-info → unrealon-1.1.0.dist-info}/WHEEL +1 -1
  5. unrealon-1.1.0.dist-info/entry_points.txt +9 -0
  6. {unrealon-1.0.9.dist-info → unrealon-1.1.0.dist-info/licenses}/LICENSE +1 -1
  7. unrealon_bridge/__init__.py +114 -0
  8. unrealon_bridge/cli.py +316 -0
  9. unrealon_bridge/client/__init__.py +93 -0
  10. unrealon_bridge/client/base.py +78 -0
  11. unrealon_bridge/client/commands.py +89 -0
  12. unrealon_bridge/client/connection.py +90 -0
  13. unrealon_bridge/client/events.py +65 -0
  14. unrealon_bridge/client/health.py +38 -0
  15. unrealon_bridge/client/html_parser.py +146 -0
  16. unrealon_bridge/client/logging.py +139 -0
  17. unrealon_bridge/client/proxy.py +70 -0
  18. unrealon_bridge/client/scheduler.py +450 -0
  19. unrealon_bridge/client/session.py +70 -0
  20. unrealon_bridge/configs/__init__.py +14 -0
  21. unrealon_bridge/configs/bridge_config.py +212 -0
  22. unrealon_bridge/configs/bridge_config.yaml +39 -0
  23. unrealon_bridge/models/__init__.py +138 -0
  24. unrealon_bridge/models/base.py +28 -0
  25. unrealon_bridge/models/command.py +41 -0
  26. unrealon_bridge/models/events.py +40 -0
  27. unrealon_bridge/models/html_parser.py +79 -0
  28. unrealon_bridge/models/logging.py +55 -0
  29. unrealon_bridge/models/parser.py +63 -0
  30. unrealon_bridge/models/proxy.py +41 -0
  31. unrealon_bridge/models/requests.py +95 -0
  32. unrealon_bridge/models/responses.py +88 -0
  33. unrealon_bridge/models/scheduler.py +592 -0
  34. unrealon_bridge/models/session.py +28 -0
  35. unrealon_bridge/server/__init__.py +91 -0
  36. unrealon_bridge/server/base.py +171 -0
  37. unrealon_bridge/server/handlers/__init__.py +23 -0
  38. unrealon_bridge/server/handlers/command.py +110 -0
  39. unrealon_bridge/server/handlers/html_parser.py +139 -0
  40. unrealon_bridge/server/handlers/logging.py +95 -0
  41. unrealon_bridge/server/handlers/parser.py +95 -0
  42. unrealon_bridge/server/handlers/proxy.py +75 -0
  43. unrealon_bridge/server/handlers/scheduler.py +545 -0
  44. unrealon_bridge/server/handlers/session.py +66 -0
  45. unrealon_browser/__init__.py +61 -18
  46. unrealon_browser/{src/cli → cli}/browser_cli.py +6 -13
  47. unrealon_browser/{src/cli → cli}/cookies_cli.py +5 -1
  48. unrealon_browser/{src/core → core}/browser_manager.py +2 -2
  49. unrealon_browser/{src/managers → managers}/captcha.py +1 -1
  50. unrealon_browser/{src/managers → managers}/cookies.py +1 -1
  51. unrealon_browser/managers/logger_bridge.py +231 -0
  52. unrealon_browser/{src/managers → managers}/profile.py +1 -1
  53. unrealon_driver/__init__.py +73 -19
  54. unrealon_driver/browser/__init__.py +8 -0
  55. unrealon_driver/browser/config.py +74 -0
  56. unrealon_driver/browser/manager.py +416 -0
  57. unrealon_driver/exceptions.py +28 -0
  58. unrealon_driver/parser/__init__.py +55 -0
  59. unrealon_driver/parser/cli_manager.py +141 -0
  60. unrealon_driver/parser/daemon_manager.py +227 -0
  61. unrealon_driver/parser/managers/__init__.py +46 -0
  62. unrealon_driver/parser/managers/browser.py +51 -0
  63. unrealon_driver/parser/managers/config.py +281 -0
  64. unrealon_driver/parser/managers/error.py +412 -0
  65. unrealon_driver/parser/managers/html.py +732 -0
  66. unrealon_driver/parser/managers/logging.py +609 -0
  67. unrealon_driver/parser/managers/result.py +321 -0
  68. unrealon_driver/parser/parser_manager.py +628 -0
  69. unrealon/sdk_config.py +0 -88
  70. unrealon-1.0.9.dist-info/METADATA +0 -810
  71. unrealon-1.0.9.dist-info/RECORD +0 -246
  72. unrealon_browser/pyproject.toml +0 -182
  73. unrealon_browser/src/__init__.py +0 -62
  74. unrealon_browser/src/managers/logger_bridge.py +0 -395
  75. unrealon_driver/README.md +0 -204
  76. unrealon_driver/pyproject.toml +0 -187
  77. unrealon_driver/src/__init__.py +0 -90
  78. unrealon_driver/src/cli/__init__.py +0 -10
  79. unrealon_driver/src/cli/main.py +0 -66
  80. unrealon_driver/src/cli/simple.py +0 -510
  81. unrealon_driver/src/config/__init__.py +0 -11
  82. unrealon_driver/src/config/auto_config.py +0 -478
  83. unrealon_driver/src/core/__init__.py +0 -18
  84. unrealon_driver/src/core/exceptions.py +0 -289
  85. unrealon_driver/src/core/parser.py +0 -638
  86. unrealon_driver/src/dto/__init__.py +0 -66
  87. unrealon_driver/src/dto/cli.py +0 -119
  88. unrealon_driver/src/dto/config.py +0 -18
  89. unrealon_driver/src/dto/events.py +0 -237
  90. unrealon_driver/src/dto/execution.py +0 -313
  91. unrealon_driver/src/dto/services.py +0 -311
  92. unrealon_driver/src/execution/__init__.py +0 -23
  93. unrealon_driver/src/execution/daemon_mode.py +0 -317
  94. unrealon_driver/src/execution/interactive_mode.py +0 -88
  95. unrealon_driver/src/execution/modes.py +0 -45
  96. unrealon_driver/src/execution/scheduled_mode.py +0 -209
  97. unrealon_driver/src/execution/test_mode.py +0 -250
  98. unrealon_driver/src/logging/__init__.py +0 -24
  99. unrealon_driver/src/logging/driver_logger.py +0 -512
  100. unrealon_driver/src/services/__init__.py +0 -24
  101. unrealon_driver/src/services/browser_service.py +0 -726
  102. unrealon_driver/src/services/llm/__init__.py +0 -15
  103. unrealon_driver/src/services/llm/browser_llm_service.py +0 -363
  104. unrealon_driver/src/services/llm/llm.py +0 -195
  105. unrealon_driver/src/services/logger_service.py +0 -232
  106. unrealon_driver/src/services/metrics_service.py +0 -185
  107. unrealon_driver/src/services/scheduler_service.py +0 -489
  108. unrealon_driver/src/services/websocket_service.py +0 -362
  109. unrealon_driver/src/utils/__init__.py +0 -16
  110. unrealon_driver/src/utils/service_factory.py +0 -317
  111. unrealon_driver/src/utils/time_formatter.py +0 -338
  112. unrealon_llm/README.md +0 -44
  113. unrealon_llm/__init__.py +0 -26
  114. unrealon_llm/pyproject.toml +0 -154
  115. unrealon_llm/src/__init__.py +0 -228
  116. unrealon_llm/src/cli/__init__.py +0 -0
  117. unrealon_llm/src/core/__init__.py +0 -11
  118. unrealon_llm/src/core/smart_client.py +0 -438
  119. unrealon_llm/src/dto/__init__.py +0 -155
  120. unrealon_llm/src/dto/models/__init__.py +0 -0
  121. unrealon_llm/src/dto/models/config.py +0 -343
  122. unrealon_llm/src/dto/models/core.py +0 -328
  123. unrealon_llm/src/dto/models/enums.py +0 -123
  124. unrealon_llm/src/dto/models/html_analysis.py +0 -345
  125. unrealon_llm/src/dto/models/statistics.py +0 -473
  126. unrealon_llm/src/dto/models/translation.py +0 -383
  127. unrealon_llm/src/dto/models/type_conversion.py +0 -462
  128. unrealon_llm/src/dto/schemas/__init__.py +0 -0
  129. unrealon_llm/src/exceptions.py +0 -392
  130. unrealon_llm/src/llm_config/__init__.py +0 -20
  131. unrealon_llm/src/llm_config/logging_config.py +0 -178
  132. unrealon_llm/src/llm_logging/__init__.py +0 -42
  133. unrealon_llm/src/llm_logging/llm_events.py +0 -107
  134. unrealon_llm/src/llm_logging/llm_logger.py +0 -466
  135. unrealon_llm/src/managers/__init__.py +0 -15
  136. unrealon_llm/src/managers/cache_manager.py +0 -67
  137. unrealon_llm/src/managers/cost_manager.py +0 -107
  138. unrealon_llm/src/managers/request_manager.py +0 -298
  139. unrealon_llm/src/modules/__init__.py +0 -0
  140. unrealon_llm/src/modules/html_processor/__init__.py +0 -25
  141. unrealon_llm/src/modules/html_processor/base_processor.py +0 -415
  142. unrealon_llm/src/modules/html_processor/details_processor.py +0 -85
  143. unrealon_llm/src/modules/html_processor/listing_processor.py +0 -91
  144. unrealon_llm/src/modules/html_processor/models/__init__.py +0 -20
  145. unrealon_llm/src/modules/html_processor/models/processing_models.py +0 -40
  146. unrealon_llm/src/modules/html_processor/models/universal_model.py +0 -56
  147. unrealon_llm/src/modules/html_processor/processor.py +0 -102
  148. unrealon_llm/src/modules/llm/__init__.py +0 -0
  149. unrealon_llm/src/modules/translator/__init__.py +0 -0
  150. unrealon_llm/src/provider.py +0 -116
  151. unrealon_llm/src/utils/__init__.py +0 -95
  152. unrealon_llm/src/utils/common.py +0 -64
  153. unrealon_llm/src/utils/data_extractor.py +0 -188
  154. unrealon_llm/src/utils/html_cleaner.py +0 -767
  155. unrealon_llm/src/utils/language_detector.py +0 -308
  156. unrealon_llm/src/utils/models_cache.py +0 -592
  157. unrealon_llm/src/utils/smart_counter.py +0 -229
  158. unrealon_llm/src/utils/token_counter.py +0 -189
  159. unrealon_sdk/README.md +0 -25
  160. unrealon_sdk/__init__.py +0 -30
  161. unrealon_sdk/pyproject.toml +0 -231
  162. unrealon_sdk/src/__init__.py +0 -150
  163. unrealon_sdk/src/cli/__init__.py +0 -12
  164. unrealon_sdk/src/cli/commands/__init__.py +0 -22
  165. unrealon_sdk/src/cli/commands/benchmark.py +0 -42
  166. unrealon_sdk/src/cli/commands/diagnostics.py +0 -573
  167. unrealon_sdk/src/cli/commands/health.py +0 -46
  168. unrealon_sdk/src/cli/commands/integration.py +0 -498
  169. unrealon_sdk/src/cli/commands/reports.py +0 -43
  170. unrealon_sdk/src/cli/commands/security.py +0 -36
  171. unrealon_sdk/src/cli/commands/server.py +0 -483
  172. unrealon_sdk/src/cli/commands/servers.py +0 -56
  173. unrealon_sdk/src/cli/commands/tests.py +0 -55
  174. unrealon_sdk/src/cli/main.py +0 -126
  175. unrealon_sdk/src/cli/utils/reporter.py +0 -519
  176. unrealon_sdk/src/clients/openapi.yaml +0 -3347
  177. unrealon_sdk/src/clients/python_http/__init__.py +0 -3
  178. unrealon_sdk/src/clients/python_http/api_config.py +0 -228
  179. unrealon_sdk/src/clients/python_http/models/BaseModel.py +0 -12
  180. unrealon_sdk/src/clients/python_http/models/BroadcastDeliveryStats.py +0 -33
  181. unrealon_sdk/src/clients/python_http/models/BroadcastMessage.py +0 -17
  182. unrealon_sdk/src/clients/python_http/models/BroadcastMessageRequest.py +0 -35
  183. unrealon_sdk/src/clients/python_http/models/BroadcastPriority.py +0 -10
  184. unrealon_sdk/src/clients/python_http/models/BroadcastResponse.py +0 -21
  185. unrealon_sdk/src/clients/python_http/models/BroadcastResultResponse.py +0 -33
  186. unrealon_sdk/src/clients/python_http/models/BroadcastTarget.py +0 -11
  187. unrealon_sdk/src/clients/python_http/models/ConnectionStats.py +0 -27
  188. unrealon_sdk/src/clients/python_http/models/ConnectionsResponse.py +0 -21
  189. unrealon_sdk/src/clients/python_http/models/DeveloperMessageResponse.py +0 -23
  190. unrealon_sdk/src/clients/python_http/models/ErrorResponse.py +0 -25
  191. unrealon_sdk/src/clients/python_http/models/HTTPValidationError.py +0 -16
  192. unrealon_sdk/src/clients/python_http/models/HealthResponse.py +0 -23
  193. unrealon_sdk/src/clients/python_http/models/HealthStatus.py +0 -33
  194. unrealon_sdk/src/clients/python_http/models/LogLevel.py +0 -10
  195. unrealon_sdk/src/clients/python_http/models/LoggingRequest.py +0 -27
  196. unrealon_sdk/src/clients/python_http/models/LoggingResponse.py +0 -23
  197. unrealon_sdk/src/clients/python_http/models/MaintenanceMode.py +0 -9
  198. unrealon_sdk/src/clients/python_http/models/MaintenanceModeRequest.py +0 -33
  199. unrealon_sdk/src/clients/python_http/models/MaintenanceStatusResponse.py +0 -39
  200. unrealon_sdk/src/clients/python_http/models/ParserCommandRequest.py +0 -25
  201. unrealon_sdk/src/clients/python_http/models/ParserMessageResponse.py +0 -21
  202. unrealon_sdk/src/clients/python_http/models/ParserRegistrationRequest.py +0 -28
  203. unrealon_sdk/src/clients/python_http/models/ParserRegistrationResponse.py +0 -25
  204. unrealon_sdk/src/clients/python_http/models/ParserType.py +0 -10
  205. unrealon_sdk/src/clients/python_http/models/ProxyBlockRequest.py +0 -19
  206. unrealon_sdk/src/clients/python_http/models/ProxyEndpointResponse.py +0 -20
  207. unrealon_sdk/src/clients/python_http/models/ProxyListResponse.py +0 -19
  208. unrealon_sdk/src/clients/python_http/models/ProxyProvider.py +0 -10
  209. unrealon_sdk/src/clients/python_http/models/ProxyPurchaseRequest.py +0 -25
  210. unrealon_sdk/src/clients/python_http/models/ProxyResponse.py +0 -47
  211. unrealon_sdk/src/clients/python_http/models/ProxyRotationRequest.py +0 -23
  212. unrealon_sdk/src/clients/python_http/models/ProxyStatus.py +0 -10
  213. unrealon_sdk/src/clients/python_http/models/ProxyUsageRequest.py +0 -19
  214. unrealon_sdk/src/clients/python_http/models/ProxyUsageStatsResponse.py +0 -26
  215. unrealon_sdk/src/clients/python_http/models/ServiceRegistrationDto.py +0 -23
  216. unrealon_sdk/src/clients/python_http/models/ServiceStatsResponse.py +0 -31
  217. unrealon_sdk/src/clients/python_http/models/SessionStartRequest.py +0 -23
  218. unrealon_sdk/src/clients/python_http/models/SuccessResponse.py +0 -25
  219. unrealon_sdk/src/clients/python_http/models/SystemNotificationResponse.py +0 -23
  220. unrealon_sdk/src/clients/python_http/models/ValidationError.py +0 -18
  221. unrealon_sdk/src/clients/python_http/models/ValidationErrorResponse.py +0 -21
  222. unrealon_sdk/src/clients/python_http/models/WebSocketMetrics.py +0 -21
  223. unrealon_sdk/src/clients/python_http/models/__init__.py +0 -44
  224. unrealon_sdk/src/clients/python_http/services/None_service.py +0 -35
  225. unrealon_sdk/src/clients/python_http/services/ParserManagement_service.py +0 -190
  226. unrealon_sdk/src/clients/python_http/services/ProxyManagement_service.py +0 -289
  227. unrealon_sdk/src/clients/python_http/services/SocketLogging_service.py +0 -187
  228. unrealon_sdk/src/clients/python_http/services/SystemHealth_service.py +0 -119
  229. unrealon_sdk/src/clients/python_http/services/WebSocketAPI_service.py +0 -198
  230. unrealon_sdk/src/clients/python_http/services/__init__.py +0 -0
  231. unrealon_sdk/src/clients/python_http/services/admin_service.py +0 -125
  232. unrealon_sdk/src/clients/python_http/services/async_None_service.py +0 -35
  233. unrealon_sdk/src/clients/python_http/services/async_ParserManagement_service.py +0 -190
  234. unrealon_sdk/src/clients/python_http/services/async_ProxyManagement_service.py +0 -289
  235. unrealon_sdk/src/clients/python_http/services/async_SocketLogging_service.py +0 -189
  236. unrealon_sdk/src/clients/python_http/services/async_SystemHealth_service.py +0 -123
  237. unrealon_sdk/src/clients/python_http/services/async_WebSocketAPI_service.py +0 -200
  238. unrealon_sdk/src/clients/python_http/services/async_admin_service.py +0 -125
  239. unrealon_sdk/src/clients/python_websocket/__init__.py +0 -28
  240. unrealon_sdk/src/clients/python_websocket/client.py +0 -490
  241. unrealon_sdk/src/clients/python_websocket/events.py +0 -732
  242. unrealon_sdk/src/clients/python_websocket/example.py +0 -136
  243. unrealon_sdk/src/clients/python_websocket/types.py +0 -871
  244. unrealon_sdk/src/core/__init__.py +0 -64
  245. unrealon_sdk/src/core/client.py +0 -556
  246. unrealon_sdk/src/core/config.py +0 -465
  247. unrealon_sdk/src/core/exceptions.py +0 -239
  248. unrealon_sdk/src/core/metadata.py +0 -191
  249. unrealon_sdk/src/core/models.py +0 -142
  250. unrealon_sdk/src/core/types.py +0 -68
  251. unrealon_sdk/src/dto/__init__.py +0 -268
  252. unrealon_sdk/src/dto/authentication.py +0 -108
  253. unrealon_sdk/src/dto/cache.py +0 -208
  254. unrealon_sdk/src/dto/common.py +0 -19
  255. unrealon_sdk/src/dto/concurrency.py +0 -393
  256. unrealon_sdk/src/dto/events.py +0 -108
  257. unrealon_sdk/src/dto/health.py +0 -339
  258. unrealon_sdk/src/dto/load_balancing.py +0 -336
  259. unrealon_sdk/src/dto/logging.py +0 -230
  260. unrealon_sdk/src/dto/performance.py +0 -165
  261. unrealon_sdk/src/dto/rate_limiting.py +0 -295
  262. unrealon_sdk/src/dto/resource_pooling.py +0 -128
  263. unrealon_sdk/src/dto/structured_logging.py +0 -112
  264. unrealon_sdk/src/dto/task_scheduling.py +0 -121
  265. unrealon_sdk/src/dto/websocket.py +0 -55
  266. unrealon_sdk/src/enterprise/__init__.py +0 -59
  267. unrealon_sdk/src/enterprise/authentication.py +0 -401
  268. unrealon_sdk/src/enterprise/cache_manager.py +0 -578
  269. unrealon_sdk/src/enterprise/error_recovery.py +0 -494
  270. unrealon_sdk/src/enterprise/event_system.py +0 -549
  271. unrealon_sdk/src/enterprise/health_monitor.py +0 -747
  272. unrealon_sdk/src/enterprise/load_balancer.py +0 -964
  273. unrealon_sdk/src/enterprise/logging/__init__.py +0 -68
  274. unrealon_sdk/src/enterprise/logging/cleanup.py +0 -156
  275. unrealon_sdk/src/enterprise/logging/development.py +0 -744
  276. unrealon_sdk/src/enterprise/logging/service.py +0 -410
  277. unrealon_sdk/src/enterprise/multithreading_manager.py +0 -853
  278. unrealon_sdk/src/enterprise/performance_monitor.py +0 -539
  279. unrealon_sdk/src/enterprise/proxy_manager.py +0 -696
  280. unrealon_sdk/src/enterprise/rate_limiter.py +0 -652
  281. unrealon_sdk/src/enterprise/resource_pool.py +0 -763
  282. unrealon_sdk/src/enterprise/task_scheduler.py +0 -709
  283. unrealon_sdk/src/internal/__init__.py +0 -10
  284. unrealon_sdk/src/internal/command_router.py +0 -497
  285. unrealon_sdk/src/internal/connection_manager.py +0 -397
  286. unrealon_sdk/src/internal/http_client.py +0 -446
  287. unrealon_sdk/src/internal/websocket_client.py +0 -420
  288. unrealon_sdk/src/provider.py +0 -471
  289. unrealon_sdk/src/utils.py +0 -234
  290. /unrealon_browser/{src/cli → cli}/__init__.py +0 -0
  291. /unrealon_browser/{src/cli → cli}/interactive_mode.py +0 -0
  292. /unrealon_browser/{src/cli → cli}/main.py +0 -0
  293. /unrealon_browser/{src/core → core}/__init__.py +0 -0
  294. /unrealon_browser/{src/dto → dto}/__init__.py +0 -0
  295. /unrealon_browser/{src/dto → dto}/models/config.py +0 -0
  296. /unrealon_browser/{src/dto → dto}/models/core.py +0 -0
  297. /unrealon_browser/{src/dto → dto}/models/dataclasses.py +0 -0
  298. /unrealon_browser/{src/dto → dto}/models/detection.py +0 -0
  299. /unrealon_browser/{src/dto → dto}/models/enums.py +0 -0
  300. /unrealon_browser/{src/dto → dto}/models/statistics.py +0 -0
  301. /unrealon_browser/{src/managers → managers}/__init__.py +0 -0
  302. /unrealon_browser/{src/managers → managers}/stealth.py +0 -0
@@ -1,510 +0,0 @@
1
- """
2
- UnrealOn Driver v3.0 Simple CLI
3
-
4
- Restored full Click-based CLI functionality from v2.0.
5
- KISS principle - does exactly what you need with new Driver v3.0 architecture.
6
- """
7
-
8
- import asyncio
9
- import signal
10
- import time
11
- from typing import Callable, Optional, Dict, Any
12
- from pathlib import Path
13
-
14
- import click
15
-
16
- from unrealon_driver.src.core.parser import Parser
17
- from unrealon_driver.src.dto.cli import ParserInstanceConfig, create_parser_config
18
- from unrealon_driver.src.config.auto_config import AutoConfig
19
- from unrealon_driver.src.dto.config import LogLevel
20
- from unrealon_driver.src.utils import TimeFormatter, ScheduleTimer, DaemonTimer
21
-
22
-
23
- class SimpleParser(Parser):
24
- """
25
- Enhanced Parser with Click CLI integration.
26
-
27
- Combines the revolutionary v3.0 Parser with the proven CLI system from v2.0.
28
- """
29
-
30
- def __init__(self, config: ParserInstanceConfig):
31
- """
32
- Initialize SimpleParser with Pydantic configuration.
33
-
34
- Args:
35
- config: ParserInstanceConfig with validated configuration
36
- """
37
- if not isinstance(config, ParserInstanceConfig):
38
- raise TypeError(f"Expected ParserInstanceConfig, got {type(config)}")
39
-
40
- # Store validated config
41
- self.cli_config = config
42
- # Initialize base Parser with converted config
43
- super().__init__(
44
- parser_id=config.parser_id,
45
- parser_name=config.parser_name,
46
- config=config.to_parser_config(),
47
- )
48
-
49
- # Override _config after super().__init__() for logger compatibility
50
- self._config = config
51
-
52
- # Shutdown event for graceful stopping
53
- self._shutdown_event = asyncio.Event()
54
-
55
- if self.logger:
56
- self.logger.info(f"🚀 SimpleParser initialized: {self.parser_name}")
57
-
58
- async def setup(self) -> None:
59
- """Setup parser resources (override in subclass if needed)."""
60
- if self.logger:
61
- self.logger.info("Setting up parser resources...")
62
-
63
- async def cleanup(self) -> None:
64
- """Cleanup parser resources (override in subclass if needed)."""
65
- if self.logger:
66
- self.logger.info("Cleaning up parser resources...")
67
- await super().cleanup()
68
-
69
- async def parse(self) -> dict:
70
- """
71
- Main parsing method - override this in your parser.
72
- Should return parsed data.
73
- """
74
- return await self.parse_data()
75
-
76
- async def parse_data(self) -> dict:
77
- """
78
- Override this method in your parser.
79
- Should return parsed data.
80
-
81
- Note: This is an alias for parse() method for CLI compatibility.
82
- """
83
- raise NotImplementedError(
84
- f"Parser '{self.parser_name}' must implement either parse() or parse_data() method."
85
- )
86
-
87
- def create_click_cli(self, custom_commands: Optional[Dict[str, Callable]] = None):
88
- """
89
- Create a Click CLI interface for this parser.
90
-
91
- Args:
92
- custom_commands: Dict of command_name -> async_function for custom commands
93
- """
94
-
95
- @click.group(invoke_without_command=True)
96
- @click.pass_context
97
- def cli(ctx):
98
- """Revolutionary parser CLI with zero configuration."""
99
- if ctx.invoked_subcommand is None:
100
- click.echo(f"🚀 {self.parser_name}")
101
- click.echo(
102
- f" {self.cli_config.description or 'Revolutionary web automation'}"
103
- )
104
- click.echo("\nAvailable commands:")
105
- click.echo(" test - Run test mode")
106
- click.echo(" daemon - Run daemon mode (WebSocket service)")
107
- click.echo(" scheduled - Run scheduled mode")
108
- click.echo(" interactive - Run interactive mode")
109
-
110
- if custom_commands:
111
- click.echo("\nCustom commands:")
112
- for cmd_name in custom_commands.keys():
113
- click.echo(f" {cmd_name}")
114
-
115
- @cli.command()
116
- @click.option("--verbose", "-v", is_flag=True, help="Verbose output")
117
- @click.option("--show-browser", is_flag=True, help="Show browser window")
118
- def test(verbose, show_browser):
119
- """Run parser in test mode."""
120
-
121
- async def run():
122
- start_time = time.time()
123
- try:
124
- click.echo(f"🧪 Starting {self.parser_name} test...")
125
- click.echo(f"🕐 Started at: {TimeFormatter.format_datetime()}")
126
-
127
- # Configure test options
128
- test_config = {}
129
- if verbose:
130
- test_config["verbose"] = True
131
- if show_browser:
132
- test_config["show_browser"] = True
133
-
134
- result = await self.test(**test_config)
135
-
136
- duration = time.time() - start_time
137
-
138
- if result["success"]:
139
- click.echo(f"✅ Test completed successfully in {TimeFormatter.format_duration(duration)}!")
140
- if result.get("data"):
141
- count = (
142
- len(result["data"])
143
- if isinstance(result["data"], (list, dict))
144
- else 1
145
- )
146
- click.echo(f"📊 Result: {count} items")
147
- else:
148
- click.echo(f"❌ Test failed after {TimeFormatter.format_duration(duration)}: {result['error']['message']}")
149
-
150
- except Exception as e:
151
- duration = time.time() - start_time
152
- click.echo(f"❌ Test error after {TimeFormatter.format_duration(duration)}: {e}")
153
- raise
154
-
155
- try:
156
- asyncio.run(run())
157
- except RuntimeError as e:
158
- if "cannot be called from a running event loop" in str(e):
159
- # Already in event loop, run synchronously
160
-
161
- loop = asyncio.get_event_loop()
162
- if loop.is_running():
163
- # Create task for running loop
164
- task = loop.create_task(run())
165
- # Don't await here as it would block
166
- else:
167
- asyncio.run(run())
168
- else:
169
- raise
170
-
171
- @cli.command()
172
- @click.option("--server", "-s", help="WebSocket server URL")
173
- @click.option("--api-key", "-k", help="API key for authentication")
174
- def daemon(server, api_key):
175
- """Run parser in daemon mode (WebSocket service)."""
176
-
177
- async def run():
178
- daemon_timer = DaemonTimer()
179
-
180
- try:
181
- click.echo(f"🔌 Starting {self.parser_name} daemon...")
182
- click.echo(f"🕐 Started at: {TimeFormatter.format_datetime()}")
183
- if server:
184
- click.echo(f"🌐 Server: {server}")
185
- if api_key:
186
- click.echo("🔑 API key provided")
187
- click.echo("Press Ctrl+C to stop\n")
188
-
189
- kwargs = {}
190
- if server:
191
- kwargs["server"] = server
192
- daemon_timer.connect()
193
- if api_key:
194
- kwargs["api_key"] = api_key
195
-
196
- # Start daemon with periodic status updates
197
- daemon_task = asyncio.create_task(self.daemon(**kwargs))
198
-
199
- # Status update task
200
- async def status_updates():
201
- while not daemon_task.done():
202
- await asyncio.sleep(30) # Every 30 seconds
203
- daemon_timer.heartbeat()
204
- click.echo(
205
- f"💓 Status - Uptime: {daemon_timer.get_uptime()}"
206
- )
207
-
208
- status_task = asyncio.create_task(status_updates())
209
-
210
- # Wait for completion
211
- await daemon_task
212
- status_task.cancel()
213
-
214
- except KeyboardInterrupt:
215
- click.echo(f"\n⏹️ Daemon stopped (Ctrl+C)")
216
- click.echo(f"⏰ Final uptime: {daemon_timer.get_uptime()}")
217
- except Exception as e:
218
- click.echo(f"❌ Daemon error: {e}")
219
- raise
220
-
221
- try:
222
- asyncio.run(run())
223
- except RuntimeError as e:
224
- if "cannot be called from a running event loop" in str(e):
225
- # Already in event loop, run synchronously
226
-
227
- loop = asyncio.get_event_loop()
228
- if loop.is_running():
229
- # Create task for running loop
230
- task = loop.create_task(run())
231
- # Don't await here as it would block
232
- else:
233
- asyncio.run(run())
234
- else:
235
- raise
236
-
237
- @cli.command()
238
- @click.option(
239
- "--every",
240
- "-e",
241
- default="30m",
242
- help="Execution interval (e.g., '30m', '1h', 'daily')",
243
- )
244
- @click.option(
245
- "--at", "-a", help="Time for daily/weekly schedules (e.g., '09:00')"
246
- )
247
- @click.option("--max-runs", type=int, help="Maximum number of runs")
248
- def scheduled(every, at, max_runs):
249
- """Run parser in scheduled mode."""
250
-
251
- async def run():
252
- schedule_timer = ScheduleTimer(every)
253
-
254
- try:
255
- click.echo(f"⏰ Starting {self.parser_name} scheduled mode...")
256
- click.echo(f"🕐 Started at: {TimeFormatter.format_datetime()}")
257
- click.echo(f"📅 Schedule: every {every}")
258
- if at:
259
- click.echo(f"🕘 At time: {at}")
260
- if max_runs:
261
- click.echo(f"🔢 Max runs: {max_runs}")
262
- click.echo("Press Ctrl+C to stop\n")
263
-
264
- kwargs = {"every": every}
265
- if at:
266
- kwargs["at"] = at
267
- if max_runs:
268
- kwargs["max_runs"] = max_runs
269
-
270
- # Custom schedule implementation with timing
271
- run_count = 0
272
- success_count = 0
273
-
274
- while True:
275
- if max_runs and run_count >= max_runs:
276
- click.echo(f"🏁 Reached maximum runs ({max_runs})")
277
- break
278
-
279
- # Start run timer
280
- schedule_timer.start_run()
281
- run_start = time.time()
282
-
283
- click.echo(
284
- f"🚀 Starting run #{run_count + 1} at {TimeFormatter.format_time()}"
285
- )
286
-
287
- try:
288
- # Execute parser
289
- result = await self.parse()
290
- duration = time.time() - run_start
291
-
292
- if result:
293
- success_count += 1
294
- click.echo(
295
- f"✅ Run #{run_count + 1} completed in {TimeFormatter.format_duration(duration)}"
296
- )
297
- else:
298
- click.echo(
299
- f"❌ Run #{run_count + 1} failed after {TimeFormatter.format_duration(duration)}"
300
- )
301
-
302
- except Exception as e:
303
- duration = time.time() - run_start
304
- click.echo(
305
- f"❌ Run #{run_count + 1} error after {TimeFormatter.format_duration(duration)}: {e}"
306
- )
307
-
308
- run_count += 1
309
-
310
- # Show status
311
- click.echo(
312
- f"📊 Progress: {success_count}/{run_count} successful"
313
- )
314
- click.echo(
315
- f"⏰ Total elapsed: {schedule_timer.get_elapsed_total()}"
316
- )
317
-
318
- if max_runs and run_count >= max_runs:
319
- break
320
-
321
- # Show next run info
322
- click.echo(
323
- f"🕐 Next run at: {TimeFormatter.format_time(schedule_timer.next_run)}"
324
- )
325
- click.echo(
326
- f"⏳ Waiting: {schedule_timer.get_time_until_next()}"
327
- )
328
-
329
- # Sleep until next run with live countdown
330
- sleep_seconds = TimeFormatter.parse_interval(every)
331
-
332
- def countdown_callback(current_time, remaining_time, remaining_seconds, update_in_place=False):
333
- if update_in_place:
334
- # Live update on same line
335
- import sys
336
- sys.stdout.write(f"\r⏳ {current_time} - Time remaining: {remaining_time}")
337
- sys.stdout.flush()
338
- else:
339
- click.echo(f"⏳ {current_time} - Time remaining: {remaining_time}")
340
-
341
- await TimeFormatter.countdown_sleep(sleep_seconds, countdown_callback)
342
-
343
- except KeyboardInterrupt:
344
- click.echo(f"\n⏹️ Scheduled mode stopped (Ctrl+C)")
345
- click.echo(
346
- f"⏰ Total runtime: {schedule_timer.get_elapsed_total()}"
347
- )
348
- click.echo(f"🔄 Runs completed: {schedule_timer.run_count}")
349
- except Exception as e:
350
- click.echo(f"❌ Scheduled mode error: {e}")
351
- raise
352
-
353
- try:
354
- asyncio.run(run())
355
- except RuntimeError as e:
356
- if "cannot be called from a running event loop" in str(e):
357
- # Already in event loop, run synchronously
358
-
359
- loop = asyncio.get_event_loop()
360
- if loop.is_running():
361
- # Create task for running loop
362
- task = loop.create_task(run())
363
- # Don't await here as it would block
364
- else:
365
- asyncio.run(run())
366
- else:
367
- raise
368
-
369
- @cli.command()
370
- def interactive():
371
- """Run parser in interactive mode."""
372
-
373
- async def run():
374
- start_time = time.time()
375
- try:
376
- click.echo(f"🎮 Starting {self.parser_name} interactive mode...")
377
- click.echo(f"🕐 Started at: {TimeFormatter.format_datetime()}")
378
- await self.interactive()
379
- except KeyboardInterrupt:
380
- duration = time.time() - start_time
381
- click.echo(f"⏹️ Interactive mode stopped (Ctrl+C)")
382
- click.echo(f"⏰ Session duration: {TimeFormatter.format_duration(duration)}")
383
- except Exception as e:
384
- duration = time.time() - start_time
385
- click.echo(f"❌ Interactive mode error after {TimeFormatter.format_duration(duration)}: {e}")
386
- raise
387
-
388
- try:
389
- asyncio.run(run())
390
- except RuntimeError as e:
391
- if "cannot be called from a running event loop" in str(e):
392
- # Already in event loop, run synchronously
393
-
394
- loop = asyncio.get_event_loop()
395
- if loop.is_running():
396
- # Create task for running loop
397
- task = loop.create_task(run())
398
- # Don't await here as it would block
399
- else:
400
- asyncio.run(run())
401
- else:
402
- raise
403
-
404
- # Add custom commands
405
- if custom_commands:
406
- for cmd_name, cmd_func in custom_commands.items():
407
-
408
- @cli.command(name=cmd_name)
409
- @click.pass_context
410
- def custom_cmd(ctx, _cmd_func=cmd_func):
411
- """Custom command."""
412
-
413
- async def run():
414
- try:
415
- result = await _cmd_func(self)
416
- if result:
417
- click.echo("✅ Command completed!")
418
- except Exception as e:
419
- click.echo(f"❌ Command error: {e}")
420
- raise
421
-
422
- try:
423
- asyncio.run(run())
424
- except RuntimeError as e:
425
- if "cannot be called from a running event loop" in str(e):
426
- # Already in event loop, run synchronously
427
- try:
428
- loop = asyncio.get_event_loop()
429
- if loop.is_running():
430
- # Create task for running loop
431
- task = loop.create_task(run())
432
- # Don't await here as it would block
433
- else:
434
- asyncio.run(run())
435
- except RuntimeError:
436
- # No event loop, just skip
437
- pass
438
- else:
439
- raise
440
-
441
- return cli
442
-
443
- # Legacy compatibility methods from v2.0
444
- async def run_test(self) -> dict:
445
- """Legacy compatibility: run parser in test mode."""
446
- result = await self.test()
447
- if hasattr(result, "data") and result.data is not None:
448
- return result.data
449
- elif hasattr(result, "data") and isinstance(result.data, dict):
450
- return result.data
451
- elif isinstance(result, dict):
452
- return result
453
- else:
454
- return {}
455
-
456
- async def run_daemon(self) -> None:
457
- """Legacy compatibility: run parser in daemon mode."""
458
- await self.daemon()
459
-
460
- async def run_scheduled(self) -> None:
461
- """Legacy compatibility: run parser in scheduled mode."""
462
- every = getattr(self, "scheduled_interval", "30m")
463
- await self.schedule(every=str(every))
464
-
465
-
466
- # Convenience function for quick Click CLI creation
467
- def create_click_parser_cli(
468
- parser_class: type,
469
- parser_id: str,
470
- parser_name: Optional[str] = None,
471
- description: Optional[str] = None,
472
- custom_commands: Optional[Dict[str, Callable]] = None,
473
- **config_kwargs,
474
- ):
475
- """
476
- Create a Click CLI for a parser class.
477
-
478
- Args:
479
- parser_class: Parser class (should inherit from SimpleParser)
480
- parser_id: Unique parser identifier
481
- parser_name: Human-readable name
482
- description: Parser description
483
- custom_commands: Dict of command_name -> async_function for custom commands
484
- **config_kwargs: Additional config parameters
485
-
486
- Returns:
487
- Click CLI group ready to run
488
-
489
- Usage:
490
- if __name__ == "__main__":
491
- cli = create_click_parser_cli(
492
- MyParser,
493
- "my_parser",
494
- custom_commands={"custom": my_custom_func}
495
- )
496
- cli()
497
- """
498
- # Create parser config
499
- config = create_parser_config(
500
- parser_id=parser_id,
501
- parser_name=parser_name,
502
- description=description,
503
- **config_kwargs,
504
- )
505
-
506
- # Create parser instance
507
- parser = parser_class(config)
508
-
509
- # Create and return CLI
510
- return parser.create_click_cli(custom_commands)
@@ -1,11 +0,0 @@
1
- """
2
- Configuration system for UnrealOn Driver v3.0
3
-
4
- Zero-configuration system with intelligent defaults and environment detection.
5
- """
6
-
7
- from .auto_config import AutoConfig
8
-
9
- __all__ = [
10
- "AutoConfig",
11
- ]