python-cq 0.15.0__tar.gz → 0.15.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.15.0 → python_cq-0.15.1}/PKG-INFO +1 -1
- {python_cq-0.15.0 → python_cq-0.15.1}/cq/__init__.py +2 -1
- {python_cq-0.15.0 → python_cq-0.15.1}/cq/_core/dispatcher/bus.py +13 -3
- {python_cq-0.15.0 → python_cq-0.15.1}/cq/_core/handler.py +16 -7
- {python_cq-0.15.0 → python_cq-0.15.1}/cq/_core/middleware.py +15 -1
- {python_cq-0.15.0 → python_cq-0.15.1}/pyproject.toml +1 -1
- {python_cq-0.15.0 → python_cq-0.15.1}/.gitignore +0 -0
- {python_cq-0.15.0 → python_cq-0.15.1}/LICENSE +0 -0
- {python_cq-0.15.0 → python_cq-0.15.1}/cq/_core/__init__.py +0 -0
- {python_cq-0.15.0 → python_cq-0.15.1}/cq/_core/common/__init__.py +0 -0
- {python_cq-0.15.0 → python_cq-0.15.1}/cq/_core/common/typing.py +0 -0
- {python_cq-0.15.0 → python_cq-0.15.1}/cq/_core/dispatcher/__init__.py +0 -0
- {python_cq-0.15.0 → python_cq-0.15.1}/cq/_core/dispatcher/base.py +0 -0
- {python_cq-0.15.0 → python_cq-0.15.1}/cq/_core/dispatcher/lazy.py +0 -0
- {python_cq-0.15.0 → python_cq-0.15.1}/cq/_core/dispatcher/pipe.py +0 -0
- {python_cq-0.15.0 → python_cq-0.15.1}/cq/_core/message.py +0 -0
- {python_cq-0.15.0 → python_cq-0.15.1}/cq/_core/pipetools.py +0 -0
- {python_cq-0.15.0 → python_cq-0.15.1}/cq/_core/related_events.py +0 -0
- {python_cq-0.15.0 → python_cq-0.15.1}/cq/_core/scope.py +0 -0
- {python_cq-0.15.0 → python_cq-0.15.1}/cq/exceptions.py +0 -0
- {python_cq-0.15.0 → python_cq-0.15.1}/cq/ext/__init__.py +0 -0
- {python_cq-0.15.0 → python_cq-0.15.1}/cq/ext/fastapi.py +0 -0
- {python_cq-0.15.0 → python_cq-0.15.1}/cq/middlewares/__init__.py +0 -0
- {python_cq-0.15.0 → python_cq-0.15.1}/cq/middlewares/retry.py +0 -0
- {python_cq-0.15.0 → python_cq-0.15.1}/cq/middlewares/scope.py +0 -0
- {python_cq-0.15.0 → python_cq-0.15.1}/cq/py.typed +0 -0
- {python_cq-0.15.0 → python_cq-0.15.1}/docs/index.md +0 -0
|
@@ -17,7 +17,7 @@ from ._core.message import (
|
|
|
17
17
|
new_query_bus,
|
|
18
18
|
query_handler,
|
|
19
19
|
)
|
|
20
|
-
from ._core.middleware import Middleware, MiddlewareResult
|
|
20
|
+
from ._core.middleware import Middleware, MiddlewareResult, resolve_handler_source
|
|
21
21
|
from ._core.pipetools import ContextCommandPipeline
|
|
22
22
|
from ._core.related_events import RelatedEvents
|
|
23
23
|
from ._core.scope import CQScope
|
|
@@ -47,4 +47,5 @@ __all__ = (
|
|
|
47
47
|
"new_event_bus",
|
|
48
48
|
"new_query_bus",
|
|
49
49
|
"query_handler",
|
|
50
|
+
"resolve_handler_source",
|
|
50
51
|
)
|
|
@@ -31,7 +31,12 @@ class Bus[I, O](Dispatcher[I, O], Protocol):
|
|
|
31
31
|
raise NotImplementedError
|
|
32
32
|
|
|
33
33
|
@abstractmethod
|
|
34
|
-
def subscribe(
|
|
34
|
+
def subscribe(
|
|
35
|
+
self,
|
|
36
|
+
input_type: type[I],
|
|
37
|
+
factory: HandlerFactory[[I], O],
|
|
38
|
+
fail_silently: bool = ...,
|
|
39
|
+
) -> Self:
|
|
35
40
|
raise NotImplementedError
|
|
36
41
|
|
|
37
42
|
|
|
@@ -50,8 +55,13 @@ class BaseBus[I, O](BaseDispatcher[I, O], Bus[I, O], ABC):
|
|
|
50
55
|
self.__listeners.extend(listeners)
|
|
51
56
|
return self
|
|
52
57
|
|
|
53
|
-
def subscribe(
|
|
54
|
-
self
|
|
58
|
+
def subscribe(
|
|
59
|
+
self,
|
|
60
|
+
input_type: type[I],
|
|
61
|
+
factory: HandlerFactory[[I], O],
|
|
62
|
+
fail_silently: bool = False,
|
|
63
|
+
) -> Self:
|
|
64
|
+
self.__registry.subscribe(input_type, factory, fail_silently=fail_silently)
|
|
55
65
|
return self
|
|
56
66
|
|
|
57
67
|
def _handlers_from(self, input_type: type[I]) -> Iterator[HandleFunction[[I], O]]:
|
|
@@ -3,7 +3,7 @@ from collections import defaultdict
|
|
|
3
3
|
from collections.abc import Awaitable, Callable, Iterator
|
|
4
4
|
from dataclasses import dataclass, field
|
|
5
5
|
from functools import partial
|
|
6
|
-
from inspect import Parameter, isclass
|
|
6
|
+
from inspect import Parameter, isclass, unwrap
|
|
7
7
|
from inspect import signature as inspect_signature
|
|
8
8
|
from typing import TYPE_CHECKING, Any, Protocol, Self, overload, runtime_checkable
|
|
9
9
|
|
|
@@ -27,14 +27,23 @@ class Handler[**P, T](Protocol):
|
|
|
27
27
|
|
|
28
28
|
@dataclass(repr=False, eq=False, frozen=True, slots=True)
|
|
29
29
|
class HandleFunction[**P, T]:
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
fail_silently: bool
|
|
30
|
+
factory: HandlerFactory[P, T]
|
|
31
|
+
source: HandlerType[P, T] | Any
|
|
32
|
+
fail_silently: bool
|
|
33
33
|
|
|
34
34
|
async def __call__(self, /, *args: P.args, **kwargs: P.kwargs) -> T:
|
|
35
|
-
handler = await self.
|
|
35
|
+
handler = await self.factory()
|
|
36
36
|
return await handler.handle(*args, **kwargs)
|
|
37
37
|
|
|
38
|
+
@classmethod
|
|
39
|
+
def create(
|
|
40
|
+
cls,
|
|
41
|
+
factory: HandlerFactory[P, T],
|
|
42
|
+
source: HandlerType[P, T] | None = None,
|
|
43
|
+
fail_silently: bool = False,
|
|
44
|
+
) -> Self:
|
|
45
|
+
return cls(factory, source or unwrap(factory), fail_silently)
|
|
46
|
+
|
|
38
47
|
|
|
39
48
|
@runtime_checkable
|
|
40
49
|
class HandlerRegistry[I, O](Protocol):
|
|
@@ -73,7 +82,7 @@ class MultipleHandlerRegistry[I, O](HandlerRegistry[I, O]):
|
|
|
73
82
|
handler_type: HandlerType[[I], O] | None = None,
|
|
74
83
|
fail_silently: bool = False,
|
|
75
84
|
) -> Self:
|
|
76
|
-
function = HandleFunction(handler_factory, handler_type, fail_silently)
|
|
85
|
+
function = HandleFunction.create(handler_factory, handler_type, fail_silently)
|
|
77
86
|
|
|
78
87
|
for key_type in _build_key_types(input_type):
|
|
79
88
|
self.__values[key_type].append(function)
|
|
@@ -101,7 +110,7 @@ class SingleHandlerRegistry[I, O](HandlerRegistry[I, O]):
|
|
|
101
110
|
handler_type: HandlerType[[I], O] | None = None,
|
|
102
111
|
fail_silently: bool = False,
|
|
103
112
|
) -> Self:
|
|
104
|
-
function = HandleFunction(handler_factory, handler_type, fail_silently)
|
|
113
|
+
function = HandleFunction.create(handler_factory, handler_type, fail_silently)
|
|
105
114
|
entries = {key_type: function for key_type in _build_key_types(input_type)}
|
|
106
115
|
|
|
107
116
|
for key_type in entries:
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
from collections.abc import AsyncGenerator, Awaitable, Callable
|
|
2
2
|
from dataclasses import dataclass, field
|
|
3
3
|
from inspect import isasyncgenfunction
|
|
4
|
-
from typing import Concatenate, Self, TypeGuard
|
|
4
|
+
from typing import Any, Concatenate, Self, TypeGuard
|
|
5
5
|
|
|
6
|
+
from cq._core.handler import HandleFunction, HandlerType
|
|
6
7
|
from cq.exceptions import MiddlewareError
|
|
7
8
|
|
|
8
9
|
type MiddlewareResult[T] = AsyncGenerator[None, T]
|
|
@@ -63,6 +64,19 @@ class _BoundMiddleware[**P, T]:
|
|
|
63
64
|
return await self.middleware(self.call_next, *args, **kwargs)
|
|
64
65
|
|
|
65
66
|
|
|
67
|
+
def resolve_handler_source[**P, T](
|
|
68
|
+
call_next: Callable[P, Awaitable[T]]
|
|
69
|
+
| _BoundMiddleware[P, T]
|
|
70
|
+
| HandleFunction[P, T],
|
|
71
|
+
/,
|
|
72
|
+
) -> HandlerType[P, T] | Any:
|
|
73
|
+
while True:
|
|
74
|
+
try:
|
|
75
|
+
call_next = call_next.call_next # type: ignore[union-attr]
|
|
76
|
+
except AttributeError:
|
|
77
|
+
return call_next.source # type: ignore[union-attr]
|
|
78
|
+
|
|
79
|
+
|
|
66
80
|
@dataclass(repr=False, eq=False, frozen=True, slots=True)
|
|
67
81
|
class _GeneratorMiddleware[**P, T]:
|
|
68
82
|
middleware: GeneratorMiddleware[P, T]
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|