python-cq 0.22.1__tar.gz → 0.23.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 (35) hide show
  1. {python_cq-0.22.1 → python_cq-0.23.1}/PKG-INFO +2 -2
  2. {python_cq-0.22.1 → python_cq-0.23.1}/cq/__init__.py +26 -23
  3. {python_cq-0.22.1 → python_cq-0.23.1}/cq/_core/message.py +1 -1
  4. {python_cq-0.22.1 → python_cq-0.23.1}/cq/_core/middleware.py +1 -1
  5. {python_cq-0.22.1/cq/_core → python_cq-0.23.1/cq/_core/queuing}/pump.py +1 -1
  6. {python_cq-0.22.1/cq/_core → python_cq-0.23.1/cq/_core/queuing}/queues/memory.py +3 -3
  7. python_cq-0.22.1/cq/_core/pipetools.py → python_cq-0.23.1/cq/_core/routing/command_pipeline.py +5 -5
  8. {python_cq-0.22.1/cq/_core → python_cq-0.23.1/cq/_core/routing}/di.py +3 -3
  9. {python_cq-0.22.1/cq/_core → python_cq-0.23.1/cq/_core/routing}/dispatchers/abc.py +4 -4
  10. {python_cq-0.22.1/cq/_core → python_cq-0.23.1/cq/_core/routing}/dispatchers/bus.py +13 -10
  11. {python_cq-0.22.1/cq/_core → python_cq-0.23.1/cq/_core/routing}/dispatchers/lazy.py +2 -2
  12. {python_cq-0.22.1/cq/_core → python_cq-0.23.1/cq/_core/routing}/dispatchers/pipe.py +1 -1
  13. {python_cq-0.22.1/cq/_core → python_cq-0.23.1/cq/_core/routing}/handler.py +35 -16
  14. python_cq-0.22.1/cq/_core/cq.py → python_cq-0.23.1/cq/_core/routing/router.py +7 -7
  15. {python_cq-0.22.1 → python_cq-0.23.1}/cq/ext/injection.py +3 -3
  16. python_cq-0.23.1/cq/middlewares/__init__.py +0 -0
  17. python_cq-0.23.1/cq/py.typed +0 -0
  18. {python_cq-0.22.1 → python_cq-0.23.1}/pyproject.toml +1 -1
  19. {python_cq-0.22.1 → python_cq-0.23.1}/.gitignore +0 -0
  20. {python_cq-0.22.1 → python_cq-0.23.1}/LICENSE +0 -0
  21. {python_cq-0.22.1 → python_cq-0.23.1}/cq/_core/__init__.py +0 -0
  22. {python_cq-0.22.1 → python_cq-0.23.1}/cq/_core/common/__init__.py +0 -0
  23. {python_cq-0.22.1 → python_cq-0.23.1}/cq/_core/common/typing.py +0 -0
  24. {python_cq-0.22.1/cq/_core/dispatchers → python_cq-0.23.1/cq/_core/queuing}/__init__.py +0 -0
  25. {python_cq-0.22.1/cq/_core → python_cq-0.23.1/cq/_core/queuing}/queues/__init__.py +0 -0
  26. {python_cq-0.22.1/cq/_core → python_cq-0.23.1/cq/_core/queuing}/queues/abc.py +0 -0
  27. {python_cq-0.22.1 → python_cq-0.23.1}/cq/_core/related_events.py +0 -0
  28. {python_cq-0.22.1/cq/ext → python_cq-0.23.1/cq/_core/routing}/__init__.py +0 -0
  29. {python_cq-0.22.1/cq/middlewares → python_cq-0.23.1/cq/_core/routing/dispatchers}/__init__.py +0 -0
  30. {python_cq-0.22.1 → python_cq-0.23.1}/cq/exceptions.py +0 -0
  31. /python_cq-0.22.1/cq/py.typed → /python_cq-0.23.1/cq/ext/__init__.py +0 -0
  32. {python_cq-0.22.1 → python_cq-0.23.1}/cq/middlewares/contextlib.py +0 -0
  33. {python_cq-0.22.1 → python_cq-0.23.1}/cq/middlewares/exc.py +0 -0
  34. {python_cq-0.22.1 → python_cq-0.23.1}/cq/middlewares/retry.py +0 -0
  35. {python_cq-0.22.1 → python_cq-0.23.1}/docs/index.md +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: python-cq
3
- Version: 0.22.1
3
+ Version: 0.23.1
4
4
  Summary: CQRS library for async Python projects.
5
5
  Project-URL: Documentation, https://python-cq.remimd.dev
6
6
  Project-URL: Repository, https://github.com/100nm/python-cq
@@ -1,9 +1,3 @@
1
- from ._core.cq import CQ
2
- from ._core.di import DIAdapter
3
- from ._core.di import NoDI as _NoDI
4
- from ._core.dispatchers.abc import Dispatcher
5
- from ._core.dispatchers.bus import Bus
6
- from ._core.dispatchers.pipe import ContextPipeline, Pipe
7
1
  from ._core.message import (
8
2
  AnyCommandBus,
9
3
  Command,
@@ -14,14 +8,20 @@ from ._core.message import (
14
8
  QueryBus,
15
9
  )
16
10
  from ._core.middleware import Middleware, MiddlewareResult, resolve_handler_source
17
- from ._core.pipetools import ContextCommandPipeline as _ContextCommandPipeline
18
- from ._core.pump import Pump
19
- from ._core.queues.abc import Consumer, Delivery, Producer, Queue
20
- from ._core.queues.memory import MemoryQueue
11
+ from ._core.queuing.pump import Pump
12
+ from ._core.queuing.queues.abc import Consumer, Delivery, Producer, Queue
13
+ from ._core.queuing.queues.memory import MemoryQueue
21
14
  from ._core.related_events import AnyIORelatedEvents, RelatedEvents
15
+ from ._core.routing.command_pipeline import (
16
+ ContextCommandPipeline as _ContextCommandPipeline,
17
+ )
18
+ from ._core.routing.di import DIAdapter
19
+ from ._core.routing.dispatchers.abc import Dispatcher
20
+ from ._core.routing.dispatchers.bus import Bus
21
+ from ._core.routing.dispatchers.pipe import ContextPipeline, Pipe
22
+ from ._core.routing.router import Router
22
23
 
23
24
  __all__ = (
24
- "CQ",
25
25
  "AnyCommandBus",
26
26
  "AnyIORelatedEvents",
27
27
  "Bus",
@@ -45,7 +45,8 @@ __all__ = (
45
45
  "QueryBus",
46
46
  "Queue",
47
47
  "RelatedEvents",
48
- "__cq__",
48
+ "Router",
49
+ "__router__",
49
50
  "command_handler",
50
51
  "event_handler",
51
52
  "new_command_bus",
@@ -55,28 +56,30 @@ __all__ = (
55
56
  "resolve_handler_source",
56
57
  )
57
58
 
59
+
58
60
  try:
59
- from .ext.injection import InjectionAdapter as _InjectionAdapter
61
+ from .ext.injection import InjectionAdapter
60
62
 
61
63
  except ImportError: # pragma: no cover
62
- __cq__ = CQ(_NoDI())
64
+ __router__ = Router()
63
65
 
64
66
  else:
65
- __cq__ = CQ(_InjectionAdapter())
67
+ __router__ = Router(InjectionAdapter())
68
+ del InjectionAdapter
66
69
 
67
- __cq__.register_defaults()
70
+ __router__.register_defaults()
68
71
 
69
- command_handler = __cq__.command_handler
70
- event_handler = __cq__.event_handler
71
- query_handler = __cq__.query_handler
72
+ command_handler = __router__.command_handler
73
+ event_handler = __router__.event_handler
74
+ query_handler = __router__.query_handler
72
75
 
73
- new_command_bus = __cq__.new_command_bus
74
- new_event_bus = __cq__.new_event_bus
75
- new_query_bus = __cq__.new_query_bus
76
+ new_command_bus = __router__.new_command_bus
77
+ new_event_bus = __router__.new_event_bus
78
+ new_query_bus = __router__.new_query_bus
76
79
 
77
80
 
78
81
  class ContextCommandPipeline[C: Command](_ContextCommandPipeline[C]):
79
82
  __slots__ = ()
80
83
 
81
- def __init__(self, di: DIAdapter = __cq__.di) -> None:
84
+ def __init__(self, di: DIAdapter = __router__.di) -> None:
82
85
  super().__init__(di)
@@ -1,6 +1,6 @@
1
1
  from typing import Any
2
2
 
3
- from cq._core.dispatchers.abc import Dispatcher
3
+ from cq._core.routing.dispatchers.abc import Dispatcher
4
4
 
5
5
  Command = object
6
6
  Event = object
@@ -3,7 +3,7 @@ from dataclasses import dataclass, field
3
3
  from inspect import isasyncgenfunction
4
4
  from typing import Any, Concatenate, Self, TypeGuard
5
5
 
6
- from cq._core.handler import HandleFunction, HandlerType
6
+ from cq._core.routing.handler import HandleFunction, HandlerType
7
7
  from cq.exceptions import MiddlewareError
8
8
 
9
9
  type MiddlewareResult[T] = AsyncGenerator[None, T]
@@ -6,7 +6,7 @@ from typing import Any, Self
6
6
  import anyio
7
7
 
8
8
  from cq._core.middleware import Middleware, MiddlewareGroup
9
- from cq._core.queues.abc import Consumer
9
+ from cq._core.queuing.queues.abc import Consumer
10
10
 
11
11
 
12
12
  @dataclass(repr=False, eq=False, frozen=True, slots=True)
@@ -7,8 +7,8 @@ import anyio
7
7
  from anyio.abc import ObjectReceiveStream, ObjectSendStream
8
8
 
9
9
  from cq._core.middleware import Middleware
10
- from cq._core.pump import Pump
11
- from cq._core.queues.abc import Delivery, Queue
10
+ from cq._core.queuing.pump import Pump
11
+ from cq._core.queuing.queues.abc import Delivery, Queue
12
12
 
13
13
 
14
14
  class MemoryQueue[T](Queue[T]):
@@ -17,7 +17,7 @@ class MemoryQueue[T](Queue[T]):
17
17
  __consumer: ObjectReceiveStream[T]
18
18
  __producer: ObjectSendStream[T]
19
19
 
20
- def __init__(self, maxsize: int = 0) -> None:
20
+ def __init__(self, maxsize: float = 0) -> None:
21
21
  self.__producer, self.__consumer = anyio.create_memory_object_stream(maxsize)
22
22
 
23
23
  async def __aenter__(self) -> Self:
@@ -1,16 +1,16 @@
1
1
  from typing import TYPE_CHECKING, Any, Self, overload
2
2
 
3
- from cq import Dispatcher
4
3
  from cq._core.common.typing import Decorator
5
- from cq._core.di import DIAdapter
6
- from cq._core.dispatchers.lazy import LazyDispatcher
7
- from cq._core.dispatchers.pipe import (
4
+ from cq._core.message import Command, CommandBus, Query, QueryBus
5
+ from cq._core.routing.di import DIAdapter
6
+ from cq._core.routing.dispatchers.abc import Dispatcher
7
+ from cq._core.routing.dispatchers.lazy import LazyDispatcher
8
+ from cq._core.routing.dispatchers.pipe import (
8
9
  ContextPipeline,
9
10
  ConvertMethod,
10
11
  ConvertMethodAsync,
11
12
  ConvertMethodSync,
12
13
  )
13
- from cq._core.message import Command, CommandBus, Query, QueryBus
14
14
 
15
15
 
16
16
  class ContextCommandPipeline[C: Command](ContextPipeline[C]):
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  from abc import abstractmethod
4
4
  from collections.abc import Awaitable, Callable
5
5
  from contextlib import nullcontext
6
- from typing import TYPE_CHECKING, Any, Protocol, runtime_checkable
6
+ from typing import TYPE_CHECKING, Any, Concatenate, Protocol, runtime_checkable
7
7
 
8
8
  from cq.middlewares.contextlib import AsyncContextManagerMiddleware
9
9
 
@@ -24,7 +24,7 @@ class DIAdapter(Protocol):
24
24
  __slots__ = ()
25
25
 
26
26
  @abstractmethod
27
- def command_scope(self) -> Middleware[[Command], Any]:
27
+ def command_scope(self) -> Middleware[Concatenate[Command, ...], Any]:
28
28
  """
29
29
  Return a middleware that wraps each command dispatch.
30
30
 
@@ -88,7 +88,7 @@ class DIAdapter(Protocol):
88
88
  class NoDI(DIAdapter):
89
89
  __slots__ = ()
90
90
 
91
- def command_scope(self) -> Middleware[[Command], Any]:
91
+ def command_scope(self) -> Middleware[Concatenate[Command, ...], Any]:
92
92
  return AsyncContextManagerMiddleware(nullcontext())
93
93
 
94
94
  def lazy[T](self, tp: type[T], /) -> Callable[[], Awaitable[T]]:
@@ -1,6 +1,6 @@
1
1
  from abc import ABC, abstractmethod
2
2
  from collections.abc import Awaitable, Callable
3
- from typing import Protocol, Self, runtime_checkable
3
+ from typing import Concatenate, Protocol, Self, runtime_checkable
4
4
 
5
5
  from cq._core.middleware import Middleware, MiddlewareGroup
6
6
 
@@ -20,18 +20,18 @@ class Dispatcher[I, O](Protocol):
20
20
  class BaseDispatcher[I, O](Dispatcher[I, O], ABC):
21
21
  __slots__ = ("__middleware_group",)
22
22
 
23
- __middleware_group: MiddlewareGroup[[I], O]
23
+ __middleware_group: MiddlewareGroup[Concatenate[I, ...], O]
24
24
 
25
25
  def __init__(self) -> None:
26
26
  self.__middleware_group = MiddlewareGroup()
27
27
 
28
- def add_middlewares(self, *middlewares: Middleware[[I], O]) -> Self:
28
+ def add_middlewares(self, *middlewares: Middleware[Concatenate[I, ...], O]) -> Self:
29
29
  self.__middleware_group.add(*middlewares)
30
30
  return self
31
31
 
32
32
  async def _invoke(
33
33
  self,
34
- handler: Callable[[I], Awaitable[O]],
34
+ handler: Callable[Concatenate[I, ...], Awaitable[O]],
35
35
  message: I,
36
36
  /,
37
37
  fail_silently: bool = False,
@@ -1,19 +1,19 @@
1
1
  from abc import ABC, abstractmethod
2
2
  from collections.abc import Awaitable, Callable, Iterator
3
- from typing import Any, Protocol, Self, runtime_checkable
3
+ from typing import Any, Concatenate, Protocol, Self, runtime_checkable
4
4
 
5
5
  import anyio
6
6
  from anyio.abc import TaskGroup
7
7
 
8
- from cq._core.dispatchers.abc import BaseDispatcher, Dispatcher
9
- from cq._core.handler import (
8
+ from cq._core.middleware import Middleware
9
+ from cq._core.routing.dispatchers.abc import BaseDispatcher, Dispatcher
10
+ from cq._core.routing.handler import (
10
11
  HandleFunction,
11
12
  HandlerFactory,
12
13
  HandlerRegistry,
13
14
  MultipleHandlerRegistry,
14
15
  SingleHandlerRegistry,
15
16
  )
16
- from cq._core.middleware import Middleware
17
17
 
18
18
  type Listener[T] = Callable[[T], Awaitable[Any]]
19
19
 
@@ -27,14 +27,14 @@ class Bus[I, O](Dispatcher[I, O], Protocol):
27
27
  raise NotImplementedError
28
28
 
29
29
  @abstractmethod
30
- def add_middlewares(self, *middlewares: Middleware[[I], O]) -> Self:
30
+ def add_middlewares(self, *middlewares: Middleware[Concatenate[I, ...], O]) -> Self:
31
31
  raise NotImplementedError
32
32
 
33
33
  @abstractmethod
34
34
  def subscribe(
35
35
  self,
36
36
  message_type: type[I],
37
- factory: HandlerFactory[[I], O],
37
+ factory: HandlerFactory[Concatenate[I, ...], O],
38
38
  fail_silently: bool = ...,
39
39
  ) -> Self:
40
40
  raise NotImplementedError
@@ -58,13 +58,16 @@ class BaseBus[I, O](BaseDispatcher[I, O], Bus[I, O], ABC):
58
58
  def subscribe(
59
59
  self,
60
60
  message_type: type[I],
61
- factory: HandlerFactory[[I], O],
61
+ factory: HandlerFactory[Concatenate[I, ...], O],
62
62
  fail_silently: bool = False,
63
63
  ) -> Self:
64
64
  self.__registry.subscribe(message_type, factory, fail_silently=fail_silently)
65
65
  return self
66
66
 
67
- def _handlers_from(self, message_type: type[I]) -> Iterator[HandleFunction[[I], O]]:
67
+ def _handlers_from(
68
+ self,
69
+ message_type: type[I],
70
+ ) -> Iterator[HandleFunction[Concatenate[I, ...], O]]:
68
71
  return self.__registry.handlers_from(message_type)
69
72
 
70
73
  def _trigger_listeners(self, message: I, /, task_group: TaskGroup) -> None:
@@ -82,7 +85,7 @@ class SimpleBus[I, O](BaseBus[I, O]):
82
85
  async with anyio.create_task_group() as task_group:
83
86
  self._trigger_listeners(message, task_group)
84
87
 
85
- for handler in self._handlers_from(type(message)):
88
+ for handler in self._handlers_from(message.__class__):
86
89
  return await self._invoke(handler, message, handler.fail_silently)
87
90
 
88
91
  return NotImplemented
@@ -98,7 +101,7 @@ class TaskBus[I](BaseBus[I, None]):
98
101
  async with anyio.create_task_group() as task_group:
99
102
  self._trigger_listeners(message, task_group)
100
103
 
101
- for handler in self._handlers_from(type(message)):
104
+ for handler in self._handlers_from(message.__class__):
102
105
  task_group.start_soon(
103
106
  self._invoke,
104
107
  handler,
@@ -2,8 +2,8 @@ from collections.abc import Awaitable, Callable
2
2
  from types import GenericAlias
3
3
  from typing import TypeAliasType
4
4
 
5
- from cq._core.di import DIAdapter
6
- from cq._core.dispatchers.abc import Dispatcher
5
+ from cq._core.routing.di import DIAdapter
6
+ from cq._core.routing.dispatchers.abc import Dispatcher
7
7
 
8
8
 
9
9
  class LazyDispatcher[I, O](Dispatcher[I, O]):
@@ -14,8 +14,8 @@ from typing import (
14
14
  )
15
15
 
16
16
  from cq._core.common.typing import Decorator, Method
17
- from cq._core.dispatchers.abc import BaseDispatcher, Dispatcher
18
17
  from cq._core.middleware import Middleware, MiddlewareGroup
18
+ from cq._core.routing.dispatchers.abc import BaseDispatcher, Dispatcher
19
19
 
20
20
  type ConvertAsync[**P, I, O] = Callable[Concatenate[O, P], Awaitable[I]]
21
21
  type ConvertSync[**P, I, O] = Callable[Concatenate[O, P], I]
@@ -5,12 +5,20 @@ from dataclasses import dataclass, field
5
5
  from functools import partial
6
6
  from inspect import Parameter, isclass, unwrap
7
7
  from inspect import signature as inspect_signature
8
- from typing import TYPE_CHECKING, Any, Protocol, Self, overload, runtime_checkable
8
+ from typing import (
9
+ TYPE_CHECKING,
10
+ Any,
11
+ Concatenate,
12
+ Protocol,
13
+ Self,
14
+ overload,
15
+ runtime_checkable,
16
+ )
9
17
 
10
18
  from type_analyzer import MatchingTypesConfig, iter_matching_types, matching_types
11
19
 
12
20
  from cq._core.common.typing import Decorator
13
- from cq._core.di import DIAdapter, NoDI
21
+ from cq._core.routing.di import DIAdapter, NoDI
14
22
 
15
23
  type HandlerType[**P, T] = type[Handler[P, T]]
16
24
  type HandlerFactory[**P, T] = Callable[..., Awaitable[Handler[P, T]]]
@@ -55,15 +63,18 @@ class HandlerRegistry[I, O](Protocol):
55
63
  raise NotImplementedError
56
64
 
57
65
  @abstractmethod
58
- def handlers_from(self, message_type: type[I]) -> Iterator[HandleFunction[[I], O]]:
66
+ def handlers_from(
67
+ self,
68
+ message_type: type[I],
69
+ ) -> Iterator[HandleFunction[Concatenate[I, ...], O]]:
59
70
  raise NotImplementedError
60
71
 
61
72
  @abstractmethod
62
73
  def subscribe(
63
74
  self,
64
75
  message_type: type[I],
65
- handler_factory: HandlerFactory[[I], O],
66
- handler_type: HandlerType[[I], O] | None = ...,
76
+ handler_factory: HandlerFactory[Concatenate[I, ...], O],
77
+ handler_type: HandlerType[Concatenate[I, ...], O] | None = ...,
67
78
  fail_silently: bool = ...,
68
79
  ) -> Self:
69
80
  raise NotImplementedError
@@ -71,7 +82,7 @@ class HandlerRegistry[I, O](Protocol):
71
82
 
72
83
  @dataclass(repr=False, eq=False, frozen=True, slots=True)
73
84
  class MultipleHandlerRegistry[I, O](HandlerRegistry[I, O]):
74
- __values: dict[type[I], list[HandleFunction[[I], O]]] = field(
85
+ __values: dict[type[I], list[HandleFunction[Concatenate[I, ...], O]]] = field(
75
86
  default_factory=partial(defaultdict, list),
76
87
  init=False,
77
88
  )
@@ -80,15 +91,18 @@ class MultipleHandlerRegistry[I, O](HandlerRegistry[I, O]):
80
91
  def message_types(self) -> KeysView[type[I]]:
81
92
  return self.__values.keys()
82
93
 
83
- def handlers_from(self, message_type: type[I]) -> Iterator[HandleFunction[[I], O]]:
94
+ def handlers_from(
95
+ self,
96
+ message_type: type[I],
97
+ ) -> Iterator[HandleFunction[Concatenate[I, ...], O]]:
84
98
  for key_type in _iter_key_types(message_type):
85
99
  yield from self.__values.get(key_type, ())
86
100
 
87
101
  def subscribe(
88
102
  self,
89
103
  message_type: type[I],
90
- handler_factory: HandlerFactory[[I], O],
91
- handler_type: HandlerType[[I], O] | None = None,
104
+ handler_factory: HandlerFactory[Concatenate[I, ...], O],
105
+ handler_type: HandlerType[Concatenate[I, ...], O] | None = None,
92
106
  fail_silently: bool = False,
93
107
  ) -> Self:
94
108
  function = HandleFunction.create(handler_factory, handler_type, fail_silently)
@@ -101,7 +115,7 @@ class MultipleHandlerRegistry[I, O](HandlerRegistry[I, O]):
101
115
 
102
116
  @dataclass(repr=False, eq=False, frozen=True, slots=True)
103
117
  class SingleHandlerRegistry[I, O](HandlerRegistry[I, O]):
104
- __values: dict[type[I], HandleFunction[[I], O]] = field(
118
+ __values: dict[type[I], HandleFunction[Concatenate[I, ...], O]] = field(
105
119
  default_factory=dict,
106
120
  init=False,
107
121
  )
@@ -110,7 +124,10 @@ class SingleHandlerRegistry[I, O](HandlerRegistry[I, O]):
110
124
  def message_types(self) -> KeysView[type[I]]:
111
125
  return self.__values.keys()
112
126
 
113
- def handlers_from(self, message_type: type[I]) -> Iterator[HandleFunction[[I], O]]:
127
+ def handlers_from(
128
+ self,
129
+ message_type: type[I],
130
+ ) -> Iterator[HandleFunction[Concatenate[I, ...], O]]:
114
131
  for key_type in _iter_key_types(message_type):
115
132
  function = self.__values.get(key_type, None)
116
133
  if function is not None:
@@ -119,8 +136,8 @@ class SingleHandlerRegistry[I, O](HandlerRegistry[I, O]):
119
136
  def subscribe(
120
137
  self,
121
138
  message_type: type[I],
122
- handler_factory: HandlerFactory[[I], O],
123
- handler_type: HandlerType[[I], O] | None = None,
139
+ handler_factory: HandlerFactory[Concatenate[I, ...], O],
140
+ handler_type: HandlerType[Concatenate[I, ...], O] | None = None,
124
141
  fail_silently: bool = False,
125
142
  ) -> Self:
126
143
  function = HandleFunction.create(handler_factory, handler_type, fail_silently)
@@ -195,12 +212,12 @@ class HandlerDecorator[I, O]:
195
212
 
196
213
  def __decorator(
197
214
  self,
198
- wrapped: HandlerType[[I], O],
215
+ wrapped: HandlerType[Concatenate[I, ...], O],
199
216
  /,
200
217
  *,
201
218
  message_type: type[I] | None = None,
202
219
  fail_silently: bool = False,
203
- ) -> HandlerType[[I], O]:
220
+ ) -> HandlerType[Concatenate[I, ...], O]:
204
221
  factory = self.di.wire(wrapped)
205
222
  message_type = message_type or _resolve_message_type(wrapped)
206
223
  self.registry.subscribe(message_type, factory, wrapped, fail_silently)
@@ -221,7 +238,9 @@ def _iter_key_types(message_type: Any) -> Iterator[Any]:
221
238
  return iter_matching_types(message_type, config)
222
239
 
223
240
 
224
- def _resolve_message_type[I, O](handler_type: HandlerType[[I], O]) -> type[I]:
241
+ def _resolve_message_type[I, O](
242
+ handler_type: HandlerType[Concatenate[I, ...], O],
243
+ ) -> type[I]:
225
244
  fake_method = handler_type.handle.__get__(NotImplemented, handler_type)
226
245
  signature = inspect_signature(fake_method, eval_str=True)
227
246
 
@@ -1,18 +1,18 @@
1
1
  from collections.abc import KeysView
2
2
  from typing import Any, Self
3
3
 
4
- from cq._core.di import DIAdapter
5
- from cq._core.dispatchers.bus import Bus, SimpleBus, TaskBus
6
- from cq._core.handler import (
4
+ from cq._core.message import Command, Event, Query
5
+ from cq._core.routing.di import DIAdapter, NoDI
6
+ from cq._core.routing.dispatchers.bus import Bus, SimpleBus, TaskBus
7
+ from cq._core.routing.handler import (
7
8
  HandlerDecorator,
8
9
  HandlerRegistry,
9
10
  MultipleHandlerRegistry,
10
11
  SingleHandlerRegistry,
11
12
  )
12
- from cq._core.message import Command, Event, Query
13
13
 
14
14
 
15
- class CQ:
15
+ class Router:
16
16
  __slots__ = ("__command_registry", "__di", "__event_registry", "__query_registry")
17
17
 
18
18
  __command_registry: HandlerRegistry[Command, Any]
@@ -20,8 +20,8 @@ class CQ:
20
20
  __event_registry: HandlerRegistry[Event, Any]
21
21
  __query_registry: HandlerRegistry[Query, Any]
22
22
 
23
- def __init__(self, di: DIAdapter, /) -> None:
24
- self.__di = di
23
+ def __init__(self, di: DIAdapter | None = None, /) -> None:
24
+ self.__di = di or NoDI()
25
25
  self.__command_registry = SingleHandlerRegistry()
26
26
  self.__event_registry = MultipleHandlerRegistry()
27
27
  self.__query_registry = SingleHandlerRegistry()
@@ -2,15 +2,15 @@ from collections.abc import AsyncIterator, Awaitable, Callable
2
2
  from contextlib import AsyncExitStack
3
3
  from dataclasses import dataclass, field
4
4
  from enum import StrEnum
5
- from typing import Any
5
+ from typing import Any, Concatenate
6
6
 
7
7
  from injection import Module, adefine_scope, mod
8
8
  from injection.exceptions import ScopeAlreadyDefinedError
9
9
 
10
- from cq._core.di import DIAdapter
11
10
  from cq._core.message import Command, CommandBus, EventBus, QueryBus
12
11
  from cq._core.middleware import Middleware, MiddlewareResult
13
12
  from cq._core.related_events import AnyIORelatedEvents, RelatedEvents
13
+ from cq._core.routing.di import DIAdapter
14
14
 
15
15
  __all__ = ("CQScope", "InjectionAdapter", "InjectionScopeMiddleware")
16
16
 
@@ -24,7 +24,7 @@ class InjectionAdapter(DIAdapter):
24
24
  module: Module = field(default_factory=mod)
25
25
  threadsafe: bool | None = field(default=None)
26
26
 
27
- def command_scope(self) -> Middleware[[Command], Any]:
27
+ def command_scope(self) -> Middleware[Concatenate[Command, ...], Any]:
28
28
  return InjectionScopeMiddleware(
29
29
  CQScope.COMMAND_DISPATCH,
30
30
  threadsafe=self.threadsafe,
File without changes
File without changes
@@ -20,7 +20,7 @@ test = [
20
20
 
21
21
  [project]
22
22
  name = "python-cq"
23
- version = "0.22.1"
23
+ version = "0.23.1"
24
24
  description = "CQRS library for async Python projects."
25
25
  license = "MIT"
26
26
  license-files = ["LICENSE"]
File without changes
File without changes
File without changes
File without changes