amqp-client-python 0.2.0__py3-none-any.whl → 0.2.0.post1__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.
@@ -10,15 +10,11 @@ class Config:
10
10
  self, options: Options, ssl_options: Optional[SSLOptions] = None
11
11
  ) -> None:
12
12
  """
13
- Create an Config object thats hold and mount the connection information.
13
+ Create a Config object that holds and manages the connection information.
14
14
 
15
15
  Args:
16
- options: hold information for estabilish connection
17
- ssl_options: hold information for estabilish SSL connections
18
-
19
- Returns:
20
-
21
- Raises:
16
+ options: holds information for establishing connection
17
+ ssl_options: holds information for establishing SSL connections
22
18
 
23
19
  Examples:
24
20
  >>> Config(
@@ -32,16 +28,13 @@ class Config:
32
28
 
33
29
  def build(self) -> "Config":
34
30
  """
35
- Create an Config object thats hold and mount the connection information.
36
-
37
- Args:
31
+ Create a Config object that holds and manages the connection information.
38
32
 
39
33
  Returns:
40
34
  Config object
41
35
 
42
- Raises:
43
-
44
36
  Examples:
37
+ >>> # config = Config(...)
45
38
  >>> config.build()
46
39
  """
47
40
  opt = {
@@ -18,7 +18,7 @@ class Options:
18
18
  **kwargs: Dict[str, Any]
19
19
  ) -> None:
20
20
  """
21
- Create an Options object that hold the credentials and configs options.
21
+ Create an Options object that holds the credentials and configuration options.
22
22
 
23
23
  Args:
24
24
  queue_name: name of queue that will be used for subscriptions
@@ -34,10 +34,6 @@ class Options:
34
34
  publisher_confirms: wait for publisher confirmations
35
35
  **kwargs: pika options
36
36
 
37
- Returns:
38
-
39
- Raises:
40
-
41
37
  Examples:
42
38
  >>> Options("example", "example.rpc", "example.rpc", "amqp://admin:admin@localhost:5672/")
43
39
 
@@ -3,18 +3,13 @@ class SSLOptions:
3
3
  self, certfile_path: str, keyfile_path: str, ca_certs_path: str
4
4
  ) -> None:
5
5
  """
6
- Create an SslOptions object that hold the certs paths.
6
+ Create an SslOptions object that holds the cert paths.
7
7
 
8
8
  Args:
9
9
  certfile_path: cert file path string
10
10
  keyfile_path: private key file path string
11
11
  ca_certs_path: ca file path string
12
12
 
13
- Returns:
14
- Um dicionário com as notas da escala e os graus.
15
-
16
- Raises:
17
-
18
13
  Examples:
19
14
  >>> SSLOptions("./.certs/cert.pem", "./.certs/privkey.pem", "./.certs/ca.pem")
20
15
  """
@@ -108,7 +108,6 @@ class AsyncChannel:
108
108
  :param pika.channel.Channel: The closed channel
109
109
  :param Exception reason: why the channel was closed
110
110
  """
111
- print("channel closed:", reason, flush=True)
112
111
  LOGGER.info(f"Channel {channel} was closed: {reason}")
113
112
  self._consuming = False
114
113
  if self._connection.is_closing or self._connection.is_closed:
@@ -238,10 +237,10 @@ class AsyncChannel:
238
237
  )
239
238
  else:
240
239
  future.set_result(body)
241
- return not self.auto_ack and self._channel_rpc.basic_ack(
240
+ return not self.auto_ack and self._channel_rpc.is_open and self._channel_rpc.basic_ack(
242
241
  basic_deliver.delivery_tag
243
242
  )
244
- not self.auto_ack and self._channel_rpc.basic_nack(
243
+ not self.auto_ack and self._channel_rpc.is_open and self._channel_rpc.basic_nack(
245
244
  basic_deliver.delivery_tag, requeue=False
246
245
  )
247
246
 
@@ -334,34 +333,41 @@ class AsyncChannel:
334
333
  routing_key: str,
335
334
  body,
336
335
  content_type,
337
- timeout,
336
+ response_timeout,
338
337
  delivery_mode=DeliveryMode.Transient,
339
338
  expiration: Optional[Union[str, None]] = None,
340
339
  **key_args,
341
340
  ):
341
+ # Create future to track RPC response
342
342
  future = self.ioloop.create_future() # type: ignore
343
+ # Generate unique correlation ID for RPC matching
343
344
  corr_id = str(uuid4())
345
+ # Store future in tracking dictionary
344
346
  self.rpc_futures[corr_id] = {"response": future}
347
+ # Setup cleanup callback for completed RPC
345
348
  clean_response = partial(self.clean_rpc_response, corr_id)
346
349
  future.add_done_callback(clean_response)
347
350
 
351
+ # Ensure RPC response consumer is operational
348
352
  await self.start_rpc_consumer()
349
353
 
354
+ # Publish RPC request with metadata headers
350
355
  self._channel.basic_publish(
351
356
  exchange_name,
352
357
  routing_key,
353
- dumps(body),
358
+ dumps(body), # Serialize payload to JSON
354
359
  properties=BasicProperties(
355
- reply_to=self._callback_queue,
356
- correlation_id=corr_id,
357
- content_type=content_type,
358
- delivery_mode=delivery_mode,
359
- expiration=expiration,
360
+ reply_to=self._callback_queue, # Response queue address
361
+ correlation_id=corr_id, # Request/response matching ID
362
+ content_type=content_type, # Payload format descriptor
363
+ delivery_mode=delivery_mode, # Persistent/Transient delivery
364
+ expiration=expiration, # Message TTL control
360
365
  **key_args,
361
366
  ),
362
367
  mandatory=False,
363
368
  )
364
369
 
370
+ # Setup timeout handler for unfulfilled requests
365
371
  def not_arrived(id: str):
366
372
  if id in self.rpc_futures:
367
373
  future = self.rpc_futures[id]
@@ -375,27 +381,40 @@ class AsyncChannel:
375
381
  )
376
382
 
377
383
  func = partial(not_arrived, corr_id)
378
- self.ioloop.call_later(timeout, func) # type: ignore
384
+ # Schedule timeout check using event loop
385
+ self.ioloop.call_later(response_timeout, func) # type: ignore
379
386
 
387
+ # Handle publisher confirms if enabled
380
388
  if self.publisher_confirms:
381
389
  return await self.handle_publish(future, corr_id)
390
+ # Return final response or exception
382
391
  return await future
383
392
 
384
393
  async def handle_publish(self, future, corr_id):
394
+ """Manages dual confirmation flow (publish + response)"""
395
+
396
+ # Create separate tracking for publish confirmation
385
397
  publish_future = self.ioloop.create_future()
398
+ # Store both futures in tracking system
386
399
  self.rpc_futures[corr_id]["published"] = publish_future
400
+ # Initiate confirmation tracking
387
401
  self.publish_confirmation(publish_future)
402
+ # Concurrently wait for first completed operation:
403
+ # - Publisher confirmation (ACK/NACK)
404
+ # - RPC response arrival
388
405
  done_all, pending_all = await wait(
389
406
  [publish_future, future], return_when=FIRST_COMPLETED
390
407
  )
408
+ # Extract potential exception from completed operation
391
409
  exception = done_all.pop().exception()
392
410
  if exception:
411
+ # Cancel remaining operations
393
412
  [undone.cancel() for undone in pending_all]
394
413
  raise exception
395
- elif len(pending_all):
414
+ elif len(pending_all): # Response still pending after confirmation
396
415
  return await future
397
416
  else:
398
- return future.result()
417
+ return future.result() # Return final result directly
399
418
 
400
419
  async def publish(
401
420
  self,
@@ -436,9 +455,15 @@ class AsyncChannel:
436
455
  return await publish_future
437
456
 
438
457
  def publish_confirmation(self, future: Future):
458
+ """Tracks message publishes requiring confirmation"""
459
+
460
+ # Increment sequence counter for message tracking
439
461
  self._message_number += 1
462
+ # Store future reference for confirmation handling
440
463
  self.futures[self._message_number] = future
464
+ # Link to delivery tracking system
441
465
  self._deliveries[self._message_number] = future
466
+ # Register cleanup callback using partial binding
442
467
  clean = partial(self.clean_publish_confirmation, self._message_number)
443
468
  future.add_done_callback(clean)
444
469
 
@@ -455,7 +480,7 @@ class AsyncChannel:
455
480
  routing_key: str,
456
481
  queue_name: str,
457
482
  callback,
458
- response_timeout,
483
+ timeout,
459
484
  content_type="application/json",
460
485
  exchange_type="topic",
461
486
  durable=True,
@@ -466,7 +491,7 @@ class AsyncChannel:
466
491
  exchange_name, queue_name, exchange_type, durable, auto_delete
467
492
  )
468
493
  self.register_handler(
469
- queue_name, routing_key, callback, content_type, response_timeout
494
+ queue_name, routing_key, callback, content_type, timeout
470
495
  )
471
496
 
472
497
  self.queue_bind(queue_name, exchange_name, routing_key)
@@ -518,7 +543,7 @@ class AsyncChannel:
518
543
  routing_key: str,
519
544
  queue_name: str,
520
545
  callback,
521
- response_timeout: Optional[int],
546
+ timeout: Optional[int],
522
547
  content_type: str = "application/json",
523
548
  exchange_type: str = "topic",
524
549
  durable: bool = True,
@@ -528,7 +553,7 @@ class AsyncChannel:
528
553
  exchange_name, queue_name, exchange_type, durable, auto_delete
529
554
  )
530
555
  self.register_handler(
531
- queue_name, routing_key, callback, content_type, response_timeout
556
+ queue_name, routing_key, callback, content_type, timeout
532
557
  )
533
558
 
534
559
  self.queue_bind(queue_name, exchange_name, routing_key)
@@ -572,7 +597,7 @@ class AsyncChannel:
572
597
  type="normal",
573
598
  ),
574
599
  )
575
- not self.auto_ack and not self._channel.basic_ack(
600
+ not self.auto_ack and self._channel.is_open and not self._channel.basic_ack(
576
601
  basic_deliver.delivery_tag
577
602
  )
578
603
 
@@ -599,7 +624,7 @@ class AsyncChannel:
599
624
  type="error",
600
625
  ),
601
626
  )
602
- return not self.auto_ack and self._channel.basic_nack(
627
+ return not self.auto_ack and self._channel.is_open and self._channel.basic_nack(
603
628
  basic_deliver.delivery_tag, requeue=False
604
629
  )
605
630
 
@@ -615,7 +640,7 @@ class AsyncChannel:
615
640
  type="error",
616
641
  ),
617
642
  )
618
- not self.auto_ack and self._channel.basic_nack(
643
+ not self.auto_ack and self._channel.is_open and self._channel.basic_nack(
619
644
  basic_deliver.delivery_tag, requeue=False
620
645
  )
621
646
 
@@ -21,6 +21,33 @@ class AsyncConnection:
21
21
  connection_type: Optional[ConnectionType] = None,
22
22
  signal=Signal(),
23
23
  ) -> None:
24
+ """
25
+ Manages asynchronous connections to RabbitMQ with automatic reconnection capabilities.
26
+
27
+ This class handles connection lifecycle, channel management, and provides methods for
28
+ publishing messages, subscribing to queues, and implementing RPC patterns.
29
+
30
+ Args:
31
+ ioloop: The asyncio event loop to use for async operations
32
+ publisher_confirms: Whether to enable publisher confirmations for this connection
33
+ prefetch_count: Maximum number of unacknowledged messages to prefetch
34
+ auto_ack: Whether to automatically acknowledge messages
35
+ connection_type: Type of connection (PUBLISH, SUBSCRIBE, RPC_CLIENT, RPC_SERVER)
36
+ signal: Signal object for event handling
37
+
38
+ Returns:
39
+ None: None
40
+
41
+ Examples:
42
+ >>> connection = AsyncConnection(
43
+ get_event_loop(),
44
+ publisher_confirms=True,
45
+ prefetch_count=10,
46
+ auto_ack=False,
47
+ connection_type=ConnectionType.PUBLISH
48
+ )
49
+ >>> connection.open("amqp://guest:guest@localhost:5672/%2F")
50
+ """
24
51
  self.ioloop = ioloop
25
52
  self.publisher_confirms = publisher_confirms
26
53
  self.connection_factory = AsyncConnectionFactoryRabbitMQ()
@@ -43,6 +70,18 @@ class AsyncConnection:
43
70
  }
44
71
 
45
72
  def open(self, uri):
73
+ """
74
+ Opens a connection to RabbitMQ using the provided URI.
75
+
76
+ If the connection is not already open and not in the process of opening,
77
+ this method will initiate a new connection.
78
+
79
+ Args:
80
+ uri: The AMQP URI to connect to (e.g., "amqp://guest:guest@localhost:5672/")
81
+
82
+ Examples:
83
+ >>> connection.open("amqp://guest:guest@localhost:5672/")
84
+ """
46
85
  self.url = uri
47
86
  if not self.is_open and not self.openning:
48
87
  if not self.ioloop:
@@ -55,13 +94,31 @@ class AsyncConnection:
55
94
  on_connection_closed=self.on_connection_closed,
56
95
  custum_ioloop=self.ioloop,
57
96
  )
97
+ return True
98
+ return False
58
99
 
59
100
  async def close(self):
101
+ """
102
+ Closes the connection to RabbitMQ gracefully.
103
+
104
+ This method will only close the connection if it is currently open.
105
+
106
+ Examples:
107
+ >>> await connection.close()
108
+ """
60
109
  if self.is_open:
61
110
  self._closing = True
62
111
  self._connection.close()
63
112
 
64
113
  def on_connection_open(self, _unused_connection):
114
+ """
115
+ Callback invoked when the connection to RabbitMQ is established.
116
+
117
+ This method creates a channel and emits a connection event.
118
+
119
+ Args:
120
+ _unused_connection: The connection object (not used)
121
+ """
65
122
  LOGGER.info(f"connection openned {_unused_connection}, {self._connection}")
66
123
  self.signal.emmit(Event.CONNECTED, condiction=self.type, loop=self.ioloop)
67
124
  self.openning = False
@@ -75,17 +132,29 @@ class AsyncConnection:
75
132
  self._channel.open(self._connection, self.callbacks)
76
133
 
77
134
  def on_connection_open_error(self, _unused_connection, err):
135
+ """
136
+ Callback invoked when the connection to RabbitMQ is established.
137
+
138
+ This method creates a channel and emits a connection event.
139
+
140
+ Args:
141
+ _unused_connection: The connection object (not used)
142
+ """
78
143
  LOGGER.info(f"connection open error: {err}, will attempt a connection")
79
144
  self.openning = False
80
145
  self.reconnect()
81
146
 
82
147
  def on_connection_closed(self, _unused_connection, reason):
83
- """This method is invoked by pika when the connection to RabbitMQ is
148
+ """
149
+ Callback invoked when the connection to RabbitMQ is closed unexpectedly.
150
+
151
+ This method is invoked by pika when the connection to RabbitMQ is
84
152
  closed unexpectedly. Since it is unexpected, we will reconnect to
85
153
  RabbitMQ if it disconnects.
86
- :param pika.connection.Connection connection: The closed connection obj
87
- :param Exception reason: exception representing reason for loss of
88
- connection.
154
+
155
+ Args:
156
+ _unused_connection: The closed connection object
157
+ reason: Exception representing reason for loss of connection
89
158
  """
90
159
  self._channel = None
91
160
  if self._closing:
@@ -98,15 +167,23 @@ class AsyncConnection:
98
167
  self.reconnect()
99
168
 
100
169
  def reconnect(self):
101
- """Will be invoked if the connection can't be opened or is
102
- closed. Indicates that a reconnect is necessary then stops the
103
- ioloop.
170
+ """
171
+ Initiates the reconnection process.
172
+
173
+ Will be invoked if the connection can't be opened or is closed.
174
+ Indicates that a reconnect is necessary.
104
175
  """
105
176
  if not self.reconnecting:
106
177
  self.reconnecting = True
107
178
  self.retry_connection()
108
179
 
109
180
  def retry_connection(self):
181
+ """
182
+ Attempts to reconnect to RabbitMQ with exponential backoff.
183
+
184
+ If reconnection is successful, this method will recover previous subscriptions
185
+ and RPC handlers.
186
+ """
110
187
  if not self.is_open:
111
188
  if self.reconnect_delay > 30:
112
189
  self.reconnect_delay = 30
@@ -125,7 +202,7 @@ class AsyncConnection:
125
202
  params["exchange_name"],
126
203
  routing_key,
127
204
  params["callback"],
128
- params["response_timeout"],
205
+ params["timeout"],
129
206
  )
130
207
  for routing_key in self.backup["rpc_subscribe"]:
131
208
  params = self.backup["rpc_subscribe"][routing_key]
@@ -134,7 +211,7 @@ class AsyncConnection:
134
211
  params["exchange_name"],
135
212
  routing_key,
136
213
  params["callback"],
137
- params["response_timeout"],
214
+ params["timeout"],
138
215
  )
139
216
 
140
217
  self.ioloop.create_task(self.add_callback(recorvery)) # type: ignore
@@ -143,6 +220,12 @@ class AsyncConnection:
143
220
 
144
221
  @property
145
222
  def is_open(self) -> Optional[bool]:
223
+ """
224
+ Checks if the connection is currently open.
225
+
226
+ Returns:
227
+ Optional[bool]: True if the connection is open, False otherwise, or None if no connection exists
228
+ """
146
229
  return self._connection and self._connection.is_open
147
230
 
148
231
  def stop(self) -> None:
@@ -170,17 +253,49 @@ class AsyncConnection:
170
253
  routing_key: str,
171
254
  body: Any,
172
255
  content_type: str,
173
- timeout,
256
+ response_timeout,
174
257
  delivery_mode,
175
258
  expiration,
176
259
  **kwargs,
177
260
  ):
261
+ """
262
+ Sends an RPC request and waits for a response.
263
+
264
+ Args:
265
+ exchange_name: The exchange to publish to
266
+ routing_key: The routing key for the message
267
+ body: The message body to send
268
+ content_type: Content type of the message
269
+ response_timeout: Timeout in seconds for waiting for a response
270
+ delivery_mode: Delivery mode (persistent or transient)
271
+ expiration: Maximum lifetime of the message in the queue
272
+ **kwargs: Additional message properties
273
+
274
+ Returns:
275
+ Any: The response from the RPC server
276
+
277
+ Raises:
278
+ PublishTimeoutException: If publisher confirmation times out
279
+ NackException: If the message is rejected by the broker
280
+ ResponseTimeoutException: If no response is received within the response_timeout
281
+
282
+ Examples:
283
+ >>> response = await connection.rpc_client(
284
+ "rpc_exchange",
285
+ "user.find",
286
+ {"id": 123},
287
+ "application/json",
288
+ 5.0,
289
+ DeliveryMode.Transient,
290
+ "60000"
291
+ )
292
+ """
178
293
  return await self._channel.rpc_client(
179
294
  exchange_name,
180
295
  routing_key,
181
296
  body,
182
297
  content_type,
183
- timeout,
298
+ response_timeout,
184
299
  delivery_mode,
185
300
  expiration,
186
301
  **kwargs,
@@ -197,6 +312,38 @@ class AsyncConnection:
197
312
  expiration,
198
313
  **kwargs,
199
314
  ):
315
+ """
316
+ Publishes a message to RabbitMQ.
317
+
318
+ Args:
319
+ exchange_name: The exchange to publish to
320
+ routing_key: The routing key for the message
321
+ body: The message body to send
322
+ content_type: Content type of the message
323
+ timeout: Timeout in seconds for publisher confirmation
324
+ delivery_mode: Delivery mode (persistent or transient)
325
+ expiration: Maximum lifetime of the message in the queue
326
+ **kwargs: Additional message properties
327
+
328
+ Returns:
329
+ Optional[bool]: True if publisher confirms enabled and message was confirmed,
330
+ None if publisher confirms disabled
331
+
332
+ Raises:
333
+ PublishTimeoutException: If publisher confirmation times out
334
+ NackException: If the message is rejected by the broker
335
+
336
+ Examples:
337
+ >>> result = await connection.publish(
338
+ "notifications",
339
+ "email.send",
340
+ {"to": "user@example.com", "subject": "Hello"},
341
+ "application/json",
342
+ 5.0,
343
+ DeliveryMode.Persistent,
344
+ "60000"
345
+ )
346
+ """
200
347
  return await self._channel.publish(
201
348
  exchange_name,
202
349
  routing_key,
@@ -209,37 +356,85 @@ class AsyncConnection:
209
356
  )
210
357
 
211
358
  async def rpc_subscribe(
212
- self, queue_name, exchange_name, routing_key, callback, response_timeout
359
+ self, queue_name, exchange_name, routing_key, callback, timeout
213
360
  ):
361
+ """
362
+ Registers an RPC handler for a specific routing key.
363
+
364
+ Args:
365
+ queue_name: The queue to consume from
366
+ exchange_name: The exchange to bind to
367
+ routing_key: The routing key to subscribe to
368
+ callback: The function to call when a message is received
369
+ timeout: Timeout in seconds for processing the received message
370
+
371
+ Examples:
372
+ >>> async def handle_rpc(body):
373
+ result = process_request(body)
374
+ return json.dumps(result).encode()
375
+ >>> await connection.rpc_subscribe(
376
+ "rpc_queue",
377
+ "rpc_exchange",
378
+ "user.find",
379
+ handle_rpc,
380
+ 10.0
381
+ )
382
+ """
214
383
  self.backup["rpc_subscribe"][routing_key] = {
215
384
  "queue_name": queue_name,
216
385
  "exchange_name": exchange_name,
217
386
  "callback": callback,
218
- "response_timeout": response_timeout,
387
+ "timeout": timeout,
219
388
  }
220
389
  await self._channel.rpc_subscribe(
221
390
  queue_name=queue_name,
222
391
  exchange_name=exchange_name,
223
392
  routing_key=routing_key,
224
393
  callback=callback,
225
- response_timeout=response_timeout,
394
+ timeout=timeout,
226
395
  )
227
396
 
228
397
  async def subscribe(
229
- self, queue_name, exchange_name, routing_key, callback, response_timeout
398
+ self,
399
+ queue_name: str,
400
+ exchange_name: str,
401
+ routing_key: str,
402
+ callback: Callable[[Any], Awaitable[None]],
403
+ timeout: Optional[float],
230
404
  ):
405
+ """
406
+ Subscribes to messages with a specific routing key.
407
+
408
+ Args:
409
+ queue_name: The queue to consume from
410
+ exchange_name: The exchange to bind to
411
+ routing_key: The routing key to subscribe to
412
+ callback: The function to call when a message is received
413
+ timeout: Timeout in seconds for processing the received message
414
+
415
+ Examples:
416
+ >>> async def handle_message(body):
417
+ print(f"Received: {body}")
418
+ >>> await connection.subscribe(
419
+ "notifications_queue",
420
+ "notifications",
421
+ "email.send",
422
+ handle_message,
423
+ 5.0
424
+ )
425
+ """
231
426
  self.backup["subscribe"][routing_key] = {
232
427
  "queue_name": queue_name,
233
428
  "exchange_name": exchange_name,
234
429
  "callback": callback,
235
- "response_timeout": response_timeout,
430
+ "timeout": timeout,
236
431
  }
237
432
  await self._channel.subscribe(
238
433
  exchange_name=exchange_name,
239
434
  queue_name=queue_name,
240
435
  routing_key=routing_key,
241
436
  callback=callback,
242
- response_timeout=response_timeout,
437
+ timeout=timeout,
243
438
  )
244
439
 
245
440
  async def add_callback(
@@ -247,6 +442,27 @@ class AsyncConnection:
247
442
  callback: Callable[..., Awaitable[Any]],
248
443
  connection_timeout: Optional[float] = None,
249
444
  ):
445
+ """
446
+ Executes a callback when the connection is ready or queues it for later execution.
447
+
448
+ If the connection and channel are open, executes the callback immediately.
449
+ Otherwise, queues the callback to be executed when the connection is established.
450
+
451
+ Args:
452
+ callback: The async function to call
453
+ connection_timeout: Maximum time to wait for the connection to be established
454
+
455
+ Returns:
456
+ Any: The result of the callback
457
+
458
+ Raises:
459
+ AutoReconnectException: When the connection cannot be established within the timeout
460
+
461
+ Examples:
462
+ >>> async def my_operation():
463
+ return await connection.publish(...)
464
+ >>> result = await connection.add_callback(my_operation, 10.0)
465
+ """
250
466
  try:
251
467
  if self.is_open and self._channel.is_open:
252
468
  return await callback()
@@ -23,8 +23,8 @@ class AsyncEventbusRabbitMQ:
23
23
  rpc_server_auto_ack: bool = False,
24
24
  ) -> None:
25
25
  """
26
- Create an AsyncEventbusRabbitMQ object thats interacts with Bus
27
- thats provides some connection management abstractions.
26
+ Create an AsyncEventbusRabbitMQ object that interacts with Bus that provides
27
+ some connection management abstractions
28
28
 
29
29
  Args:
30
30
  config: the Config object
@@ -40,27 +40,25 @@ class AsyncEventbusRabbitMQ:
40
40
  rpc_server_auto_ack: set to True to ack messages before processing on rpc server connection
41
41
 
42
42
  Returns:
43
- AsyncEventbusRabbitMQ object
44
-
45
- Raises:
43
+ None: None
46
44
 
47
45
  Examples:
48
46
  >>> async_eventbus = AsyncEventbusRabbitMQ(
49
47
  config, loop, rpc_client_publisher_confirms=True,
50
48
  rpc_server_publisher_confirms=False, rpc_server_auto_ack=False)
51
49
  ### register subscribe
52
- >>> def handler(*body):
50
+ >>> def subscribe_handler(body):
53
51
  print(f"do something with: {body}")
54
- >>> subscribe_event = ExampleEvent("rpc_exchange")
55
- >>> await eventbus.subscribe(subscribe_event, handler, "user.find")
52
+ >>> await eventbus.subscribe("rpc_exchange", "user.find", subscribe_handler)
56
53
  ### provide resource
57
- >>> def handler2(*body):
54
+ >>> def rpc_provider_handler(body) -> Union[str, bytes]:
58
55
  print(f"do something with: {body}")
59
- return "response"
60
- >>> await eventbus.provide_resource("user.find2", handle2)
56
+ return b"response"
57
+ >>> await eventbus.provide_resource("user.find2", rpc_provider_handler)
61
58
  """
62
59
  self._loop: Optional[AbstractEventLoop] = loop
63
60
  self._signal = Signal()
61
+ self._used_connections: List[AsyncConnection] = []
64
62
  self._pub_connection = AsyncConnection(
65
63
  self._loop,
66
64
  pub_publisher_confirms,
@@ -108,7 +106,7 @@ class AsyncEventbusRabbitMQ:
108
106
  **kwargs
109
107
  ) -> bytes:
110
108
  """
111
- Sends a publish message to queue of the bus and waits for a response
109
+ Sends a publish message to a queue of the bus and waits for a response
112
110
 
113
111
  Args:
114
112
  exchange: exchange name
@@ -125,14 +123,14 @@ class AsyncEventbusRabbitMQ:
125
123
 
126
124
  Raises:
127
125
  AutoReconnectException: when cannout reconnect on the gived timeout
128
- PublishTimeoutException: if publish confirmation is setted to True and \
126
+ PublishTimeoutException: if publish confirmation is set to True and \
129
127
  does not receive confirmation on the gived timeout
130
- NackException: if publish confirmation is setted to True and receives a nack
128
+ NackException: if publish confirmation is set to True and receives a nack
131
129
  ResponseTimeoutException: if response timeout is reached
132
130
  RpcProviderException: if the rpc provider responded with an error
133
131
 
134
132
  Examples:
135
- >>> await eventbus.rpc_client("example.rpc", "user.find", [{"name": "example"}], "application/json")
133
+ >>> await eventbus.rpc_client("example.rpc", "user.find", {"name": "example"}, "application/json")
136
134
  """
137
135
 
138
136
  async def add_rpc_client():
@@ -165,10 +163,10 @@ class AsyncEventbusRabbitMQ:
165
163
  **kwargs
166
164
  ) -> Optional[bool]:
167
165
  """
168
- Sends a publish message to the bus following parameters passed
166
+ Sends a publish message to the bus following the parameters passed
169
167
 
170
168
  Args:
171
- exchange: exchange name
169
+ exchange_name: exchange name
172
170
  routing_key: routing key name
173
171
  body: body that will be sent
174
172
  content_type: content type of message
@@ -178,15 +176,14 @@ class AsyncEventbusRabbitMQ:
178
176
  expiration: maximum lifetime of message to stay on the queue
179
177
 
180
178
  Returns:
181
- None: if publish confirmation is setted to False
182
- True: if successful when publish confirmation is setted to True
179
+ None: if publish confirmation is set to False
180
+ True: if successful when publish confirmation is set to True
183
181
 
184
182
  Raises:
185
183
  AutoReconnectException: when cannout reconnect on the gived timeout
186
- PublishTimeoutException: if publish confirmation is setted to True and \
184
+ PublishTimeoutException: if publish confirmation is set to True and \
187
185
  does not receive confirmation on the gived timeout
188
- NackException: if publish confirmation is setted to True and receives a nack
189
-
186
+ NackException: if publish confirmation is set to True and receives a nack
190
187
 
191
188
  Examples:
192
189
  >>> exchange_name = "example.rpc"
@@ -212,30 +209,27 @@ class AsyncEventbusRabbitMQ:
212
209
  async def provide_resource(
213
210
  self,
214
211
  name: str,
215
- handler: Callable[[List[Any]], Awaitable[Union[bytes, str]]],
216
- response_timeout: Optional[int] = None,
212
+ handler: Callable[[Any], Awaitable[Union[bytes, str]]],
213
+ timeout: Optional[int] = None,
217
214
  connection_timeout: int = 16,
218
215
  ) -> None:
219
216
  """
220
- Register a provider to listen on queue of bus
217
+ Register a provider to listen on RPC request queue
221
218
 
222
219
  Args:
223
220
  name: routing_key name
224
221
  handler: message handler, it will be called when a message is received
225
- response_timeout: timeout in seconds for waiting for process the received message
222
+ timeout: timeout in seconds for waiting for process the received message
226
223
  connection_timeout: timeout for waiting for connection restabilishment
227
224
 
228
- Returns:
229
- None: None
230
-
231
225
  Raises:
232
226
  AutoReconnectException: when cannout reconnect on the gived timeout
233
227
 
234
228
  Examples:
235
- >>> async def handle(body) -> Union[bytes, str]:
229
+ >>> async def handler(body) -> Union[bytes, str]:
236
230
  print(f"received message: {body}")
237
231
  return b"[]"
238
- >>> await eventbus.provide_resource("user.find", handle)
232
+ >>> await eventbus.provide_resource("user.find", handler)
239
233
  """
240
234
 
241
235
  async def add_resource():
@@ -244,10 +238,11 @@ class AsyncEventbusRabbitMQ:
244
238
  self.config.options.rpc_exchange_name,
245
239
  name,
246
240
  handler,
247
- response_timeout,
241
+ timeout,
248
242
  )
249
243
 
250
- self._rpc_server_connection.open(self.config.url)
244
+ if self._rpc_server_connection.open(self.config.url):
245
+ self._used_connections.append(self._rpc_server_connection)
251
246
  await self._rpc_server_connection.add_callback(add_resource, connection_timeout)
252
247
 
253
248
  async def subscribe(
@@ -255,7 +250,7 @@ class AsyncEventbusRabbitMQ:
255
250
  exchange_name: str,
256
251
  routing_key: str,
257
252
  handler: Callable[[Any], Awaitable[None]],
258
- response_timeout: Optional[float] = None,
253
+ timeout: Optional[float] = None,
259
254
  connection_timeout: int = 16,
260
255
  ) -> None:
261
256
  """
@@ -265,12 +260,9 @@ class AsyncEventbusRabbitMQ:
265
260
  exchange_name: exchange name
266
261
  routing_key: routing_key name
267
262
  handler: message handler, it will be called when a message is received
268
- response_timeout: timeout in seconds for waiting for process the received message
263
+ timeout: timeout in seconds for waiting for process the received message
269
264
  connection_timeout: timeout for waiting for connection restabilishment
270
265
 
271
- Returns:
272
- None: None
273
-
274
266
  Raises:
275
267
  AutoReconnectException: when cannout reconnect on the gived timeout
276
268
 
@@ -279,9 +271,9 @@ class AsyncEventbusRabbitMQ:
279
271
  print(f"received message: {body}")
280
272
  >>> exchange_name = "example"
281
273
  >>> routing_key = "user.find3"
282
- >>> response_timeout = 20
274
+ >>> timeout = 20
283
275
  >>> connection_timeout = 16
284
- >>> await eventbus.subscribe(exchange_name, routing_key, handle, response_timeout, connection_timeout)
276
+ >>> await eventbus.subscribe(exchange_name, routing_key, handle, timeout, connection_timeout)
285
277
  """
286
278
 
287
279
  async def add_subscribe():
@@ -290,13 +282,45 @@ class AsyncEventbusRabbitMQ:
290
282
  exchange_name,
291
283
  routing_key,
292
284
  handler,
293
- response_timeout,
285
+ timeout,
294
286
  )
295
287
 
296
- self._sub_connection.open(self.config.url)
288
+ if self._sub_connection.open(self.config.url):
289
+ self._used_connections.append(self._sub_connection)
297
290
  await self._sub_connection.add_callback(add_subscribe, connection_timeout)
298
291
 
299
- async def dispose(self, stop_event_loop=True) -> None:
292
+ async def restore(self) -> None:
293
+ """
294
+ Restores connections and subscriptions after a disconnection.
295
+
296
+ This method attempts to reopen connections that were closed and
297
+ re-establishes any previously registered subscriptions and RPC providers.
298
+
299
+ Examples:
300
+ >>> # After a dispose, call restore to re-establish connections
301
+ >>> await eventbus.restore()
302
+ """
303
+ for connection in self._used_connections:
304
+ if not connection.is_open:
305
+ connection.open(self.config.url)
306
+
307
+ async def dispose(self, stop_event_loop: bool = True) -> None:
308
+ """
309
+ Closes all connections and optionally stops the event loop.
310
+
311
+ This method properly disposes of all resources used by the event bus,
312
+ including publisher, subscriber, RPC client, and RPC server connections.
313
+
314
+ Args:
315
+ stop_event_loop: Whether to stop the event loop after closing connections.
316
+
317
+ Examples:
318
+ >>> # Close all connections and stop the event loop
319
+ >>> await eventbus.dispose()
320
+
321
+ >>> # Close all connections but keep the event loop running
322
+ >>> await eventbus.dispose(stop_event_loop=False)
323
+ """
300
324
  await self._pub_connection.close()
301
325
  await self._sub_connection.close()
302
326
  await self._rpc_client_connection.close()
@@ -127,7 +127,7 @@ class ChannelRabbitMQ:
127
127
  self.rpc_publisher = False
128
128
  self.rpc_consumer = False
129
129
  if not self._stopping:
130
- if not self._connection.is_open():
130
+ if not self._connection.is_open:
131
131
  if self._connection.ioloop_is_open:
132
132
  self._connection.ioloop.call_later(5, self.reconnect)
133
133
  # self._connection._connection.ioloop.call_later(5, self._connection.pause)
@@ -146,7 +146,7 @@ class ChannelRabbitMQ:
146
146
  LOGGER.debug("Closing the channel")
147
147
  self._channel.close()
148
148
 
149
- def start_rpc_consumer(self):
149
+ def start_rpc_consumer(self, exchange, routing_key, message, content_type, correlation_id):
150
150
  self.rpc_consumer = True
151
151
  LOGGER.info("Starting rpc consumer")
152
152
 
@@ -162,6 +162,17 @@ class ChannelRabbitMQ:
162
162
  consumer_tag=None,
163
163
  )
164
164
 
165
+ self._channel.basic_publish(
166
+ exchange,
167
+ routing_key,
168
+ message,
169
+ properties=BasicProperties(
170
+ reply_to=self._callback_queue,
171
+ correlation_id=correlation_id,
172
+ content_type=content_type,
173
+ ),
174
+ )
175
+
165
176
  LOGGER.info(f"Declaring queue {self._callback_queue}")
166
177
  self._channel_rpc.queue_declare(
167
178
  queue=self._callback_queue,
@@ -189,18 +200,19 @@ class ChannelRabbitMQ:
189
200
  last_id = str(uuid4())
190
201
  self.futures[last_id] = future
191
202
  self.response = None
192
- self._channel.basic_publish(
193
- exchange,
194
- routing_key,
195
- message,
196
- properties=BasicProperties(
197
- reply_to=self._callback_queue,
198
- correlation_id=last_id,
199
- content_type=content_type,
200
- ),
201
- )
202
203
  if not self.rpc_consumer:
203
- self.start_rpc_consumer()
204
+ self.start_rpc_consumer(exchange, routing_key, message, content_type, last_id)
205
+ else:
206
+ self._channel.basic_publish(
207
+ exchange,
208
+ routing_key,
209
+ message,
210
+ properties=BasicProperties(
211
+ reply_to=self._callback_queue,
212
+ correlation_id=last_id,
213
+ content_type=content_type,
214
+ ),
215
+ )
204
216
 
205
217
  def prevent_infinite_loop(last_id):
206
218
  if last_id in self.futures:
@@ -332,5 +344,5 @@ class ChannelRabbitMQ:
332
344
  future.set_result(body)
333
345
 
334
346
  def close(self):
335
- if self.is_open():
347
+ if self.is_open:
336
348
  self._channel.close()
@@ -56,7 +56,7 @@ class ConnectionRabbitMQ:
56
56
 
57
57
  def reconnect(self):
58
58
  LOGGER.debug("reconnect %s", self.ioloop_is_open)
59
- if not self.is_open():
59
+ if not self.is_open:
60
60
  self._connection = self._connectionFactory.create_connection(
61
61
  self._uri,
62
62
  self.on_connection_open,
@@ -119,7 +119,7 @@ class ConnectionRabbitMQ:
119
119
  "durable": durable,
120
120
  "callback": callback,
121
121
  }
122
- if self.is_open():
122
+ if self.is_open:
123
123
  self._channel.declare_exchange(
124
124
  exchange=exchange,
125
125
  durable=durable,
@@ -190,7 +190,7 @@ class ConnectionRabbitMQ:
190
190
  self.ioloop.add_callback_threadsafe(channel_openned)
191
191
 
192
192
  def channel_open(self, callback=lambda x: x):
193
- if not self.is_open():
193
+ if not self.is_open:
194
194
  raise EventBusException("No connection open!")
195
195
  if not self.channel_is_open():
196
196
  self._channel.open(self, callback)
@@ -200,7 +200,7 @@ class ConnectionRabbitMQ:
200
200
  return self._connection and self._connection.is_open
201
201
 
202
202
  def channel_is_open(self):
203
- return self._channel and self._channel.is_open()
203
+ return self._channel and self._channel.is_open
204
204
 
205
205
  def publish(self, exchange_name: str, routing_key: str, message: str):
206
206
  if not self.ioloop_is_open:
@@ -271,5 +271,5 @@ class ConnectionRabbitMQ:
271
271
 
272
272
  def close(self):
273
273
  self._channel.close()
274
- if self.is_open():
274
+ if self.is_open:
275
275
  self._connection.close()
@@ -185,13 +185,13 @@ class EventbusRabbitMQ:
185
185
  self.event_loop.add_callback_threadsafe(rpc_server_setup)
186
186
 
187
187
  def dispose(self, stop_event_loop=True):
188
- if self.pub_connection.is_open():
188
+ if self.pub_connection.is_open:
189
189
  self.pub_connection.close()
190
- if self.sub_connection.is_open():
190
+ if self.sub_connection.is_open:
191
191
  self.sub_connection.close()
192
- if self.rpc_client_connection.is_open():
192
+ if self.rpc_client_connection.is_open:
193
193
  self.rpc_client_connection.close()
194
- if self.rpc_server_connection.is_open():
194
+ if self.rpc_server_connection.is_open:
195
195
  self.rpc_server_connection.close()
196
196
  if stop_event_loop:
197
197
  self.event_loop.add_callback_threadsafe(self.event_loop.stop)
@@ -1,38 +1,41 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: amqp-client-python
3
- Version: 0.2.0
3
+ Version: 0.2.0.post1
4
4
  Summary: Python AMQP Client Library
5
- Home-page: https://github.com/nutes-uepb/amqp-client-python
5
+ Project-URL: Homepage, https://github.com/nutes-uepb/amqp-client-python
6
+ Project-URL: Repository, https://github.com/nutes-uepb/amqp-client-python
7
+ Project-URL: Bug Tracker, https://github.com/nutes-uepb/amqp-client-python/issues
8
+ Project-URL: Source, https://github.com/nutes-uepb/amqp-client-python
9
+ Author-email: NUTES UEPB <dev.seniorsaudemovel@gmail.com>
10
+ Maintainer-email: "João Pedro Miranda C. Hluchan" <berrytern@gmail.com>
6
11
  License: Apache-2.0
7
- Keywords: packaging,dependency,amqp-client-python
8
- Author: NUTES UEPB
9
- Author-email: dev.seniorsaudemovel@gmail.com
10
- Requires-Python: >=3.7,<4.0
12
+ License-File: LICENSE
13
+ Keywords: amqp-client-python,dependency,packaging
11
14
  Classifier: Development Status :: 5 - Production/Stable
12
15
  Classifier: Intended Audience :: Developers
13
16
  Classifier: License :: OSI Approved :: Apache Software License
14
17
  Classifier: Natural Language :: English
15
18
  Classifier: Operating System :: OS Independent
16
19
  Classifier: Programming Language :: Python :: 3
17
- Classifier: Programming Language :: Python :: 3.7
18
20
  Classifier: Programming Language :: Python :: 3.8
19
21
  Classifier: Programming Language :: Python :: 3.9
20
22
  Classifier: Programming Language :: Python :: 3.10
21
23
  Classifier: Programming Language :: Python :: 3.11
22
24
  Classifier: Programming Language :: Python :: 3.12
25
+ Classifier: Programming Language :: Python :: 3.13
26
+ Classifier: Programming Language :: Python :: 3.14
23
27
  Classifier: Topic :: Communications
24
28
  Classifier: Topic :: Internet
25
29
  Classifier: Topic :: Software Development :: Libraries
26
30
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
27
31
  Classifier: Topic :: System :: Networking
28
- Requires-Dist: pika (>=1.3.0,<2.0.0)
29
- Project-URL: Bug Tracker, https://github.com/nutes-uepb/amqp-client-python/issues
30
- Project-URL: Repository, https://github.com/nutes-uepb/amqp-client-python
32
+ Requires-Python: <4.0,>=3.9
33
+ Requires-Dist: pika<2.0.0,>=1.3.0
31
34
  Description-Content-Type: text/markdown
32
35
 
33
36
  # AMQP Client Python
34
37
 
35
- Client with high level of abstraction for manipulation of messages in the event bus RabbitMQ.
38
+ A Python client providing a high-level abstraction for interacting with RabbitMQ, simplifying message publishing, subscribing, and RPC patterns.
36
39
 
37
40
  --------
38
41
 
@@ -53,6 +56,18 @@ Client with high level of abstraction for manipulation of messages in the event
53
56
 
54
57
  **Source Code**: <a href="https://github.com/nutes-uepb/amqp-client-python" target="_blank">https://github.com/nutes-uepb/amqp-client-python</a>
55
58
 
59
+ **Discord Server**: <a href="https://discord.gg/RkXNeZpNZk" target="_blank">https://discord.gg/RkXNeZpNZk</a>
60
+
61
+ ### 🦀 Looking for higher performance? Try `amqp-rs`!
62
+ If you need higher throughput, thread safety, and built-in compression, check out [**amqp-rs**](https://pypi.org/project/amqp-rs/).
63
+
64
+ It is a high-performance Python extension developed in Rust using PyO3 and `tokio`. It shares a similar API and design philosophy with this library, but adds native thread safety, `zstd`/`zlib`/`lz4` compression, robust TLS/SSL support, and graceful shutdowns.
65
+
66
+ You can install it via `pip` or `uv`:
67
+ ```bash
68
+ pip install amqp-rs
69
+ ```
70
+
56
71
  ---
57
72
  ### Features:
58
73
  - Automatic creation and management of queues, exchanges and channels;
@@ -69,6 +84,18 @@ Client with high level of abstraction for manipulation of messages in the event
69
84
  | 0.2.0 | 0.2.0 |
70
85
  | 0.1.14 | ~0.1.12 |
71
86
 
87
+ ### Installation
88
+
89
+ You can install `amqp-client-python` using pip:
90
+ ```bash
91
+ pip install amqp-client-python
92
+ ```
93
+
94
+ ### Prerequisites
95
+
96
+ * Python 3.7+
97
+ * A running RabbitMQ instance.
98
+
72
99
  ### Examples:
73
100
  #### you can use [sync](https://github.com/nutes-uepb/amqp-client-python/blob/develop/amqp_client_python/rabbitmq/eventbus_rabbitmq.py) , [async eventbus](https://github.com/nutes-uepb/amqp-client-python/blob/develop/amqp_client_python/rabbitmq/async_eventbus_rabbitmq.py) and [sync wrapper](https://github.com/nutes-uepb/amqp-client-python/blob/develop/amqp_client_python/rabbitmq/eventbus_wrapper_rabbitmq.py) of async eventbus
74
101
  <details><summary>async usage </summary>
@@ -229,4 +256,4 @@ When using [**EventbusRabbitMQ**](https://github.com/nutes-uepb/amqp-client-pyth
229
256
  [known-vulnerabilities-image]: https://snyk.io/test/github/nutes-uepb/amqp-client-python/badge.svg?targetFile=requirements.txt
230
257
  [known-vulnerabilities-url]: https://snyk.io/test/github/nutes-uepb/amqp-client-python?targetFile=requirements.txt
231
258
  [releases-image]: https://img.shields.io/github/release-date/nutes-uepb/amqp-client-python.svg
232
- [releases-url]: https://github.com/nutes-uepb/amqp-client-python/releases
259
+ [releases-url]: https://github.com/nutes-uepb/amqp-client-python/releases
@@ -1,8 +1,10 @@
1
1
  amqp_client_python/__init__.py,sha256=6kv8G2KlcvbSVIE8Inxb3ugMNSTjg7KK9_HvyDprfb8,213
2
+ amqp_client_python/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ amqp_client_python/signals.py,sha256=6mW4oWBQnbJwuKox6ceeDbxTM8v9aCDEb0o2zyhpb5g,1263
2
4
  amqp_client_python/domain/models/__init__.py,sha256=T57j9Sr5Z0pWyGT598CpAx_KhoV-MVpgHTvfESZAa90,92
3
- amqp_client_python/domain/models/config.py,sha256=5uoSMpNWYQuJqE1QwVIA52nrKpcsetfOkzvVTtmZsNU,2288
4
- amqp_client_python/domain/models/options.py,sha256=jFHdoUjyi2v8xQD9W6koCr8icdyHVaKjdD_KYdPlsqE,2169
5
- amqp_client_python/domain/models/ssl_options.py,sha256=NADGDjxNBfd0QcBY3GSOhoffYmcLYURgzEYIj3ct3xQ,710
5
+ amqp_client_python/domain/models/config.py,sha256=g2AWrlEvHCS1h2zlny29phREyG9GmD0rtGQHS3C7LVU,2268
6
+ amqp_client_python/domain/models/options.py,sha256=lx-x4uyMpyjelZjMuyUxLsORz1ro1vDjD33j0EGYD-o,2141
7
+ amqp_client_python/domain/models/ssl_options.py,sha256=xOTSIKfbNZbYepY6o3SxuZvLPX3J5pvRoJXIJlyBsrI,613
6
8
  amqp_client_python/domain/utils/__init__.py,sha256=ppob9KPfzq9K3Fd2-RJr6CnwmPDOdgaAzPqOV0Q17P0,75
7
9
  amqp_client_python/domain/utils/connection_type.py,sha256=AnEF8Nd3cQBCGX8rPKwEkKts8kwnGUAVr0nxnbpynLE,164
8
10
  amqp_client_python/domain/utils/types.py,sha256=veT5lgZhUxophpmWItYaz56XxJTXGJ2L6J6oG_TbSWs,160
@@ -24,22 +26,20 @@ amqp_client_python/exceptions/response_timeout_exception.py,sha256=us_PiJPSk1pnz
24
26
  amqp_client_python/exceptions/rpc_provider_exception.py,sha256=_1Ytb8BOUT_9xEtG_ibGx3cEMMM4kUVtduEVtXn-d6M,280
25
27
  amqp_client_python/exceptions/thread_unsafe_exception.py,sha256=zcC4VyuxXWo66Tts1AQtkg07GK3OjXu3LEtt1AUj4jk,281
26
28
  amqp_client_python/exceptions/timeout_exception.py,sha256=0YT-vivS44mHF4Jc3o2rlZFc6l_zzNjcxCHPS9ArgN0,271
27
- amqp_client_python/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
29
  amqp_client_python/rabbitmq/__init__.py,sha256=ZFaBSr8TDzZlHwaT344ao20W2FD5c3RI2sa5kiEeKeI,630
29
- amqp_client_python/rabbitmq/async_channel.py,sha256=xljTUf2XLTpGkLgHM5APNOcC7MGv8Ib68R4UKZHNfvo,25105
30
+ amqp_client_python/rabbitmq/async_channel.py,sha256=OtW0agoSMG-v38lKJsFNRMaFoqubEauQCmLaLN7bQek,26667
30
31
  amqp_client_python/rabbitmq/async_channel_factory.py,sha256=ec_5B3Sgazi_ncIG5lI5nnmkH3NprwvyjMhvgpG1BWA,371
31
- amqp_client_python/rabbitmq/async_connection.py,sha256=U651qEYQUO7DBf33iuztYWRh1TiDJ1t-OPdMxmqZaqg,9225
32
+ amqp_client_python/rabbitmq/async_connection.py,sha256=lWArTU5lXKMrKnnTivhrWs8c9PJnUNMAD5_QI3FZu-s,16906
32
33
  amqp_client_python/rabbitmq/async_connection_factory.py,sha256=3N5MM1fPUdodAFLh58rf6vvwN9OAclDVzmG85Qve-Ss,849
33
- amqp_client_python/rabbitmq/async_eventbus_rabbitmq.py,sha256=d_jcoF3KL4LVyVGoxoEjsuKHPfPXE7ErUlvGP4hw7y0,11766
34
+ amqp_client_python/rabbitmq/async_eventbus_rabbitmq.py,sha256=4PCtqhVNT3cq-d0anfdKPzhmmETD-HMqIu-MVuZmZZA,12950
34
35
  amqp_client_python/rabbitmq/channel_factory_rabbitmq.py,sha256=h_vGqHgL0DOtXC0tmVd5gzXVlNKL48rxpKpwaN3AlOM,310
35
- amqp_client_python/rabbitmq/channel_rabbitmq.py,sha256=HSE3rqFxFrQVpVrs-PhW_2xc8onKFwQNsoXcmmJH1IY,13184
36
+ amqp_client_python/rabbitmq/channel_rabbitmq.py,sha256=S3SqGCfVRoIuPyZW40bQZBpWEgbe5YlvZ8ei23a2VVw,13737
36
37
  amqp_client_python/rabbitmq/connection_factory_rabbitmq.py,sha256=EKPG5gEsGwtpSKOhoPI5vK1sJOUARbOflOug6VREIrk,1022
37
- amqp_client_python/rabbitmq/connection_rabbitmq.py,sha256=7bv7ci1u0tQK74OvggRRoMfG2oABCnDO3cXoDsm7bdM,9782
38
- amqp_client_python/rabbitmq/eventbus_rabbitmq.py,sha256=HyfkeIRi4T3mP3XNAHfirr_Pxy2rhMBiE0W2EPsDnlM,6988
38
+ amqp_client_python/rabbitmq/connection_rabbitmq.py,sha256=9A8NAPAB3i-5E43SV5sxjKFFoRb4pIhzAAUHrvOvOng,9772
39
+ amqp_client_python/rabbitmq/eventbus_rabbitmq.py,sha256=GZoJGVeBkMTPrQ5dIJqad-MdGmuuJsxGaXV1YGLdk5o,6980
39
40
  amqp_client_python/rabbitmq/eventbus_wrapper_rabbitmq.py,sha256=i3C-sZO9EifanfRXReiib56fxxzjV3Cx71rdbJORg78,7442
40
41
  amqp_client_python/rabbitmq/ioloop_factory.py,sha256=vfgndKLcazQU0a4elI5RNHnQCTEua--Jjo99bzX8iHo,856
41
- amqp_client_python/signals.py,sha256=6mW4oWBQnbJwuKox6ceeDbxTM8v9aCDEb0o2zyhpb5g,1263
42
- amqp_client_python-0.2.0.dist-info/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
43
- amqp_client_python-0.2.0.dist-info/METADATA,sha256=K-H7fvA9N-ayfq9OVhPAlAbOW6g7zxk2ekqmOPz-SF8,9117
44
- amqp_client_python-0.2.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
45
- amqp_client_python-0.2.0.dist-info/RECORD,,
42
+ amqp_client_python-0.2.0.post1.dist-info/METADATA,sha256=w5Hdo9NIX282a9bOtOVK-AIJvvRLU0aUBjr4LPxr2ys,10206
43
+ amqp_client_python-0.2.0.post1.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
44
+ amqp_client_python-0.2.0.post1.dist-info/licenses/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
45
+ amqp_client_python-0.2.0.post1.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.9.0
2
+ Generator: hatchling 1.29.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any