python-cqrs 0.0.17__tar.gz → 0.0.18__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 (48) hide show
  1. {python_cqrs-0.0.17/src/python_cqrs.egg-info → python_cqrs-0.0.18}/PKG-INFO +1 -1
  2. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/pyproject.toml +1 -1
  3. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/dispatcher/dispatcher.py +4 -2
  4. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/events/event.py +2 -2
  5. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/events/map.py +4 -2
  6. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/mediator.py +3 -1
  7. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/middlewares/base.py +1 -1
  8. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/outbox/repository.py +17 -4
  9. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/outbox/sqlalchemy.py +12 -8
  10. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/requests/map.py +1 -7
  11. {python_cqrs-0.0.17 → python_cqrs-0.0.18/src/python_cqrs.egg-info}/PKG-INFO +1 -1
  12. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/LICENSE +0 -0
  13. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/README.md +0 -0
  14. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/setup.cfg +0 -0
  15. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/__init__.py +0 -0
  16. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/adapters/__init__.py +0 -0
  17. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/adapters/amqp.py +0 -0
  18. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/adapters/kafka.py +0 -0
  19. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/compressors/__init__.py +0 -0
  20. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/compressors/protocol.py +0 -0
  21. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/compressors/zlib.py +0 -0
  22. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/container/__init__.py +0 -0
  23. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/container/di.py +0 -0
  24. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/container/protocol.py +0 -0
  25. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/dispatcher/__init__.py +0 -0
  26. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/events/__init__.py +0 -0
  27. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/events/bootstrap.py +0 -0
  28. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/events/event_emitter.py +0 -0
  29. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/events/event_handler.py +0 -0
  30. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/message_brokers/__init__.py +0 -0
  31. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/message_brokers/amqp.py +0 -0
  32. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/message_brokers/devnull.py +0 -0
  33. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/message_brokers/kafka.py +0 -0
  34. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/message_brokers/protocol.py +0 -0
  35. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/middlewares/__init__.py +0 -0
  36. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/middlewares/logging.py +0 -0
  37. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/outbox/__init__.py +0 -0
  38. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/outbox/producer.py +0 -0
  39. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/outbox/protocol.py +0 -0
  40. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/requests/__init__.py +0 -0
  41. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/requests/bootstrap.py +0 -0
  42. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/requests/request.py +0 -0
  43. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/requests/request_handler.py +0 -0
  44. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/cqrs/response.py +0 -0
  45. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/python_cqrs.egg-info/SOURCES.txt +0 -0
  46. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/python_cqrs.egg-info/dependency_links.txt +0 -0
  47. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/python_cqrs.egg-info/requires.txt +0 -0
  48. {python_cqrs-0.0.17 → python_cqrs-0.0.18}/src/python_cqrs.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-cqrs
3
- Version: 0.0.17
3
+ Version: 0.0.18
4
4
  Summary: Python CQRS pattern implementation
5
5
  Author: Nikita Kunov
6
6
  Author-email: Dmitriy Kutlubaev <kutlubaev00@mail.ru>, Vadim Kozyrevskiy <vadikko2@mail.ru>
@@ -29,7 +29,7 @@ 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 = "0.0.17"
32
+ version = "0.0.18"
33
33
 
34
34
  [project.optional-dependencies]
35
35
  dev = [
@@ -13,12 +13,14 @@ from cqrs import (
13
13
 
14
14
  logger = logging.getLogger("cqrs")
15
15
 
16
+ Resp = typing.TypeVar("Resp", res.Response, None, contravariant=True)
17
+
16
18
 
17
19
  class RequestHandlerDoesNotExist(Exception): ...
18
20
 
19
21
 
20
- class RequestDispatchResult(pydantic.BaseModel):
21
- response: res.Response | None = pydantic.Field(default=None)
22
+ class RequestDispatchResult(pydantic.BaseModel, typing.Generic[Resp]):
23
+ response: Resp = pydantic.Field(default=None)
22
24
  events: typing.List[cqrs_events.Event] = pydantic.Field(default_factory=list)
23
25
 
24
26
 
@@ -15,7 +15,7 @@ class DomainEvent(Event, frozen=True):
15
15
  """
16
16
 
17
17
 
18
- _P = typing.TypeVar("_P")
18
+ _P = typing.TypeVar("_P", object, None, contravariant=True)
19
19
 
20
20
 
21
21
  class NotificationEvent(Event, frozen=True):
@@ -82,7 +82,7 @@ class ECSTEvent(Event, typing.Generic[_P], frozen=True):
82
82
  event_name: typing.Text
83
83
  event_type: typing.ClassVar = "ecst_event"
84
84
 
85
- payload: _P | None = pydantic.Field(default=None)
85
+ payload: _P = pydantic.Field(default=None)
86
86
 
87
87
  model_config = pydantic.ConfigDict(from_attributes=True)
88
88
 
@@ -3,14 +3,16 @@ import typing
3
3
  from cqrs.events import event, event_handler
4
4
 
5
5
  _KT = typing.TypeVar("_KT", bound=typing.Type[event.Event])
6
- _VT = typing.List[typing.Type[event_handler.EventHandler[event.Event]]]
6
+ _VT: typing.TypeAlias = typing.List[
7
+ typing.Type[event_handler.EventHandler[event.Event]]
8
+ ]
7
9
 
8
10
 
9
11
  class EventMap(typing.Dict[_KT, _VT]):
10
12
  def bind(
11
13
  self,
12
14
  event_type: _KT,
13
- handler_type: typing.Type[event_handler.EventHandler[event.Event]],
15
+ handler_type: typing.Type[event_handler.EventHandler],
14
16
  ) -> None:
15
17
  if event_type not in self:
16
18
  self[event_type] = [handler_type]
@@ -9,6 +9,8 @@ from cqrs import (
9
9
  response,
10
10
  )
11
11
 
12
+ Resp = typing.TypeVar("Resp", response.Response, None, contravariant=True)
13
+
12
14
 
13
15
  class RequestMediator:
14
16
  """
@@ -56,7 +58,7 @@ class RequestMediator:
56
58
  middleware_chain=middleware_chain, # type: ignore
57
59
  )
58
60
 
59
- async def send(self, request: requests.Request) -> response.Response | None:
61
+ async def send(self, request: requests.Request) -> Resp:
60
62
  dispatch_result = await self._dispatcher.dispatch(request)
61
63
 
62
64
  if dispatch_result.events:
@@ -4,7 +4,7 @@ import typing
4
4
  from cqrs import requests, response
5
5
 
6
6
  Req = typing.TypeVar("Req", bound=requests.Request, contravariant=True)
7
- Res = typing.TypeVar("Res", response.Response, None, covariant=True)
7
+ Res = typing.TypeVar("Res", response.Response, None, contravariant=True)
8
8
  HandleType = typing.Callable[[Req], typing.Awaitable[Res]]
9
9
 
10
10
 
@@ -6,7 +6,7 @@ import uuid
6
6
  import cqrs
7
7
  from cqrs.events import event as ev
8
8
 
9
- Event: typing.TypeAlias = ev.NotificationEvent | ev.ECSTEvent
9
+ Event = typing.TypeVar("Event", ev.NotificationEvent, ev.ECSTEvent, contravariant=True)
10
10
  Session = typing.TypeVar("Session")
11
11
 
12
12
 
@@ -17,7 +17,11 @@ class EventStatus(enum.StrEnum):
17
17
 
18
18
 
19
19
  class OutboxedEventRepository(abc.ABC, typing.Generic[Session]):
20
- def __init__(self, session_factory: typing.Callable[[], Session], compressor: cqrs.Compressor | None = None):
20
+ def __init__(
21
+ self,
22
+ session_factory: typing.Callable[[], Session],
23
+ compressor: cqrs.Compressor | None = None,
24
+ ):
21
25
  self._session_factory = session_factory
22
26
  self._compressor = compressor
23
27
 
@@ -38,11 +42,20 @@ class OutboxedEventRepository(abc.ABC, typing.Generic[Session]):
38
42
  """Get one event from the repository."""
39
43
 
40
44
  @abc.abstractmethod
41
- async def get_many(self, session: Session, batch_size: int = 100) -> typing.List[Event]:
45
+ async def get_many(
46
+ self,
47
+ session: Session,
48
+ batch_size: int = 100,
49
+ ) -> typing.List[Event]:
42
50
  """Get many events from the repository."""
43
51
 
44
52
  @abc.abstractmethod
45
- async def update_status(self, session: Session, event_id: uuid.UUID, new_status: EventStatus):
53
+ async def update_status(
54
+ self,
55
+ session: Session,
56
+ event_id: uuid.UUID,
57
+ new_status: EventStatus,
58
+ ):
46
59
  """Update the event status"""
47
60
 
48
61
  @abc.abstractmethod
@@ -175,7 +175,10 @@ class SqlAlchemyOutboxedEventRepository(
175
175
  repository.OutboxedEventRepository[sql_session.AsyncSession],
176
176
  ):
177
177
  EVENT_CLASS_MAPPING: typing.ClassVar[
178
- typing.Dict[EventType, typing.Type[repository.Event]]
178
+ typing.Dict[
179
+ EventType,
180
+ typing.Type[ev.NotificationEvent] | typing.Type[ev.ECSTEvent],
181
+ ]
179
182
  ] = {
180
183
  EventType.NOTIFICATION_EVENT: ev.NotificationEvent,
181
184
  EventType.ECST_EVENT: ev.ECSTEvent,
@@ -198,14 +201,15 @@ class SqlAlchemyOutboxedEventRepository(
198
201
 
199
202
  def _process_events(self, model: OutboxModel) -> repository.Event:
200
203
  event_dict = model.row_to_dict()
201
- event_dict["payload"] = orjson.loads(
202
- self._compressor.decompress(event_dict["payload"])
203
- if self._compressor
204
- else event_dict["payload"],
205
- )
204
+ if event_dict["payload"] is not None:
205
+ event_dict["payload"] = orjson.loads(
206
+ self._compressor.decompress(event_dict["payload"])
207
+ if self._compressor
208
+ else event_dict["payload"],
209
+ )
206
210
  return self.EVENT_CLASS_MAPPING[event_dict["event_type"]].model_validate(
207
211
  event_dict,
208
- )
212
+ ) # type: ignore
209
213
 
210
214
  async def get_many(
211
215
  self,
@@ -250,7 +254,7 @@ class SqlAlchemyOutboxedEventRepository(
250
254
  else event_dict["payload"],
251
255
  )
252
256
 
253
- return self.EVENT_CLASS_MAPPING[event.event_type].model_validate(event_dict)
257
+ return self._process_events(event)
254
258
 
255
259
  async def update_status(
256
260
  self,
@@ -1,15 +1,9 @@
1
1
  import typing
2
2
 
3
- from cqrs import response
4
3
  from cqrs.requests import request, request_handler
5
4
 
6
5
  _KT = typing.TypeVar("_KT", bound=typing.Type[request.Request])
7
- _VT = typing.TypeVar(
8
- "_VT",
9
- bound=typing.Type[
10
- request_handler.RequestHandler[request.Request, response.Response]
11
- ],
12
- )
6
+ _VT = typing.TypeVar("_VT", bound=typing.Type[request_handler.RequestHandler])
13
7
 
14
8
 
15
9
  class RequestMap(typing.Dict[_KT, _VT]):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-cqrs
3
- Version: 0.0.17
3
+ Version: 0.0.18
4
4
  Summary: Python CQRS pattern implementation
5
5
  Author: Nikita Kunov
6
6
  Author-email: Dmitriy Kutlubaev <kutlubaev00@mail.ru>, Vadim Kozyrevskiy <vadikko2@mail.ru>
File without changes
File without changes
File without changes