qena-shared-lib 0.1.1__py3-none-any.whl → 0.1.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.
@@ -94,7 +94,6 @@ class RabbitMqManager(AsyncEventLoopMixin):
94
94
 
95
95
  def __init__(
96
96
  self,
97
- listeners: list[Listener | type[ListenerBase]],
98
97
  logstash: BaseLogstashSender,
99
98
  parameters: Parameters | str | None = None,
100
99
  reconnect_delay: float = 5.0,
@@ -102,24 +101,7 @@ class RabbitMqManager(AsyncEventLoopMixin):
102
101
  listener_global_retry_policy: RetryPolicy | None = None,
103
102
  container: Container | None = None,
104
103
  ):
105
- for index, listener in enumerate(listeners):
106
- if not isinstance(listener, Listener) and (
107
- not isinstance(listener, type)
108
- or not issubclass(listener, ListenerBase)
109
- ):
110
- raise TypeError(
111
- f"listener {index} is {type(listener)}, expected instance of type or subclass of `Listener` or `type[ListenerBase]`"
112
- )
113
-
114
- self._listener_classes = [
115
- listener_class
116
- for listener_class in listeners
117
- if isinstance(listener_class, type)
118
- and issubclass(listener_class, ListenerBase)
119
- ]
120
- self._listeners = [
121
- listener for listener in listeners if isinstance(listener, Listener)
122
- ]
104
+ self._listeners: list[Listener] = []
123
105
 
124
106
  if isinstance(parameters, str):
125
107
  self._parameters = URLParameters(parameters)
@@ -139,8 +121,6 @@ class RabbitMqManager(AsyncEventLoopMixin):
139
121
  type[Exception], ExceptionHandlerContainer
140
122
  ] = {}
141
123
 
142
- self._register_listener_classes()
143
-
144
124
  self.exception_handler(RabbitMQException)(handle_rabbitmq_exception)
145
125
  self.exception_handler(ValidationError)(handle_validation_error)
146
126
  self.exception_handler(ServiceException)(handle_microservice_exception)
@@ -150,26 +130,6 @@ class RabbitMqManager(AsyncEventLoopMixin):
150
130
  self._logstash = logstash
151
131
  self._logger = LoggerProvider.default().get_logger("rabbitmq")
152
132
 
153
- def _register_listener_classes(self):
154
- for listener_class in self._listener_classes:
155
- inner_listener = getattr(listener_class, LISTENER_ATTRIBUTE, None)
156
-
157
- if inner_listener is None:
158
- raise AttributeError(
159
- "listener is possibly not with `Consumer` or `RpcWorker`"
160
- )
161
-
162
- if not isinstance(inner_listener, Listener):
163
- raise TypeError(
164
- f"listener class {type(listener_class)} is not a type `Listener`, posibilly not decorated with `Consumer` or `RpcWorker`"
165
- )
166
-
167
- self._container.register(
168
- service=ListenerBase,
169
- factory=listener_class,
170
- scope=Scope.singleton,
171
- )
172
-
173
133
  @property
174
134
  def container(self) -> Container:
175
135
  return self._container
@@ -239,6 +199,40 @@ class RabbitMqManager(AsyncEventLoopMixin):
239
199
 
240
200
  return True, None
241
201
 
202
+ def include_listener(self, listener: Listener | type[ListenerBase]):
203
+ if isinstance(listener, Listener):
204
+ self._listeners.append(listener)
205
+
206
+ return
207
+
208
+ if isinstance(listener, type) and issubclass(listener, ListenerBase):
209
+ self._register_listener_classes(listener)
210
+
211
+ return
212
+
213
+ raise TypeError(
214
+ f"listener is {type(listener)}, expected instance of type or subclass of `Listener` or `type[ListenerBase]`"
215
+ )
216
+
217
+ def _register_listener_classes(self, listener_class: type):
218
+ inner_listener = getattr(listener_class, LISTENER_ATTRIBUTE, None)
219
+
220
+ if inner_listener is None:
221
+ raise AttributeError(
222
+ "listener is possibly not with `Consumer` or `RpcWorker`"
223
+ )
224
+
225
+ if not isinstance(inner_listener, Listener):
226
+ raise TypeError(
227
+ f"listener class {type(listener_class)} is not a type `Listener`, posibilly not decorated with `Consumer` or `RpcWorker`"
228
+ )
229
+
230
+ self._container.register(
231
+ service=ListenerBase,
232
+ factory=listener_class,
233
+ scope=Scope.singleton,
234
+ )
235
+
242
236
  def include_service(
243
237
  self,
244
238
  rabbit_mq_service: AbstractRabbitMQService
@@ -407,9 +401,7 @@ class RabbitMqManager(AsyncEventLoopMixin):
407
401
  exception = task.exception()
408
402
 
409
403
  if exception is not None:
410
- if not self._disconnected and not isinstance(
411
- exception, (ConnectionClosedByClient, ChannelClosedByClient)
412
- ):
404
+ if self._can_reconnect(exception):
413
405
  self._logstash.error(
414
406
  message="couldn't drain the channel pool",
415
407
  exception=exception,
@@ -462,13 +454,7 @@ class RabbitMqManager(AsyncEventLoopMixin):
462
454
  if exception is not None:
463
455
  if not self._connected and not self._connected_future.done():
464
456
  self._connected_future.set_exception(exception)
465
- elif (
466
- self._connected
467
- and not self._disconnected
468
- and not isinstance(
469
- exception, (ConnectionClosedByClient, ChannelClosedByClient)
470
- )
471
- ):
457
+ elif self._can_reconnect(exception):
472
458
  self._logstash.error(
473
459
  message="couldn't fill the channel pool",
474
460
  exception=exception,
@@ -538,13 +524,7 @@ class RabbitMqManager(AsyncEventLoopMixin):
538
524
  if exception is not None:
539
525
  if not self._connected and not self._connected_future.done():
540
526
  self._connected_future.set_exception(exception)
541
- elif (
542
- self._connected
543
- and not self._disconnected
544
- and not isinstance(
545
- exception, (ConnectionClosedByClient, ChannelClosedByClient)
546
- )
547
- ):
527
+ elif self._can_reconnect(exception):
548
528
  self._logstash.error(
549
529
  message="couldn't configure and initialize all listeners and services",
550
530
  exception=exception,
@@ -671,13 +651,7 @@ class RabbitMqManager(AsyncEventLoopMixin):
671
651
 
672
652
  return
673
653
 
674
- if (
675
- self._connected
676
- and not self._disconnected
677
- and not isinstance(
678
- exception, (ConnectionClosedByClient, ChannelClosedByClient)
679
- )
680
- ):
654
+ if self._can_reconnect(exception):
681
655
  self._logstash.error(
682
656
  message="connection to rabbitmq closed unexpectedly, attempting to reconnect",
683
657
  exception=exception,
@@ -696,13 +670,7 @@ class RabbitMqManager(AsyncEventLoopMixin):
696
670
  try:
697
671
  connected_future = self.connect()
698
672
  except Exception as e:
699
- if (
700
- self._connected
701
- and not self._disconnected
702
- and not isinstance(
703
- e, (ConnectionClosedByClient, ChannelClosedByClient)
704
- )
705
- ):
673
+ if self._can_reconnect(e):
706
674
  if not self._connected_future.done():
707
675
  self._connected_future.set_result(None)
708
676
 
@@ -727,15 +695,18 @@ class RabbitMqManager(AsyncEventLoopMixin):
727
695
  if exception is None:
728
696
  return
729
697
 
730
- if (
731
- self._connected
732
- and not self._disconnected
733
- and not isinstance(
734
- exception, (ConnectionClosedByClient, ChannelClosedByClient)
735
- )
736
- ):
698
+ if self._can_reconnect(exception):
737
699
  self._logstash.error(
738
700
  message="couldn't reconnect to rabbitmq, attempting to reconnect",
739
701
  exception=exception,
740
702
  )
741
703
  self._reconnect()
704
+
705
+ def _can_reconnect(self, exception: BaseException) -> bool:
706
+ return (
707
+ self._connected
708
+ and not self._disconnected
709
+ and not isinstance(
710
+ exception, (ConnectionClosedByClient, ChannelClosedByClient)
711
+ )
712
+ )
@@ -181,33 +181,34 @@ class ScheduleManager(AsyncEventLoopMixin):
181
181
 
182
182
  def __init__(
183
183
  self,
184
- schedulers: list[Scheduler | type[SchedulerBase]],
185
184
  logstash: BaseLogstashSender,
186
185
  container: Container | None = None,
187
186
  ):
188
187
  self._container = container or Container()
189
188
  self._logstash = logstash
190
189
  self._scheduled_tasks: list[ScheduledTask] = []
191
-
192
- for index, scheduler in enumerate(schedulers):
193
- if isinstance(scheduler, Scheduler):
194
- self._scheduled_tasks.extend(scheduler.scheduled_tasks)
195
- elif isinstance(scheduler, type) and issubclass(
196
- scheduler, SchedulerBase
197
- ):
198
- self._container.register(
199
- service=SchedulerBase,
200
- factory=scheduler,
201
- scope=Scope.singleton,
202
- )
203
- else:
204
- raise TypeError(
205
- f"scheduler {index} is {type(scheduler)}, expected instance of type or subclass of `Scheduler` or `type[SchedulerBase]`"
206
- )
207
-
208
190
  self._next_run_in = None
209
191
  self._logger = LoggerProvider.default().get_logger("schedule_manager")
210
192
 
193
+ def include_scheduler(self, scheduler: Scheduler | type[SchedulerBase]):
194
+ if isinstance(scheduler, Scheduler):
195
+ self._scheduled_tasks.extend(scheduler.scheduled_tasks)
196
+
197
+ return
198
+
199
+ if isinstance(scheduler, type) and issubclass(scheduler, SchedulerBase):
200
+ self._container.register(
201
+ service=SchedulerBase,
202
+ factory=scheduler,
203
+ scope=Scope.singleton,
204
+ )
205
+
206
+ return
207
+
208
+ raise TypeError(
209
+ f"scheduler is {type(scheduler)}, expected instance of type or subclass of `Scheduler` or `type[SchedulerBase]`"
210
+ )
211
+
211
212
  @property
212
213
  def container(self) -> Container:
213
214
  return self._container
@@ -26,14 +26,14 @@ __all__ = [
26
26
  ]
27
27
 
28
28
 
29
- MESSAGE = "you are not authorized to access request resouce"
29
+ MESSAGE = "you are not authorized to access requested resouce"
30
30
  RESPONSE_CODE = int(environ.get("UNAUTHORIZED_RESPONSE_CODE") or 0)
31
31
 
32
32
 
33
33
  class PasswordHasher(AsyncEventLoopMixin):
34
- def __init__(self):
34
+ def __init__(self, schemes=None):
35
35
  self._crypt_context = CryptContext(
36
- schemes=["bcrypt"], deprecated="auto"
36
+ schemes=schemes or ["bcrypt"], deprecated="auto"
37
37
  )
38
38
 
39
39
  def hash(self, password: str) -> Future[str]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qena-shared-lib
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: A shared tools for other services
5
5
  Requires-Python: >=3.10
6
6
  Requires-Dist: cronsim~=2.0
@@ -224,13 +224,11 @@ def main() -> FastAPI:
224
224
  ...
225
225
 
226
226
  rabbitmq = RabbitMqManager(
227
- listeners=[
228
- UserConsumer
229
- ],
230
227
  logstash=logstash,
231
228
  container=builder.container,
232
229
  )
233
230
 
231
+ rabbitmq.include_listener(UserConsumer)
234
232
  builder.add_singleton(
235
233
  service=RabbitMqManager,
236
234
  instance=rabbitmq,
@@ -314,13 +312,11 @@ def main() -> FastAPI:
314
312
  ...
315
313
 
316
314
  schedule_manager = ScheduleManager(
317
- schedulers=[
318
- TaskScheduler
319
- ],
320
315
  logstash=logstash,
321
316
  container=builder.container
322
317
  )
323
318
 
319
+ schedule_manager.include_scheduler(TaskScheduler)
324
320
  builder.with_singleton(
325
321
  service=ScheduleManager,
326
322
  instance=schedule_manager,
@@ -6,8 +6,8 @@ qena_shared_lib/exceptions.py,sha256=cNeksC8ZavKgoqKLBik1NR-lCcdLZzITHMXww5deY5Y
6
6
  qena_shared_lib/http.py,sha256=90bmDfs522KxKBj2o0vO-MgmDqa3EZOfaNUFp1DuUdQ,23864
7
7
  qena_shared_lib/logging.py,sha256=JL6bAmkK1BJA84rZNpvDEmrec3dogQRpSug4fj1Omkw,1618
8
8
  qena_shared_lib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- qena_shared_lib/scheduler.py,sha256=Y1pSIU8P7_-tuesqpvAKm_DPRCqFB8o0srhXOF_r5BU,11965
10
- qena_shared_lib/security.py,sha256=mDozOTcazVz6QPN3Np8-IM2g9REqo_UCcQDE9HKlUEw,6005
9
+ qena_shared_lib/scheduler.py,sha256=MAYc566aW1y0nm7oq8g7GTtjN9PhATwLP7VF4cQVUHA,11855
10
+ qena_shared_lib/security.py,sha256=BR03IzEzFw2Zgtg3gYz1-hdsyBOB5A304G0I1y1KrrQ,6032
11
11
  qena_shared_lib/utils.py,sha256=bvPnjaFx7npVGSUO6IKdpiAHfUECsGRCeDW8UOjVckU,845
12
12
  qena_shared_lib/dependencies/__init__.py,sha256=W12RgJbhqZ9GiSV1nLlHmpwPzvQv8t7f4JEoazM_WYg,350
13
13
  qena_shared_lib/dependencies/http.py,sha256=3KopQjq05qbYROMPZjji2Zz7qQLU6_2u3qKisLrjLks,1469
@@ -17,7 +17,7 @@ qena_shared_lib/logstash/_base.py,sha256=b_wWbdIpl9aIqGdnNI-oYuZmiiUhx5rWXIbZzUR
17
17
  qena_shared_lib/logstash/_http_sender.py,sha256=Sq3bJOXuOafqloROGblnmyUd0RuU3zF0QLpQDYjiy-g,1765
18
18
  qena_shared_lib/logstash/_tcp_sender.py,sha256=ncvc3wYxOJPkB7c_0W8vboaxMRJ_1UYGdA8LN2NXUpo,2306
19
19
  qena_shared_lib/rabbitmq/__init__.py,sha256=WKAcKpRXXX9kqfHVEkyX6p2yIWzB07TMsBBWbV8nrKA,1209
20
- qena_shared_lib/rabbitmq/_base.py,sha256=2_HYL5zHIl201H8O2Vu_R3aNC2S1SHstEU6ttHvtj3c,24224
20
+ qena_shared_lib/rabbitmq/_base.py,sha256=rOUpYK3FJu3U5rU4vF--31c_Ycpnt4FL9qGkZNGLnYY,23068
21
21
  qena_shared_lib/rabbitmq/_channel.py,sha256=R0xzZvLkeE4YWsyLhx8bPDramsTFDZIcCgfsDyFmSB4,5429
22
22
  qena_shared_lib/rabbitmq/_exception_handlers.py,sha256=bhz-oteXcIEvYA-f4Mj6nFy66z-iVqk5rOARSx_8zSg,4733
23
23
  qena_shared_lib/rabbitmq/_exceptions.py,sha256=Mg56Uk4eBEwTnWC91_WPS3_8d-yaqNkbb_32IpX_R-c,1208
@@ -26,6 +26,6 @@ qena_shared_lib/rabbitmq/_pool.py,sha256=1_ftW0D3sPHI6v5c72oA03s05up4-1QqZ7d8icn
26
26
  qena_shared_lib/rabbitmq/_publisher.py,sha256=48JdpvNzFaw3Bw5LhunFxcjm3qNWz3AXKyXtcpzcohQ,2380
27
27
  qena_shared_lib/rabbitmq/_rpc_client.py,sha256=E-J5PIfA1T3j1y9KoxjNTzSLdK95MbaePulNxiqGb-M,8724
28
28
  qena_shared_lib/rabbitmq/_utils.py,sha256=5WZjYm4MdDrjL1dsrZuT8eKKiWfUef29_FJ262-hfSM,438
29
- qena_shared_lib-0.1.1.dist-info/METADATA,sha256=Y2ORNfT5rd26iuX5v_CTqN9pWYC7Ilg2llwV1y6i0Ow,7809
30
- qena_shared_lib-0.1.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
31
- qena_shared_lib-0.1.1.dist-info/RECORD,,
29
+ qena_shared_lib-0.1.2.dist-info/METADATA,sha256=GovQUH1CKBUrgBKkduLdtgSku8znAVAGjgMfyzqdZAU,7793
30
+ qena_shared_lib-0.1.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
31
+ qena_shared_lib-0.1.2.dist-info/RECORD,,