conson-xp 1.18.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 (176) hide show
  1. conson_xp-1.18.0.dist-info/METADATA +412 -0
  2. conson_xp-1.18.0.dist-info/RECORD +176 -0
  3. conson_xp-1.18.0.dist-info/WHEEL +4 -0
  4. conson_xp-1.18.0.dist-info/entry_points.txt +5 -0
  5. conson_xp-1.18.0.dist-info/licenses/LICENSE +29 -0
  6. xp/__init__.py +9 -0
  7. xp/cli/__init__.py +5 -0
  8. xp/cli/__main__.py +6 -0
  9. xp/cli/commands/__init__.py +153 -0
  10. xp/cli/commands/conbus/__init__.py +25 -0
  11. xp/cli/commands/conbus/conbus.py +128 -0
  12. xp/cli/commands/conbus/conbus_actiontable_commands.py +233 -0
  13. xp/cli/commands/conbus/conbus_autoreport_commands.py +108 -0
  14. xp/cli/commands/conbus/conbus_blink_commands.py +163 -0
  15. xp/cli/commands/conbus/conbus_config_commands.py +29 -0
  16. xp/cli/commands/conbus/conbus_custom_commands.py +57 -0
  17. xp/cli/commands/conbus/conbus_datapoint_commands.py +113 -0
  18. xp/cli/commands/conbus/conbus_discover_commands.py +61 -0
  19. xp/cli/commands/conbus/conbus_event_commands.py +81 -0
  20. xp/cli/commands/conbus/conbus_lightlevel_commands.py +207 -0
  21. xp/cli/commands/conbus/conbus_linknumber_commands.py +102 -0
  22. xp/cli/commands/conbus/conbus_modulenumber_commands.py +104 -0
  23. xp/cli/commands/conbus/conbus_msactiontable_commands.py +94 -0
  24. xp/cli/commands/conbus/conbus_output_commands.py +163 -0
  25. xp/cli/commands/conbus/conbus_raw_commands.py +62 -0
  26. xp/cli/commands/conbus/conbus_receive_commands.py +59 -0
  27. xp/cli/commands/conbus/conbus_scan_commands.py +58 -0
  28. xp/cli/commands/file_commands.py +186 -0
  29. xp/cli/commands/homekit/__init__.py +3 -0
  30. xp/cli/commands/homekit/homekit.py +118 -0
  31. xp/cli/commands/homekit/homekit_start_commands.py +43 -0
  32. xp/cli/commands/module_commands.py +187 -0
  33. xp/cli/commands/reverse_proxy_commands.py +178 -0
  34. xp/cli/commands/server/__init__.py +3 -0
  35. xp/cli/commands/server/server_commands.py +135 -0
  36. xp/cli/commands/telegram/__init__.py +5 -0
  37. xp/cli/commands/telegram/telegram.py +41 -0
  38. xp/cli/commands/telegram/telegram_blink_commands.py +79 -0
  39. xp/cli/commands/telegram/telegram_checksum_commands.py +112 -0
  40. xp/cli/commands/telegram/telegram_discover_commands.py +41 -0
  41. xp/cli/commands/telegram/telegram_linknumber_commands.py +86 -0
  42. xp/cli/commands/telegram/telegram_parse_commands.py +75 -0
  43. xp/cli/commands/telegram/telegram_version_commands.py +52 -0
  44. xp/cli/main.py +87 -0
  45. xp/cli/utils/__init__.py +1 -0
  46. xp/cli/utils/click_tree.py +57 -0
  47. xp/cli/utils/datapoint_type_choice.py +57 -0
  48. xp/cli/utils/decorators.py +351 -0
  49. xp/cli/utils/error_handlers.py +201 -0
  50. xp/cli/utils/formatters.py +312 -0
  51. xp/cli/utils/module_type_choice.py +56 -0
  52. xp/cli/utils/serial_number_type.py +52 -0
  53. xp/cli/utils/system_function_choice.py +57 -0
  54. xp/cli/utils/xp_module_type.py +53 -0
  55. xp/connection/__init__.py +13 -0
  56. xp/connection/exceptions.py +22 -0
  57. xp/models/__init__.py +36 -0
  58. xp/models/actiontable/__init__.py +1 -0
  59. xp/models/actiontable/actiontable.py +43 -0
  60. xp/models/actiontable/msactiontable_xp20.py +53 -0
  61. xp/models/actiontable/msactiontable_xp24.py +58 -0
  62. xp/models/actiontable/msactiontable_xp33.py +65 -0
  63. xp/models/conbus/__init__.py +1 -0
  64. xp/models/conbus/conbus.py +87 -0
  65. xp/models/conbus/conbus_autoreport.py +67 -0
  66. xp/models/conbus/conbus_blink.py +80 -0
  67. xp/models/conbus/conbus_client_config.py +55 -0
  68. xp/models/conbus/conbus_connection_status.py +40 -0
  69. xp/models/conbus/conbus_custom.py +58 -0
  70. xp/models/conbus/conbus_datapoint.py +89 -0
  71. xp/models/conbus/conbus_discover.py +64 -0
  72. xp/models/conbus/conbus_event_raw.py +47 -0
  73. xp/models/conbus/conbus_lightlevel.py +52 -0
  74. xp/models/conbus/conbus_linknumber.py +54 -0
  75. xp/models/conbus/conbus_output.py +57 -0
  76. xp/models/conbus/conbus_raw.py +45 -0
  77. xp/models/conbus/conbus_receive.py +42 -0
  78. xp/models/conbus/conbus_writeconfig.py +60 -0
  79. xp/models/homekit/__init__.py +1 -0
  80. xp/models/homekit/homekit_accessory.py +35 -0
  81. xp/models/homekit/homekit_config.py +106 -0
  82. xp/models/homekit/homekit_conson_config.py +86 -0
  83. xp/models/log_entry.py +130 -0
  84. xp/models/protocol/__init__.py +1 -0
  85. xp/models/protocol/conbus_protocol.py +312 -0
  86. xp/models/response.py +42 -0
  87. xp/models/telegram/__init__.py +1 -0
  88. xp/models/telegram/action_type.py +31 -0
  89. xp/models/telegram/datapoint_type.py +82 -0
  90. xp/models/telegram/event_telegram.py +140 -0
  91. xp/models/telegram/event_type.py +15 -0
  92. xp/models/telegram/input_action_type.py +69 -0
  93. xp/models/telegram/input_type.py +17 -0
  94. xp/models/telegram/module_type.py +188 -0
  95. xp/models/telegram/module_type_code.py +205 -0
  96. xp/models/telegram/output_telegram.py +103 -0
  97. xp/models/telegram/reply_telegram.py +297 -0
  98. xp/models/telegram/system_function.py +116 -0
  99. xp/models/telegram/system_telegram.py +94 -0
  100. xp/models/telegram/telegram.py +28 -0
  101. xp/models/telegram/telegram_type.py +19 -0
  102. xp/models/telegram/timeparam_type.py +51 -0
  103. xp/models/write_config_type.py +33 -0
  104. xp/services/__init__.py +26 -0
  105. xp/services/actiontable/__init__.py +1 -0
  106. xp/services/actiontable/actiontable_serializer.py +273 -0
  107. xp/services/actiontable/msactiontable_serializer.py +7 -0
  108. xp/services/actiontable/msactiontable_xp20_serializer.py +169 -0
  109. xp/services/actiontable/msactiontable_xp24_serializer.py +120 -0
  110. xp/services/actiontable/msactiontable_xp33_serializer.py +239 -0
  111. xp/services/conbus/__init__.py +1 -0
  112. xp/services/conbus/actiontable/__init__.py +1 -0
  113. xp/services/conbus/actiontable/actiontable_download_service.py +158 -0
  114. xp/services/conbus/actiontable/actiontable_list_service.py +91 -0
  115. xp/services/conbus/actiontable/actiontable_show_service.py +89 -0
  116. xp/services/conbus/actiontable/actiontable_upload_service.py +211 -0
  117. xp/services/conbus/actiontable/msactiontable_service.py +232 -0
  118. xp/services/conbus/conbus_blink_all_service.py +181 -0
  119. xp/services/conbus/conbus_blink_service.py +158 -0
  120. xp/services/conbus/conbus_custom_service.py +156 -0
  121. xp/services/conbus/conbus_datapoint_queryall_service.py +182 -0
  122. xp/services/conbus/conbus_datapoint_service.py +170 -0
  123. xp/services/conbus/conbus_discover_service.py +312 -0
  124. xp/services/conbus/conbus_event_raw_service.py +181 -0
  125. xp/services/conbus/conbus_output_service.py +194 -0
  126. xp/services/conbus/conbus_raw_service.py +122 -0
  127. xp/services/conbus/conbus_receive_service.py +115 -0
  128. xp/services/conbus/conbus_scan_service.py +150 -0
  129. xp/services/conbus/write_config_service.py +194 -0
  130. xp/services/homekit/__init__.py +1 -0
  131. xp/services/homekit/homekit_cache_service.py +307 -0
  132. xp/services/homekit/homekit_conbus_service.py +93 -0
  133. xp/services/homekit/homekit_config_validator.py +310 -0
  134. xp/services/homekit/homekit_conson_validator.py +121 -0
  135. xp/services/homekit/homekit_dimminglight.py +182 -0
  136. xp/services/homekit/homekit_dimminglight_service.py +148 -0
  137. xp/services/homekit/homekit_hap_service.py +342 -0
  138. xp/services/homekit/homekit_lightbulb.py +120 -0
  139. xp/services/homekit/homekit_lightbulb_service.py +86 -0
  140. xp/services/homekit/homekit_module_service.py +56 -0
  141. xp/services/homekit/homekit_outlet.py +168 -0
  142. xp/services/homekit/homekit_outlet_service.py +121 -0
  143. xp/services/homekit/homekit_service.py +359 -0
  144. xp/services/log_file_service.py +309 -0
  145. xp/services/module_type_service.py +257 -0
  146. xp/services/protocol/__init__.py +21 -0
  147. xp/services/protocol/conbus_event_protocol.py +360 -0
  148. xp/services/protocol/conbus_protocol.py +318 -0
  149. xp/services/protocol/protocol_factory.py +78 -0
  150. xp/services/protocol/telegram_protocol.py +264 -0
  151. xp/services/reverse_proxy_service.py +435 -0
  152. xp/services/server/__init__.py +1 -0
  153. xp/services/server/base_server_service.py +366 -0
  154. xp/services/server/cp20_server_service.py +65 -0
  155. xp/services/server/device_service_factory.py +94 -0
  156. xp/services/server/server_service.py +428 -0
  157. xp/services/server/xp130_server_service.py +67 -0
  158. xp/services/server/xp20_server_service.py +92 -0
  159. xp/services/server/xp230_server_service.py +58 -0
  160. xp/services/server/xp24_server_service.py +245 -0
  161. xp/services/server/xp33_server_service.py +535 -0
  162. xp/services/telegram/__init__.py +1 -0
  163. xp/services/telegram/telegram_blink_service.py +138 -0
  164. xp/services/telegram/telegram_checksum_service.py +149 -0
  165. xp/services/telegram/telegram_datapoint_service.py +82 -0
  166. xp/services/telegram/telegram_discover_service.py +277 -0
  167. xp/services/telegram/telegram_link_number_service.py +216 -0
  168. xp/services/telegram/telegram_output_service.py +322 -0
  169. xp/services/telegram/telegram_service.py +380 -0
  170. xp/services/telegram/telegram_version_service.py +288 -0
  171. xp/utils/__init__.py +12 -0
  172. xp/utils/checksum.py +61 -0
  173. xp/utils/dependencies.py +531 -0
  174. xp/utils/event_helper.py +31 -0
  175. xp/utils/serialization.py +205 -0
  176. xp/utils/time_utils.py +134 -0
@@ -0,0 +1,351 @@
1
+ """Common decorators for CLI commands."""
2
+
3
+ import functools
4
+ from typing import Any, Callable, Tuple, Type
5
+
6
+ import click
7
+
8
+ from xp.cli.utils.formatters import OutputFormatter
9
+
10
+
11
+ def handle_service_errors(
12
+ *service_exceptions: Type[Exception],
13
+ ) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
14
+ """Handle common service exceptions with consistent JSON error formatting.
15
+
16
+ Args:
17
+ service_exceptions: Tuple of exception types to catch and handle.
18
+
19
+ Returns:
20
+ Decorator function that wraps commands with error handling.
21
+ """
22
+
23
+ def decorator(func: Callable[..., Any]) -> Callable[..., Any]:
24
+ """Apply error handling to the decorated function.
25
+
26
+ Args:
27
+ func: The function to decorate.
28
+
29
+ Returns:
30
+ Wrapped function with error handling.
31
+ """
32
+
33
+ @functools.wraps(func)
34
+ def wrapper(*args: Any, **kwargs: Any) -> Any:
35
+ """Execute function with error handling.
36
+
37
+ Args:
38
+ args: Positional arguments passed to the decorated function.
39
+ kwargs: Keyword arguments passed to the decorated function.
40
+
41
+ Returns:
42
+ Result from the decorated function.
43
+
44
+ Raises:
45
+ SystemExit: When a service exception or unexpected error occurs.
46
+ """
47
+ formatter = OutputFormatter(True)
48
+
49
+ try:
50
+ return func(*args, **kwargs)
51
+ except service_exceptions as e:
52
+ error_response = formatter.error_response(str(e))
53
+ click.echo(error_response)
54
+ raise SystemExit(1)
55
+ except Exception as e:
56
+ # Handle unexpected errors
57
+ error_response = formatter.error_response(f"Unexpected error: {e}")
58
+ click.echo(error_response)
59
+ raise SystemExit(1)
60
+
61
+ return wrapper
62
+
63
+ return decorator
64
+
65
+
66
+ def common_options(func: Callable[..., Any]) -> Callable[..., Any]:
67
+ """Add validation option to command.
68
+
69
+ Args:
70
+ func: The function to decorate.
71
+
72
+ Returns:
73
+ Decorated function with common options.
74
+ """
75
+ return func
76
+
77
+
78
+ def telegram_parser_command(
79
+ service_exceptions: Tuple[Type[Exception], ...] = (),
80
+ ) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
81
+ """Apply telegram parsing commands with standard error handling.
82
+
83
+ Args:
84
+ service_exceptions: Additional service exceptions to handle.
85
+
86
+ Returns:
87
+ Decorator function for telegram parsing commands.
88
+ """
89
+
90
+ def decorator(func: Callable[..., Any]) -> Callable[..., Any]:
91
+ """Apply telegram parser decorators.
92
+
93
+ Args:
94
+ func: The function to decorate.
95
+
96
+ Returns:
97
+ Decorated function with telegram parsing support.
98
+ """
99
+ # Apply common options
100
+ func = common_options(func)
101
+
102
+ # Apply error handling for telegram parsing
103
+ from xp.services.telegram.telegram_service import TelegramParsingError
104
+
105
+ exceptions = (TelegramParsingError,) + service_exceptions
106
+ func = handle_service_errors(*exceptions)(func)
107
+
108
+ return func
109
+
110
+ return decorator
111
+
112
+
113
+ def service_command(
114
+ *service_exceptions: Type[Exception],
115
+ ) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
116
+ """Apply service-based commands with error handling and JSON output.
117
+
118
+ Args:
119
+ service_exceptions: Service exception types to handle.
120
+
121
+ Returns:
122
+ Decorator function for service commands.
123
+ """
124
+
125
+ def decorator(func: Callable[..., Any]) -> Callable[..., Any]:
126
+ """Apply service command decorators.
127
+
128
+ Args:
129
+ func: The function to decorate.
130
+
131
+ Returns:
132
+ Decorated function with service error handling.
133
+ """
134
+ func = handle_service_errors(*service_exceptions)(func)
135
+ return func
136
+
137
+ return decorator
138
+
139
+
140
+ def list_command(
141
+ *service_exceptions: Type[Exception],
142
+ ) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
143
+ """Apply list/search commands with common options.
144
+
145
+ Args:
146
+ service_exceptions: Service exception types to handle.
147
+
148
+ Returns:
149
+ Decorator function for list commands.
150
+ """
151
+
152
+ def decorator(func: Callable[..., Any]) -> Callable[..., Any]:
153
+ """Apply list command decorators.
154
+
155
+ Args:
156
+ func: The function to decorate.
157
+
158
+ Returns:
159
+ Decorated function with list error handling.
160
+ """
161
+ func = handle_service_errors(*service_exceptions)(func)
162
+ return func
163
+
164
+ return decorator
165
+
166
+
167
+ def file_operation_command() -> Callable[[Callable[..., Any]], Callable[..., Any]]:
168
+ """Apply file operation commands with common filters.
169
+
170
+ Returns:
171
+ Decorator function for file operation commands.
172
+ """
173
+
174
+ def decorator(func: Callable[..., Any]) -> Callable[..., Any]:
175
+ """Apply file operation decorators.
176
+
177
+ Args:
178
+ func: The function to decorate.
179
+
180
+ Returns:
181
+ Decorated function with filter options.
182
+ """
183
+ func = click.option(
184
+ "--time-range", help="Filter by time range (HH:MM:SS,mmm-HH:MM:SS,mmm)"
185
+ )(func)
186
+ func = click.option(
187
+ "--filter-direction",
188
+ type=click.Choice(["tx", "rx"]),
189
+ help="Filter by direction",
190
+ )(func)
191
+ func = click.option(
192
+ "--filter-type",
193
+ type=click.Choice(["event", "system", "reply"]),
194
+ help="Filter by telegram type",
195
+ )(func)
196
+ return func
197
+
198
+ return decorator
199
+
200
+
201
+ def with_formatter(
202
+ formatter_class: Any = None,
203
+ ) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
204
+ """Inject a formatter instance into the command.
205
+
206
+ Args:
207
+ formatter_class: Custom formatter class to use.
208
+
209
+ Returns:
210
+ Decorator function that injects a formatter.
211
+ """
212
+
213
+ def decorator(func: Callable[..., Any]) -> Callable[..., Any]:
214
+ """Apply formatter injection.
215
+
216
+ Args:
217
+ func: The function to decorate.
218
+
219
+ Returns:
220
+ Wrapped function with formatter injection.
221
+ """
222
+
223
+ @functools.wraps(func)
224
+ def wrapper(*args: Any, **kwargs: Any) -> Any:
225
+ """Execute function with injected formatter.
226
+
227
+ Args:
228
+ args: Positional arguments passed to the decorated function.
229
+ kwargs: Keyword arguments passed to the decorated function.
230
+
231
+ Returns:
232
+ Result from the decorated function.
233
+ """
234
+ formatter_cls = formatter_class or OutputFormatter
235
+ formatter = formatter_cls(True)
236
+ kwargs["formatter"] = formatter
237
+ return func(*args, **kwargs)
238
+
239
+ return wrapper
240
+
241
+ return decorator
242
+
243
+
244
+ def require_arguments(
245
+ *required_args: str,
246
+ ) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
247
+ """Validate required arguments are present.
248
+
249
+ Args:
250
+ required_args: Names of required arguments.
251
+
252
+ Returns:
253
+ Decorator function that validates required arguments.
254
+ """
255
+
256
+ def decorator(func: Callable[..., Any]) -> Callable[..., Any]:
257
+ """Apply argument validation.
258
+
259
+ Args:
260
+ func: The function to decorate.
261
+
262
+ Returns:
263
+ Wrapped function with argument validation.
264
+ """
265
+
266
+ @functools.wraps(func)
267
+ def wrapper(*args: Any, **kwargs: Any) -> Any:
268
+ """Execute function with argument validation.
269
+
270
+ Args:
271
+ args: Positional arguments passed to the decorated function.
272
+ kwargs: Keyword arguments passed to the decorated function.
273
+
274
+ Returns:
275
+ Result from the decorated function.
276
+
277
+ Raises:
278
+ SystemExit: When required arguments are missing.
279
+ """
280
+ formatter = OutputFormatter(True)
281
+
282
+ # Check for missing required arguments
283
+ missing_args = [
284
+ arg_name
285
+ for arg_name in required_args
286
+ if arg_name in kwargs and kwargs[arg_name] is None
287
+ ]
288
+
289
+ if missing_args:
290
+ error_msg = f"Missing required arguments: {', '.join(missing_args)}"
291
+ error_response = formatter.error_response(error_msg)
292
+ click.echo(error_response)
293
+ raise SystemExit(1)
294
+
295
+ return func(*args, **kwargs)
296
+
297
+ return wrapper
298
+
299
+ return decorator
300
+
301
+
302
+ def connection_command() -> Callable[[Callable[..., Any]], Callable[..., Any]]:
303
+ """Apply commands that connect to remote services.
304
+
305
+ Returns:
306
+ Decorator function for connection commands.
307
+ """
308
+
309
+ def decorator(func: Callable[..., Any]) -> Callable[..., Any]:
310
+ """Apply connection command decorators.
311
+
312
+ Args:
313
+ func: The function to decorate.
314
+
315
+ Returns:
316
+ Wrapped function with connection error handling.
317
+ """
318
+
319
+ @functools.wraps(func)
320
+ def wrapper(*args: Any, **kwargs: Any) -> Any:
321
+ """Execute function with connection error handling.
322
+
323
+ Args:
324
+ args: Positional arguments passed to the decorated function.
325
+ kwargs: Keyword arguments passed to the decorated function.
326
+
327
+ Returns:
328
+ Result from the decorated function.
329
+
330
+ Raises:
331
+ SystemExit: When a connection timeout occurs.
332
+ Exception: Re-raises other exceptions for handling by other decorators.
333
+ """
334
+ formatter = OutputFormatter(True)
335
+
336
+ try:
337
+ return func(*args, **kwargs)
338
+ except Exception as e:
339
+ if "Connection timeout" in str(e):
340
+ # Special handling for connection timeouts
341
+ error_msg = "Connection timeout - server may be unreachable"
342
+ error_response = formatter.error_response(error_msg)
343
+ click.echo(error_response)
344
+ raise SystemExit(1)
345
+ else:
346
+ # Re-raise other exceptions to be handled by other decorators
347
+ raise
348
+
349
+ return wrapper
350
+
351
+ return decorator
@@ -0,0 +1,201 @@
1
+ """Error handling utilities for CLI commands."""
2
+
3
+ from typing import Any, Dict, Optional
4
+
5
+ import click
6
+
7
+ from xp.cli.utils.formatters import OutputFormatter
8
+
9
+
10
+ class CLIErrorHandler:
11
+ """Centralized error handling for CLI commands."""
12
+
13
+ @staticmethod
14
+ def handle_parsing_error(
15
+ error: Exception,
16
+ raw_input: str,
17
+ context: Optional[Dict[str, Any]] = None,
18
+ ) -> None:
19
+ """Handle telegram parsing errors with JSON formatting.
20
+
21
+ Args:
22
+ error: The parsing error that occurred.
23
+ raw_input: The raw input that failed to parse.
24
+ context: Additional context information.
25
+
26
+ Raises:
27
+ SystemExit: Always exits with code 1 after displaying error.
28
+ """
29
+ formatter = OutputFormatter(True)
30
+ error_data = {"raw_input": raw_input}
31
+
32
+ if context:
33
+ error_data.update(context)
34
+
35
+ error_response = formatter.error_response(str(error), error_data)
36
+ click.echo(error_response)
37
+ raise SystemExit(1)
38
+
39
+ @staticmethod
40
+ def handle_connection_error(
41
+ error: Exception, config: Optional[Dict[str, Any]] = None
42
+ ) -> None:
43
+ """Handle connection/network errors with JSON formatting.
44
+
45
+ Args:
46
+ error: The connection error that occurred.
47
+ config: Configuration information (IP, port, timeout).
48
+
49
+ Raises:
50
+ SystemExit: Always exits with code 1 after displaying error.
51
+ """
52
+ formatter = OutputFormatter(True)
53
+
54
+ if "Connection timeout" in str(error):
55
+ if config:
56
+ error_msg = f"Connection timeout after {config.get('timeout', 'unknown')} seconds"
57
+ error_data = {
58
+ "host": config.get("ip", "unknown"),
59
+ "port": config.get("port", "unknown"),
60
+ "timeout": config.get("timeout", "unknown"),
61
+ }
62
+ else:
63
+ error_msg = "Connection timeout"
64
+ error_data = {}
65
+
66
+ error_response = formatter.error_response(error_msg, error_data)
67
+ click.echo(error_response)
68
+ raise SystemExit(1)
69
+ else:
70
+ # Generic connection error
71
+ error_response = formatter.error_response(str(error))
72
+ click.echo(error_response)
73
+ raise SystemExit(1)
74
+
75
+ @staticmethod
76
+ def handle_service_error(
77
+ error: Exception, operation: str, context: Optional[Dict[str, Any]] = None
78
+ ) -> None:
79
+ """Handle general service errors with JSON formatting.
80
+
81
+ Args:
82
+ error: The service error that occurred.
83
+ operation: Description of the operation that failed.
84
+ context: Additional context information.
85
+
86
+ Raises:
87
+ SystemExit: Always exits with code 1 after displaying error.
88
+ """
89
+ formatter = OutputFormatter(True)
90
+ error_data = {"operation": operation}
91
+
92
+ if context:
93
+ error_data.update(context)
94
+
95
+ error_response = formatter.error_response(str(error), error_data)
96
+ click.echo(error_response)
97
+ raise SystemExit(1)
98
+
99
+ @staticmethod
100
+ def handle_validation_error(error: Exception, input_data: str) -> None:
101
+ """Handle validation errors with JSON formatting.
102
+
103
+ Args:
104
+ error: The validation error that occurred.
105
+ input_data: The input that failed validation.
106
+
107
+ Raises:
108
+ SystemExit: Always exits with code 1 after displaying error.
109
+ """
110
+ formatter = OutputFormatter(True)
111
+ error_data = {"valid_format": False, "raw_input": input_data}
112
+
113
+ error_response = formatter.error_response(str(error), error_data)
114
+ click.echo(error_response)
115
+ raise SystemExit(1)
116
+
117
+ @staticmethod
118
+ def handle_file_error(
119
+ error: Exception,
120
+ file_path: str,
121
+ operation: str = "processing",
122
+ ) -> None:
123
+ """Handle file operation errors with JSON formatting.
124
+
125
+ Args:
126
+ error: The file error that occurred.
127
+ file_path: Path to the file that caused the error.
128
+ operation: Type of file operation (parsing, reading, etc.).
129
+
130
+ Raises:
131
+ SystemExit: Always exits with code 1 after displaying error.
132
+ """
133
+ formatter = OutputFormatter(True)
134
+ error_data = {"file_path": file_path, "operation": operation}
135
+
136
+ error_response = formatter.error_response(str(error), error_data)
137
+ click.echo(error_response)
138
+ raise SystemExit(1)
139
+
140
+ @staticmethod
141
+ def handle_not_found_error(
142
+ error: Exception, item_type: str, identifier: str
143
+ ) -> None:
144
+ """Handle 'not found' errors with JSON formatting.
145
+
146
+ Args:
147
+ error: The not found error that occurred.
148
+ item_type: Type of item that was not found.
149
+ identifier: Identifier used to search for the item.
150
+
151
+ Raises:
152
+ SystemExit: Always exits with code 1 after displaying error.
153
+ """
154
+ formatter = OutputFormatter(True)
155
+ error_data = {"item_type": item_type, "identifier": identifier}
156
+
157
+ error_response = formatter.error_response(str(error), error_data)
158
+ click.echo(error_response)
159
+ raise SystemExit(1)
160
+
161
+
162
+ class ServerErrorHandler(CLIErrorHandler):
163
+ """Specialized error handler for server operations."""
164
+
165
+ @staticmethod
166
+ def handle_server_startup_error(
167
+ error: Exception, port: int, config_path: str
168
+ ) -> None:
169
+ """Handle server startup errors with JSON formatting.
170
+
171
+ Args:
172
+ error: The server startup error that occurred.
173
+ port: Port number the server attempted to use.
174
+ config_path: Path to the configuration file.
175
+
176
+ Raises:
177
+ SystemExit: Always exits with code 1 after displaying error.
178
+ """
179
+ formatter = OutputFormatter(True)
180
+ error_data = {
181
+ "port": port,
182
+ "config": config_path,
183
+ "operation": "server_startup",
184
+ }
185
+
186
+ error_response = formatter.error_response(str(error), error_data)
187
+ click.echo(error_response)
188
+ raise SystemExit(1)
189
+
190
+ @staticmethod
191
+ def handle_server_not_running_error() -> None:
192
+ """Handle errors when server is not running with JSON formatting.
193
+
194
+ Raises:
195
+ SystemExit: Always exits with code 1 after displaying error.
196
+ """
197
+ error_response = OutputFormatter(True).error_response(
198
+ "No server is currently running"
199
+ )
200
+ click.echo(error_response)
201
+ raise SystemExit(1)