qena-shared-lib 0.1.16__py3-none-any.whl → 0.1.18__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 (33) hide show
  1. qena_shared_lib/__init__.py +3 -2
  2. qena_shared_lib/application.py +4 -4
  3. qena_shared_lib/background.py +9 -7
  4. qena_shared_lib/exception_handling.py +409 -0
  5. qena_shared_lib/exceptions.py +170 -57
  6. qena_shared_lib/http/__init__.py +90 -0
  7. qena_shared_lib/{http.py → http/_base.py} +36 -36
  8. qena_shared_lib/http/_exception_handlers.py +202 -0
  9. qena_shared_lib/kafka/__init__.py +21 -0
  10. qena_shared_lib/kafka/_base.py +233 -0
  11. qena_shared_lib/kafka/_consumer.py +597 -0
  12. qena_shared_lib/kafka/_exception_handlers.py +124 -0
  13. qena_shared_lib/kafka/_producer.py +133 -0
  14. qena_shared_lib/logging.py +17 -13
  15. qena_shared_lib/rabbitmq/__init__.py +4 -6
  16. qena_shared_lib/rabbitmq/_base.py +68 -132
  17. qena_shared_lib/rabbitmq/_channel.py +2 -4
  18. qena_shared_lib/rabbitmq/_exception_handlers.py +69 -142
  19. qena_shared_lib/rabbitmq/_listener.py +246 -157
  20. qena_shared_lib/rabbitmq/_publisher.py +5 -5
  21. qena_shared_lib/rabbitmq/_rpc_client.py +21 -22
  22. qena_shared_lib/remotelogging/_base.py +20 -20
  23. qena_shared_lib/remotelogging/logstash/_base.py +2 -2
  24. qena_shared_lib/remotelogging/logstash/_http_sender.py +2 -4
  25. qena_shared_lib/remotelogging/logstash/_tcp_sender.py +2 -2
  26. qena_shared_lib/scheduler.py +24 -15
  27. qena_shared_lib/security.py +39 -32
  28. qena_shared_lib/utils.py +13 -11
  29. {qena_shared_lib-0.1.16.dist-info → qena_shared_lib-0.1.18.dist-info}/METADATA +9 -1
  30. qena_shared_lib-0.1.18.dist-info/RECORD +38 -0
  31. qena_shared_lib/exception_handlers.py +0 -235
  32. qena_shared_lib-0.1.16.dist-info/RECORD +0 -31
  33. {qena_shared_lib-0.1.16.dist-info → qena_shared_lib-0.1.18.dist-info}/WHEEL +0 -0
@@ -2,6 +2,7 @@ from enum import Enum
2
2
  from typing import Any
3
3
 
4
4
  from fastapi import status
5
+ from typing_extensions import Self
5
6
 
6
7
  __all__ = [
7
8
  "BadGateway",
@@ -18,6 +19,7 @@ __all__ = [
18
19
  "IAmATeapot",
19
20
  "InsufficientStorage",
20
21
  "InternalServerError",
22
+ "KafkaDisconnectedError",
21
23
  "LengthRequired",
22
24
  "Locked",
23
25
  "LoopDetected",
@@ -64,8 +66,8 @@ class Severity(Enum):
64
66
 
65
67
 
66
68
  class ServiceException(Exception):
67
- _GENERAL_SEVERITY: Severity | None = None
68
- _GENERAL_EXTRACT_EXC_INFO: bool | None = None
69
+ GENERAL_SEVERITY: Severity | None = None
70
+ GENERAL_EXTRACT_EXC_INFO: bool | None = None
69
71
 
70
72
  def __init__(
71
73
  self,
@@ -80,8 +82,8 @@ class ServiceException(Exception):
80
82
 
81
83
  if severity is not None:
82
84
  self._severity = severity
83
- elif self._GENERAL_SEVERITY is not None:
84
- self._severity = self._GENERAL_SEVERITY
85
+ elif self.GENERAL_SEVERITY is not None:
86
+ self._severity = self.GENERAL_SEVERITY
85
87
  else:
86
88
  self._severity = Severity.LOW
87
89
 
@@ -95,8 +97,8 @@ class ServiceException(Exception):
95
97
 
96
98
  if extract_exc_info is not None:
97
99
  self._extract_exc_info = extract_exc_info
98
- elif self._GENERAL_EXTRACT_EXC_INFO is not None:
99
- self._extract_exc_info = self._GENERAL_EXTRACT_EXC_INFO
100
+ elif self.GENERAL_EXTRACT_EXC_INFO is not None:
101
+ self._extract_exc_info = self.GENERAL_EXTRACT_EXC_INFO
100
102
  else:
101
103
  self._extract_exc_info = False
102
104
 
@@ -132,7 +134,7 @@ class ServiceException(Exception):
132
134
 
133
135
 
134
136
  class HTTPServiceError(ServiceException):
135
- _GENERAL_STATUS_CODE: int | None = None
137
+ GENERAL_STATUS_CODE: int | None = None
136
138
 
137
139
  def __init__(
138
140
  self,
@@ -163,7 +165,7 @@ class HTTPServiceError(ServiceException):
163
165
  if status_code is not None:
164
166
  self._status_code = status_code
165
167
  else:
166
- self._status_code = self._GENERAL_STATUS_CODE
168
+ self._status_code = self.GENERAL_STATUS_CODE
167
169
 
168
170
  self._headers = headers
169
171
  self._response_code = response_code
@@ -197,179 +199,179 @@ class HTTPServiceError(ServiceException):
197
199
 
198
200
 
199
201
  class ClientError(HTTPServiceError):
200
- _GENERAL_SEVERITY = Severity.MEDIUM
201
- _GENERAL_EXTRACT_EXC_INFO = False
202
+ GENERAL_SEVERITY = Severity.MEDIUM
203
+ GENERAL_EXTRACT_EXC_INFO = False
202
204
 
203
205
 
204
206
  class BadRequest(ClientError):
205
- _GENERAL_STATUS_CODE = status.HTTP_400_BAD_REQUEST
207
+ GENERAL_STATUS_CODE = status.HTTP_400_BAD_REQUEST
206
208
 
207
209
 
208
210
  class Unauthorized(ClientError):
209
- _GENERAL_STATUS_CODE = status.HTTP_401_UNAUTHORIZED
211
+ GENERAL_STATUS_CODE = status.HTTP_401_UNAUTHORIZED
210
212
 
211
213
 
212
214
  class PaymentRequired(ClientError):
213
- _GENERAL_STATUS_CODE = status.HTTP_402_PAYMENT_REQUIRED
215
+ GENERAL_STATUS_CODE = status.HTTP_402_PAYMENT_REQUIRED
214
216
 
215
217
 
216
218
  class Forbidden(ClientError):
217
- _GENERAL_STATUS_CODE = status.HTTP_403_FORBIDDEN
219
+ GENERAL_STATUS_CODE = status.HTTP_403_FORBIDDEN
218
220
 
219
221
 
220
222
  class NotFound(ClientError):
221
- _GENERAL_STATUS_CODE = status.HTTP_404_NOT_FOUND
223
+ GENERAL_STATUS_CODE = status.HTTP_404_NOT_FOUND
222
224
 
223
225
 
224
226
  class MethodNotAllowed(ClientError):
225
- _GENERAL_STATUS_CODE = status.HTTP_405_METHOD_NOT_ALLOWED
227
+ GENERAL_STATUS_CODE = status.HTTP_405_METHOD_NOT_ALLOWED
226
228
 
227
229
 
228
230
  class NotAcceptable(ClientError):
229
- _GENERAL_STATUS_CODE = status.HTTP_406_NOT_ACCEPTABLE
231
+ GENERAL_STATUS_CODE = status.HTTP_406_NOT_ACCEPTABLE
230
232
 
231
233
 
232
234
  class ProxyAuthenticationRequired(ClientError):
233
- _GENERAL_STATUS_CODE = status.HTTP_407_PROXY_AUTHENTICATION_REQUIRED
235
+ GENERAL_STATUS_CODE = status.HTTP_407_PROXY_AUTHENTICATION_REQUIRED
234
236
 
235
237
 
236
238
  class RequestTimeout(ClientError):
237
- _GENERAL_STATUS_CODE = status.HTTP_408_REQUEST_TIMEOUT
239
+ GENERAL_STATUS_CODE = status.HTTP_408_REQUEST_TIMEOUT
238
240
 
239
241
 
240
242
  class Conflict(ClientError):
241
- _GENERAL_STATUS_CODE = status.HTTP_409_CONFLICT
243
+ GENERAL_STATUS_CODE = status.HTTP_409_CONFLICT
242
244
 
243
245
 
244
246
  class Gone(ClientError):
245
- _GENERAL_STATUS_CODE = status.HTTP_410_GONE
247
+ GENERAL_STATUS_CODE = status.HTTP_410_GONE
246
248
 
247
249
 
248
250
  class LengthRequired(ClientError):
249
- _GENERAL_STATUS_CODE = status.HTTP_411_LENGTH_REQUIRED
251
+ GENERAL_STATUS_CODE = status.HTTP_411_LENGTH_REQUIRED
250
252
 
251
253
 
252
254
  class PreconditionFailed(ClientError):
253
- _GENERAL_STATUS_CODE = status.HTTP_412_PRECONDITION_FAILED
255
+ GENERAL_STATUS_CODE = status.HTTP_412_PRECONDITION_FAILED
254
256
 
255
257
 
256
258
  class PayloadTooLarge(ClientError):
257
- _GENERAL_STATUS_CODE = status.HTTP_413_REQUEST_ENTITY_TOO_LARGE
259
+ GENERAL_STATUS_CODE = status.HTTP_413_REQUEST_ENTITY_TOO_LARGE
258
260
 
259
261
 
260
262
  class URITooLong(ClientError):
261
- _GENERAL_STATUS_CODE = status.HTTP_414_REQUEST_URI_TOO_LONG
263
+ GENERAL_STATUS_CODE = status.HTTP_414_REQUEST_URI_TOO_LONG
262
264
 
263
265
 
264
266
  class UnsupportedMediaType(ClientError):
265
- _GENERAL_STATUS_CODE = status.HTTP_415_UNSUPPORTED_MEDIA_TYPE
267
+ GENERAL_STATUS_CODE = status.HTTP_415_UNSUPPORTED_MEDIA_TYPE
266
268
 
267
269
 
268
270
  class RangeNotSatisfiable(ClientError):
269
- _GENERAL_STATUS_CODE = status.HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE
271
+ GENERAL_STATUS_CODE = status.HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE
270
272
 
271
273
 
272
274
  class ExpectationFailed(ClientError):
273
- _GENERAL_STATUS_CODE = status.HTTP_417_EXPECTATION_FAILED
275
+ GENERAL_STATUS_CODE = status.HTTP_417_EXPECTATION_FAILED
274
276
 
275
277
 
276
278
  class IAmATeapot(ClientError):
277
- _GENERAL_STATUS_CODE = status.HTTP_418_IM_A_TEAPOT
279
+ GENERAL_STATUS_CODE = status.HTTP_418_IM_A_TEAPOT
278
280
 
279
281
 
280
282
  class MisdirectedRequest(ClientError):
281
- _GENERAL_STATUS_CODE = status.HTTP_421_MISDIRECTED_REQUEST
283
+ GENERAL_STATUS_CODE = status.HTTP_421_MISDIRECTED_REQUEST
282
284
 
283
285
 
284
286
  class UnprocessableEntity(ClientError):
285
- _GENERAL_STATUS_CODE = status.HTTP_422_UNPROCESSABLE_ENTITY
287
+ GENERAL_STATUS_CODE = status.HTTP_422_UNPROCESSABLE_ENTITY
286
288
 
287
289
 
288
290
  class Locked(ClientError):
289
- _GENERAL_STATUS_CODE = status.HTTP_423_LOCKED
291
+ GENERAL_STATUS_CODE = status.HTTP_423_LOCKED
290
292
 
291
293
 
292
294
  class FailedDependency(ClientError):
293
- _GENERAL_STATUS_CODE = status.HTTP_424_FAILED_DEPENDENCY
295
+ GENERAL_STATUS_CODE = status.HTTP_424_FAILED_DEPENDENCY
294
296
 
295
297
 
296
298
  class TooEarly(ClientError):
297
- _GENERAL_STATUS_CODE = status.HTTP_425_TOO_EARLY
299
+ GENERAL_STATUS_CODE = status.HTTP_425_TOO_EARLY
298
300
 
299
301
 
300
302
  class UpgradeRequired(ClientError):
301
- _GENERAL_STATUS_CODE = status.HTTP_426_UPGRADE_REQUIRED
303
+ GENERAL_STATUS_CODE = status.HTTP_426_UPGRADE_REQUIRED
302
304
 
303
305
 
304
306
  class PreconditionRequired(ClientError):
305
- _GENERAL_STATUS_CODE = status.HTTP_428_PRECONDITION_REQUIRED
307
+ GENERAL_STATUS_CODE = status.HTTP_428_PRECONDITION_REQUIRED
306
308
 
307
309
 
308
310
  class TooManyRequests(ClientError):
309
- _GENERAL_STATUS_CODE = status.HTTP_429_TOO_MANY_REQUESTS
311
+ GENERAL_STATUS_CODE = status.HTTP_429_TOO_MANY_REQUESTS
310
312
 
311
313
 
312
314
  class RequestHeaderFieldsTooLarge(ClientError):
313
- _GENERAL_STATUS_CODE = status.HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE
315
+ GENERAL_STATUS_CODE = status.HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE
314
316
 
315
317
 
316
318
  class UnavailableForLegalReasons(ClientError):
317
- _GENERAL_STATUS_CODE = status.HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS
319
+ GENERAL_STATUS_CODE = status.HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS
318
320
 
319
321
 
320
322
  class ServerError(HTTPServiceError):
321
- _GENERAL_SEVERITY = Severity.HIGH
322
- _GENERAL_EXTRACT_EXC_INFO = True
323
+ GENERAL_SEVERITY = Severity.HIGH
324
+ GENERAL_EXTRACT_EXC_INFO = True
323
325
 
324
326
 
325
327
  class InternalServerError(ServerError):
326
- _GENERAL_STATUS_CODE = status.HTTP_500_INTERNAL_SERVER_ERROR
328
+ GENERAL_STATUS_CODE = status.HTTP_500_INTERNAL_SERVER_ERROR
327
329
 
328
330
 
329
331
  class NotImplemented(ServerError):
330
- _GENERAL_STATUS_CODE = status.HTTP_501_NOT_IMPLEMENTED
332
+ GENERAL_STATUS_CODE = status.HTTP_501_NOT_IMPLEMENTED
331
333
 
332
334
 
333
335
  class BadGateway(ServerError):
334
- _GENERAL_STATUS_CODE = status.HTTP_502_BAD_GATEWAY
336
+ GENERAL_STATUS_CODE = status.HTTP_502_BAD_GATEWAY
335
337
 
336
338
 
337
339
  class ServiceUnavailable(ServerError):
338
- _GENERAL_STATUS_CODE = status.HTTP_503_SERVICE_UNAVAILABLE
340
+ GENERAL_STATUS_CODE = status.HTTP_503_SERVICE_UNAVAILABLE
339
341
 
340
342
 
341
343
  class GatewayTimeout(ServerError):
342
- _GENERAL_STATUS_CODE = status.HTTP_504_GATEWAY_TIMEOUT
344
+ GENERAL_STATUS_CODE = status.HTTP_504_GATEWAY_TIMEOUT
343
345
 
344
346
 
345
347
  class HTTPVersionNotSupported(ServerError):
346
- _GENERAL_STATUS_CODE = status.HTTP_505_HTTP_VERSION_NOT_SUPPORTED
348
+ GENERAL_STATUS_CODE = status.HTTP_505_HTTP_VERSION_NOT_SUPPORTED
347
349
 
348
350
 
349
351
  class VariantAlsoNegotiates(ServerError):
350
- _GENERAL_STATUS_CODE = status.HTTP_506_VARIANT_ALSO_NEGOTIATES
352
+ GENERAL_STATUS_CODE = status.HTTP_506_VARIANT_ALSO_NEGOTIATES
351
353
 
352
354
 
353
355
  class InsufficientStorage(ServerError):
354
- _GENERAL_STATUS_CODE = status.HTTP_507_INSUFFICIENT_STORAGE
356
+ GENERAL_STATUS_CODE = status.HTTP_507_INSUFFICIENT_STORAGE
355
357
 
356
358
 
357
359
  class LoopDetected(ServerError):
358
- _GENERAL_STATUS_CODE = status.HTTP_508_LOOP_DETECTED
360
+ GENERAL_STATUS_CODE = status.HTTP_508_LOOP_DETECTED
359
361
 
360
362
 
361
363
  class NotExtended(ServerError):
362
- _GENERAL_STATUS_CODE = status.HTTP_510_NOT_EXTENDED
364
+ GENERAL_STATUS_CODE = status.HTTP_510_NOT_EXTENDED
363
365
 
364
366
 
365
367
  class NetworkAuthenticationRequired(ServerError):
366
- _GENERAL_STATUS_CODE = status.HTTP_511_NETWORK_AUTHENTICATION_REQUIRED
368
+ GENERAL_STATUS_CODE = status.HTTP_511_NETWORK_AUTHENTICATION_REQUIRED
367
369
 
368
370
 
369
371
  class RabbitMQServiceException(ServiceException):
370
- _GENERAL_SEVERITY = Severity.HIGH
371
- _GENERAL_EXTRACT_EXC_INFO = True
372
- _GENERAL_CODE: int | None = None
372
+ GENERAL_SEVERITY = Severity.HIGH
373
+ GENERAL_EXTRACT_EXC_INFO = True
374
+ GENERAL_CODE: int | None = None
373
375
 
374
376
  def __init__(
375
377
  self,
@@ -393,8 +395,8 @@ class RabbitMQServiceException(ServiceException):
393
395
 
394
396
  if code is not None:
395
397
  self._code = code
396
- elif self._GENERAL_CODE is not None:
397
- self._code = self._GENERAL_CODE
398
+ elif self.GENERAL_CODE is not None:
399
+ self._code = self.GENERAL_CODE
398
400
  else:
399
401
  self._code = 0
400
402
 
@@ -429,3 +431,114 @@ class RabbitMQRpcRequestPendingError(Exception):
429
431
 
430
432
  class RabbitMQConnectionUnhealthyError(Exception):
431
433
  pass
434
+
435
+
436
+ class KafkaDisconnectedError(Exception):
437
+ pass
438
+
439
+
440
+ class ServiceType(Enum):
441
+ HTTP = 0
442
+ RABBIT_MQ = 1
443
+
444
+
445
+ class GenericServiceExceptionFactory:
446
+ def __init__(
447
+ self,
448
+ message: str,
449
+ severity: Severity | None = None,
450
+ tags: list[str] | None = None,
451
+ extra: dict[str, str] | None = None,
452
+ remote_logging: bool = True,
453
+ extract_exc_info: bool = True,
454
+ ):
455
+ self._message = message
456
+ self._severity = severity
457
+ self._tags = tags
458
+ self._extra = extra
459
+ self._remote_logging = remote_logging
460
+ self._extract_exc_info = extract_exc_info
461
+
462
+ self._http_service_error: type[HTTPServiceError] = InternalServerError
463
+ self._rabbitmq_service_exception: type[RabbitMQServiceException] = (
464
+ RabbitMQServiceException
465
+ )
466
+
467
+ self._body: Any | None = None
468
+ self._status_code: int | None = None
469
+ self._headers: dict[str, str] | None = None
470
+ self._response_code: int | None = None
471
+ self._corrective_action: str | None = None
472
+ self._code: int | None = None
473
+ self._data: Any | None = None
474
+
475
+ def for_http_service_error(
476
+ self, http_service_error: type[HTTPServiceError]
477
+ ) -> Self:
478
+ self._http_service_error = http_service_error
479
+
480
+ return self
481
+
482
+ def for_rabbitmq_service_exception(
483
+ self, rabbitmq_service_exception: type[RabbitMQServiceException]
484
+ ) -> Self:
485
+ self._rabbitmq_service_exception = rabbitmq_service_exception
486
+
487
+ return self
488
+
489
+ def with_http_service_error(
490
+ self,
491
+ body: Any | None = None,
492
+ status_code: int | None = None,
493
+ headers: dict[str, str] | None = None,
494
+ response_code: int | None = None,
495
+ corrective_action: str | None = None,
496
+ ) -> Self:
497
+ self._body = body
498
+ self._status_code = status_code
499
+ self._headers = headers
500
+ self._response_code = response_code
501
+ self._corrective_action = corrective_action
502
+
503
+ return self
504
+
505
+ def with_rabbitmq_service_exception(
506
+ self,
507
+ code: int | None = None,
508
+ data: Any | None = None,
509
+ ) -> Self:
510
+ self._code = code
511
+ self._data = data
512
+
513
+ return self
514
+
515
+ def create(self, service_type: ServiceType) -> ServiceException:
516
+ assert self._http_service_error is not None
517
+ assert self._rabbitmq_service_exception is not None
518
+
519
+ match service_type:
520
+ case ServiceType.HTTP:
521
+ return self._http_service_error(
522
+ message=self._message,
523
+ body=self._body,
524
+ status_code=self._status_code,
525
+ headers=self._headers,
526
+ response_code=self._response_code,
527
+ corrective_action=self._corrective_action,
528
+ severity=self._severity,
529
+ tags=self._tags,
530
+ extra=self._extra,
531
+ remote_logging=self._remote_logging,
532
+ extract_exc_info=self._extract_exc_info,
533
+ )
534
+ case ServiceType.RABBIT_MQ:
535
+ return self._rabbitmq_service_exception(
536
+ message=self._message,
537
+ code=self._code,
538
+ data=self._data,
539
+ severity=self._severity,
540
+ tags=self._tags,
541
+ extra=self._extra,
542
+ remote_logging=self._remote_logging,
543
+ extract_exc_info=self._extract_exc_info,
544
+ )
@@ -0,0 +1,90 @@
1
+ from ._base import (
2
+ ROUTE_HANDLER_ATTRIBUTE,
3
+ APIRouter,
4
+ BackgroundTasks,
5
+ Body,
6
+ ControllerBase,
7
+ Cookie,
8
+ Depends,
9
+ File,
10
+ FileResponse,
11
+ Form,
12
+ Header,
13
+ HTMLResponse,
14
+ HTTPException,
15
+ JSONResponse,
16
+ Path,
17
+ PlainTextResponse,
18
+ Query,
19
+ RedirectResponse,
20
+ Request,
21
+ Response,
22
+ RouteHandlerMetadata,
23
+ Security,
24
+ StreamingResponse,
25
+ UploadFile,
26
+ WebSocket,
27
+ WebSocketDisconnect,
28
+ WebSocketException,
29
+ api_controller,
30
+ delete,
31
+ get,
32
+ head,
33
+ options,
34
+ patch,
35
+ post,
36
+ put,
37
+ status,
38
+ trace,
39
+ )
40
+ from ._exception_handlers import (
41
+ AbstractHttpExceptionHandler,
42
+ HttpGeneralExceptionHandler,
43
+ HTTPServiceExceptionHandler,
44
+ RequestValidationErrorHandler,
45
+ )
46
+
47
+ __all__ = [
48
+ "AbstractHttpExceptionHandler",
49
+ "api_controller",
50
+ "APIRouter",
51
+ "BackgroundTasks",
52
+ "Body",
53
+ "ControllerBase",
54
+ "Cookie",
55
+ "delete",
56
+ "Depends",
57
+ "File",
58
+ "FileResponse",
59
+ "Form",
60
+ "get",
61
+ "head",
62
+ "Header",
63
+ "HTMLResponse",
64
+ "HTTPException",
65
+ "HttpGeneralExceptionHandler",
66
+ "HTTPServiceExceptionHandler",
67
+ "JSONResponse",
68
+ "options",
69
+ "patch",
70
+ "Path",
71
+ "PlainTextResponse",
72
+ "post",
73
+ "put",
74
+ "Query",
75
+ "RedirectResponse",
76
+ "Request",
77
+ "RequestValidationErrorHandler",
78
+ "Response",
79
+ "Response",
80
+ "ROUTE_HANDLER_ATTRIBUTE",
81
+ "RouteHandlerMetadata",
82
+ "Security",
83
+ "status",
84
+ "StreamingResponse",
85
+ "trace",
86
+ "UploadFile",
87
+ "WebSocket",
88
+ "WebSocketDisconnect",
89
+ "WebSocketException",
90
+ ]
@@ -75,7 +75,7 @@ __all__ = [
75
75
 
76
76
  AC = TypeVar("AC")
77
77
  API_CONTROLLER_ATTRIBUTE = "__api_controller_router__"
78
- ROUTE_HANDLER_ATTRIBUTE = "__route_handler_meta__"
78
+ ROUTE_HANDLER_ATTRIBUTE = "__route_handler_metadata__"
79
79
 
80
80
 
81
81
  class HTTPMethods(Enum):
@@ -90,7 +90,7 @@ class HTTPMethods(Enum):
90
90
 
91
91
 
92
92
  @dataclass
93
- class RouteHandlerMeta:
93
+ class RouteHandlerMetadata:
94
94
  method: HTTPMethods
95
95
  path: str | None = None
96
96
  response_model: Any | None = None
@@ -173,7 +173,7 @@ def get(
173
173
  setattr(
174
174
  route_handler,
175
175
  ROUTE_HANDLER_ATTRIBUTE,
176
- RouteHandlerMeta(
176
+ RouteHandlerMetadata(
177
177
  method=HTTPMethods.GET,
178
178
  path=path,
179
179
  response_model=response_model,
@@ -230,7 +230,7 @@ def put(
230
230
  setattr(
231
231
  route_handler,
232
232
  ROUTE_HANDLER_ATTRIBUTE,
233
- RouteHandlerMeta(
233
+ RouteHandlerMetadata(
234
234
  method=HTTPMethods.PUT,
235
235
  path=path,
236
236
  response_model=response_model,
@@ -287,7 +287,7 @@ def post(
287
287
  setattr(
288
288
  route_handler,
289
289
  ROUTE_HANDLER_ATTRIBUTE,
290
- RouteHandlerMeta(
290
+ RouteHandlerMetadata(
291
291
  method=HTTPMethods.POST,
292
292
  path=path,
293
293
  response_model=response_model,
@@ -344,7 +344,7 @@ def delete(
344
344
  setattr(
345
345
  route_handler,
346
346
  ROUTE_HANDLER_ATTRIBUTE,
347
- RouteHandlerMeta(
347
+ RouteHandlerMetadata(
348
348
  method=HTTPMethods.DELETE,
349
349
  path=path,
350
350
  response_model=response_model,
@@ -401,7 +401,7 @@ def options(
401
401
  setattr(
402
402
  route_handler,
403
403
  ROUTE_HANDLER_ATTRIBUTE,
404
- RouteHandlerMeta(
404
+ RouteHandlerMetadata(
405
405
  method=HTTPMethods.OPTIONS,
406
406
  path=path,
407
407
  response_model=response_model,
@@ -458,7 +458,7 @@ def head(
458
458
  setattr(
459
459
  route_handler,
460
460
  ROUTE_HANDLER_ATTRIBUTE,
461
- RouteHandlerMeta(
461
+ RouteHandlerMetadata(
462
462
  method=HTTPMethods.HEAD,
463
463
  path=path,
464
464
  response_model=response_model,
@@ -515,7 +515,7 @@ def patch(
515
515
  setattr(
516
516
  route_handler,
517
517
  ROUTE_HANDLER_ATTRIBUTE,
518
- RouteHandlerMeta(
518
+ RouteHandlerMetadata(
519
519
  method=HTTPMethods.PATCH,
520
520
  path=path,
521
521
  response_model=response_model,
@@ -572,7 +572,7 @@ def trace(
572
572
  setattr(
573
573
  route_handler,
574
574
  ROUTE_HANDLER_ATTRIBUTE,
575
- RouteHandlerMeta(
575
+ RouteHandlerMetadata(
576
576
  method=HTTPMethods.TRACE,
577
577
  path=path,
578
578
  response_model=response_model,
@@ -622,21 +622,21 @@ class ControllerBase:
622
622
  if attribute is None:
623
623
  continue
624
624
 
625
- route_handler_meta = getattr(
625
+ route_handler_metadata = getattr(
626
626
  attribute, ROUTE_HANDLER_ATTRIBUTE, None
627
627
  )
628
628
 
629
- if route_handler_meta is None:
629
+ if route_handler_metadata is None:
630
630
  continue
631
631
 
632
- if not isinstance(route_handler_meta, RouteHandlerMeta):
632
+ if not isinstance(route_handler_metadata, RouteHandlerMetadata):
633
633
  raise TypeError(
634
- f"expected `{ROUTE_HANDLER_ATTRIBUTE}` to be of type `RouteHandlerMeta`, got {type(route_handler_meta)}"
634
+ f"expected `{ROUTE_HANDLER_ATTRIBUTE}` to be of type `RouteHandlerMetadata`, got {type(route_handler_metadata)}"
635
635
  )
636
636
 
637
637
  api_router_method = None
638
638
 
639
- match route_handler_meta.method:
639
+ match route_handler_metadata.method:
640
640
  case HTTPMethods.GET:
641
641
  api_router_method = api_router.get
642
642
  case HTTPMethods.PUT:
@@ -656,30 +656,30 @@ class ControllerBase:
656
656
 
657
657
  if api_router_method is None:
658
658
  raise ValueError(
659
- f"api router method {route_handler_meta.method} not supported"
659
+ f"api router method {route_handler_metadata.method} not supported"
660
660
  )
661
661
 
662
662
  api_router_method(
663
- path=route_handler_meta.path or "",
664
- response_model=route_handler_meta.response_model,
665
- status_code=route_handler_meta.status_code,
666
- tags=route_handler_meta.tags,
667
- dependencies=route_handler_meta.dependencies,
668
- summary=route_handler_meta.summary,
669
- description=route_handler_meta.description,
670
- response_description=route_handler_meta.response_description,
671
- responses=route_handler_meta.responses,
672
- deprecated=route_handler_meta.deprecated,
673
- response_model_include=route_handler_meta.response_model_include,
674
- response_model_exclude=route_handler_meta.response_model_exclude,
675
- response_model_by_alias=route_handler_meta.response_model_by_alias,
676
- response_model_exclude_unset=route_handler_meta.response_model_exclude_unset,
677
- response_model_exclude_defaults=route_handler_meta.response_model_exclude_defaults,
678
- response_model_exclude_none=route_handler_meta.response_model_exclude_none,
679
- include_in_schema=route_handler_meta.include_in_schema,
680
- response_class=route_handler_meta.response_class,
681
- name=route_handler_meta.name,
682
- openapi_extra=route_handler_meta.openapi_extra,
663
+ path=route_handler_metadata.path or "",
664
+ response_model=route_handler_metadata.response_model,
665
+ status_code=route_handler_metadata.status_code,
666
+ tags=route_handler_metadata.tags,
667
+ dependencies=route_handler_metadata.dependencies,
668
+ summary=route_handler_metadata.summary,
669
+ description=route_handler_metadata.description,
670
+ response_description=route_handler_metadata.response_description,
671
+ responses=route_handler_metadata.responses,
672
+ deprecated=route_handler_metadata.deprecated,
673
+ response_model_include=route_handler_metadata.response_model_include,
674
+ response_model_exclude=route_handler_metadata.response_model_exclude,
675
+ response_model_by_alias=route_handler_metadata.response_model_by_alias,
676
+ response_model_exclude_unset=route_handler_metadata.response_model_exclude_unset,
677
+ response_model_exclude_defaults=route_handler_metadata.response_model_exclude_defaults,
678
+ response_model_exclude_none=route_handler_metadata.response_model_exclude_none,
679
+ include_in_schema=route_handler_metadata.include_in_schema,
680
+ response_class=route_handler_metadata.response_class,
681
+ name=route_handler_metadata.name,
682
+ openapi_extra=route_handler_metadata.openapi_extra,
683
683
  )(attribute)
684
684
 
685
685
  return api_router