python-cq 0.7.2__tar.gz → 0.7.4__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.7.2 → python_cq-0.7.4}/PKG-INFO +2 -2
- {python_cq-0.7.2 → python_cq-0.7.4}/cq/_core/handler.py +21 -9
- {python_cq-0.7.2 → python_cq-0.7.4}/cq/_core/message.py +6 -5
- {python_cq-0.7.2 → python_cq-0.7.4}/cq/middlewares/scope.py +4 -3
- {python_cq-0.7.2 → python_cq-0.7.4}/pyproject.toml +2 -2
- {python_cq-0.7.2 → python_cq-0.7.4}/.gitignore +0 -0
- {python_cq-0.7.2 → python_cq-0.7.4}/LICENSE +0 -0
- {python_cq-0.7.2 → python_cq-0.7.4}/README.md +0 -0
- {python_cq-0.7.2 → python_cq-0.7.4}/cq/__init__.py +0 -0
- {python_cq-0.7.2 → python_cq-0.7.4}/cq/_core/__init__.py +0 -0
- {python_cq-0.7.2 → python_cq-0.7.4}/cq/_core/dispatcher/__init__.py +0 -0
- {python_cq-0.7.2 → python_cq-0.7.4}/cq/_core/dispatcher/base.py +0 -0
- {python_cq-0.7.2 → python_cq-0.7.4}/cq/_core/dispatcher/bus.py +0 -0
- {python_cq-0.7.2 → python_cq-0.7.4}/cq/_core/dispatcher/pipe.py +0 -0
- {python_cq-0.7.2 → python_cq-0.7.4}/cq/_core/middleware.py +0 -0
- {python_cq-0.7.2 → python_cq-0.7.4}/cq/_core/related_events.py +0 -0
- {python_cq-0.7.2 → python_cq-0.7.4}/cq/_core/scope.py +0 -0
- {python_cq-0.7.2 → python_cq-0.7.4}/cq/exceptions.py +0 -0
- {python_cq-0.7.2 → python_cq-0.7.4}/cq/middlewares/__init__.py +0 -0
- {python_cq-0.7.2 → python_cq-0.7.4}/cq/middlewares/retry.py +0 -0
- {python_cq-0.7.2 → python_cq-0.7.4}/cq/py.typed +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-cq
|
|
3
|
-
Version: 0.7.
|
|
4
|
-
Summary: Lightweight CQRS library.
|
|
3
|
+
Version: 0.7.4
|
|
4
|
+
Summary: Lightweight CQRS library for async Python projects.
|
|
5
5
|
Project-URL: Repository, https://github.com/100nm/python-cq
|
|
6
6
|
Author: remimd
|
|
7
7
|
License-Expression: MIT
|
|
@@ -94,6 +94,8 @@ class HandlerDecorator[I, O]:
|
|
|
94
94
|
self,
|
|
95
95
|
input_or_handler_type: type[I],
|
|
96
96
|
/,
|
|
97
|
+
*,
|
|
98
|
+
threadsafe: bool | None = ...,
|
|
97
99
|
) -> Callable[[HandlerType[[I], O]], HandlerType[[I], O]]: ...
|
|
98
100
|
|
|
99
101
|
@overload
|
|
@@ -101,6 +103,8 @@ class HandlerDecorator[I, O]:
|
|
|
101
103
|
self,
|
|
102
104
|
input_or_handler_type: HandlerType[[I], O],
|
|
103
105
|
/,
|
|
106
|
+
*,
|
|
107
|
+
threadsafe: bool | None = ...,
|
|
104
108
|
) -> HandlerType[[I], O]: ...
|
|
105
109
|
|
|
106
110
|
@overload
|
|
@@ -108,31 +112,39 @@ class HandlerDecorator[I, O]:
|
|
|
108
112
|
self,
|
|
109
113
|
input_or_handler_type: None = ...,
|
|
110
114
|
/,
|
|
115
|
+
*,
|
|
116
|
+
threadsafe: bool | None = ...,
|
|
111
117
|
) -> Callable[[HandlerType[[I], O]], HandlerType[[I], O]]: ...
|
|
112
118
|
|
|
113
119
|
def __call__(
|
|
114
120
|
self,
|
|
115
121
|
input_or_handler_type: type[I] | HandlerType[[I], O] | None = None,
|
|
116
122
|
/,
|
|
123
|
+
*,
|
|
124
|
+
threadsafe: bool | None = None,
|
|
117
125
|
) -> Any:
|
|
118
|
-
if
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
input_or_handler_type,
|
|
123
|
-
Handler,
|
|
126
|
+
if (
|
|
127
|
+
input_or_handler_type is not None
|
|
128
|
+
and isclass(input_or_handler_type)
|
|
129
|
+
and issubclass(input_or_handler_type, Handler)
|
|
124
130
|
):
|
|
125
|
-
return self.__decorator(input_or_handler_type)
|
|
131
|
+
return self.__decorator(input_or_handler_type, threadsafe=threadsafe)
|
|
126
132
|
|
|
127
|
-
return partial(
|
|
133
|
+
return partial(
|
|
134
|
+
self.__decorator,
|
|
135
|
+
input_type=input_or_handler_type, # type: ignore[arg-type]
|
|
136
|
+
threadsafe=threadsafe,
|
|
137
|
+
)
|
|
128
138
|
|
|
129
139
|
def __decorator(
|
|
130
140
|
self,
|
|
131
141
|
wrapped: HandlerType[[I], O],
|
|
142
|
+
/,
|
|
132
143
|
*,
|
|
133
144
|
input_type: type[I] | None = None,
|
|
145
|
+
threadsafe: bool | None = None,
|
|
134
146
|
) -> HandlerType[[I], O]:
|
|
135
|
-
factory = self.injection_module.make_async_factory(wrapped)
|
|
147
|
+
factory = self.injection_module.make_async_factory(wrapped, threadsafe)
|
|
136
148
|
input_type = input_type or _resolve_input_type(wrapped)
|
|
137
149
|
self.manager.subscribe(input_type, factory)
|
|
138
150
|
return wrapped
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Any
|
|
1
|
+
from typing import Any, Final
|
|
2
2
|
|
|
3
3
|
import injection
|
|
4
4
|
|
|
@@ -22,23 +22,24 @@ type QueryBus[T] = Bus[Query, T]
|
|
|
22
22
|
AnyCommandBus = CommandBus[Any]
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
command_handler: HandlerDecorator[Command, Any] = HandlerDecorator(
|
|
25
|
+
command_handler: Final[HandlerDecorator[Command, Any]] = HandlerDecorator(
|
|
26
26
|
SingleHandlerManager(),
|
|
27
27
|
)
|
|
28
|
-
event_handler: HandlerDecorator[Event, None] = HandlerDecorator(
|
|
28
|
+
event_handler: Final[HandlerDecorator[Event, None]] = HandlerDecorator(
|
|
29
29
|
MultipleHandlerManager(),
|
|
30
30
|
)
|
|
31
|
-
query_handler: HandlerDecorator[Query, Any] = HandlerDecorator(
|
|
31
|
+
query_handler: Final[HandlerDecorator[Query, Any]] = HandlerDecorator(
|
|
32
32
|
SingleHandlerManager(),
|
|
33
33
|
)
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
@injection.injectable(inject=False, mode="fallback")
|
|
37
|
-
def new_command_bus() -> CommandBus: # type: ignore[type-arg]
|
|
37
|
+
def new_command_bus(*, threadsafe: bool | None = None) -> CommandBus: # type: ignore[type-arg]
|
|
38
38
|
bus = SimpleBus(command_handler.manager)
|
|
39
39
|
transaction_scope_middleware = InjectionScopeMiddleware(
|
|
40
40
|
CQScope.TRANSACTION,
|
|
41
41
|
exist_ok=True,
|
|
42
|
+
threadsafe=threadsafe,
|
|
42
43
|
)
|
|
43
44
|
bus.add_middlewares(transaction_scope_middleware)
|
|
44
45
|
return bus
|
|
@@ -17,16 +17,17 @@ __all__ = ("InjectionScopeMiddleware",)
|
|
|
17
17
|
class InjectionScopeMiddleware:
|
|
18
18
|
scope_name: str
|
|
19
19
|
exist_ok: bool = field(default=False, kw_only=True)
|
|
20
|
+
threadsafe: bool | None = field(default=None, kw_only=True)
|
|
20
21
|
|
|
21
22
|
async def __call__(self, *args: Any, **kwargs: Any) -> MiddlewareResult[Any]:
|
|
22
23
|
async with AsyncExitStack() as stack:
|
|
24
|
+
cm = adefine_scope(self.scope_name, threadsafe=self.threadsafe)
|
|
23
25
|
try:
|
|
24
|
-
await stack.enter_async_context(
|
|
25
|
-
adefine_scope(self.scope_name),
|
|
26
|
-
)
|
|
26
|
+
await stack.enter_async_context(cm)
|
|
27
27
|
|
|
28
28
|
except ScopeAlreadyDefinedError:
|
|
29
29
|
if not self.exist_ok:
|
|
30
30
|
raise
|
|
31
31
|
|
|
32
|
+
del cm
|
|
32
33
|
yield
|
|
@@ -21,8 +21,8 @@ test = [
|
|
|
21
21
|
|
|
22
22
|
[project]
|
|
23
23
|
name = "python-cq"
|
|
24
|
-
version = "0.7.
|
|
25
|
-
description = "Lightweight CQRS library."
|
|
24
|
+
version = "0.7.4"
|
|
25
|
+
description = "Lightweight CQRS library for async Python projects."
|
|
26
26
|
license = "MIT"
|
|
27
27
|
license-files = ["LICENSE"]
|
|
28
28
|
readme = "README.md"
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|