python-cqrs 2.6.1__tar.gz → 3.0.1__tar.gz

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 (58) hide show
  1. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/PKG-INFO +24 -10
  2. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/README.md +21 -9
  3. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/pyproject.toml +3 -1
  4. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/events/event.py +1 -10
  5. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/producer.py +5 -22
  6. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/python_cqrs.egg-info/PKG-INFO +24 -10
  7. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/python_cqrs.egg-info/requires.txt +1 -0
  8. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/LICENSE +0 -0
  9. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/setup.cfg +0 -0
  10. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/__init__.py +0 -0
  11. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/adapters/__init__.py +0 -0
  12. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/adapters/amqp.py +0 -0
  13. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/adapters/kafka.py +0 -0
  14. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/compressors/__init__.py +0 -0
  15. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/compressors/protocol.py +0 -0
  16. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/compressors/zlib.py +0 -0
  17. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/container/__init__.py +0 -0
  18. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/container/di.py +0 -0
  19. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/container/protocol.py +0 -0
  20. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/decoders/__init__.py +0 -0
  21. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/decoders/kafka/__init__.py +0 -0
  22. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/decoders/kafka/empty_message.py +0 -0
  23. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/deserializers/__init__.py +0 -0
  24. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/deserializers/json.py +0 -0
  25. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/deserializers/protobuf.py +0 -0
  26. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/dispatcher/__init__.py +0 -0
  27. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/dispatcher/dispatcher.py +0 -0
  28. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/events/__init__.py +0 -0
  29. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/events/bootstrap.py +0 -0
  30. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/events/event_emitter.py +0 -0
  31. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/events/event_handler.py +0 -0
  32. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/events/map.py +0 -0
  33. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/mediator.py +0 -0
  34. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/message_brokers/__init__.py +0 -0
  35. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/message_brokers/amqp.py +0 -0
  36. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/message_brokers/devnull.py +0 -0
  37. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/message_brokers/kafka.py +0 -0
  38. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/message_brokers/protocol.py +0 -0
  39. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/middlewares/__init__.py +0 -0
  40. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/middlewares/base.py +0 -0
  41. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/middlewares/logging.py +0 -0
  42. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/outbox/__init__.py +0 -0
  43. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/outbox/map.py +0 -0
  44. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/outbox/mock.py +0 -0
  45. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/outbox/repository.py +0 -0
  46. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/outbox/sqlalchemy.py +0 -0
  47. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/requests/__init__.py +0 -0
  48. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/requests/bootstrap.py +0 -0
  49. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/requests/map.py +0 -0
  50. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/requests/request.py +0 -0
  51. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/requests/request_handler.py +0 -0
  52. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/response.py +0 -0
  53. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/serializers/__init__.py +0 -0
  54. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/serializers/default.py +0 -0
  55. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/cqrs/serializers/protobuf.py +0 -0
  56. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/python_cqrs.egg-info/SOURCES.txt +0 -0
  57. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/python_cqrs.egg-info/dependency_links.txt +0 -0
  58. {python_cqrs-2.6.1 → python_cqrs-3.0.1}/src/python_cqrs.egg-info/top_level.txt +0 -0
@@ -1,9 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-cqrs
3
- Version: 2.6.1
3
+ Version: 3.0.1
4
4
  Summary: Python CQRS pattern implementation
5
5
  Author-email: Vadim Kozyrevskiy <vadikko2@mail.ru>, Dmitry Kutlubaev <kutlubaev00@mail.ru>
6
6
  Maintainer-email: Vadim Kozyrevskiy <vadikko2@mail.ru>
7
+ Project-URL: Documentation, https://vadikko2.github.io/python-cqrs-mkdocs/
7
8
  Project-URL: Issues, https://github.com/vadikko2/python-cqrs/issues
8
9
  Project-URL: Repository, https://github.com/vadikko2/python-cqrs
9
10
  Classifier: Development Status :: 4 - Beta
@@ -23,6 +24,7 @@ Requires-Dist: sqlalchemy[asyncio]==2.0.*
23
24
  Requires-Dist: retry-async==0.1.4
24
25
  Requires-Dist: python-dotenv==1.0.1
25
26
  Provides-Extra: dev
27
+ Requires-Dist: pycln==2.5.0; extra == "dev"
26
28
  Requires-Dist: pre-commit==3.8.0; extra == "dev"
27
29
  Requires-Dist: pyright==1.1.377; extra == "dev"
28
30
  Requires-Dist: ruff==0.6.2; extra == "dev"
@@ -234,7 +236,7 @@ from cqrs.message_brokers import kafka as kafka_broker
234
236
 
235
237
 
236
238
  producer = kafka_adapter.kafka_producer_factory(
237
- dsn="localhost:9094",
239
+ dsn="localhost:9092",
238
240
  topics=["test.topic1", "test.topic2"],
239
241
  )
240
242
  broker = kafka_broker.KafkaMessageBroker(producer)
@@ -312,22 +314,34 @@ It can be utilized in conjunction with the KafkaMessageBroker.
312
314
  ```python
313
315
  import asyncio
314
316
  import cqrs
315
- from cqrs.message_brokers import kafka as kafka_broker
317
+ from cqrs.message_brokers import kafka
318
+ from cqrs.adapters import kafka as kafka_adapters
319
+ from cqrs.compressors import zlib
316
320
 
317
321
  session_factory = async_sessionmaker(
318
- create_async_engine(
319
- f"mysql+asyncmy://{USER}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}",
320
- isolation_level="REPEATABLE READ",
321
- )
322
+ create_async_engine(
323
+ f"mysql+asyncmy://{USER}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}",
324
+ isolation_level="REPEATABLE READ",
325
+ )
322
326
  )
323
327
 
324
328
  broker = kafka.KafkaMessageBroker(
325
- producer=kafka_adapters.kafka_producer_factory(dsn="localhost:9092"),
329
+ producer=kafka_adapters.kafka_producer_factory(dsn="localhost:9092"),
326
330
  )
327
331
 
328
- producer = cqrs.EventProducer(cqrs.SqlAlchemyOutboxedEventRepository(session_factory, zlib.ZlibCompressor()), broker)
332
+ producer = cqrs.EventProducer(broker, cqrs.SqlAlchemyOutboxedEventRepository(session_factory, zlib.ZlibCompressor()))
333
+
334
+
335
+ async def periodically_task():
336
+ async for messages in producer.event_batch_generator():
337
+ for message in messages:
338
+ await producer.send_message(message)
339
+ await producer.repository.commit()
340
+ await asyncio.sleep(10)
341
+
342
+
329
343
  loop = asyncio.get_event_loop()
330
- loop.run_until_complete(app.periodically_task())
344
+ loop.run_until_complete(periodically_task())
331
345
  ```
332
346
 
333
347
  A complete example can be found in
@@ -189,7 +189,7 @@ from cqrs.message_brokers import kafka as kafka_broker
189
189
 
190
190
 
191
191
  producer = kafka_adapter.kafka_producer_factory(
192
- dsn="localhost:9094",
192
+ dsn="localhost:9092",
193
193
  topics=["test.topic1", "test.topic2"],
194
194
  )
195
195
  broker = kafka_broker.KafkaMessageBroker(producer)
@@ -267,22 +267,34 @@ It can be utilized in conjunction with the KafkaMessageBroker.
267
267
  ```python
268
268
  import asyncio
269
269
  import cqrs
270
- from cqrs.message_brokers import kafka as kafka_broker
270
+ from cqrs.message_brokers import kafka
271
+ from cqrs.adapters import kafka as kafka_adapters
272
+ from cqrs.compressors import zlib
271
273
 
272
274
  session_factory = async_sessionmaker(
273
- create_async_engine(
274
- f"mysql+asyncmy://{USER}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}",
275
- isolation_level="REPEATABLE READ",
276
- )
275
+ create_async_engine(
276
+ f"mysql+asyncmy://{USER}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}",
277
+ isolation_level="REPEATABLE READ",
278
+ )
277
279
  )
278
280
 
279
281
  broker = kafka.KafkaMessageBroker(
280
- producer=kafka_adapters.kafka_producer_factory(dsn="localhost:9092"),
282
+ producer=kafka_adapters.kafka_producer_factory(dsn="localhost:9092"),
281
283
  )
282
284
 
283
- producer = cqrs.EventProducer(cqrs.SqlAlchemyOutboxedEventRepository(session_factory, zlib.ZlibCompressor()), broker)
285
+ producer = cqrs.EventProducer(broker, cqrs.SqlAlchemyOutboxedEventRepository(session_factory, zlib.ZlibCompressor()))
286
+
287
+
288
+ async def periodically_task():
289
+ async for messages in producer.event_batch_generator():
290
+ for message in messages:
291
+ await producer.send_message(message)
292
+ await producer.repository.commit()
293
+ await asyncio.sleep(10)
294
+
295
+
284
296
  loop = asyncio.get_event_loop()
285
- loop.run_until_complete(app.periodically_task())
297
+ loop.run_until_complete(periodically_task())
286
298
  ```
287
299
 
288
300
  A complete example can be found in
@@ -29,11 +29,12 @@ maintainers = [{name = "Vadim Kozyrevskiy", email = "vadikko2@mail.ru"}]
29
29
  name = "python-cqrs"
30
30
  readme = "README.md"
31
31
  requires-python = ">=3.10"
32
- version = "2.6.1"
32
+ version = "3.0.1"
33
33
 
34
34
  [project.optional-dependencies]
35
35
  dev = [
36
36
  # Develope tools
37
+ "pycln==2.5.0",
37
38
  "pre-commit==3.8.0",
38
39
  "pyright==1.1.377",
39
40
  "ruff==0.6.2",
@@ -60,6 +61,7 @@ protobuf = [
60
61
  ]
61
62
 
62
63
  [project.urls]
64
+ Documentation = "https://vadikko2.github.io/python-cqrs-mkdocs/"
63
65
  Issues = "https://github.com/vadikko2/python-cqrs/issues"
64
66
  Repository = "https://github.com/vadikko2/python-cqrs"
65
67
 
@@ -8,16 +8,7 @@ import dotenv
8
8
  import pydantic
9
9
 
10
10
  logger = logging.getLogger("cqrs")
11
-
12
- try:
13
- from google.protobuf.message import Message # noqa
14
- except ImportError:
15
- logger.warning(
16
- "Please install protobuf dependencies with: `pip install python-cqrs[protobuf]`",
17
- )
18
-
19
11
  dotenv.load_dotenv()
20
-
21
12
  DEFAULT_OUTPUT_TOPIC = os.getenv("DEFAULT_OUTPUT_TOPIC", "output_topic")
22
13
 
23
14
 
@@ -52,7 +43,7 @@ class NotificationEvent(Event, typing.Generic[_P], frozen=True):
52
43
 
53
44
  model_config = pydantic.ConfigDict(from_attributes=True)
54
45
 
55
- def proto(self) -> "Message":
46
+ def proto(self):
56
47
  raise NotImplementedError("Method not implemented")
57
48
 
58
49
  def __hash__(self):
@@ -1,4 +1,3 @@
1
- import asyncio
2
1
  import logging
3
2
  import typing
4
3
 
@@ -17,20 +16,18 @@ class EventProducer:
17
16
  def __init__(
18
17
  self,
19
18
  message_broker: broker_protocol.MessageBroker,
20
- repository: repository_protocol.OutboxedEventRepository | None = None,
19
+ repository: repository_protocol.OutboxedEventRepository,
21
20
  ):
22
21
  self.message_broker = message_broker
23
22
  self.repository = repository
24
23
 
25
- async def periodically_task(
24
+ async def event_batch_generator(
26
25
  self,
27
26
  batch_size: int = 100,
28
- wait_ms: int = 500,
29
- ) -> None:
30
- """Calls produce periodically with specified delay"""
27
+ ) -> typing.AsyncIterator[typing.List[repository_protocol.OutboxedEvent]]:
28
+ """Return messages for produce"""
31
29
  while True:
32
- await asyncio.sleep(float(wait_ms) / 1000.0)
33
- await self.produce_batch(batch_size)
30
+ yield await self.repository.get_many(batch_size)
34
31
 
35
32
  async def send_message(self, event: repository_protocol.OutboxedEvent):
36
33
  try:
@@ -60,17 +57,3 @@ class EventProducer:
60
57
  event.id,
61
58
  repository_protocol.EventStatus.PRODUCED,
62
59
  )
63
-
64
- async def produce_batch(self, batch_size: int = 100) -> None:
65
- if not self.repository:
66
- logger.debug("Repository not found")
67
- return
68
- outboxed_events: typing.List[
69
- repository_protocol.OutboxedEvent
70
- ] = await self.repository.get_many(
71
- batch_size,
72
- )
73
- logger.debug(f"Got {len(outboxed_events)} new events")
74
- for event in outboxed_events:
75
- await self.send_message(event)
76
- await self.repository.commit()
@@ -1,9 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-cqrs
3
- Version: 2.6.1
3
+ Version: 3.0.1
4
4
  Summary: Python CQRS pattern implementation
5
5
  Author-email: Vadim Kozyrevskiy <vadikko2@mail.ru>, Dmitry Kutlubaev <kutlubaev00@mail.ru>
6
6
  Maintainer-email: Vadim Kozyrevskiy <vadikko2@mail.ru>
7
+ Project-URL: Documentation, https://vadikko2.github.io/python-cqrs-mkdocs/
7
8
  Project-URL: Issues, https://github.com/vadikko2/python-cqrs/issues
8
9
  Project-URL: Repository, https://github.com/vadikko2/python-cqrs
9
10
  Classifier: Development Status :: 4 - Beta
@@ -23,6 +24,7 @@ Requires-Dist: sqlalchemy[asyncio]==2.0.*
23
24
  Requires-Dist: retry-async==0.1.4
24
25
  Requires-Dist: python-dotenv==1.0.1
25
26
  Provides-Extra: dev
27
+ Requires-Dist: pycln==2.5.0; extra == "dev"
26
28
  Requires-Dist: pre-commit==3.8.0; extra == "dev"
27
29
  Requires-Dist: pyright==1.1.377; extra == "dev"
28
30
  Requires-Dist: ruff==0.6.2; extra == "dev"
@@ -234,7 +236,7 @@ from cqrs.message_brokers import kafka as kafka_broker
234
236
 
235
237
 
236
238
  producer = kafka_adapter.kafka_producer_factory(
237
- dsn="localhost:9094",
239
+ dsn="localhost:9092",
238
240
  topics=["test.topic1", "test.topic2"],
239
241
  )
240
242
  broker = kafka_broker.KafkaMessageBroker(producer)
@@ -312,22 +314,34 @@ It can be utilized in conjunction with the KafkaMessageBroker.
312
314
  ```python
313
315
  import asyncio
314
316
  import cqrs
315
- from cqrs.message_brokers import kafka as kafka_broker
317
+ from cqrs.message_brokers import kafka
318
+ from cqrs.adapters import kafka as kafka_adapters
319
+ from cqrs.compressors import zlib
316
320
 
317
321
  session_factory = async_sessionmaker(
318
- create_async_engine(
319
- f"mysql+asyncmy://{USER}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}",
320
- isolation_level="REPEATABLE READ",
321
- )
322
+ create_async_engine(
323
+ f"mysql+asyncmy://{USER}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}",
324
+ isolation_level="REPEATABLE READ",
325
+ )
322
326
  )
323
327
 
324
328
  broker = kafka.KafkaMessageBroker(
325
- producer=kafka_adapters.kafka_producer_factory(dsn="localhost:9092"),
329
+ producer=kafka_adapters.kafka_producer_factory(dsn="localhost:9092"),
326
330
  )
327
331
 
328
- producer = cqrs.EventProducer(cqrs.SqlAlchemyOutboxedEventRepository(session_factory, zlib.ZlibCompressor()), broker)
332
+ producer = cqrs.EventProducer(broker, cqrs.SqlAlchemyOutboxedEventRepository(session_factory, zlib.ZlibCompressor()))
333
+
334
+
335
+ async def periodically_task():
336
+ async for messages in producer.event_batch_generator():
337
+ for message in messages:
338
+ await producer.send_message(message)
339
+ await producer.repository.commit()
340
+ await asyncio.sleep(10)
341
+
342
+
329
343
  loop = asyncio.get_event_loop()
330
- loop.run_until_complete(app.periodically_task())
344
+ loop.run_until_complete(periodically_task())
331
345
  ```
332
346
 
333
347
  A complete example can be found in
@@ -7,6 +7,7 @@ retry-async==0.1.4
7
7
  python-dotenv==1.0.1
8
8
 
9
9
  [dev]
10
+ pycln==2.5.0
10
11
  pre-commit==3.8.0
11
12
  pyright==1.1.377
12
13
  ruff==0.6.2
File without changes
File without changes