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.
- {python_cq-0.22.1 → python_cq-0.23.1}/PKG-INFO +2 -2
- {python_cq-0.22.1 → python_cq-0.23.1}/cq/__init__.py +26 -23
- {python_cq-0.22.1 → python_cq-0.23.1}/cq/_core/message.py +1 -1
- {python_cq-0.22.1 → python_cq-0.23.1}/cq/_core/middleware.py +1 -1
- {python_cq-0.22.1/cq/_core → python_cq-0.23.1/cq/_core/queuing}/pump.py +1 -1
- {python_cq-0.22.1/cq/_core → python_cq-0.23.1/cq/_core/queuing}/queues/memory.py +3 -3
- python_cq-0.22.1/cq/_core/pipetools.py → python_cq-0.23.1/cq/_core/routing/command_pipeline.py +5 -5
- {python_cq-0.22.1/cq/_core → python_cq-0.23.1/cq/_core/routing}/di.py +3 -3
- {python_cq-0.22.1/cq/_core → python_cq-0.23.1/cq/_core/routing}/dispatchers/abc.py +4 -4
- {python_cq-0.22.1/cq/_core → python_cq-0.23.1/cq/_core/routing}/dispatchers/bus.py +13 -10
- {python_cq-0.22.1/cq/_core → python_cq-0.23.1/cq/_core/routing}/dispatchers/lazy.py +2 -2
- {python_cq-0.22.1/cq/_core → python_cq-0.23.1/cq/_core/routing}/dispatchers/pipe.py +1 -1
- {python_cq-0.22.1/cq/_core → python_cq-0.23.1/cq/_core/routing}/handler.py +35 -16
- python_cq-0.22.1/cq/_core/cq.py → python_cq-0.23.1/cq/_core/routing/router.py +7 -7
- {python_cq-0.22.1 → python_cq-0.23.1}/cq/ext/injection.py +3 -3
- python_cq-0.23.1/cq/middlewares/__init__.py +0 -0
- python_cq-0.23.1/cq/py.typed +0 -0
- {python_cq-0.22.1 → python_cq-0.23.1}/pyproject.toml +1 -1
- {python_cq-0.22.1 → python_cq-0.23.1}/.gitignore +0 -0
- {python_cq-0.22.1 → python_cq-0.23.1}/LICENSE +0 -0
- {python_cq-0.22.1 → python_cq-0.23.1}/cq/_core/__init__.py +0 -0
- {python_cq-0.22.1 → python_cq-0.23.1}/cq/_core/common/__init__.py +0 -0
- {python_cq-0.22.1 → python_cq-0.23.1}/cq/_core/common/typing.py +0 -0
- {python_cq-0.22.1/cq/_core/dispatchers → python_cq-0.23.1/cq/_core/queuing}/__init__.py +0 -0
- {python_cq-0.22.1/cq/_core → python_cq-0.23.1/cq/_core/queuing}/queues/__init__.py +0 -0
- {python_cq-0.22.1/cq/_core → python_cq-0.23.1/cq/_core/queuing}/queues/abc.py +0 -0
- {python_cq-0.22.1 → python_cq-0.23.1}/cq/_core/related_events.py +0 -0
- {python_cq-0.22.1/cq/ext → python_cq-0.23.1/cq/_core/routing}/__init__.py +0 -0
- {python_cq-0.22.1/cq/middlewares → python_cq-0.23.1/cq/_core/routing/dispatchers}/__init__.py +0 -0
- {python_cq-0.22.1 → python_cq-0.23.1}/cq/exceptions.py +0 -0
- /python_cq-0.22.1/cq/py.typed → /python_cq-0.23.1/cq/ext/__init__.py +0 -0
- {python_cq-0.22.1 → python_cq-0.23.1}/cq/middlewares/contextlib.py +0 -0
- {python_cq-0.22.1 → python_cq-0.23.1}/cq/middlewares/exc.py +0 -0
- {python_cq-0.22.1 → python_cq-0.23.1}/cq/middlewares/retry.py +0 -0
- {python_cq-0.22.1 → python_cq-0.23.1}/docs/index.md +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: python-cq
|
|
3
|
-
Version: 0.
|
|
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.
|
|
18
|
-
from ._core.
|
|
19
|
-
from ._core.queues.
|
|
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
|
-
"
|
|
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
|
|
61
|
+
from .ext.injection import InjectionAdapter
|
|
60
62
|
|
|
61
63
|
except ImportError: # pragma: no cover
|
|
62
|
-
|
|
64
|
+
__router__ = Router()
|
|
63
65
|
|
|
64
66
|
else:
|
|
65
|
-
|
|
67
|
+
__router__ = Router(InjectionAdapter())
|
|
68
|
+
del InjectionAdapter
|
|
66
69
|
|
|
67
|
-
|
|
70
|
+
__router__.register_defaults()
|
|
68
71
|
|
|
69
|
-
command_handler =
|
|
70
|
-
event_handler =
|
|
71
|
-
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 =
|
|
74
|
-
new_event_bus =
|
|
75
|
-
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 =
|
|
84
|
+
def __init__(self, di: DIAdapter = __router__.di) -> None:
|
|
82
85
|
super().__init__(di)
|
|
@@ -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:
|
|
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:
|
python_cq-0.22.1/cq/_core/pipetools.py → python_cq-0.23.1/cq/_core/routing/command_pipeline.py
RENAMED
|
@@ -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.
|
|
6
|
-
from cq._core.
|
|
7
|
-
from cq._core.dispatchers.
|
|
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.
|
|
9
|
-
from cq._core.
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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](
|
|
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.
|
|
5
|
-
from cq._core.
|
|
6
|
-
from cq._core.
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_cq-0.22.1/cq/middlewares → python_cq-0.23.1/cq/_core/routing/dispatchers}/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|