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
@@ -0,0 +1,38 @@
1
+ qena_shared_lib/__init__.py,sha256=1mV9wGMBQc_Hb2NLNJmcAOgjzsno9vnc34o3mRfr7eI,438
2
+ qena_shared_lib/application.py,sha256=0pvuy5PxH5fw5FptTI4ksUxNAh-hzr_d5beAMDiBzi8,7117
3
+ qena_shared_lib/background.py,sha256=SCZhZOwWgv5T0X4tMB_aTecKlMdT12bzqpbA4qoZQPA,3473
4
+ qena_shared_lib/exception_handling.py,sha256=oiPVaxD74y-dbB8hJsncPNd-Fphot60Q60tZQTbCZ50,13392
5
+ qena_shared_lib/exceptions.py,sha256=vKqZjU5XmVNE-zjQ5kZ9HlOELbAD8E6TPP1Kv6tPVKE,14593
6
+ qena_shared_lib/logging.py,sha256=HZiqbXpmJsAI7hheAaQ9EA8uj9yU0pMVCg64d_V0wzA,1748
7
+ qena_shared_lib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ qena_shared_lib/scheduler.py,sha256=Spp5PnpFJ0U4aLeFCNmje9zUA4zwkL-b7X8SSGkGssM,13579
9
+ qena_shared_lib/security.py,sha256=RAXBkfhytJl-2SOXYQTJMnUb789-8DNZKRjRtpod16Y,6372
10
+ qena_shared_lib/utils.py,sha256=crD8NJD1Se7ZHPCaQBCi3c7Y46lMvk8OsN_bZTbcyto,1184
11
+ qena_shared_lib/dependencies/__init__.py,sha256=W12RgJbhqZ9GiSV1nLlHmpwPzvQv8t7f4JEoazM_WYg,350
12
+ qena_shared_lib/dependencies/http.py,sha256=IBsMnRr8Jh8ixf2IcU6n1aYRMazI3fF9GLZxHM2dsXk,1492
13
+ qena_shared_lib/dependencies/miscellaneous.py,sha256=iGwAjatXb_JVSF13n1vdTRAgSKv19VtHo9ZbjjbkIco,753
14
+ qena_shared_lib/http/__init__.py,sha256=OqKrE7jYFjy4gAYYtjTOp2cZGNU2GIEMFcyOQYdbalk,1599
15
+ qena_shared_lib/http/_base.py,sha256=5jPAjiDmJIxjtMdhxNHpcTM_xbXC5eBMvy3U0tpB25Q,25199
16
+ qena_shared_lib/http/_exception_handlers.py,sha256=fkxW7KqyCy923f4f6s1qmd8gO-Oaoi-mLR9gaIWC-PU,6265
17
+ qena_shared_lib/kafka/__init__.py,sha256=59aii_0Is8cwEVQlK4w9Jk3YrOqojTa6ReJO0SBedog,392
18
+ qena_shared_lib/kafka/_base.py,sha256=H27YrSgA8iifSDkptFRSTcR4P-hoMqOLqPXpw9WpgvA,8251
19
+ qena_shared_lib/kafka/_consumer.py,sha256=aEOtAqMhFPIMYbKK_BMDwR2rd_eaDzBJ6xR3Ud5LhPE,19294
20
+ qena_shared_lib/kafka/_exception_handlers.py,sha256=D7Xh5eSpSkumQKvPfBmVB_E6vQxD58y41bFpP5Jzhqk,4084
21
+ qena_shared_lib/kafka/_producer.py,sha256=QtYfKzNtxeIT1EtGpS-tvFC342oPoleF1AOl20LfNXs,3941
22
+ qena_shared_lib/rabbitmq/__init__.py,sha256=h5mkAbluZBgZZXw52dO4adNjlvhE-qS1LJUPn4Kpvhs,1217
23
+ qena_shared_lib/rabbitmq/_base.py,sha256=pKJL0PNrhUOXw4XUJ1iZsuCPVY3ykvO8ebIfeX9HwXo,21502
24
+ qena_shared_lib/rabbitmq/_channel.py,sha256=l67iMB2NqprQeypHBIS_jLeiQEqYxunh76-wq8zEHLw,5898
25
+ qena_shared_lib/rabbitmq/_exception_handlers.py,sha256=jL4McHxetlNOTpmnLggg3akwsVkXy8dGQLHHPPEDeiM,3718
26
+ qena_shared_lib/rabbitmq/_listener.py,sha256=Nl8-YWxf8xlF70vqtwmJrpkjBDKrcqjJHNRFpAVxS-I,51969
27
+ qena_shared_lib/rabbitmq/_pool.py,sha256=eEJswSoWoWzjh290doFYccn1cwQW6DgbdpHeU-7nZSg,2006
28
+ qena_shared_lib/rabbitmq/_publisher.py,sha256=57WruxVlZemA7XVDNHSNB3_2gI-ycIKDobepLGa_QoM,2511
29
+ qena_shared_lib/rabbitmq/_rpc_client.py,sha256=DKYvyPnmaMfa8Ymw1nLKinuFeG_H0Lc1OL8EUjN8M6U,9353
30
+ qena_shared_lib/remotelogging/__init__.py,sha256=DEmzWGadTT9-utyEAAmyVDkWFhsonY4wbWIy1J34C14,245
31
+ qena_shared_lib/remotelogging/_base.py,sha256=NL-eoC9e3nc1757qi3V__-k7hiMwP6_6TkDKXEd7v5E,15376
32
+ qena_shared_lib/remotelogging/logstash/__init__.py,sha256=-sg2V8gYuAKtnHSXfLorpdu_LUB_Gpldw0pCuWIsSc0,186
33
+ qena_shared_lib/remotelogging/logstash/_base.py,sha256=INDQXgLTLiLx-wTIMw30a_y1Y6bg9mvxKzC5_ZTmvy8,959
34
+ qena_shared_lib/remotelogging/logstash/_http_sender.py,sha256=2PUZ526zzLiP6wfW6AeVfzm3qowv5KpHYXMgkd6xrn0,1776
35
+ qena_shared_lib/remotelogging/logstash/_tcp_sender.py,sha256=s7oW7ovYq8OHqN8tF4rXhPK9knCHx5Dsx5Bu_p4XerQ,2455
36
+ qena_shared_lib-0.1.18.dist-info/METADATA,sha256=xFJcPojg9ZwzmVFyH9ipRFdndtZ7zhNE_jifyebqzxM,12142
37
+ qena_shared_lib-0.1.18.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
38
+ qena_shared_lib-0.1.18.dist-info/RECORD,,
@@ -1,235 +0,0 @@
1
- from collections.abc import Iterable
2
- from typing import Any, cast
3
-
4
- from fastapi import Request, Response, status
5
- from fastapi.exceptions import RequestValidationError
6
- from fastapi.responses import JSONResponse
7
- from pydantic_core import to_jsonable_python
8
-
9
- from .exceptions import (
10
- HTTPServiceError,
11
- RabbitMQServiceException,
12
- ServiceException,
13
- Severity,
14
- )
15
- from .logging import LoggerProvider
16
- from .remotelogging import BaseRemoteLogSender
17
-
18
- __all__ = [
19
- "AbstractHttpExceptionHandler",
20
- "GeneralHttpExceptionHandler",
21
- "HTTPServiceExceptionHandler",
22
- "RequestValidationErrorHandler",
23
- ]
24
-
25
-
26
- class AbstractHttpExceptionHandler:
27
- @property
28
- def exception(self) -> type[Exception]:
29
- raise NotImplementedError()
30
-
31
-
32
- class HTTPServiceExceptionHandler(AbstractHttpExceptionHandler):
33
- @property
34
- def exception(self) -> type[Exception]:
35
- return cast(type[Exception], ServiceException)
36
-
37
- def __init__(
38
- self,
39
- remote_logger: BaseRemoteLogSender,
40
- logger_provider: LoggerProvider,
41
- ):
42
- self._remote_logger = remote_logger
43
- self._logger = logger_provider.get_logger("http.exception_handler")
44
-
45
- def __call__(
46
- self, request: Request, exception: ServiceException
47
- ) -> Response:
48
- exception_severity = exception.severity or Severity.LOW
49
- user_agent = request.headers.get("user-agent", "__unknown__")
50
- message = exception.message
51
- tags = [
52
- "HTTP",
53
- request.method,
54
- request.url.path,
55
- exception.__class__.__name__,
56
- ]
57
- extra = {
58
- "serviceType": "HTTP",
59
- "method": request.method,
60
- "path": request.url.path,
61
- "userAgent": user_agent,
62
- "exception": exception.__class__.__name__,
63
- }
64
- exc_info = (
65
- (type(exception), exception, exception.__traceback__)
66
- if exception.extract_exc_info
67
- else None
68
- )
69
-
70
- match exception_severity:
71
- case Severity.LOW:
72
- remote_logger_method = self._remote_logger.info
73
- logger_method = self._logger.info
74
- case Severity.MEDIUM:
75
- remote_logger_method = self._remote_logger.warning
76
- logger_method = self._logger.warning
77
- case _:
78
- message = "something went wrong"
79
- remote_logger_method = self._remote_logger.error
80
- logger_method = self._logger.error
81
-
82
- content: dict[str, Any] = {
83
- "severity": exception_severity.name,
84
- "message": message,
85
- }
86
- status_code = self._status_code_from_severity(exception.severity)
87
- headers = None
88
-
89
- match exception:
90
- case HTTPServiceError() as http_service_error:
91
- if http_service_error.body is not None:
92
- extra_body = to_jsonable_python(http_service_error.body)
93
- is_updated = False
94
-
95
- try:
96
- if isinstance(extra_body, Iterable):
97
- content.update(extra_body)
98
-
99
- is_updated = True
100
- except:
101
- pass
102
-
103
- if not is_updated:
104
- content["data"] = extra_body
105
-
106
- if http_service_error.response_code is not None:
107
- content["code"] = http_service_error.response_code
108
- str_response_code = str(http_service_error.response_code)
109
- extra["responseCode"] = str_response_code
110
-
111
- tags.append(str_response_code)
112
-
113
- if http_service_error.corrective_action is not None:
114
- content["correctiveAction"] = (
115
- http_service_error.corrective_action
116
- )
117
-
118
- if http_service_error.status_code is not None:
119
- status_code = http_service_error.status_code
120
- str_status_code = str(status_code)
121
- extra["statusCode"] = str_status_code
122
-
123
- tags.append(str_status_code)
124
-
125
- if http_service_error.headers is not None:
126
- headers = http_service_error.headers
127
- case RabbitMQServiceException() as rabbitmq_service_exception:
128
- str_error_code = str(rabbitmq_service_exception.code)
129
- extra["code"] = str_error_code
130
-
131
- tags.append(str_error_code)
132
-
133
- if exception.tags:
134
- tags.extend(exception.tags)
135
-
136
- if exception.extra:
137
- extra.update(exception.extra)
138
-
139
- if exception.remote_logging:
140
- remote_logger_method(
141
- message=exception.message,
142
- tags=tags,
143
- extra=extra,
144
- exception=exception if exception.extract_exc_info else None,
145
- )
146
- else:
147
- logger_method(
148
- "\n%s %s\n%s",
149
- request.method,
150
- request.url.path,
151
- exception.message,
152
- exc_info=exc_info,
153
- )
154
-
155
- return JSONResponse(
156
- content=content,
157
- status_code=status_code,
158
- headers=headers,
159
- )
160
-
161
- def _status_code_from_severity(self, severity: Severity | None) -> int:
162
- if (
163
- severity is None
164
- or severity is Severity.LOW
165
- or severity is Severity.MEDIUM
166
- ):
167
- return cast(int, status.HTTP_400_BAD_REQUEST)
168
-
169
- return cast(int, status.HTTP_500_INTERNAL_SERVER_ERROR)
170
-
171
-
172
- class RequestValidationErrorHandler(AbstractHttpExceptionHandler):
173
- @property
174
- def exception(self) -> type[Exception]:
175
- return cast(type[Exception], RequestValidationError)
176
-
177
- def __init__(self, logger_provider: LoggerProvider):
178
- self._logger = logger_provider.get_logger("http.exception_handler")
179
-
180
- def __call__(
181
- self, request: Request, error: RequestValidationError
182
- ) -> Response:
183
- message = "invalid request data"
184
-
185
- self._logger.warning(
186
- "\n%s %s\n%s", request.method, request.url.path, message
187
- )
188
-
189
- return JSONResponse(
190
- content={
191
- "severity": Severity.MEDIUM.name,
192
- "message": message,
193
- "code": 100,
194
- "detail": to_jsonable_python(error.errors()),
195
- },
196
- status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
197
- )
198
-
199
-
200
- class GeneralHttpExceptionHandler(AbstractHttpExceptionHandler):
201
- @property
202
- def exception(self) -> type[Exception]:
203
- return Exception
204
-
205
- def __init__(self, remote_logger: BaseRemoteLogSender):
206
- self._remote_logger = remote_logger
207
-
208
- def __call__(self, request: Request, exception: Exception) -> Response:
209
- user_agent = request.get("user-agent", "__unknown__")
210
-
211
- self._remote_logger.error(
212
- message=f"something went wrong on endpoint `{request.method} {request.url.path}`",
213
- tags=[
214
- "HTTP",
215
- request.method,
216
- request.url.path,
217
- exception.__class__.__name__,
218
- ],
219
- extra={
220
- "serviceType": "HTTP",
221
- "method": request.method,
222
- "path": request.url.path,
223
- "userAgent": user_agent,
224
- "exception": exception.__class__.__name__,
225
- },
226
- exception=exception,
227
- )
228
-
229
- return JSONResponse(
230
- content={
231
- "severity": Severity.HIGH.name,
232
- "message": "something went wrong",
233
- },
234
- status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
235
- )
@@ -1,31 +0,0 @@
1
- qena_shared_lib/__init__.py,sha256=gYwkSbX7aC96BKp7FysOBDOsbli527haUQpaFtSpF7c,418
2
- qena_shared_lib/application.py,sha256=4a1RfI9ZqM5iVHCykjQ_zeDfb7lwqqP5uThS1wYWOAU,7111
3
- qena_shared_lib/background.py,sha256=A6ohscchVpBzT2igDnAV6WgbJoQtmjqJYLxZBl6HiNE,3323
4
- qena_shared_lib/exception_handlers.py,sha256=wEnmWyLZZBnl1zJpkRNr_m_VNdGr85IBWZxhGdlHe-E,7715
5
- qena_shared_lib/exceptions.py,sha256=D9Vs2q03VW_Eo7pD_8RYsZGNkVOOQ4Aq9HpUcnxeRlA,11031
6
- qena_shared_lib/http.py,sha256=2u5T9aXmUrg5WoRb3uaKUqG_m_mWey_O-KXi_ANVfz4,25047
7
- qena_shared_lib/logging.py,sha256=dEDkhBjU5LY7TspdsylO0hCcrPQz-7xiJx6RWKo4otk,1548
8
- qena_shared_lib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- qena_shared_lib/scheduler.py,sha256=XNXHrUPkYMfV26DQyFJrMJvjXZhFqMoVaknHrE5E_So,13149
10
- qena_shared_lib/security.py,sha256=iVk-TUtm9Zl8BZlV51iSyTQOibIiCoHIgVFnXNItrqk,6277
11
- qena_shared_lib/utils.py,sha256=yoDbtEAhqa30Fubh6h5w919Vuybq23M8yWG-YOa3Cqc,1032
12
- qena_shared_lib/dependencies/__init__.py,sha256=W12RgJbhqZ9GiSV1nLlHmpwPzvQv8t7f4JEoazM_WYg,350
13
- qena_shared_lib/dependencies/http.py,sha256=IBsMnRr8Jh8ixf2IcU6n1aYRMazI3fF9GLZxHM2dsXk,1492
14
- qena_shared_lib/dependencies/miscellaneous.py,sha256=iGwAjatXb_JVSF13n1vdTRAgSKv19VtHo9ZbjjbkIco,753
15
- qena_shared_lib/rabbitmq/__init__.py,sha256=1Rw7OP-A9UacuQWHzKbSOa9zFHa4FsEyFTVgAps01tw,1267
16
- qena_shared_lib/rabbitmq/_base.py,sha256=k1RFyMo5zCyUZo7Bn8PPkuCx2pVW9Gb0O08q0WbMFoQ,23125
17
- qena_shared_lib/rabbitmq/_channel.py,sha256=IitD3OPgg4dkGq5voSr4U5UOuHmCRGMTi4Gi83_zODk,5932
18
- qena_shared_lib/rabbitmq/_exception_handlers.py,sha256=Gc8IXWLddl0qr7KHXWjyq_Rl52zMlb8iQiLO-2zwvlk,5757
19
- qena_shared_lib/rabbitmq/_listener.py,sha256=C5J8RqiLCC_ZUMTySqJc3B7fW9_N9cCs2AxsjDeCFyM,48400
20
- qena_shared_lib/rabbitmq/_pool.py,sha256=eEJswSoWoWzjh290doFYccn1cwQW6DgbdpHeU-7nZSg,2006
21
- qena_shared_lib/rabbitmq/_publisher.py,sha256=aTasICX_XBuq2FEud3luuaLseCkALb8zUt_ht9EjjKs,2506
22
- qena_shared_lib/rabbitmq/_rpc_client.py,sha256=BdfsUWRjkmFwD8HLg5Lnrwao98M4Zwj8vS3-Ybk5MmA,9328
23
- qena_shared_lib/remotelogging/__init__.py,sha256=DEmzWGadTT9-utyEAAmyVDkWFhsonY4wbWIy1J34C14,245
24
- qena_shared_lib/remotelogging/_base.py,sha256=XYd_4iGkXJNT5HC_vLoj5wP4QQp6PCJreVnFv8rQHps,15394
25
- qena_shared_lib/remotelogging/logstash/__init__.py,sha256=-sg2V8gYuAKtnHSXfLorpdu_LUB_Gpldw0pCuWIsSc0,186
26
- qena_shared_lib/remotelogging/logstash/_base.py,sha256=ZNxE9SjZJW3sWKUUn3i52__X0mZuykaZLL3mp-52EOQ,961
27
- qena_shared_lib/remotelogging/logstash/_http_sender.py,sha256=kTUdHE1OOSI72tDbIxmwv1-g8shHldfZ0-nBoSu8TyU,1810
28
- qena_shared_lib/remotelogging/logstash/_tcp_sender.py,sha256=hIxDW2zEM07rr7BtgmJ5gR9Cs-MXiPD9qtQoVnrmNJ8,2467
29
- qena_shared_lib-0.1.16.dist-info/METADATA,sha256=OgRzBYcHpZnknzpnDXbRRSP7AScsVGvF-rQRV9nUfAc,11819
30
- qena_shared_lib-0.1.16.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
31
- qena_shared_lib-0.1.16.dist-info/RECORD,,