buz 2.23.0__py3-none-any.whl → 2.25.0__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.
@@ -3,18 +3,11 @@ from typing import Generic, Type, TypeVar
3
3
 
4
4
  from buz import Handler
5
5
  from buz.command import Command
6
- from buz.wrapper.async_unsafe import async_unsafe
7
6
 
8
7
  TCommand = TypeVar("TCommand", bound=Command)
9
8
 
10
9
 
11
10
  class CommandHandler(Generic[TCommand], Handler[TCommand], ABC):
12
- def __new__(cls, *args, **kwargs):
13
- instance = super().__new__(cls)
14
- original_handle = instance.handle
15
- instance.handle = async_unsafe()(original_handle)
16
- return instance
17
-
18
11
  @classmethod
19
12
  @abstractmethod
20
13
  def handles(cls) -> Type[TCommand]:
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from abc import abstractmethod, ABC
4
4
  from datetime import datetime
5
- from typing import Sequence, Any
5
+ from typing import Sequence, Any, Optional
6
6
 
7
7
  from buz.kafka.domain.models.create_kafka_topic import CreateKafkaTopic
8
8
  from buz.kafka.infrastructure.interfaces.connection_manager import ConnectionManager
@@ -63,6 +63,7 @@ class KafkaAdminClient(ConnectionManager, ABC):
63
63
  *,
64
64
  topic: str,
65
65
  new_number_of_partitions: int,
66
+ consumer_groups_to_ignore: Optional[set[str]] = None,
66
67
  ) -> None:
67
68
  pass
68
69
 
@@ -271,6 +271,7 @@ class KafkaPythonAdminClient(KafkaAdminClient):
271
271
  *,
272
272
  topic: str,
273
273
  new_number_of_partitions: int,
274
+ consumer_groups_to_ignore: Optional[set[str]] = None,
274
275
  ) -> None:
275
276
  self._logger.info(
276
277
  f'Increasing topic "{topic}" partitions: Verifying the new number of partitions "{new_number_of_partitions}"'
@@ -290,6 +291,10 @@ class KafkaPythonAdminClient(KafkaAdminClient):
290
291
  self._logger.info(f'Increasing topic "{topic}" partitions: Extracting related consumer groups')
291
292
  related_consumer_groups = self.__get_consumer_groups_related_to_a_topic(topic_partitions)
292
293
 
294
+ if consumer_groups_to_ignore:
295
+ consumer_groups_to_ignore_set = set[str](consumer_groups_to_ignore)
296
+ related_consumer_groups = related_consumer_groups - consumer_groups_to_ignore_set
297
+
293
298
  self._logger.info(
294
299
  f'Increasing topic "{topic}" partitions: The following consumer groups will be updated:"{related_consumer_groups}"'
295
300
  )
@@ -3,19 +3,12 @@ from typing import Generic, Type, TypeVar
3
3
 
4
4
  from buz import Handler
5
5
  from buz.query import Query, QueryResponse
6
- from buz.wrapper.async_unsafe import async_unsafe
7
6
 
8
7
  TQuery = TypeVar("TQuery", bound=Query)
9
8
  TQueryResponse = TypeVar("TQueryResponse", bound=QueryResponse)
10
9
 
11
10
 
12
11
  class QueryHandler(Generic[TQuery, TQueryResponse], Handler[TQuery], ABC):
13
- def __new__(cls, *args, **kwargs):
14
- instance = super().__new__(cls)
15
- original_handle = instance.handle
16
- instance.handle = async_unsafe()(original_handle)
17
- return instance
18
-
19
12
  @classmethod
20
13
  @abstractmethod
21
14
  def handles(cls) -> Type[TQuery]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: buz
3
- Version: 2.23.0
3
+ Version: 2.25.0
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
@@ -15,7 +15,7 @@ buz/command/more_than_one_command_handler_related_exception.py,sha256=dNCMXCAKVc
15
15
  buz/command/synchronous/__init__.py,sha256=ZAH35jpte6zpxb70iQfZfGSg_OsXqVNYwNkCJy7Qnzk,268
16
16
  buz/command/synchronous/base_command_handler.py,sha256=GkmxttA1_Wu2X5O7iR-tLRdnmT-JDgeyURPwkjLPGhg,1393
17
17
  buz/command/synchronous/command_bus.py,sha256=FHJH4lerThu5fWRISM0VIK8ebyfqgDGqNNCqItbmGPI,175
18
- buz/command/synchronous/command_handler.py,sha256=M9nQhW9Ilkix09U6Pv6ZpoqA-gezrm7H_gqjoLDc_A4,676
18
+ buz/command/synchronous/command_handler.py,sha256=pP11Njbth89NQiVPqlALtKmabVtOX4sucdbiCp-sceI,422
19
19
  buz/command/synchronous/middleware/__init__.py,sha256=wE97veOW2cCGpTZ-3bvc3aU6NdQmSOYfdX9kAUETJ0w,406
20
20
  buz/command/synchronous/middleware/base_handle_middleware.py,sha256=qHnbucL7j6Dnw7E8ACBf32pzDD9squYPp6UiK2heb5A,774
21
21
  buz/command/synchronous/middleware/handle_middleware.py,sha256=oIsmB30mu-Cd9IQc1qMKbUIaIMHipSEXOw2swVrtbkk,420
@@ -169,7 +169,7 @@ buz/kafka/domain/models/kafka_supported_sasl_mechanisms.py,sha256=ASyDaFgseQRcUJ
169
169
  buz/kafka/domain/models/kafka_supported_security_protocols.py,sha256=ffY2-9sOj4XIkJTSQVkqeOb4KnuqEYXISDarfDN8r9Q,161
170
170
  buz/kafka/domain/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
171
171
  buz/kafka/domain/services/async_kafka_producer.py,sha256=gSq3WwEVux_gp3EKDAMN1WsM027uklB58E-WnKpyhPs,533
172
- buz/kafka/domain/services/kafka_admin_client.py,sha256=6WJzMPTYSKTUq0Dtxj1rzGAWK-GAYGolW_LFDB_faVU,2042
172
+ buz/kafka/domain/services/kafka_admin_client.py,sha256=Q89JY0Yjp2KqhXmP7IFZkoDXT8A9CsNqPxTy0oywsdI,2114
173
173
  buz/kafka/domain/services/kafka_admin_test_client.py,sha256=91l_vFIo1yhJLQQCC_OmeXZ5F429zP7Hx5g4FNllpfE,1625
174
174
  buz/kafka/domain/services/kafka_producer.py,sha256=8bLTV328orrPHcARzkc6no4vyJzrArVtCsjmSRXDjos,506
175
175
  buz/kafka/infrastructure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -199,7 +199,7 @@ buz/kafka/infrastructure/interfaces/async_connection_manager.py,sha256=JbaLu5UVV
199
199
  buz/kafka/infrastructure/interfaces/connection_manager.py,sha256=EWnvShJHOg8QYe6a3ma0urjKjmVMDBi7q8T2cv_i_MQ,200
200
200
  buz/kafka/infrastructure/kafka_python/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
201
201
  buz/kafka/infrastructure/kafka_python/exception/consumer_interrupted_exception.py,sha256=fqhgV7HILdVdv-p1CsOIaaESKY2ZXBtRGYbrVSdPLg0,164
202
- buz/kafka/infrastructure/kafka_python/kafka_python_admin_client.py,sha256=ikNTLUp3CrLgctvQDEcYTCjz8eRBTffg6cQFP8n0MNY,17571
202
+ buz/kafka/infrastructure/kafka_python/kafka_python_admin_client.py,sha256=rvyjRmafKJZL68TxRpT0lENNU1dpQXU0Rv8E8M2rEzc,17846
203
203
  buz/kafka/infrastructure/kafka_python/kafka_python_admin_test_client.py,sha256=5xP23dQ7FDuy7dIWNw39C3bMVmaUj9ZQhEEJISRv9ec,2986
204
204
  buz/kafka/infrastructure/kafka_python/kafka_python_producer.py,sha256=McH_YNQcte7HzNRvS_4bgaz1ng7v4ESoi4mUkrQFLYw,3627
205
205
  buz/kafka/infrastructure/kafka_python/translators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -250,7 +250,7 @@ buz/query/synchronous/middleware/base_handle_middleware.py,sha256=4lqJB2C-GHl3T5
250
250
  buz/query/synchronous/middleware/handle_middleware.py,sha256=Xr2HSlRrW3slluyUiJ6zH0Rw0oeWD3uMN-1hjuFbC_k,433
251
251
  buz/query/synchronous/middleware/handle_middleware_chain_resolver.py,sha256=OIpGLJ_2a8cGsp-LmA3Q1Lvb1pB65MIuA-geiPrQKHM,1070
252
252
  buz/query/synchronous/query_bus.py,sha256=eYl_sGH5TcELkOXc4RnV4Tkmcs-VLc1vzd-YMduQ1YI,189
253
- buz/query/synchronous/query_handler.py,sha256=NuolVPZelmjOe6-q_hFC3Y0gm7ih2A6aanKufo6wHR0,759
253
+ buz/query/synchronous/query_handler.py,sha256=q8zqXjU9btid_q4wbL73QgaiWjMzGDFvwZ5AQN4q0CA,505
254
254
  buz/query/synchronous/self_process/__init__.py,sha256=fU1OoXXXH5dMGKz8y7mwTVvyhNj6BCKDTxuxH_q-leM,125
255
255
  buz/query/synchronous/self_process/self_process_query_bus.py,sha256=pKGJxXBWtqU4i0fzb30OCNhAVPCkUh7IlfNzgAhCUC8,1157
256
256
  buz/query/synchronous/synced_async/__init__.py,sha256=TdFmIBeFIpl3Tvmh_FJpJMXJdPdfRxOstVqnPUi23mo,125
@@ -264,10 +264,8 @@ buz/serializer/message_to_bytes_serializer.py,sha256=uQ6JSTn24mLQvN48alwVXa6lfgf
264
264
  buz/serializer/message_to_json_bytes_serializer.py,sha256=RGZJ64t4t4Pz2FCASZZCv-2LiWnertC8scE9ZzQkBsU,764
265
265
  buz/wrapper/__init__.py,sha256=GnRdJFcncn-qp0hzDG9dBHLmTJSbHFVjE_yr-MdW_n4,77
266
266
  buz/wrapper/async_to_sync.py,sha256=OfK-vrVUhuN-LLLvekLdMbQYtH0ue5lfbvuasj6ovMI,698
267
- buz/wrapper/async_unsafe.py,sha256=vg-BM8Dh7MqKiMAc8qsMPexLUuHI1bn4APzMXeSrBgk,2026
268
267
  buz/wrapper/event_loop.py,sha256=pfBJ1g-8A2a3YgW8Gf9Fg0kkewoh3-wgTy2KIFDyfHk,266
269
- buz/wrapper/synchronous_only_operation_exception.py,sha256=qCTaNSuIY7_HXTOmzlNGhks1nRApeW5K8W5aHC-dL-4,180
270
- buz-2.23.0.dist-info/LICENSE,sha256=jcLgcIIVaBqaZNwe0kzGWSU99YgwMcI0IGv142wkYSM,1062
271
- buz-2.23.0.dist-info/METADATA,sha256=YxHyoXLE0SlA_UxWPBACGbNIeXkeOnEW9_gfe6yDOo8,12580
272
- buz-2.23.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
273
- buz-2.23.0.dist-info/RECORD,,
268
+ buz-2.25.0.dist-info/LICENSE,sha256=jcLgcIIVaBqaZNwe0kzGWSU99YgwMcI0IGv142wkYSM,1062
269
+ buz-2.25.0.dist-info/METADATA,sha256=WUora6YRaCePV9E4JVNYsWwp_UrOY38AowoV3y2AhW4,12580
270
+ buz-2.25.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
271
+ buz-2.25.0.dist-info/RECORD,,
@@ -1,67 +0,0 @@
1
- import logging
2
- import os
3
- from asyncio import get_running_loop
4
- from functools import wraps
5
- from typing import Callable, Any
6
-
7
- from buz.wrapper.synchronous_only_operation_exception import SynchronousOnlyOperationException
8
-
9
- logger = logging.getLogger(__name__)
10
-
11
-
12
- def async_unsafe() -> Callable[[Callable], Callable]:
13
- """
14
- Copy-paste from Django source code. If BUZ_SYNC_HANDLERS_FAIL_ON_ASYNC env var is True then an exception is raised to
15
- prevent event loop from being blocked. If the env var is False, a warning is logged.
16
- """
17
-
18
- def decorator(func: Callable) -> Callable:
19
- @wraps(func)
20
- def inner(*args: Any, **kwargs: Any) -> Any:
21
- try:
22
- get_running_loop()
23
- except RuntimeError:
24
- pass
25
- else:
26
- if __get_bool_env("BUZ_SYNC_HANDLERS_FAIL_ON_ASYNC") is True:
27
- raise SynchronousOnlyOperationException()
28
-
29
- logger.warning(
30
- f"You should not call this from an async context - use a thread or sync_to_async. Class {__get_class_name(func, args)}"
31
- )
32
-
33
- return func(*args, **kwargs)
34
-
35
- return inner
36
-
37
- return decorator
38
-
39
-
40
- def __get_bool_env(var_name: str) -> bool:
41
- """
42
- >>> get_bool_env("MY_BOOL_VAR")
43
- False
44
- >>> os.environ["MY_BOOL_VAR"] = "1"
45
- >>> get_bool_env("MY_BOOL_VAR")
46
- True
47
- >>> os.environ["MY_BOOL_VAR"] = "true"
48
- >>> get_bool_env("MY_BOOL_VAR")
49
- True
50
- >>> os.environ["MY_BOOL_VAR"] = "True"
51
- >>> get_bool_env("MY_BOOL_VAR")
52
- True
53
- >>> os.environ["MY_BOOL_VAR"] = "0"
54
- >>> get_bool_env("MY_BOOL_VAR")
55
- False
56
- >>> os.environ["MY_BOOL_VAR"] = "false"
57
- >>> get_bool_env("MY_BOOL_VAR")
58
- False
59
- """
60
- return os.environ.get(var_name, "0").lower() in ("true", "1")
61
-
62
-
63
- def __get_class_name(func: Callable, args: tuple) -> str:
64
- if hasattr(func, "__self__"):
65
- return func.__self__.__class__.__name__
66
-
67
- return args[0].__class__.__name__ if len(args) > 0 else "Unknown"
@@ -1,3 +0,0 @@
1
- class SynchronousOnlyOperationException(Exception):
2
- def __init__(self):
3
- super().__init__("You cannot call this from an async context - use a thread or sync_to_async.")
File without changes
File without changes