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.
- qena_shared_lib/__init__.py +3 -2
- qena_shared_lib/application.py +4 -4
- qena_shared_lib/background.py +9 -7
- qena_shared_lib/exception_handling.py +409 -0
- qena_shared_lib/exceptions.py +170 -57
- qena_shared_lib/http/__init__.py +90 -0
- qena_shared_lib/{http.py → http/_base.py} +36 -36
- qena_shared_lib/http/_exception_handlers.py +202 -0
- qena_shared_lib/kafka/__init__.py +21 -0
- qena_shared_lib/kafka/_base.py +233 -0
- qena_shared_lib/kafka/_consumer.py +597 -0
- qena_shared_lib/kafka/_exception_handlers.py +124 -0
- qena_shared_lib/kafka/_producer.py +133 -0
- qena_shared_lib/logging.py +17 -13
- qena_shared_lib/rabbitmq/__init__.py +4 -6
- qena_shared_lib/rabbitmq/_base.py +68 -132
- qena_shared_lib/rabbitmq/_channel.py +2 -4
- qena_shared_lib/rabbitmq/_exception_handlers.py +69 -142
- qena_shared_lib/rabbitmq/_listener.py +246 -157
- qena_shared_lib/rabbitmq/_publisher.py +5 -5
- qena_shared_lib/rabbitmq/_rpc_client.py +21 -22
- qena_shared_lib/remotelogging/_base.py +20 -20
- qena_shared_lib/remotelogging/logstash/_base.py +2 -2
- qena_shared_lib/remotelogging/logstash/_http_sender.py +2 -4
- qena_shared_lib/remotelogging/logstash/_tcp_sender.py +2 -2
- qena_shared_lib/scheduler.py +24 -15
- qena_shared_lib/security.py +39 -32
- qena_shared_lib/utils.py +13 -11
- {qena_shared_lib-0.1.16.dist-info → qena_shared_lib-0.1.18.dist-info}/METADATA +9 -1
- qena_shared_lib-0.1.18.dist-info/RECORD +38 -0
- qena_shared_lib/exception_handlers.py +0 -235
- qena_shared_lib-0.1.16.dist-info/RECORD +0 -31
- {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,,
|
File without changes
|