crackerjack 0.33.0__py3-none-any.whl → 0.33.2__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.

Potentially problematic release.


This version of crackerjack might be problematic. Click here for more details.

Files changed (198) hide show
  1. crackerjack/__main__.py +1350 -34
  2. crackerjack/adapters/__init__.py +17 -0
  3. crackerjack/adapters/lsp_client.py +358 -0
  4. crackerjack/adapters/rust_tool_adapter.py +194 -0
  5. crackerjack/adapters/rust_tool_manager.py +193 -0
  6. crackerjack/adapters/skylos_adapter.py +231 -0
  7. crackerjack/adapters/zuban_adapter.py +560 -0
  8. crackerjack/agents/base.py +7 -3
  9. crackerjack/agents/coordinator.py +271 -33
  10. crackerjack/agents/documentation_agent.py +9 -15
  11. crackerjack/agents/dry_agent.py +3 -15
  12. crackerjack/agents/formatting_agent.py +1 -1
  13. crackerjack/agents/import_optimization_agent.py +36 -180
  14. crackerjack/agents/performance_agent.py +17 -98
  15. crackerjack/agents/performance_helpers.py +7 -31
  16. crackerjack/agents/proactive_agent.py +1 -3
  17. crackerjack/agents/refactoring_agent.py +16 -85
  18. crackerjack/agents/refactoring_helpers.py +7 -42
  19. crackerjack/agents/security_agent.py +9 -48
  20. crackerjack/agents/test_creation_agent.py +356 -513
  21. crackerjack/agents/test_specialist_agent.py +0 -4
  22. crackerjack/api.py +6 -25
  23. crackerjack/cli/cache_handlers.py +204 -0
  24. crackerjack/cli/cache_handlers_enhanced.py +683 -0
  25. crackerjack/cli/facade.py +100 -0
  26. crackerjack/cli/handlers.py +224 -9
  27. crackerjack/cli/interactive.py +6 -4
  28. crackerjack/cli/options.py +642 -55
  29. crackerjack/cli/utils.py +2 -1
  30. crackerjack/code_cleaner.py +58 -117
  31. crackerjack/config/global_lock_config.py +8 -48
  32. crackerjack/config/hooks.py +53 -62
  33. crackerjack/core/async_workflow_orchestrator.py +24 -34
  34. crackerjack/core/autofix_coordinator.py +3 -17
  35. crackerjack/core/enhanced_container.py +4 -13
  36. crackerjack/core/file_lifecycle.py +12 -89
  37. crackerjack/core/performance.py +2 -2
  38. crackerjack/core/performance_monitor.py +15 -55
  39. crackerjack/core/phase_coordinator.py +104 -204
  40. crackerjack/core/resource_manager.py +14 -90
  41. crackerjack/core/service_watchdog.py +62 -95
  42. crackerjack/core/session_coordinator.py +149 -0
  43. crackerjack/core/timeout_manager.py +14 -72
  44. crackerjack/core/websocket_lifecycle.py +13 -78
  45. crackerjack/core/workflow_orchestrator.py +171 -174
  46. crackerjack/docs/INDEX.md +11 -0
  47. crackerjack/docs/generated/api/API_REFERENCE.md +10895 -0
  48. crackerjack/docs/generated/api/CLI_REFERENCE.md +109 -0
  49. crackerjack/docs/generated/api/CROSS_REFERENCES.md +1755 -0
  50. crackerjack/docs/generated/api/PROTOCOLS.md +3 -0
  51. crackerjack/docs/generated/api/SERVICES.md +1252 -0
  52. crackerjack/documentation/__init__.py +31 -0
  53. crackerjack/documentation/ai_templates.py +756 -0
  54. crackerjack/documentation/dual_output_generator.py +765 -0
  55. crackerjack/documentation/mkdocs_integration.py +518 -0
  56. crackerjack/documentation/reference_generator.py +977 -0
  57. crackerjack/dynamic_config.py +55 -50
  58. crackerjack/executors/async_hook_executor.py +10 -15
  59. crackerjack/executors/cached_hook_executor.py +117 -43
  60. crackerjack/executors/hook_executor.py +8 -34
  61. crackerjack/executors/hook_lock_manager.py +26 -183
  62. crackerjack/executors/individual_hook_executor.py +13 -11
  63. crackerjack/executors/lsp_aware_hook_executor.py +270 -0
  64. crackerjack/executors/tool_proxy.py +417 -0
  65. crackerjack/hooks/lsp_hook.py +79 -0
  66. crackerjack/intelligence/adaptive_learning.py +25 -10
  67. crackerjack/intelligence/agent_orchestrator.py +2 -5
  68. crackerjack/intelligence/agent_registry.py +34 -24
  69. crackerjack/intelligence/agent_selector.py +5 -7
  70. crackerjack/interactive.py +17 -6
  71. crackerjack/managers/async_hook_manager.py +0 -1
  72. crackerjack/managers/hook_manager.py +79 -1
  73. crackerjack/managers/publish_manager.py +44 -8
  74. crackerjack/managers/test_command_builder.py +1 -15
  75. crackerjack/managers/test_executor.py +1 -3
  76. crackerjack/managers/test_manager.py +98 -7
  77. crackerjack/managers/test_manager_backup.py +10 -9
  78. crackerjack/mcp/cache.py +2 -2
  79. crackerjack/mcp/client_runner.py +1 -1
  80. crackerjack/mcp/context.py +191 -68
  81. crackerjack/mcp/dashboard.py +7 -5
  82. crackerjack/mcp/enhanced_progress_monitor.py +31 -28
  83. crackerjack/mcp/file_monitor.py +30 -23
  84. crackerjack/mcp/progress_components.py +31 -21
  85. crackerjack/mcp/progress_monitor.py +50 -53
  86. crackerjack/mcp/rate_limiter.py +6 -6
  87. crackerjack/mcp/server_core.py +17 -16
  88. crackerjack/mcp/service_watchdog.py +2 -1
  89. crackerjack/mcp/state.py +4 -7
  90. crackerjack/mcp/task_manager.py +11 -9
  91. crackerjack/mcp/tools/core_tools.py +173 -32
  92. crackerjack/mcp/tools/error_analyzer.py +3 -2
  93. crackerjack/mcp/tools/execution_tools.py +8 -10
  94. crackerjack/mcp/tools/execution_tools_backup.py +42 -30
  95. crackerjack/mcp/tools/intelligence_tool_registry.py +7 -5
  96. crackerjack/mcp/tools/intelligence_tools.py +5 -2
  97. crackerjack/mcp/tools/monitoring_tools.py +33 -70
  98. crackerjack/mcp/tools/proactive_tools.py +24 -11
  99. crackerjack/mcp/tools/progress_tools.py +5 -8
  100. crackerjack/mcp/tools/utility_tools.py +20 -14
  101. crackerjack/mcp/tools/workflow_executor.py +62 -40
  102. crackerjack/mcp/websocket/app.py +8 -0
  103. crackerjack/mcp/websocket/endpoints.py +352 -357
  104. crackerjack/mcp/websocket/jobs.py +40 -57
  105. crackerjack/mcp/websocket/monitoring_endpoints.py +2935 -0
  106. crackerjack/mcp/websocket/server.py +7 -25
  107. crackerjack/mcp/websocket/websocket_handler.py +6 -17
  108. crackerjack/mixins/__init__.py +0 -2
  109. crackerjack/mixins/error_handling.py +1 -70
  110. crackerjack/models/config.py +12 -1
  111. crackerjack/models/config_adapter.py +49 -1
  112. crackerjack/models/protocols.py +122 -122
  113. crackerjack/models/resource_protocols.py +55 -210
  114. crackerjack/monitoring/ai_agent_watchdog.py +13 -13
  115. crackerjack/monitoring/metrics_collector.py +426 -0
  116. crackerjack/monitoring/regression_prevention.py +8 -8
  117. crackerjack/monitoring/websocket_server.py +643 -0
  118. crackerjack/orchestration/advanced_orchestrator.py +11 -6
  119. crackerjack/orchestration/coverage_improvement.py +3 -3
  120. crackerjack/orchestration/execution_strategies.py +26 -6
  121. crackerjack/orchestration/test_progress_streamer.py +8 -5
  122. crackerjack/plugins/base.py +2 -2
  123. crackerjack/plugins/hooks.py +7 -0
  124. crackerjack/plugins/managers.py +11 -8
  125. crackerjack/security/__init__.py +0 -1
  126. crackerjack/security/audit.py +6 -35
  127. crackerjack/services/anomaly_detector.py +392 -0
  128. crackerjack/services/api_extractor.py +615 -0
  129. crackerjack/services/backup_service.py +2 -2
  130. crackerjack/services/bounded_status_operations.py +15 -152
  131. crackerjack/services/cache.py +127 -1
  132. crackerjack/services/changelog_automation.py +395 -0
  133. crackerjack/services/config.py +15 -9
  134. crackerjack/services/config_merge.py +19 -80
  135. crackerjack/services/config_template.py +506 -0
  136. crackerjack/services/contextual_ai_assistant.py +48 -22
  137. crackerjack/services/coverage_badge_service.py +171 -0
  138. crackerjack/services/coverage_ratchet.py +27 -25
  139. crackerjack/services/debug.py +3 -3
  140. crackerjack/services/dependency_analyzer.py +460 -0
  141. crackerjack/services/dependency_monitor.py +14 -11
  142. crackerjack/services/documentation_generator.py +491 -0
  143. crackerjack/services/documentation_service.py +675 -0
  144. crackerjack/services/enhanced_filesystem.py +6 -5
  145. crackerjack/services/enterprise_optimizer.py +865 -0
  146. crackerjack/services/error_pattern_analyzer.py +676 -0
  147. crackerjack/services/file_hasher.py +1 -1
  148. crackerjack/services/git.py +8 -25
  149. crackerjack/services/health_metrics.py +10 -8
  150. crackerjack/services/heatmap_generator.py +735 -0
  151. crackerjack/services/initialization.py +11 -30
  152. crackerjack/services/input_validator.py +5 -97
  153. crackerjack/services/intelligent_commit.py +327 -0
  154. crackerjack/services/log_manager.py +15 -12
  155. crackerjack/services/logging.py +4 -3
  156. crackerjack/services/lsp_client.py +628 -0
  157. crackerjack/services/memory_optimizer.py +19 -87
  158. crackerjack/services/metrics.py +42 -33
  159. crackerjack/services/parallel_executor.py +9 -67
  160. crackerjack/services/pattern_cache.py +1 -1
  161. crackerjack/services/pattern_detector.py +6 -6
  162. crackerjack/services/performance_benchmarks.py +18 -59
  163. crackerjack/services/performance_cache.py +20 -81
  164. crackerjack/services/performance_monitor.py +27 -95
  165. crackerjack/services/predictive_analytics.py +510 -0
  166. crackerjack/services/quality_baseline.py +234 -0
  167. crackerjack/services/quality_baseline_enhanced.py +646 -0
  168. crackerjack/services/quality_intelligence.py +785 -0
  169. crackerjack/services/regex_patterns.py +618 -524
  170. crackerjack/services/regex_utils.py +43 -123
  171. crackerjack/services/secure_path_utils.py +5 -164
  172. crackerjack/services/secure_status_formatter.py +30 -141
  173. crackerjack/services/secure_subprocess.py +11 -92
  174. crackerjack/services/security.py +9 -41
  175. crackerjack/services/security_logger.py +12 -24
  176. crackerjack/services/server_manager.py +124 -16
  177. crackerjack/services/status_authentication.py +16 -159
  178. crackerjack/services/status_security_manager.py +4 -131
  179. crackerjack/services/thread_safe_status_collector.py +19 -125
  180. crackerjack/services/unified_config.py +21 -13
  181. crackerjack/services/validation_rate_limiter.py +5 -54
  182. crackerjack/services/version_analyzer.py +459 -0
  183. crackerjack/services/version_checker.py +1 -1
  184. crackerjack/services/websocket_resource_limiter.py +10 -144
  185. crackerjack/services/zuban_lsp_service.py +390 -0
  186. crackerjack/slash_commands/__init__.py +2 -7
  187. crackerjack/slash_commands/run.md +2 -2
  188. crackerjack/tools/validate_input_validator_patterns.py +14 -40
  189. crackerjack/tools/validate_regex_patterns.py +19 -48
  190. {crackerjack-0.33.0.dist-info → crackerjack-0.33.2.dist-info}/METADATA +196 -25
  191. crackerjack-0.33.2.dist-info/RECORD +229 -0
  192. crackerjack/CLAUDE.md +0 -207
  193. crackerjack/RULES.md +0 -380
  194. crackerjack/py313.py +0 -234
  195. crackerjack-0.33.0.dist-info/RECORD +0 -187
  196. {crackerjack-0.33.0.dist-info → crackerjack-0.33.2.dist-info}/WHEEL +0 -0
  197. {crackerjack-0.33.0.dist-info → crackerjack-0.33.2.dist-info}/entry_points.txt +0 -0
  198. {crackerjack-0.33.0.dist-info → crackerjack-0.33.2.dist-info}/licenses/LICENSE +0 -0
@@ -1,9 +1,3 @@
1
- """WebSocket and network resource lifecycle management.
2
-
3
- Provides comprehensive cleanup patterns for WebSocket connections,
4
- HTTP clients, and network resources to prevent resource leaks.
5
- """
6
-
7
1
  import asyncio
8
2
  import contextlib
9
3
  import logging
@@ -19,11 +13,9 @@ from .resource_manager import ManagedResource, ResourceManager
19
13
 
20
14
 
21
15
  class ManagedWebSocketConnection(ManagedResource):
22
- """WebSocket connection with automatic cleanup on error scenarios."""
23
-
24
16
  def __init__(
25
17
  self,
26
- websocket: t.Any, # websockets protocols have import issues
18
+ websocket: t.Any,
27
19
  manager: ResourceManager | None = None,
28
20
  ) -> None:
29
21
  super().__init__(manager)
@@ -31,20 +23,17 @@ class ManagedWebSocketConnection(ManagedResource):
31
23
  self.logger = logging.getLogger(__name__)
32
24
 
33
25
  async def cleanup(self) -> None:
34
- """Clean up WebSocket connection."""
35
26
  if not self._closed and not self.websocket.closed:
36
27
  self._closed = True
37
28
 
38
29
  try:
39
30
  await asyncio.wait_for(self.websocket.close(), timeout=5.0)
40
31
  except (TimeoutError, websockets.ConnectionClosed):
41
- # Expected when connection is already closed or times out
42
32
  pass
43
33
  except Exception as e:
44
34
  self.logger.warning(f"Error closing WebSocket connection: {e}")
45
35
 
46
36
  async def send_safe(self, message: str) -> bool:
47
- """Send message safely, returning True if successful."""
48
37
  if self._closed or self.websocket.closed:
49
38
  return False
50
39
 
@@ -61,8 +50,6 @@ class ManagedWebSocketConnection(ManagedResource):
61
50
 
62
51
 
63
52
  class ManagedHTTPClient(ManagedResource):
64
- """HTTP client session with automatic cleanup."""
65
-
66
53
  def __init__(
67
54
  self,
68
55
  session: aiohttp.ClientSession,
@@ -72,7 +59,6 @@ class ManagedHTTPClient(ManagedResource):
72
59
  self.session = session
73
60
 
74
61
  async def cleanup(self) -> None:
75
- """Clean up HTTP client session."""
76
62
  if not self._closed and not self.session.closed:
77
63
  self._closed = True
78
64
 
@@ -83,8 +69,6 @@ class ManagedHTTPClient(ManagedResource):
83
69
 
84
70
 
85
71
  class ManagedWebSocketServer(ManagedResource):
86
- """WebSocket server with comprehensive lifecycle management."""
87
-
88
72
  def __init__(
89
73
  self,
90
74
  port: int,
@@ -94,7 +78,7 @@ class ManagedWebSocketServer(ManagedResource):
94
78
  super().__init__(manager)
95
79
  self.port = port
96
80
  self.host = host
97
- self.server: t.Any | None = None # websockets server type has import issues
81
+ self.server: t.Any | None = None
98
82
  self.connections: set[ManagedWebSocketConnection] = set()
99
83
  self.logger = logging.getLogger(__name__)
100
84
  self._server_task: asyncio.Task[t.Any] | None = None
@@ -103,13 +87,11 @@ class ManagedWebSocketServer(ManagedResource):
103
87
  self,
104
88
  handler: t.Callable[[t.Any], t.Awaitable[None]],
105
89
  ) -> None:
106
- """Start the WebSocket server."""
107
90
  if self.server:
108
91
  return
109
92
 
110
- # Wrap handler to manage connections
111
93
  async def managed_handler(
112
- websocket: t.Any, # websocket protocol type
94
+ websocket: t.Any,
113
95
  ) -> None:
114
96
  managed_conn = ManagedWebSocketConnection(websocket, self.manager)
115
97
  self.connections.add(managed_conn)
@@ -124,26 +106,24 @@ class ManagedWebSocketServer(ManagedResource):
124
106
  managed_handler,
125
107
  self.host,
126
108
  self.port,
127
- # Configure timeouts and limits
128
109
  ping_interval=20,
129
110
  ping_timeout=10,
130
111
  close_timeout=10,
131
- max_size=2**20, # 1MB
112
+ max_size=2**20,
132
113
  max_queue=32,
133
114
  )
134
115
 
135
- self.logger.info(f"WebSocket server started on {self.host}:{self.port}")
116
+ self.logger.info(f"WebSocket server started on {self.host}: {self.port}")
136
117
 
137
118
  async def cleanup(self) -> None:
138
- """Clean up WebSocket server and all connections."""
139
119
  if self._closed:
140
120
  return
141
121
  self._closed = True
142
122
 
143
- # Close all active connections
144
123
  if self.connections:
145
124
  close_tasks = [
146
- asyncio.create_task(conn.cleanup()) for conn in list(self.connections)
125
+ asyncio.create_task(conn.cleanup())
126
+ for conn in list[t.Any](self.connections)
147
127
  ]
148
128
 
149
129
  if close_tasks:
@@ -151,7 +131,6 @@ class ManagedWebSocketServer(ManagedResource):
151
131
 
152
132
  self.connections.clear()
153
133
 
154
- # Close server
155
134
  if self.server:
156
135
  try:
157
136
  self.server.close()
@@ -163,13 +142,10 @@ class ManagedWebSocketServer(ManagedResource):
163
142
  self.server = None
164
143
 
165
144
  def get_connection_count(self) -> int:
166
- """Get the number of active connections."""
167
145
  return len([conn for conn in self.connections if not conn._closed])
168
146
 
169
147
 
170
148
  class ManagedSubprocess(ManagedResource):
171
- """Subprocess with enhanced lifecycle management and resource cleanup."""
172
-
173
149
  def __init__(
174
150
  self,
175
151
  process: subprocess.Popen[bytes],
@@ -183,19 +159,16 @@ class ManagedSubprocess(ManagedResource):
183
159
  self._monitor_task: asyncio.Task[t.Any] | None = None
184
160
 
185
161
  async def start_monitoring(self) -> None:
186
- """Start monitoring the process for unexpected termination."""
187
162
  if self._monitor_task:
188
163
  return
189
164
 
190
165
  self._monitor_task = asyncio.create_task(self._monitor_process())
191
166
 
192
167
  async def _monitor_process(self) -> None:
193
- """Monitor process health and log unexpected terminations."""
194
168
  try:
195
169
  while self.process.poll() is None:
196
170
  await asyncio.sleep(5.0)
197
171
 
198
- # Process has terminated
199
172
  return_code = self.process.returncode
200
173
  if return_code != 0:
201
174
  self.logger.warning(
@@ -207,12 +180,10 @@ class ManagedSubprocess(ManagedResource):
207
180
  self.logger.warning(f"Error monitoring process: {e}")
208
181
 
209
182
  async def cleanup(self) -> None:
210
- """Clean up subprocess with graceful termination."""
211
183
  if self._closed:
212
184
  return
213
185
  self._closed = True
214
186
 
215
- # Cancel monitoring
216
187
  if self._monitor_task and not self._monitor_task.done():
217
188
  self._monitor_task.cancel()
218
189
  try:
@@ -220,10 +191,8 @@ class ManagedSubprocess(ManagedResource):
220
191
  except asyncio.CancelledError:
221
192
  pass
222
193
 
223
- # Clean up process
224
194
  if self.process.poll() is None:
225
195
  try:
226
- # Try graceful termination first
227
196
  self.process.terminate()
228
197
 
229
198
  try:
@@ -232,7 +201,6 @@ class ManagedSubprocess(ManagedResource):
232
201
  f"Process {self.process.pid} terminated gracefully"
233
202
  )
234
203
  except subprocess.TimeoutExpired:
235
- # Force kill if graceful termination fails
236
204
  self.process.kill()
237
205
  try:
238
206
  self.process.wait(timeout=2.0)
@@ -243,7 +211,6 @@ class ManagedSubprocess(ManagedResource):
243
211
  )
244
212
 
245
213
  except ProcessLookupError:
246
- # Process already terminated
247
214
  pass
248
215
  except Exception as e:
249
216
  self.logger.warning(
@@ -251,13 +218,10 @@ class ManagedSubprocess(ManagedResource):
251
218
  )
252
219
 
253
220
  def is_running(self) -> bool:
254
- """Check if the process is still running."""
255
221
  return not self._closed and self.process.poll() is None
256
222
 
257
223
 
258
224
  class NetworkResourceManager:
259
- """Manager for network-related resources with health monitoring."""
260
-
261
225
  def __init__(self) -> None:
262
226
  self.resource_manager = ResourceManager()
263
227
  self.logger = logging.getLogger(__name__)
@@ -267,7 +231,6 @@ class NetworkResourceManager:
267
231
  port: int,
268
232
  host: str = "127.0.0.1",
269
233
  ) -> ManagedWebSocketServer:
270
- """Create a managed WebSocket server."""
271
234
  server = ManagedWebSocketServer(port, host, self.resource_manager)
272
235
  return server
273
236
 
@@ -276,7 +239,6 @@ class NetworkResourceManager:
276
239
  timeout: aiohttp.ClientTimeout | None = None,
277
240
  **kwargs: t.Any,
278
241
  ) -> ManagedHTTPClient:
279
- """Create a managed HTTP client session."""
280
242
  timeout = timeout or aiohttp.ClientTimeout(total=30.0)
281
243
  session = aiohttp.ClientSession(timeout=timeout, **kwargs)
282
244
  return ManagedHTTPClient(session, self.resource_manager)
@@ -286,16 +248,14 @@ class NetworkResourceManager:
286
248
  process: subprocess.Popen[bytes],
287
249
  timeout: float = 30.0,
288
250
  ) -> ManagedSubprocess:
289
- """Create a managed subprocess."""
290
251
  return ManagedSubprocess(process, timeout, self.resource_manager)
291
252
 
292
253
  async def check_port_available(self, port: int, host: str = "127.0.0.1") -> bool:
293
- """Check if a port is available for binding."""
294
254
  try:
295
255
  with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
296
256
  sock.settimeout(1.0)
297
257
  result = sock.connect_ex((host, port))
298
- return result != 0 # Port is available if connection fails
258
+ return result != 0
299
259
  except Exception:
300
260
  return False
301
261
 
@@ -306,7 +266,6 @@ class NetworkResourceManager:
306
266
  timeout: float = 30.0,
307
267
  poll_interval: float = 0.5,
308
268
  ) -> bool:
309
- """Wait for a port to become available (service to start)."""
310
269
  start_time = time.time()
311
270
 
312
271
  while time.time() - start_time < timeout:
@@ -314,7 +273,7 @@ class NetworkResourceManager:
314
273
  with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
315
274
  sock.settimeout(1.0)
316
275
  result = sock.connect_ex((host, port))
317
- if result == 0: # Connection successful
276
+ if result == 0:
318
277
  return True
319
278
 
320
279
  await asyncio.sleep(poll_interval)
@@ -322,7 +281,6 @@ class NetworkResourceManager:
322
281
  return False
323
282
 
324
283
  async def cleanup_all(self) -> None:
325
- """Clean up all managed network resources."""
326
284
  await self.resource_manager.cleanup_all()
327
285
 
328
286
  async def __aenter__(self) -> "NetworkResourceManager":
@@ -337,14 +295,12 @@ class NetworkResourceManager:
337
295
  await self.cleanup_all()
338
296
 
339
297
 
340
- # Context manager helpers for common network resource patterns
341
298
  @contextlib.asynccontextmanager
342
299
  async def with_websocket_server(
343
300
  port: int,
344
301
  handler: t.Callable[[t.Any], t.Awaitable[None]],
345
302
  host: str = "127.0.0.1",
346
- ):
347
- """Context manager for a WebSocket server with automatic cleanup."""
303
+ ) -> t.AsyncIterator[t.Any]:
348
304
  async with NetworkResourceManager() as manager:
349
305
  server = await manager.create_websocket_server(port, host)
350
306
  try:
@@ -355,8 +311,7 @@ async def with_websocket_server(
355
311
 
356
312
 
357
313
  @contextlib.asynccontextmanager
358
- async def with_http_client(**kwargs: t.Any):
359
- """Context manager for an HTTP client with automatic cleanup."""
314
+ async def with_http_client(**kwargs: t.Any) -> t.AsyncIterator[t.Any]:
360
315
  async with NetworkResourceManager() as manager:
361
316
  client = await manager.create_http_client(**kwargs)
362
317
  try:
@@ -370,10 +325,8 @@ async def with_managed_subprocess(
370
325
  command: list[str],
371
326
  timeout: float = 30.0,
372
327
  **popen_kwargs: t.Any,
373
- ):
374
- """Context manager for a subprocess with automatic cleanup."""
328
+ ) -> t.AsyncIterator[t.Any]:
375
329
  async with NetworkResourceManager() as manager:
376
- # Ensure we get bytes output for consistent type handling
377
330
  process = subprocess.Popen[bytes](command, text=False, **popen_kwargs)
378
331
  managed_proc = manager.create_subprocess(process, timeout)
379
332
  try:
@@ -384,8 +337,6 @@ async def with_managed_subprocess(
384
337
 
385
338
 
386
339
  class WebSocketHealthMonitor:
387
- """Health monitor for WebSocket connections and servers."""
388
-
389
340
  def __init__(self, check_interval: float = 30.0) -> None:
390
341
  self.check_interval = check_interval
391
342
  self.monitored_servers: list[ManagedWebSocketServer] = []
@@ -393,23 +344,19 @@ class WebSocketHealthMonitor:
393
344
  self._monitor_task: asyncio.Task[t.Any] | None = None
394
345
 
395
346
  def add_server(self, server: ManagedWebSocketServer) -> None:
396
- """Add a server to health monitoring."""
397
347
  self.monitored_servers.append(server)
398
348
 
399
349
  def remove_server(self, server: ManagedWebSocketServer) -> None:
400
- """Remove a server from health monitoring."""
401
350
  if server in self.monitored_servers:
402
351
  self.monitored_servers.remove(server)
403
352
 
404
353
  async def start_monitoring(self) -> None:
405
- """Start health monitoring."""
406
354
  if self._monitor_task:
407
355
  return
408
356
 
409
357
  self._monitor_task = asyncio.create_task(self._monitor_loop())
410
358
 
411
359
  async def stop_monitoring(self) -> None:
412
- """Stop health monitoring."""
413
360
  if self._monitor_task and not self._monitor_task.done():
414
361
  self._monitor_task.cancel()
415
362
  try:
@@ -418,7 +365,6 @@ class WebSocketHealthMonitor:
418
365
  pass
419
366
 
420
367
  async def _monitor_loop(self) -> None:
421
- """Main monitoring loop."""
422
368
  try:
423
369
  while True:
424
370
  for server in self.monitored_servers.copy():
@@ -433,37 +379,26 @@ class WebSocketHealthMonitor:
433
379
  pass
434
380
 
435
381
  async def _check_server_health(self, server: ManagedWebSocketServer) -> None:
436
- """Check health of a specific server."""
437
382
  if server._closed:
438
383
  self.remove_server(server)
439
384
  return
440
385
 
441
386
  connection_count = server.get_connection_count()
442
387
 
443
- # Log health metrics
444
388
  self.logger.debug(
445
- f"Server {server.host}:{server.port} - "
389
+ f"Server {server.host}: {server.port} - "
446
390
  f"Active connections: {connection_count}"
447
391
  )
448
392
 
449
- # Could add more sophisticated health checks here:
450
- # - Memory usage monitoring
451
- # - Connection rate limiting
452
- # - Error rate monitoring
453
- # - Automatic restart on failure
454
-
455
393
 
456
- # Global network resource cleanup
457
394
  _global_network_managers: list[NetworkResourceManager] = []
458
395
 
459
396
 
460
397
  def register_network_manager(manager: NetworkResourceManager) -> None:
461
- """Register a network resource manager for global cleanup."""
462
398
  _global_network_managers.append(manager)
463
399
 
464
400
 
465
401
  async def cleanup_all_network_resources() -> None:
466
- """Clean up all globally registered network resource managers."""
467
402
  cleanup_tasks = [
468
403
  asyncio.create_task(manager.cleanup_all())
469
404
  for manager in _global_network_managers