buz 2.15.10rc5__py3-none-any.whl → 2.15.11__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 (26) hide show
  1. buz/event/infrastructure/buz_kafka/base_buz_aiokafka_async_consumer.py +7 -5
  2. buz/event/infrastructure/buz_kafka/kafka_event_async_subscriber_executor.py +20 -3
  3. buz/event/infrastructure/buz_kafka/kafka_event_sync_subscriber_executor.py +20 -5
  4. buz/event/infrastructure/buz_kafka/models/kafka_delivery_context.py +10 -0
  5. buz/event/infrastructure/kombu/kombu_consumer.py +10 -2
  6. buz/event/infrastructure/kombu/models/kombu_delivery_context.py +7 -0
  7. buz/event/infrastructure/models/__init__.py +0 -0
  8. buz/event/infrastructure/models/delivery_context.py +6 -0
  9. buz/event/infrastructure/models/execution_context.py +8 -0
  10. buz/event/middleware/async_consume_middleware.py +9 -2
  11. buz/event/middleware/async_consume_middleware_chain_resolver.py +16 -5
  12. buz/event/middleware/base_async_consume_middleware.py +23 -6
  13. buz/event/middleware/base_consume_middleware.py +9 -6
  14. buz/event/middleware/consume_middleware.py +5 -2
  15. buz/event/middleware/consume_middleware_chain_resolver.py +13 -4
  16. buz/event/sync/models/__init__.py +0 -0
  17. buz/event/sync/models/sync_delivery_context.py +7 -0
  18. buz/event/sync/sync_event_bus.py +10 -2
  19. buz/kafka/domain/models/kafka_poll_record.py +1 -0
  20. buz/kafka/infrastructure/aiokafka/rebalance/kafka_callback_rebalancer.py +3 -1
  21. buz/queue/in_memory/in_memory_multiqueue_repository.py +10 -6
  22. buz/queue/multiqueue_repository.py +5 -1
  23. {buz-2.15.10rc5.dist-info → buz-2.15.11.dist-info}/METADATA +2 -2
  24. {buz-2.15.10rc5.dist-info → buz-2.15.11.dist-info}/RECORD +26 -19
  25. {buz-2.15.10rc5.dist-info → buz-2.15.11.dist-info}/LICENSE +0 -0
  26. {buz-2.15.10rc5.dist-info → buz-2.15.11.dist-info}/WHEEL +0 -0
@@ -114,8 +114,8 @@ class BaseBuzAIOKafkaAsyncConsumer(AsyncConsumer):
114
114
  async def configure_http_check_server(self, health_check_port: int) -> web.TCPSite:
115
115
  self._logger.info(f"Starting health check server on port {health_check_port}")
116
116
  app = web.Application()
117
- app.router.add_get("/health", lambda request: self.__health_check())
118
- app.router.add_get("/ready", lambda request: self.__is_ready())
117
+ app.router.add_get("/health", self.__health_check)
118
+ app.router.add_get("/ready", self.__is_ready)
119
119
 
120
120
  runner = web.AppRunner(app)
121
121
  await runner.setup()
@@ -351,6 +351,8 @@ class BaseBuzAIOKafkaAsyncConsumer(AsyncConsumer):
351
351
  self._logger.info(
352
352
  f"rebalancing in progress, assigning partitions {topics_partitions} to consumer {consumer.get_consumer_group()}"
353
353
  )
354
+ for topic_partition in topics_partitions:
355
+ self.__queue_per_consumer_mapper[consumer].create_key(topic_partition)
354
356
 
355
357
  async def __on_partition_revoked(self, consumer: AIOKafkaConsumer, topics_partitions: set[TopicPartition]) -> None:
356
358
  self._logger.info(
@@ -362,7 +364,7 @@ class BaseBuzAIOKafkaAsyncConsumer(AsyncConsumer):
362
364
  consumer_fqn=consumer.get_consumer_group(),
363
365
  ):
364
366
  for topic_partition in topics_partitions:
365
- self.__queue_per_consumer_mapper[consumer].clear(topic_partition)
367
+ self.__queue_per_consumer_mapper[consumer].remove_key(topic_partition)
366
368
 
367
369
  self.decrease_number_of_rebalancing_in_progress()
368
370
 
@@ -382,7 +384,7 @@ class BaseBuzAIOKafkaAsyncConsumer(AsyncConsumer):
382
384
  async def __manage_kafka_consumers_stopping(self) -> None:
383
385
  await gather(*[kafka_consumer.stop() for kafka_consumer in self.__queue_per_consumer_mapper.keys()])
384
386
 
385
- async def __health_check(self) -> web.Response:
387
+ async def __health_check(self, request: web.Request) -> web.Response:
386
388
  health_information = {
387
389
  "subscribers": [subscriber.fqn() for subscriber in self.__subscribers],
388
390
  "number_of_subscribers": len(self.__subscribers),
@@ -391,7 +393,7 @@ class BaseBuzAIOKafkaAsyncConsumer(AsyncConsumer):
391
393
 
392
394
  return web.Response(text=json.dumps(health_information), content_type="application/json")
393
395
 
394
- async def __is_ready(self) -> web.Response:
396
+ async def __is_ready(self, request: web.Request) -> web.Response:
395
397
  is_ready = self.__is_worked_initialized
396
398
  status_code = 200 if is_ready else 503
397
399
 
@@ -8,6 +8,7 @@ from buz.event.infrastructure.buz_kafka.consume_strategy.kafka_on_fail_strategy
8
8
  from buz.event.infrastructure.buz_kafka.exceptions.max_consumer_retry_exception import MaxConsumerRetryException
9
9
  from buz.event.infrastructure.buz_kafka.exceptions.retry_exception import ConsumerRetryException
10
10
  from buz.event.infrastructure.buz_kafka.kafka_event_subscriber_executor import KafkaEventSubscriberExecutor
11
+ from buz.event.infrastructure.models.execution_context import ExecutionContext
11
12
  from buz.event.middleware.async_consume_middleware import AsyncConsumeMiddleware
12
13
  from buz.event.middleware.async_consume_middleware_chain_resolver import AsyncConsumeMiddlewareChainResolver
13
14
  from buz.event.strategies.retry.consume_retrier import ConsumeRetrier
@@ -15,6 +16,7 @@ from buz.event.strategies.retry.reject_callback import RejectCallback
15
16
  from buz.kafka.domain.exceptions.not_valid_kafka_message_exception import NotValidKafkaMessageException
16
17
  from buz.kafka.domain.models.kafka_consumer_record import KafkaConsumerRecord
17
18
  from buz.kafka.domain.models.kafka_poll_record import KafkaPollRecord
19
+ from buz.event.infrastructure.buz_kafka.models.kafka_delivery_context import KafkaDeliveryContext
18
20
  from buz.kafka.infrastructure.deserializers.byte_deserializer import ByteDeserializer
19
21
  from buz.kafka.infrastructure.serializers.kafka_header_serializer import KafkaHeaderSerializer
20
22
 
@@ -67,18 +69,33 @@ class KafkaEventAsyncSubscriberExecutor(KafkaEventSubscriberExecutor):
67
69
  value=deserialized_value,
68
70
  headers=self.__header_deserializer.deserialize(kafka_poll_record.headers),
69
71
  ),
72
+ ExecutionContext(
73
+ delivery_context=KafkaDeliveryContext(
74
+ topic=kafka_poll_record.topic,
75
+ consumer_group=self.__subscriber.fqn(),
76
+ partition=kafka_poll_record.partition,
77
+ timestamp=kafka_poll_record.timestamp,
78
+ )
79
+ ),
70
80
  )
71
81
  except NotValidKafkaMessageException:
72
82
  self.__logger.error(
73
83
  f'The message "{str(kafka_poll_record.value)}" is not valid, it will be consumed but not processed'
74
84
  )
75
85
 
76
- async def __consumption_callback(self, subscriber: AsyncSubscriber, message: KafkaConsumerRecord[Event]) -> None:
86
+ async def __consumption_callback(
87
+ self, subscriber: AsyncSubscriber, message: KafkaConsumerRecord[Event], execution_context: ExecutionContext
88
+ ) -> None:
77
89
  await self.__consume_middleware_chain_resolver.resolve(
78
- event=message.value, subscriber=subscriber, consume=self.__perform_consume
90
+ event=message.value,
91
+ subscriber=subscriber,
92
+ execution_context=execution_context,
93
+ consume=self.__perform_consume,
79
94
  )
80
95
 
81
- async def __perform_consume(self, event: Event, subscriber: AsyncSubscriber) -> None:
96
+ async def __perform_consume(
97
+ self, event: Event, subscriber: AsyncSubscriber, execution_context: ExecutionContext
98
+ ) -> None:
82
99
  number_of_executions = 0
83
100
  should_retry = True
84
101
 
@@ -7,6 +7,8 @@ from buz.event.infrastructure.buz_kafka.consume_strategy.kafka_on_fail_strategy
7
7
  from buz.event.infrastructure.buz_kafka.exceptions.max_consumer_retry_exception import MaxConsumerRetryException
8
8
  from buz.event.infrastructure.buz_kafka.exceptions.retry_exception import ConsumerRetryException
9
9
  from buz.event.infrastructure.buz_kafka.kafka_event_subscriber_executor import KafkaEventSubscriberExecutor
10
+ from buz.event.infrastructure.buz_kafka.models.kafka_delivery_context import KafkaDeliveryContext
11
+ from buz.event.infrastructure.models.execution_context import ExecutionContext
10
12
  from buz.event.middleware.consume_middleware import ConsumeMiddleware
11
13
  from buz.event.middleware.consume_middleware_chain_resolver import ConsumeMiddlewareChainResolver
12
14
  from buz.event.strategies.retry.consume_retrier import ConsumeRetrier
@@ -64,11 +66,19 @@ class KafkaEventSyncSubscriberExecutor(KafkaEventSubscriberExecutor):
64
66
  await get_running_loop().run_in_executor(
65
67
  None,
66
68
  lambda: self.__execution_callback(
67
- self.__subscriber,
68
- KafkaConsumerRecord(
69
+ subscriber=self.__subscriber,
70
+ message=KafkaConsumerRecord(
69
71
  value=deserialized_value,
70
72
  headers=self.__header_deserializer.deserialize(kafka_poll_record.headers),
71
73
  ),
74
+ execution_context=ExecutionContext(
75
+ delivery_context=KafkaDeliveryContext(
76
+ topic=kafka_poll_record.topic,
77
+ consumer_group=self.__subscriber.fqn(),
78
+ partition=kafka_poll_record.partition,
79
+ timestamp=kafka_poll_record.timestamp,
80
+ )
81
+ ),
72
82
  ),
73
83
  )
74
84
 
@@ -77,12 +87,17 @@ class KafkaEventSyncSubscriberExecutor(KafkaEventSubscriberExecutor):
77
87
  f'The message "{str(kafka_poll_record.value)}" is not valid, it will be consumed but not processed'
78
88
  )
79
89
 
80
- def __execution_callback(self, subscriber: Subscriber, message: KafkaConsumerRecord[Event]) -> None:
90
+ def __execution_callback(
91
+ self, subscriber: Subscriber, message: KafkaConsumerRecord[Event], execution_context: ExecutionContext
92
+ ) -> None:
81
93
  self.__consume_middleware_chain_resolver.resolve(
82
- event=message.value, subscriber=subscriber, consume=self.__perform_consume
94
+ event=message.value,
95
+ subscriber=subscriber,
96
+ execution_context=execution_context,
97
+ consume=self.__perform_consume,
83
98
  )
84
99
 
85
- def __perform_consume(self, event: Event, subscriber: Subscriber) -> None:
100
+ def __perform_consume(self, event: Event, subscriber: Subscriber, execution_context: ExecutionContext) -> None:
86
101
  number_of_executions = 0
87
102
  should_retry = True
88
103
 
@@ -0,0 +1,10 @@
1
+ from dataclasses import dataclass
2
+ from buz.event.infrastructure.models.delivery_context import DeliveryContext
3
+
4
+
5
+ @dataclass(frozen=True)
6
+ class KafkaDeliveryContext(DeliveryContext):
7
+ topic: str
8
+ consumer_group: str
9
+ partition: int
10
+ timestamp: int
@@ -2,6 +2,8 @@ import asyncio
2
2
  from logging import Logger
3
3
  from typing import Optional, Callable, cast
4
4
 
5
+ from buz.event.infrastructure.kombu.models.kombu_delivery_context import KombuDeliveryContext
6
+ from buz.event.infrastructure.models.execution_context import ExecutionContext
5
7
  from kombu import Connection, Queue, Consumer as MessageConsumer, Message
6
8
  from kombu.mixins import ConsumerMixin
7
9
  from kombu.transport.pyamqp import Channel
@@ -110,12 +112,18 @@ class KombuConsumer(ConsumerMixin, Consumer):
110
112
  # The problem here is that the chain resolver works with syncsubscribers, an asyncsubscriber would require of a async function,
111
113
  # but we are using run-until-complete to run the async function, so we are not really using the async function, we are just running it as a sync function, so we can cast the asyncsubscriber to a subscriber
112
114
  subscriber = cast(Subscriber, meta_subscriber)
113
- self.__consume_middleware_chain_resolver.resolve(event, subscriber, self.__perform_consume)
115
+ execution_context = ExecutionContext(delivery_context=KombuDeliveryContext())
116
+ self.__consume_middleware_chain_resolver.resolve(
117
+ event=event,
118
+ subscriber=subscriber,
119
+ execution_context=execution_context,
120
+ consume=self.__perform_consume,
121
+ )
114
122
  message.ack()
115
123
  except Exception as exc:
116
124
  self.__on_consume_exception(message, event, meta_subscribers, exc)
117
125
 
118
- def __perform_consume(self, event: Event, subscriber: MetaSubscriber) -> None:
126
+ def __perform_consume(self, event: Event, subscriber: MetaSubscriber, execution_context: ExecutionContext) -> None:
119
127
  if isinstance(subscriber, AsyncSubscriber):
120
128
  self.__get_or_create_event_loop().run_until_complete(subscriber.consume(event))
121
129
  return
@@ -0,0 +1,7 @@
1
+ from dataclasses import dataclass
2
+ from buz.event.infrastructure.models.delivery_context import DeliveryContext
3
+
4
+
5
+ @dataclass(frozen=True)
6
+ class KombuDeliveryContext(DeliveryContext):
7
+ pass
File without changes
@@ -0,0 +1,6 @@
1
+ from dataclasses import dataclass
2
+
3
+
4
+ @dataclass(frozen=True)
5
+ class DeliveryContext:
6
+ pass
@@ -0,0 +1,8 @@
1
+ from dataclasses import dataclass
2
+
3
+ from buz.event.infrastructure.models.delivery_context import DeliveryContext
4
+
5
+
6
+ @dataclass(frozen=True)
7
+ class ExecutionContext:
8
+ delivery_context: DeliveryContext
@@ -3,12 +3,19 @@ from typing import Awaitable, Callable
3
3
 
4
4
  from buz.event import Event
5
5
  from buz.event.async_subscriber import AsyncSubscriber
6
+ from buz.event.infrastructure.models.execution_context import ExecutionContext
6
7
  from buz.middleware import Middleware
7
8
 
8
- AsyncConsumeCallable = Callable[[Event, AsyncSubscriber], Awaitable[None]]
9
+ AsyncConsumeCallable = Callable[[Event, AsyncSubscriber, ExecutionContext], Awaitable[None]]
9
10
 
10
11
 
11
12
  class AsyncConsumeMiddleware(Middleware):
12
13
  @abstractmethod
13
- async def on_consume(self, event: Event, subscriber: AsyncSubscriber, consume: AsyncConsumeCallable) -> None:
14
+ async def on_consume(
15
+ self,
16
+ event: Event,
17
+ subscriber: AsyncSubscriber,
18
+ consume: AsyncConsumeCallable,
19
+ execution_context: ExecutionContext,
20
+ ) -> None:
14
21
  pass
@@ -2,6 +2,7 @@ from typing import Sequence
2
2
  from buz.event import Event
3
3
  from buz.event.async_subscriber import AsyncSubscriber
4
4
 
5
+ from buz.event.infrastructure.models.execution_context import ExecutionContext
5
6
  from buz.event.middleware.async_consume_middleware import AsyncConsumeCallable, AsyncConsumeMiddleware
6
7
  from buz.middleware import MiddlewareChainBuilder
7
8
 
@@ -14,16 +15,26 @@ class AsyncConsumeMiddlewareChainResolver:
14
15
  self.__middlewares = middlewares
15
16
  self.__middleware_chain_builder: MiddlewareChainBuilder[
16
17
  AsyncConsumeCallable, AsyncConsumeMiddleware
17
- ] = MiddlewareChainBuilder(middlewares)
18
+ ] = MiddlewareChainBuilder(self.__middlewares)
18
19
 
19
- async def resolve(self, event: Event, subscriber: AsyncSubscriber, consume: AsyncConsumeCallable) -> None:
20
+ async def resolve(
21
+ self,
22
+ event: Event,
23
+ subscriber: AsyncSubscriber,
24
+ consume: AsyncConsumeCallable,
25
+ execution_context: ExecutionContext,
26
+ ) -> None:
20
27
  chain_callable: AsyncConsumeCallable = self.__middleware_chain_builder.get_chain_callable(
21
28
  consume, self.__get_middleware_callable
22
29
  )
23
30
 
24
- await chain_callable(event, subscriber)
31
+ await chain_callable(event, subscriber, execution_context)
25
32
 
26
33
  def __get_middleware_callable(
27
- self, middleware: AsyncConsumeMiddleware, consume_callable: AsyncConsumeCallable
34
+ self,
35
+ middleware: AsyncConsumeMiddleware,
36
+ consume_callable: AsyncConsumeCallable,
28
37
  ) -> AsyncConsumeCallable:
29
- return lambda event, subscriber: middleware.on_consume(event, subscriber, consume_callable)
38
+ return lambda event, subscriber, execution_context: middleware.on_consume(
39
+ event, subscriber, consume_callable, execution_context
40
+ )
@@ -2,19 +2,36 @@ from abc import abstractmethod
2
2
 
3
3
  from buz.event import Event
4
4
  from buz.event.async_subscriber import AsyncSubscriber
5
+ from buz.event.infrastructure.models.execution_context import ExecutionContext
5
6
  from buz.event.middleware.async_consume_middleware import AsyncConsumeMiddleware, AsyncConsumeCallable
6
7
 
7
8
 
8
9
  class BaseAsyncConsumeMiddleware(AsyncConsumeMiddleware):
9
- async def on_consume(self, event: Event, subscriber: AsyncSubscriber, consume: AsyncConsumeCallable) -> None:
10
- await self._before_on_consume(event, subscriber)
11
- await consume(event, subscriber)
12
- await self._after_on_consume(event, subscriber)
10
+ async def on_consume(
11
+ self,
12
+ event: Event,
13
+ subscriber: AsyncSubscriber,
14
+ consume: AsyncConsumeCallable,
15
+ execution_context: ExecutionContext,
16
+ ) -> None:
17
+ await self._before_on_consume(event, subscriber, execution_context)
18
+ await consume(event, subscriber, execution_context)
19
+ await self._after_on_consume(event, subscriber, execution_context)
13
20
 
14
21
  @abstractmethod
15
- async def _before_on_consume(self, event: Event, subscriber: AsyncSubscriber) -> None:
22
+ async def _before_on_consume(
23
+ self,
24
+ event: Event,
25
+ subscriber: AsyncSubscriber,
26
+ execution_context: ExecutionContext,
27
+ ) -> None:
16
28
  pass
17
29
 
18
30
  @abstractmethod
19
- async def _after_on_consume(self, event: Event, subscriber: AsyncSubscriber) -> None:
31
+ async def _after_on_consume(
32
+ self,
33
+ event: Event,
34
+ subscriber: AsyncSubscriber,
35
+ execution_context: ExecutionContext,
36
+ ) -> None:
20
37
  pass
@@ -1,19 +1,22 @@
1
1
  from abc import abstractmethod
2
2
 
3
3
  from buz.event import Event, Subscriber
4
+ from buz.event.infrastructure.models.execution_context import ExecutionContext
4
5
  from buz.event.middleware import ConsumeMiddleware, ConsumeCallable
5
6
 
6
7
 
7
8
  class BaseConsumeMiddleware(ConsumeMiddleware):
8
- def on_consume(self, event: Event, subscriber: Subscriber, consume: ConsumeCallable) -> None:
9
- self._before_on_consume(event, subscriber)
10
- consume(event, subscriber)
11
- self._after_on_consume(event, subscriber)
9
+ def on_consume(
10
+ self, event: Event, subscriber: Subscriber, consume: ConsumeCallable, execution_context: ExecutionContext
11
+ ) -> None:
12
+ self._before_on_consume(event, subscriber, execution_context)
13
+ consume(event, subscriber, execution_context)
14
+ self._after_on_consume(event, subscriber, execution_context)
12
15
 
13
16
  @abstractmethod
14
- def _before_on_consume(self, event: Event, subscriber: Subscriber) -> None:
17
+ def _before_on_consume(self, event: Event, subscriber: Subscriber, execution_context: ExecutionContext) -> None:
15
18
  pass
16
19
 
17
20
  @abstractmethod
18
- def _after_on_consume(self, event: Event, subscriber: Subscriber) -> None:
21
+ def _after_on_consume(self, event: Event, subscriber: Subscriber, execution_context: ExecutionContext) -> None:
19
22
  pass
@@ -2,12 +2,15 @@ from abc import abstractmethod
2
2
  from typing import Callable
3
3
 
4
4
  from buz.event import Event, Subscriber
5
+ from buz.event.infrastructure.models.execution_context import ExecutionContext
5
6
  from buz.middleware import Middleware
6
7
 
7
- ConsumeCallable = Callable[[Event, Subscriber], None]
8
+ ConsumeCallable = Callable[[Event, Subscriber, ExecutionContext], None]
8
9
 
9
10
 
10
11
  class ConsumeMiddleware(Middleware):
11
12
  @abstractmethod
12
- def on_consume(self, event: Event, subscriber: Subscriber, consume: ConsumeCallable) -> None:
13
+ def on_consume(
14
+ self, event: Event, subscriber: Subscriber, consume: ConsumeCallable, execution_context: ExecutionContext
15
+ ) -> None:
13
16
  pass
@@ -1,5 +1,6 @@
1
1
  from typing import Sequence
2
2
  from buz.event import Event, Subscriber
3
+ from buz.event.infrastructure.models.execution_context import ExecutionContext
3
4
  from buz.event.middleware import ConsumeMiddleware, ConsumeCallable
4
5
  from buz.middleware import MiddlewareChainBuilder
5
6
 
@@ -9,15 +10,23 @@ class ConsumeMiddlewareChainResolver:
9
10
  self.__middlewares = middlewares
10
11
  self.__middleware_chain_builder: MiddlewareChainBuilder[
11
12
  ConsumeCallable, ConsumeMiddleware
12
- ] = MiddlewareChainBuilder(middlewares)
13
+ ] = MiddlewareChainBuilder(self.__middlewares)
13
14
 
14
- def resolve(self, event: Event, subscriber: Subscriber, consume: ConsumeCallable) -> None:
15
+ def resolve(
16
+ self,
17
+ event: Event,
18
+ subscriber: Subscriber,
19
+ consume: ConsumeCallable,
20
+ execution_context: ExecutionContext,
21
+ ) -> None:
15
22
  chain_callable: ConsumeCallable = self.__middleware_chain_builder.get_chain_callable(
16
23
  consume, self.__get_middleware_callable
17
24
  )
18
- chain_callable(event, subscriber)
25
+ chain_callable(event, subscriber, execution_context)
19
26
 
20
27
  def __get_middleware_callable(
21
28
  self, middleware: ConsumeMiddleware, consume_callable: ConsumeCallable
22
29
  ) -> ConsumeCallable:
23
- return lambda event, subscriber: middleware.on_consume(event, subscriber, consume_callable)
30
+ return lambda event, subscriber, execution_context: middleware.on_consume(
31
+ event, subscriber, consume_callable, execution_context
32
+ )
File without changes
@@ -0,0 +1,7 @@
1
+ from dataclasses import dataclass
2
+ from buz.event.infrastructure.models.delivery_context import DeliveryContext
3
+
4
+
5
+ @dataclass(frozen=True)
6
+ class SyncDeliveryContext(DeliveryContext):
7
+ pass
@@ -1,12 +1,14 @@
1
1
  from typing import Optional, Iterable
2
2
 
3
3
  from buz.event import Event, EventBus, Subscriber
4
+ from buz.event.infrastructure.models.execution_context import ExecutionContext
4
5
  from buz.event.middleware import (
5
6
  PublishMiddleware,
6
7
  ConsumeMiddleware,
7
8
  PublishMiddlewareChainResolver,
8
9
  ConsumeMiddlewareChainResolver,
9
10
  )
11
+ from buz.event.sync.models.sync_delivery_context import SyncDeliveryContext
10
12
  from buz.locator import Locator
11
13
 
12
14
 
@@ -26,10 +28,16 @@ class SyncEventBus(EventBus):
26
28
 
27
29
  def __perform_publish(self, event: Event) -> None:
28
30
  subscribers = self.__locator.get(event)
31
+ execution_context = ExecutionContext(delivery_context=SyncDeliveryContext())
29
32
  for subscriber in subscribers:
30
- self.__consume_middleware_chain_resolver.resolve(event, subscriber, self.__perform_consume)
33
+ self.__consume_middleware_chain_resolver.resolve(
34
+ event=event,
35
+ subscriber=subscriber,
36
+ execution_context=execution_context,
37
+ consume=self.__perform_consume,
38
+ )
31
39
 
32
- def __perform_consume(self, event: Event, subscriber: Subscriber) -> None:
40
+ def __perform_consume(self, event: Event, subscriber: Subscriber, execution_context: ExecutionContext) -> None:
33
41
  subscriber.consume(event)
34
42
 
35
43
  def bulk_publish(self, events: Iterable[Event]) -> None:
@@ -9,6 +9,7 @@ class KafkaPollRecord:
9
9
  key: Optional[Union[str, bytes]]
10
10
  headers: list[tuple[str, bytes]]
11
11
  value: Optional[bytes]
12
+ timestamp: int
12
13
  partition: int
13
14
  topic: str
14
15
  offset: int
@@ -47,4 +47,6 @@ class KafkaCallbackRebalancer(ConsumerRebalanceListener):
47
47
 
48
48
  if self.__rebalancing_start_time is not None:
49
49
  elapsed_time_ms = int((datetime.now() - self.__rebalancing_start_time).total_seconds() * 1000)
50
- self.__logger.info(f"Rebalancing process ended, elapsed time: {elapsed_time_ms} ms")
50
+ self.__logger.info(
51
+ f"Rebalancing for topic {set(v.topic for v in assigned)} ended, elapsed time: {elapsed_time_ms} ms"
52
+ )
@@ -12,18 +12,22 @@ class InMemoryMultiqueueRepository(MultiqueueRepository[K, R]):
12
12
  self.__queues = cast(dict[K, Queue[R]], {})
13
13
  self.__last_key_index = 0
14
14
 
15
- def clear(self, key: K) -> None:
16
- self.__queues.pop(key, None)
15
+ def create_key(self, key: K) -> None:
16
+ self.__queues[key] = Queue[R]()
17
+
18
+ def remove_key(self, key: K) -> None:
19
+ if key not in self.__queues:
20
+ return
21
+
22
+ self.__queues.pop(key)
17
23
 
18
24
  def push(self, key: K, record: R) -> None:
19
25
  if key not in self.__queues:
20
- self.__add_key(key)
26
+ return
27
+
21
28
  queue = self.__queues[key]
22
29
  queue.put(record)
23
30
 
24
- def __add_key(self, key: K) -> None:
25
- self.__queues[key] = Queue[R]()
26
-
27
31
  def pop(self) -> Optional[R]:
28
32
  if not self.__queues:
29
33
  return None
@@ -7,7 +7,11 @@ R = TypeVar("R")
7
7
 
8
8
  class MultiqueueRepository(ABC, Generic[K, R]):
9
9
  @abstractmethod
10
- def clear(self, key: K) -> None:
10
+ def create_key(self, key: K) -> None:
11
+ pass
12
+
13
+ @abstractmethod
14
+ def remove_key(self, key: K) -> None:
11
15
  pass
12
16
 
13
17
  @abstractmethod
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: buz
3
- Version: 2.15.10rc5
3
+ Version: 2.15.11
4
4
  Summary: Buz is a set of light, simple and extensible implementations of event, command and query buses.
5
5
  License: MIT
6
6
  Author: Luis Pintado Lozano
@@ -22,7 +22,7 @@ Classifier: Typing :: Typed
22
22
  Provides-Extra: aiokafka
23
23
  Provides-Extra: kombu
24
24
  Provides-Extra: pypendency
25
- Requires-Dist: aiohttp (>=3.11.13,<4.0.0)
25
+ Requires-Dist: aiohttp (>=3.12.15,<4.0.0)
26
26
  Requires-Dist: aiokafka[lz4] (==0.12.0) ; extra == "aiokafka"
27
27
  Requires-Dist: asgiref (>=3.8.1,<4.0.0) ; extra == "aiokafka"
28
28
  Requires-Dist: cachetools (>=5.5.0,<6.0.0)
@@ -47,7 +47,7 @@ buz/event/exceptions/worker_execution_exception.py,sha256=6mgztvXOCG_9VZ_Jptkk72
47
47
  buz/event/infrastructure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
48
  buz/event/infrastructure/buz_kafka/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
49
  buz/event/infrastructure/buz_kafka/async_buz_kafka_event_bus.py,sha256=SyLblUVlwWOaNfZzK7vL6Ee4m-85vZVCH0rjOgqVAww,4913
50
- buz/event/infrastructure/buz_kafka/base_buz_aiokafka_async_consumer.py,sha256=M5mdbht294CE6UYtH7wfV9BoZTJIMLdyO9Wvb94PG_Q,20867
50
+ buz/event/infrastructure/buz_kafka/base_buz_aiokafka_async_consumer.py,sha256=guVuZUQjxR-1ECuHjJ7Z7DTtIs2E7BSmazuP73dxgcY,21013
51
51
  buz/event/infrastructure/buz_kafka/buz_aiokafka_async_consumer.py,sha256=DRe3u69LD7Yt9WjA_hK_PRznM08_Mz4hxC_4poppjck,6446
52
52
  buz/event/infrastructure/buz_kafka/buz_aiokafka_multi_threaded_consumer.py,sha256=-pJVJq3b2SFmPT7SNmdPhqN2o64Hsjwds-shQ-Y7ytg,6389
53
53
  buz/event/infrastructure/buz_kafka/buz_kafka_event_bus.py,sha256=ymRSvcYVgbVCPgHN6rMBVBHQ5heCSwCDl6EffyqGVX8,4601
@@ -59,9 +59,10 @@ buz/event/infrastructure/buz_kafka/exceptions/__init__.py,sha256=47DEQpj8HBSa-_T
59
59
  buz/event/infrastructure/buz_kafka/exceptions/kafka_event_bus_config_not_valid_exception.py,sha256=VUKZXA2ygjg21P4DADFl_Tace6RwSXia1MRYvJypxbM,135
60
60
  buz/event/infrastructure/buz_kafka/exceptions/max_consumer_retry_exception.py,sha256=5O33uUC8FLILY1C13tQwkfsLSXrmbe0vMaUfBmOuXdU,264
61
61
  buz/event/infrastructure/buz_kafka/exceptions/retry_exception.py,sha256=Fq9kvI3DpFsGD3x2icmQ1fYIsuKZAFqI3tCibAuEtSQ,441
62
- buz/event/infrastructure/buz_kafka/kafka_event_async_subscriber_executor.py,sha256=KDJjeY1z8ZJGKGmEUB7OxknenBCI0o0WkgcNkNmQITU,6804
62
+ buz/event/infrastructure/buz_kafka/kafka_event_async_subscriber_executor.py,sha256=zQg2QJFT5-NUea5uP0RiWzmJHPqs_oJlcbDRDzstSeU,7536
63
63
  buz/event/infrastructure/buz_kafka/kafka_event_subscriber_executor.py,sha256=EyG2vsFYErWAyqxdXqSwxx5Zi_y0d6i0h05XavJMnxg,254
64
- buz/event/infrastructure/buz_kafka/kafka_event_sync_subscriber_executor.py,sha256=tuK9gHJXuGwHtfjYNEoLi-aKOGv_YjOeqPg_1zns7NM,6849
64
+ buz/event/infrastructure/buz_kafka/kafka_event_sync_subscriber_executor.py,sha256=i3Gr173p91UZ4N-giQkZHVikCntu6A2ihVlqkUsReOc,7636
65
+ buz/event/infrastructure/buz_kafka/models/kafka_delivery_context.py,sha256=Kvi1Pq9EvR_UQ6e-DbvB2l3m7rTvq2k4UmEZuHUg-qU,259
65
66
  buz/event/infrastructure/buz_kafka/publish_strategy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
66
67
  buz/event/infrastructure/buz_kafka/publish_strategy/publish_strategy.py,sha256=zIkgMnUU7ueG6QHEubMzdTHOtqdldIbS7k5FDLNmqVk,178
67
68
  buz/event/infrastructure/buz_kafka/publish_strategy/topic_per_event_kafka_publish_strategy.py,sha256=aLKj6GyLJNcMbuDA1QBa-RzWKBHEorBuPFkkqo_H60k,405
@@ -70,28 +71,32 @@ buz/event/infrastructure/kombu/allowed_kombu_serializer.py,sha256=LQ6futYsInawTC
70
71
  buz/event/infrastructure/kombu/consume_strategy/__init__.py,sha256=6dnAv-bOxoDL31gQD1dErRocdJvkLHTgdqeb4S33eWc,302
71
72
  buz/event/infrastructure/kombu/consume_strategy/consume_strategy.py,sha256=Zsv7QVpZXRLYvlV2nRbSdSwT_FgEELLyzUxdT6DyX8Q,179
72
73
  buz/event/infrastructure/kombu/consume_strategy/queue_per_subscriber_consume_strategy.py,sha256=Vsa1uC7dwS3jJ-dp_lvrE-hVWnN91-ma8oVqdLuXHMo,786
73
- buz/event/infrastructure/kombu/kombu_consumer.py,sha256=cCTlbGM3LomTsNu6YmWvXrA3Gsn8_LkM4USbmQ8uYDk,7842
74
+ buz/event/infrastructure/kombu/kombu_consumer.py,sha256=hGpPRUOVlu9zba_2XYsIhYXdXkja5j_3w-oh-cgovFM,8307
74
75
  buz/event/infrastructure/kombu/kombu_event_bus.py,sha256=VSLBtamp-YOta4KyqmfXvDurvPiHZSL9QPCozMK3Qyw,4017
76
+ buz/event/infrastructure/kombu/models/kombu_delivery_context.py,sha256=oj6IBEj19fUs0U1HwZll_uIEORABiyrr6Z_WotGJexs,191
75
77
  buz/event/infrastructure/kombu/publish_strategy/__init__.py,sha256=96ssn7ydJwLXYoVyrhfGcwCpXr4_5Sl0DbN6UCoeNc8,315
76
78
  buz/event/infrastructure/kombu/publish_strategy/fanout_exchange_per_event_publish_strategy.py,sha256=Pw85A1oI-cPtzHCQTr0XHQjb7-u9LVmKR3eBIonHsUU,397
77
79
  buz/event/infrastructure/kombu/publish_strategy/publish_strategy.py,sha256=mcpXSRPbIYedt1vsoiBBAzqzR3E6o77ZzF6IOFsVRUw,309
78
80
  buz/event/infrastructure/kombu/retry_strategy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
79
81
  buz/event/infrastructure/kombu/retry_strategy/publish_retry_policy.py,sha256=2wNMuIYRz8zECTRkcEwHX6INT1xc403MeUcZul_q0yE,562
80
82
  buz/event/infrastructure/kombu/retry_strategy/simple_publish_retry_policy.py,sha256=kuHXdMKuG87NBQlrABabF-Wl-r3QgS2f9zEUapzMnd0,1357
83
+ buz/event/infrastructure/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
81
84
  buz/event/infrastructure/models/consuming_task.py,sha256=GJvn6fGTN5ZQJaOuQCX17JP7SInIGvTLTk7DLoqnLQ4,302
85
+ buz/event/infrastructure/models/delivery_context.py,sha256=D6_wppbYEkfoBgDaPeUaQPWFUMvZiHn-4QaAxDmWUZo,92
86
+ buz/event/infrastructure/models/execution_context.py,sha256=tohrJMSHWA5U7WByGE47LSjteAN8_IMyHoXtjyrHJMM,200
82
87
  buz/event/infrastructure/queue/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
83
88
  buz/event/meta_base_subscriber.py,sha256=IP2Siol98OmoeCoOISiaCJxgxJG2SCrhmbAN4t01aWg,698
84
89
  buz/event/meta_subscriber.py,sha256=JPhhRqHkDOBWhuqtPmseUtAoYde1OmTBViqVbLBhvME,359
85
90
  buz/event/middleware/__init__.py,sha256=vbmskMeXurTSgwXqPsRQBydHhNAYnbEoqFc1pqemI7Y,897
86
- buz/event/middleware/async_consume_middleware.py,sha256=314z7ZyhvQIvi90kEO0t-FlnHSyRjArk3RqKOdDE6bM,459
87
- buz/event/middleware/async_consume_middleware_chain_resolver.py,sha256=Hw75JAs5pyZVDi7-nD4I1nbUXjwYpHQW9PctafGS4ks,1193
91
+ buz/event/middleware/async_consume_middleware.py,sha256=n_EsDMNFgOIu7UVPGRC0iaxCIfGL-p_3xo5Avq43zYA,640
92
+ buz/event/middleware/async_consume_middleware_chain_resolver.py,sha256=dIiyob5TYavjcD5QL31_Yqya9x3ujWtL7cUZK4bEVvk,1459
88
93
  buz/event/middleware/async_publish_middleware.py,sha256=JIxbRx7HVf_Q1iEziN_5RKGVJ-Oen_f1c3OL9QLmoxE,358
89
94
  buz/event/middleware/async_publish_middleware_chain_resolver.py,sha256=Hqj8CRZXJD6h9KuJaKl88iToOFN7BijoatoDo66En8w,1016
90
- buz/event/middleware/base_async_consume_middleware.py,sha256=7yncBDiAJYgAhKvXVqkY0jf-dH4Ug-qwqzd_DQESmjg,795
91
- buz/event/middleware/base_consume_middleware.py,sha256=9G1jsr_Wm-avsTfWAndi5_tf4WW6dSLwQ3rN0-jc7AE,651
95
+ buz/event/middleware/base_async_consume_middleware.py,sha256=9IAY-c57PlUq93rAUB3aVDXBVCNH_UO57xHOTiYeWvw,1167
96
+ buz/event/middleware/base_consume_middleware.py,sha256=GQxuAjHFVs_nKZXvYjBn9h4EZyUFHz1xdwl6qW5TVo8,912
92
97
  buz/event/middleware/base_publish_middleware.py,sha256=vtM8oA4LZjbZn4omPy-cIAUxQQwL-_Xb4ScU85DwjMU,531
93
- buz/event/middleware/consume_middleware.py,sha256=BCcs1LgIc5YZx5nf7nE_bMuiiXxscqBE4LqD-nd4JS0,363
94
- buz/event/middleware/consume_middleware_chain_resolver.py,sha256=_btZkLn_HIBiQls5apOZDJ6B0STeNBh_Rek4nZgZizQ,1028
98
+ buz/event/middleware/consume_middleware.py,sha256=MEzfXfV1hMI0TKHU9f4zqWZsNykgu02X2lr9ZM1WLaw,511
99
+ buz/event/middleware/consume_middleware_chain_resolver.py,sha256=--Dz--OqSJnrkkp2UGdLL4QqzGw2Sbe74i_5zSVs9HM,1277
95
100
  buz/event/middleware/exceptions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
96
101
  buz/event/middleware/exceptions/event_already_in_progress_exception.py,sha256=1Wouo05mddhdBxcWuhHr1rLassTux76AWDdyXx7YoDI,296
97
102
  buz/event/middleware/publish_middleware.py,sha256=mSuXfQSUf_miwx0QGuYmME5TOrkzX53AZ98ZwCC6zU8,315
@@ -112,7 +117,9 @@ buz/event/strategies/retry/max_retries_negative_exception.py,sha256=UdM5T4cxRv_a
112
117
  buz/event/strategies/retry/reject_callback.py,sha256=TnmUt0AkB2DEQMieec9TtB7IAkRHdFAFepAclbiCRns,316
113
118
  buz/event/subscriber.py,sha256=WxppO8PFP5zO-gwLZNg1DKSY_uFdsF8JgWIJa6nTTds,237
114
119
  buz/event/sync/__init__.py,sha256=uJmU80PGVNNL2HoRFXp4loQTn1VK8gLo-hMEvgVPpBQ,91
115
- buz/event/sync/sync_event_bus.py,sha256=nXNJqoaWQWV3asYCAIReH2nN5AOjvJH2OFODHOrWM6M,1403
120
+ buz/event/sync/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
121
+ buz/event/sync/models/sync_delivery_context.py,sha256=LHjrS6gV-19NEKwtAXVmefjPd-Dsp_Ym8RZb84T3lm8,190
122
+ buz/event/sync/sync_event_bus.py,sha256=LTJHNKy8LrbygO343AA4Zt_hmgTP9uY6TLdjKs8LuHM,1821
116
123
  buz/event/transactional_outbox/__init__.py,sha256=k8ZBWCi12pWKXchHfgW_Raw4sVR8XkBLuPNW9jB9X2k,1381
117
124
  buz/event/transactional_outbox/event_to_outbox_record_translator.py,sha256=oSn1iQuW-cZLvlXYIJPnSwm3JYUwGMm9f1pqnlF0cJI,534
118
125
  buz/event/transactional_outbox/fqn_to_event_mapper.py,sha256=ujcq6CfYqRJtM8f3SEEltbWN0Ru7NM5JfrbNdh4nvhQ,773
@@ -153,7 +160,7 @@ buz/kafka/domain/models/kafka_connection_credentials.py,sha256=-9VbkY8etqQgjZVjS
153
160
  buz/kafka/domain/models/kafka_connection_plain_text_credentials.py,sha256=DzhJClYFGhZWpO82DNemJ_y1aMLotB0fVbD6-UrI2gA,588
154
161
  buz/kafka/domain/models/kafka_connection_sasl_credentials.py,sha256=SG45bU8EFlV0cUObkW_a0wvfRuZU6HelqQVPVu-EV0o,591
155
162
  buz/kafka/domain/models/kafka_consumer_record.py,sha256=2oJvTBAr8jQq4FglsSgtkno29XLmxgC49O6uriKCdqw,230
156
- buz/kafka/domain/models/kafka_poll_record.py,sha256=Yt55L6rGM_taJ615_YyO1gBJIgpVruD0VG0rgSLXSq4,305
163
+ buz/kafka/domain/models/kafka_poll_record.py,sha256=kaKk9m02c2JDt8LOuFECUKK0HYK8Zb-hEPWEmLhm1mc,324
157
164
  buz/kafka/domain/models/kafka_supported_compression_type.py,sha256=ZEY1kPzYQlkPhEg0y2EMdZXUQ_oSHhjbGj9MIQvU09E,141
158
165
  buz/kafka/domain/models/kafka_supported_sasl_mechanisms.py,sha256=ASyDaFgseQRcUJA2kubQSdCkG6KhGmpMAzTFj5NwK5w,212
159
166
  buz/kafka/domain/models/kafka_supported_security_protocols.py,sha256=ffY2-9sOj4XIkJTSQVkqeOb4KnuqEYXISDarfDN8r9Q,161
@@ -167,7 +174,7 @@ buz/kafka/infrastructure/aiokafka/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeR
167
174
  buz/kafka/infrastructure/aiokafka/aiokafka_consumer.py,sha256=3-73e2CJhSjHONsCH_kZB1x5EwhnzLG2cCKGmkU4q0s,10008
168
175
  buz/kafka/infrastructure/aiokafka/aiokafka_producer.py,sha256=LteHKIHpT6MKplwmwsPYMsd2GWNJCzus65XDHCIdoN8,3823
169
176
  buz/kafka/infrastructure/aiokafka/rebalance/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
170
- buz/kafka/infrastructure/aiokafka/rebalance/kafka_callback_rebalancer.py,sha256=E0BB5mNU7x9LOpPF_77YuFl7sIaIwDL4bnOG6o5h8uw,2194
177
+ buz/kafka/infrastructure/aiokafka/rebalance/kafka_callback_rebalancer.py,sha256=0IMc_TH4cHjIQiBWOFei_yMx6GbhO58CS-daKzffly4,2259
171
178
  buz/kafka/infrastructure/aiokafka/translators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
172
179
  buz/kafka/infrastructure/aiokafka/translators/consumer_initial_offset_position_translator.py,sha256=WmxkQfoXeTy9mIJtGGhM0eDKeQxhcJczeVAGCbtonVI,617
173
180
  buz/kafka/infrastructure/cdc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -241,16 +248,16 @@ buz/query/synchronous/self_process/self_process_query_bus.py,sha256=pKGJxXBWtqU4
241
248
  buz/query/synchronous/synced_async/__init__.py,sha256=TdFmIBeFIpl3Tvmh_FJpJMXJdPdfRxOstVqnPUi23mo,125
242
249
  buz/query/synchronous/synced_async/synced_async_query_bus.py,sha256=WxXHeEl1Pnh5Yiui8oMJKIOdzhQBGq1yAnAEk_gniRg,470
243
250
  buz/queue/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
244
- buz/queue/in_memory/in_memory_multiqueue_repository.py,sha256=2jFSeVVbliOV-6m7AhjSkTT2stgFuHmfvNfrPTyyTzs,1523
251
+ buz/queue/in_memory/in_memory_multiqueue_repository.py,sha256=F-5Cw6Ny8OmcmYSHOBCiSdZZfcCNBK99otq0qIPQ2Wk,1568
245
252
  buz/queue/in_memory/in_memory_queue_repository.py,sha256=hUPuQRmbrzQtR5gv4XYCM9aFQHX0U3Q3lt0yi0MIPYk,505
246
- buz/queue/multiqueue_repository.py,sha256=Wc4OE_jDB4mLyyhWKnizXskvgYm2glxvGW2ez1oa9Zs,531
253
+ buz/queue/multiqueue_repository.py,sha256=Lg5QiMOsT_ZfzuOokjKlNsTJGoicqA7dt5gT4C9ppL8,612
247
254
  buz/queue/queue_repository.py,sha256=W3_lkosFu71XoiqRTT7An4kVjJQ3w0fZmFlaAfHeraM,385
248
255
  buz/serializer/message_to_bytes_serializer.py,sha256=uQ6JSTn24mLQvN48alwVXa6lfgfgCJN5vSzo829VuBQ,332
249
256
  buz/serializer/message_to_json_bytes_serializer.py,sha256=RGZJ64t4t4Pz2FCASZZCv-2LiWnertC8scE9ZzQkBsU,764
250
257
  buz/wrapper/__init__.py,sha256=GnRdJFcncn-qp0hzDG9dBHLmTJSbHFVjE_yr-MdW_n4,77
251
258
  buz/wrapper/async_to_sync.py,sha256=OfK-vrVUhuN-LLLvekLdMbQYtH0ue5lfbvuasj6ovMI,698
252
259
  buz/wrapper/event_loop.py,sha256=pfBJ1g-8A2a3YgW8Gf9Fg0kkewoh3-wgTy2KIFDyfHk,266
253
- buz-2.15.10rc5.dist-info/LICENSE,sha256=Jytu2S-2SPEgsB0y6BF-_LUxIWY7402fl0JSh36TLZE,1062
254
- buz-2.15.10rc5.dist-info/METADATA,sha256=_A4RF9Cj31ACjYG6USaqvQun5VK74cl1scb9wQkc7S8,1601
255
- buz-2.15.10rc5.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
256
- buz-2.15.10rc5.dist-info/RECORD,,
260
+ buz-2.15.11.dist-info/LICENSE,sha256=Jytu2S-2SPEgsB0y6BF-_LUxIWY7402fl0JSh36TLZE,1062
261
+ buz-2.15.11.dist-info/METADATA,sha256=BuIeKxWGRrmcHeBDjBgw9ZW9Et1fisfy0hbqnGjKqHU,1598
262
+ buz-2.15.11.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
263
+ buz-2.15.11.dist-info/RECORD,,