python-cq 0.2.0__tar.gz → 0.2.2__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.2.0 → python_cq-0.2.2}/PKG-INFO +1 -1
- {python_cq-0.2.0 → python_cq-0.2.2}/cq/__init__.py +14 -6
- {python_cq-0.2.0 → python_cq-0.2.2}/cq/_core/dispatcher/base.py +5 -8
- {python_cq-0.2.0 → python_cq-0.2.2}/cq/_core/dispatcher/bus.py +3 -8
- {python_cq-0.2.0 → python_cq-0.2.2}/cq/_core/dispatcher/pipe.py +14 -2
- python_cq-0.2.2/cq/_core/message.py +51 -0
- {python_cq-0.2.0 → python_cq-0.2.2}/cq/_core/middleware.py +5 -1
- python_cq-0.2.2/cq/exceptions.py +7 -0
- {python_cq-0.2.0 → python_cq-0.2.2}/cq/middlewares/retry.py +2 -0
- {python_cq-0.2.0 → python_cq-0.2.2}/pyproject.toml +1 -1
- python_cq-0.2.0/cq/_core/command.py +0 -22
- python_cq-0.2.0/cq/_core/event.py +0 -20
- python_cq-0.2.0/cq/_core/query.py +0 -21
- {python_cq-0.2.0 → python_cq-0.2.2}/README.md +0 -0
- {python_cq-0.2.0 → python_cq-0.2.2}/cq/_core/__init__.py +0 -0
- {python_cq-0.2.0 → python_cq-0.2.2}/cq/_core/dispatcher/__init__.py +0 -0
- {python_cq-0.2.0 → python_cq-0.2.2}/cq/_core/dto.py +0 -0
- {python_cq-0.2.0 → python_cq-0.2.2}/cq/middlewares/__init__.py +0 -0
- {python_cq-0.2.0 → python_cq-0.2.2}/cq/py.typed +0 -0
|
@@ -1,16 +1,23 @@
|
|
|
1
|
-
from ._core.
|
|
1
|
+
from ._core.dispatcher.bus import Bus
|
|
2
|
+
from ._core.dispatcher.pipe import Pipe
|
|
3
|
+
from ._core.dto import DTO
|
|
4
|
+
from ._core.message import (
|
|
2
5
|
AnyCommandBus,
|
|
3
6
|
Command,
|
|
4
7
|
CommandBus,
|
|
8
|
+
Event,
|
|
9
|
+
EventBus,
|
|
10
|
+
Message,
|
|
11
|
+
Query,
|
|
12
|
+
QueryBus,
|
|
5
13
|
command_handler,
|
|
14
|
+
event_handler,
|
|
6
15
|
find_command_bus,
|
|
16
|
+
find_event_bus,
|
|
17
|
+
find_query_bus,
|
|
18
|
+
query_handler,
|
|
7
19
|
)
|
|
8
|
-
from ._core.dispatcher.bus import Bus
|
|
9
|
-
from ._core.dispatcher.pipe import Pipe
|
|
10
|
-
from ._core.dto import DTO
|
|
11
|
-
from ._core.event import Event, EventBus, event_handler, find_event_bus
|
|
12
20
|
from ._core.middleware import Middleware, MiddlewareResult
|
|
13
|
-
from ._core.query import Query, QueryBus, find_query_bus, query_handler
|
|
14
21
|
|
|
15
22
|
__all__ = (
|
|
16
23
|
"AnyCommandBus",
|
|
@@ -20,6 +27,7 @@ __all__ = (
|
|
|
20
27
|
"DTO",
|
|
21
28
|
"Event",
|
|
22
29
|
"EventBus",
|
|
30
|
+
"Message",
|
|
23
31
|
"Middleware",
|
|
24
32
|
"MiddlewareResult",
|
|
25
33
|
"Pipe",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
from abc import ABC, abstractmethod
|
|
3
|
-
from collections.abc import Awaitable
|
|
4
|
-
from typing import
|
|
3
|
+
from collections.abc import Awaitable, Callable
|
|
4
|
+
from typing import Protocol, Self, runtime_checkable
|
|
5
5
|
|
|
6
6
|
from cq._core.middleware import Middleware, MiddlewareGroup
|
|
7
7
|
|
|
@@ -15,7 +15,7 @@ class Dispatcher[I, O](Protocol):
|
|
|
15
15
|
raise NotImplementedError
|
|
16
16
|
|
|
17
17
|
@abstractmethod
|
|
18
|
-
def dispatch_no_wait(self,
|
|
18
|
+
def dispatch_no_wait(self, *input_values: I) -> None:
|
|
19
19
|
raise NotImplementedError
|
|
20
20
|
|
|
21
21
|
@abstractmethod
|
|
@@ -31,12 +31,9 @@ class BaseDispatcher[I, O](Dispatcher[I, O], ABC):
|
|
|
31
31
|
def __init__(self) -> None:
|
|
32
32
|
self.__middleware_group = MiddlewareGroup()
|
|
33
33
|
|
|
34
|
-
def dispatch_no_wait(self,
|
|
34
|
+
def dispatch_no_wait(self, *input_values: I) -> None:
|
|
35
35
|
asyncio.gather(
|
|
36
|
-
*(
|
|
37
|
-
self.dispatch(input_value)
|
|
38
|
-
for input_value in (first_input_value, *input_values)
|
|
39
|
-
),
|
|
36
|
+
*(self.dispatch(input_value) for input_value in input_values),
|
|
40
37
|
return_exceptions=True,
|
|
41
38
|
)
|
|
42
39
|
|
|
@@ -40,13 +40,8 @@ class SubscriberDecorator[I, O]:
|
|
|
40
40
|
bus_type: BusType[I, O] | TypeAliasType | GenericAlias
|
|
41
41
|
injection_module: injection.Module = field(default_factory=injection.mod)
|
|
42
42
|
|
|
43
|
-
def __call__[
|
|
44
|
-
|
|
45
|
-
first_input_type: type[I],
|
|
46
|
-
/,
|
|
47
|
-
*input_types: type[I],
|
|
48
|
-
) -> Callable[[T], T]:
|
|
49
|
-
def decorator(wrapped: T) -> T:
|
|
43
|
+
def __call__(self, first_input_type: type[I], /, *input_types: type[I]): # type: ignore[no-untyped-def]
|
|
44
|
+
def decorator(wrapped): # type: ignore[no-untyped-def]
|
|
50
45
|
if not isclass(wrapped) or not issubclass(wrapped, Handler):
|
|
51
46
|
raise TypeError(f"`{wrapped}` isn't a valid handler.")
|
|
52
47
|
|
|
@@ -56,7 +51,7 @@ class SubscriberDecorator[I, O]:
|
|
|
56
51
|
for input_type in (first_input_type, *input_types):
|
|
57
52
|
bus.subscribe(input_type, factory)
|
|
58
53
|
|
|
59
|
-
return wrapped
|
|
54
|
+
return wrapped
|
|
60
55
|
|
|
61
56
|
return decorator
|
|
62
57
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
from collections.abc import Callable
|
|
1
|
+
from collections.abc import Awaitable, Callable
|
|
2
2
|
from dataclasses import dataclass, field
|
|
3
|
-
from typing import Any,
|
|
3
|
+
from typing import Any, Self
|
|
4
4
|
|
|
5
5
|
from cq._core.dispatcher.base import BaseDispatcher, Dispatcher
|
|
6
6
|
|
|
@@ -38,6 +38,18 @@ class Pipe[I, O](BaseDispatcher[I, O]):
|
|
|
38
38
|
|
|
39
39
|
return decorator(wrapped) if wrapped else decorator
|
|
40
40
|
|
|
41
|
+
def add_static_step[T](
|
|
42
|
+
self,
|
|
43
|
+
input_value: T,
|
|
44
|
+
*,
|
|
45
|
+
dispatcher: Dispatcher[T, Any] | None = None,
|
|
46
|
+
) -> Self:
|
|
47
|
+
@self.step(dispatcher=dispatcher)
|
|
48
|
+
async def converter(_: Any) -> T:
|
|
49
|
+
return input_value
|
|
50
|
+
|
|
51
|
+
return self
|
|
52
|
+
|
|
41
53
|
async def dispatch(self, input_value: I, /) -> O:
|
|
42
54
|
return await self._invoke_with_middlewares(self.__execute, input_value)
|
|
43
55
|
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from abc import ABC
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
import injection
|
|
5
|
+
|
|
6
|
+
from cq._core.dispatcher.bus import Bus, SimpleBus, SubscriberDecorator, TaskBus
|
|
7
|
+
from cq._core.dto import DTO
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Message(DTO, ABC):
|
|
11
|
+
__slots__ = ()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Command(Message, ABC):
|
|
15
|
+
__slots__ = ()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Event(Message, ABC):
|
|
19
|
+
__slots__ = ()
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Query(Message, ABC):
|
|
23
|
+
__slots__ = ()
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
type CommandBus[T] = Bus[Command, T]
|
|
27
|
+
type EventBus = Bus[Event, None]
|
|
28
|
+
type QueryBus[T] = Bus[Query, T]
|
|
29
|
+
|
|
30
|
+
AnyCommandBus = CommandBus[Any]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
command_handler: SubscriberDecorator[Command, Any] = SubscriberDecorator(CommandBus)
|
|
34
|
+
event_handler: SubscriberDecorator[Event, None] = SubscriberDecorator(EventBus)
|
|
35
|
+
query_handler: SubscriberDecorator[Query, Any] = SubscriberDecorator(QueryBus)
|
|
36
|
+
|
|
37
|
+
injection.set_constant(SimpleBus(), CommandBus, alias=True)
|
|
38
|
+
injection.set_constant(TaskBus(), EventBus, alias=True)
|
|
39
|
+
injection.set_constant(SimpleBus(), QueryBus, alias=True)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def find_command_bus[T]() -> CommandBus[T]:
|
|
43
|
+
return injection.find_instance(CommandBus)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def find_event_bus() -> EventBus:
|
|
47
|
+
return injection.find_instance(EventBus)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def find_query_bus[T]() -> QueryBus[T]:
|
|
51
|
+
return injection.find_instance(QueryBus)
|
|
@@ -2,6 +2,8 @@ from collections.abc import AsyncGenerator, Awaitable, Callable, Iterator
|
|
|
2
2
|
from dataclasses import dataclass, field
|
|
3
3
|
from typing import Self
|
|
4
4
|
|
|
5
|
+
from cq.exceptions import MiddlewareError
|
|
6
|
+
|
|
5
7
|
type MiddlewareResult[T] = AsyncGenerator[None, T]
|
|
6
8
|
type Middleware[**P, T] = Callable[P, MiddlewareResult[T]]
|
|
7
9
|
|
|
@@ -47,7 +49,9 @@ class MiddlewareGroup[**P, T]:
|
|
|
47
49
|
await generator.athrow(exc)
|
|
48
50
|
else:
|
|
49
51
|
await generator.asend(value)
|
|
50
|
-
|
|
52
|
+
raise MiddlewareError(
|
|
53
|
+
f"Too many `yield` keywords in `{middleware}`."
|
|
54
|
+
)
|
|
51
55
|
|
|
52
56
|
except StopAsyncIteration:
|
|
53
57
|
...
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
from abc import ABC
|
|
2
|
-
from typing import Any
|
|
3
|
-
|
|
4
|
-
import injection
|
|
5
|
-
|
|
6
|
-
from cq._core.dispatcher.bus import Bus, SimpleBus, SubscriberDecorator
|
|
7
|
-
from cq._core.dto import DTO
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class Command(DTO, ABC):
|
|
11
|
-
__slots__ = ()
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
type CommandBus[T] = Bus[Command, T]
|
|
15
|
-
AnyCommandBus = CommandBus[Any]
|
|
16
|
-
command_handler: SubscriberDecorator[Command, Any] = SubscriberDecorator(CommandBus)
|
|
17
|
-
|
|
18
|
-
injection.set_constant(SimpleBus(), CommandBus, alias=True)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
def find_command_bus[T]() -> CommandBus[T]:
|
|
22
|
-
return injection.find_instance(CommandBus)
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
from abc import ABC
|
|
2
|
-
|
|
3
|
-
import injection
|
|
4
|
-
|
|
5
|
-
from cq._core.dispatcher.bus import Bus, SubscriberDecorator, TaskBus
|
|
6
|
-
from cq._core.dto import DTO
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class Event(DTO, ABC):
|
|
10
|
-
__slots__ = ()
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
type EventBus = Bus[Event, None]
|
|
14
|
-
event_handler: SubscriberDecorator[Event, None] = SubscriberDecorator(EventBus)
|
|
15
|
-
|
|
16
|
-
injection.set_constant(TaskBus(), EventBus, alias=True)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def find_event_bus() -> EventBus:
|
|
20
|
-
return injection.find_instance(EventBus)
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
from abc import ABC
|
|
2
|
-
from typing import Any
|
|
3
|
-
|
|
4
|
-
import injection
|
|
5
|
-
|
|
6
|
-
from cq._core.dispatcher.bus import Bus, SimpleBus, SubscriberDecorator
|
|
7
|
-
from cq._core.dto import DTO
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class Query(DTO, ABC):
|
|
11
|
-
__slots__ = ()
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
type QueryBus[T] = Bus[Query, T]
|
|
15
|
-
query_handler: SubscriberDecorator[Query, Any] = SubscriberDecorator(QueryBus)
|
|
16
|
-
|
|
17
|
-
injection.set_constant(SimpleBus(), QueryBus, alias=True)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def find_query_bus[T]() -> QueryBus[T]:
|
|
21
|
-
return injection.find_instance(QueryBus)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|