python-cq 0.21.1__py3-none-any.whl → 0.22.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.
- cq/_core/cq.py +1 -3
- cq/_core/di.py +14 -23
- cq/_core/pipetools.py +0 -3
- cq/ext/injection.py +7 -14
- cq/middlewares/contextlib.py +27 -0
- {python_cq-0.21.1.dist-info → python_cq-0.22.0.dist-info}/METADATA +1 -1
- {python_cq-0.21.1.dist-info → python_cq-0.22.0.dist-info}/RECORD +9 -10
- cq/_core/middlewares/__init__.py +0 -0
- cq/_core/middlewares/scope.py +0 -14
- {python_cq-0.21.1.dist-info → python_cq-0.22.0.dist-info}/WHEEL +0 -0
- {python_cq-0.21.1.dist-info → python_cq-0.22.0.dist-info}/licenses/LICENSE +0 -0
cq/_core/cq.py
CHANGED
|
@@ -10,7 +10,6 @@ from cq._core.handler import (
|
|
|
10
10
|
SingleHandlerRegistry,
|
|
11
11
|
)
|
|
12
12
|
from cq._core.message import Command, Event, Query
|
|
13
|
-
from cq._core.middlewares.scope import CommandDispatchScopeMiddleware
|
|
14
13
|
|
|
15
14
|
|
|
16
15
|
class CQ:
|
|
@@ -57,8 +56,7 @@ class CQ:
|
|
|
57
56
|
|
|
58
57
|
def new_command_bus(self) -> Bus[Command, Any]:
|
|
59
58
|
bus = SimpleBus(self.__command_registry)
|
|
60
|
-
|
|
61
|
-
bus.add_middlewares(command_middleware)
|
|
59
|
+
bus.add_middlewares(self.__di.command_scope())
|
|
62
60
|
return bus
|
|
63
61
|
|
|
64
62
|
def new_event_bus(self) -> Bus[Event, None]:
|
cq/_core/di.py
CHANGED
|
@@ -3,10 +3,12 @@ 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,
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Protocol, runtime_checkable
|
|
7
|
+
|
|
8
|
+
from cq.middlewares.contextlib import AsyncContextManagerMiddleware
|
|
7
9
|
|
|
8
10
|
if TYPE_CHECKING: # pragma: no cover
|
|
9
|
-
from cq import CommandBus, EventBus, QueryBus
|
|
11
|
+
from cq import Command, CommandBus, EventBus, Middleware, QueryBus
|
|
10
12
|
|
|
11
13
|
|
|
12
14
|
@runtime_checkable
|
|
@@ -22,30 +24,19 @@ class DIAdapter(Protocol):
|
|
|
22
24
|
__slots__ = ()
|
|
23
25
|
|
|
24
26
|
@abstractmethod
|
|
25
|
-
def command_scope(self) ->
|
|
27
|
+
def command_scope(self) -> Middleware[[Command], Any]:
|
|
26
28
|
"""
|
|
27
|
-
Return
|
|
28
|
-
command dispatch.
|
|
29
|
+
Return a middleware that wraps each command dispatch.
|
|
29
30
|
|
|
30
31
|
**Responsibilities**
|
|
31
32
|
|
|
32
|
-
The
|
|
33
|
-
instance and register it so that it is resolvable
|
|
34
|
-
the duration of the
|
|
35
|
-
|
|
36
|
-
**Nested calls**
|
|
37
|
-
|
|
38
|
-
``command_scope`` is entered in two distinct situations:
|
|
39
|
-
|
|
40
|
-
1. Around a standard command dispatch (via
|
|
41
|
-
``CommandDispatchScopeMiddleware``).
|
|
42
|
-
2. Around each step of a ``ContextCommandPipeline``, which itself
|
|
43
|
-
wraps a command dispatch.
|
|
33
|
+
The middleware must at minimum manage the lifecycle of a
|
|
34
|
+
``RelatedEvents`` instance and register it so that it is resolvable
|
|
35
|
+
via injection for the duration of the dispatch.
|
|
44
36
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
call instead of opening a second, conflicting scope.
|
|
37
|
+
If you already have an async context manager for the scope, wrap it
|
|
38
|
+
with ``cq.middlewares.contextlib.AsyncContextManagerMiddleware``
|
|
39
|
+
instead of writing the middleware by hand.
|
|
49
40
|
"""
|
|
50
41
|
|
|
51
42
|
raise NotImplementedError
|
|
@@ -97,8 +88,8 @@ class DIAdapter(Protocol):
|
|
|
97
88
|
class NoDI(DIAdapter):
|
|
98
89
|
__slots__ = ()
|
|
99
90
|
|
|
100
|
-
def command_scope(self) ->
|
|
101
|
-
return nullcontext()
|
|
91
|
+
def command_scope(self) -> Middleware[[Command], Any]:
|
|
92
|
+
return AsyncContextManagerMiddleware(nullcontext())
|
|
102
93
|
|
|
103
94
|
def lazy[T](self, tp: type[T], /) -> Callable[[], Awaitable[T]]:
|
|
104
95
|
tp_str = getattr(tp, "__name__", str(tp))
|
cq/_core/pipetools.py
CHANGED
|
@@ -11,7 +11,6 @@ from cq._core.dispatchers.pipe import (
|
|
|
11
11
|
ConvertMethodSync,
|
|
12
12
|
)
|
|
13
13
|
from cq._core.message import Command, CommandBus, Query, QueryBus
|
|
14
|
-
from cq._core.middlewares.scope import CommandDispatchScopeMiddleware
|
|
15
14
|
|
|
16
15
|
|
|
17
16
|
class ContextCommandPipeline[C: Command](ContextPipeline[C]):
|
|
@@ -22,8 +21,6 @@ class ContextCommandPipeline[C: Command](ContextPipeline[C]):
|
|
|
22
21
|
def __init__(self, di: DIAdapter) -> None:
|
|
23
22
|
super().__init__(LazyDispatcher(CommandBus, di))
|
|
24
23
|
self.__query_dispatcher = LazyDispatcher(QueryBus, di)
|
|
25
|
-
command_middleware = CommandDispatchScopeMiddleware(di)
|
|
26
|
-
self.add_middlewares(command_middleware)
|
|
27
24
|
|
|
28
25
|
def add_static_query_step[Q: Query](self, query: Q, /) -> Self:
|
|
29
26
|
return self.add_static_step(query, dispatcher=self.__query_dispatcher)
|
cq/ext/injection.py
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
from collections.abc import AsyncIterator
|
|
2
|
-
from contextlib import AsyncExitStack
|
|
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, Awaitable, Callable
|
|
6
6
|
|
|
7
7
|
from injection import Module, adefine_scope, mod
|
|
8
8
|
from injection.exceptions import ScopeAlreadyDefinedError
|
|
9
9
|
|
|
10
10
|
from cq._core.di import DIAdapter
|
|
11
|
-
from cq._core.message import CommandBus, EventBus, QueryBus
|
|
12
|
-
from cq._core.middleware import MiddlewareResult
|
|
11
|
+
from cq._core.message import Command, CommandBus, EventBus, QueryBus
|
|
12
|
+
from cq._core.middleware import Middleware, MiddlewareResult
|
|
13
13
|
from cq._core.related_events import AnyIORelatedEvents, RelatedEvents
|
|
14
14
|
|
|
15
15
|
__all__ = ("CQScope", "InjectionAdapter", "InjectionScopeMiddleware")
|
|
@@ -24,12 +24,11 @@ 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) ->
|
|
28
|
-
return InjectionScopeMiddleware(
|
|
27
|
+
def command_scope(self) -> Middleware[[Command], Any]:
|
|
28
|
+
return InjectionScopeMiddleware(
|
|
29
29
|
CQScope.COMMAND_DISPATCH,
|
|
30
|
-
exist_ok=True,
|
|
31
30
|
threadsafe=self.threadsafe,
|
|
32
|
-
)
|
|
31
|
+
)
|
|
33
32
|
|
|
34
33
|
def lazy[T](self, tp: type[T], /) -> Callable[[], Awaitable[T]]:
|
|
35
34
|
awaitable = self.module.aget_lazy_instance(tp, threadsafe=self.threadsafe)
|
|
@@ -83,12 +82,6 @@ class InjectionScopeMiddleware:
|
|
|
83
82
|
threadsafe: bool | None = field(default=None, kw_only=True)
|
|
84
83
|
|
|
85
84
|
async def __call__(self, /, *args: Any, **kwargs: Any) -> MiddlewareResult[Any]:
|
|
86
|
-
async with self._cm: # type: ignore[attr-defined]
|
|
87
|
-
yield
|
|
88
|
-
|
|
89
|
-
@property
|
|
90
|
-
@asynccontextmanager
|
|
91
|
-
async def _cm(self) -> AsyncIterator[None]:
|
|
92
85
|
async with AsyncExitStack() as stack:
|
|
93
86
|
try:
|
|
94
87
|
await stack.enter_async_context(
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import TYPE_CHECKING, Any, AsyncContextManager, ContextManager
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING: # pragma: no cover
|
|
7
|
+
from cq import MiddlewareResult
|
|
8
|
+
|
|
9
|
+
__all__ = ("AsyncContextManagerMiddleware", "ContextManagerMiddleware")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass(repr=False, eq=False, frozen=True, slots=True)
|
|
13
|
+
class AsyncContextManagerMiddleware:
|
|
14
|
+
context: AsyncContextManager[Any]
|
|
15
|
+
|
|
16
|
+
async def __call__(self, /, *args: Any, **kwargs: Any) -> MiddlewareResult[Any]:
|
|
17
|
+
async with self.context:
|
|
18
|
+
yield
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass(repr=False, eq=False, frozen=True, slots=True)
|
|
22
|
+
class ContextManagerMiddleware:
|
|
23
|
+
context: ContextManager[Any]
|
|
24
|
+
|
|
25
|
+
async def __call__(self, /, *args: Any, **kwargs: Any) -> MiddlewareResult[Any]:
|
|
26
|
+
with self.context:
|
|
27
|
+
yield
|
|
@@ -2,12 +2,12 @@ cq/__init__.py,sha256=efZeCSuvUsBJ00dVLEs3DcNd1fdPhgYhH4xkCQVpO9Y,1963
|
|
|
2
2
|
cq/exceptions.py,sha256=lmIpWDbPPwdS9bAAKxUvampA1KKmB706wWaB2mKZyPc,111
|
|
3
3
|
cq/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
cq/_core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
-
cq/_core/cq.py,sha256=
|
|
6
|
-
cq/_core/di.py,sha256=
|
|
5
|
+
cq/_core/cq.py,sha256=YDYcLMHAIlyCJ1NSm0sR_JnsVJ0wYZ1ndkUE0sArzic,2304
|
|
6
|
+
cq/_core/di.py,sha256=vqHvDTvXNRH8C_we1fKMicvQ6SuGM8aedHQaMrP6Llo,3369
|
|
7
7
|
cq/_core/handler.py,sha256=2lc5B1WS3NOm_lJakOF9aTlto5Hh9cvJl6dppYknWzs,7276
|
|
8
8
|
cq/_core/message.py,sha256=HpoYHstxRTWoUw_FuqDkytzyvK0Mb0U96Bz15ZEBd70,278
|
|
9
9
|
cq/_core/middleware.py,sha256=RX_bLoqBL2p_dyCQs-jeozGVe6s7L9O4hDiwFxEprDY,3686
|
|
10
|
-
cq/_core/pipetools.py,sha256=
|
|
10
|
+
cq/_core/pipetools.py,sha256=o2FqEfnIaoFwfY0maxI2rg6bK4vlBJK3KdHvQL4vPk0,1583
|
|
11
11
|
cq/_core/pump.py,sha256=Kxrmdex1Yf2YhbA45e7n7Whwdp9fAi_npaAND8_cSrc,1749
|
|
12
12
|
cq/_core/related_events.py,sha256=vPltQdmQjnfb3eOB2lO6dxqjJEsGOjOyCNj7_2ehNAk,1389
|
|
13
13
|
cq/_core/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -17,17 +17,16 @@ cq/_core/dispatchers/abc.py,sha256=E_amQ95TvcmicNRcUzftvRcqI0-Un-qqpm4XcepLyg0,1
|
|
|
17
17
|
cq/_core/dispatchers/bus.py,sha256=eOhZXZxBOFS5Emx4h7a5ulgT5hWtyQtwxTIU5RqHRGw,3305
|
|
18
18
|
cq/_core/dispatchers/lazy.py,sha256=byvwDZBBoTpnd40MCSTWNQ2ubyK_ib-pjxYoumqfSaY,715
|
|
19
19
|
cq/_core/dispatchers/pipe.py,sha256=gdq0ihPlBgcAVSQrR0ovcFVdQhUB6Ejj6Lg5K76L2Rg,9723
|
|
20
|
-
cq/_core/middlewares/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
|
-
cq/_core/middlewares/scope.py,sha256=4LFH8uccow6LJa-1Eu8HiSjbz69D_T0dQJ7SpdPhLUA,405
|
|
22
20
|
cq/_core/queues/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
23
21
|
cq/_core/queues/abc.py,sha256=zXb9Nre9gaKPCbQbkUErnJGRn14UP1K7GpR_N7DFhkE,690
|
|
24
22
|
cq/_core/queues/memory.py,sha256=VIZN3jIcnE7ij4NKhCJu6jEfvSgk5_EadtQejsxR2Lo,1811
|
|
25
23
|
cq/ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
26
|
-
cq/ext/injection.py,sha256=
|
|
24
|
+
cq/ext/injection.py,sha256=6up8NqcUYwMjbGdxV653Ai4Bb49OckF6vIhocwz_bjk,3113
|
|
27
25
|
cq/middlewares/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
26
|
+
cq/middlewares/contextlib.py,sha256=8fXNI6Y3pOjLbDz8JRHb1KXU8cbPWksUV6qhcRCvd5s,821
|
|
28
27
|
cq/middlewares/exc.py,sha256=ecAMoksj6B4osySSZ9g_cBR35_tiABQdpII-Drxkz44,1604
|
|
29
28
|
cq/middlewares/retry.py,sha256=L6X_Wa2TZ0IYNXmi8oexTXQyM_lkjJt5Ew4D-2VzwBY,957
|
|
30
|
-
python_cq-0.
|
|
31
|
-
python_cq-0.
|
|
32
|
-
python_cq-0.
|
|
33
|
-
python_cq-0.
|
|
29
|
+
python_cq-0.22.0.dist-info/METADATA,sha256=XtA7nmM9n-qTSqojG1-YVSA3mGY87YTjC0ykeiYNQ90,4507
|
|
30
|
+
python_cq-0.22.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
31
|
+
python_cq-0.22.0.dist-info/licenses/LICENSE,sha256=oC77BOa9kaaQni5rW-Z-ytz3E5h4EVg248BHg9UFgyg,1063
|
|
32
|
+
python_cq-0.22.0.dist-info/RECORD,,
|
cq/_core/middlewares/__init__.py
DELETED
|
File without changes
|
cq/_core/middlewares/scope.py
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
from dataclasses import dataclass
|
|
2
|
-
from typing import Any
|
|
3
|
-
|
|
4
|
-
from cq._core.di import DIAdapter
|
|
5
|
-
from cq._core.middleware import MiddlewareResult
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
@dataclass(repr=False, eq=False, frozen=True, slots=True)
|
|
9
|
-
class CommandDispatchScopeMiddleware:
|
|
10
|
-
di: DIAdapter
|
|
11
|
-
|
|
12
|
-
async def __call__(self, /, *args: Any, **kwargs: Any) -> MiddlewareResult[Any]:
|
|
13
|
-
async with self.di.command_scope():
|
|
14
|
-
yield
|
|
File without changes
|
|
File without changes
|