python-cq 0.25.2__py3-none-any.whl → 0.26.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/__init__.py CHANGED
@@ -7,7 +7,12 @@ from ._core.message import (
7
7
  Query,
8
8
  QueryBus,
9
9
  )
10
- from ._core.middleware import Middleware, MiddlewareResult, resolve_handler_source
10
+ from ._core.middleware import (
11
+ Middleware,
12
+ MiddlewareResult,
13
+ resolve_handler_source,
14
+ through_middlewares,
15
+ )
11
16
  from ._core.queuing.pump import Pump
12
17
  from ._core.queuing.queues.abc import Consumer, Delivery, Producer, Queue
13
18
  from ._core.queuing.queues.memory import MemoryQueue
@@ -54,6 +59,7 @@ __all__ = (
54
59
  "new_query_bus",
55
60
  "query_handler",
56
61
  "resolve_handler_source",
62
+ "through_middlewares",
57
63
  )
58
64
 
59
65
 
cq/_core/middleware.py CHANGED
@@ -1,5 +1,6 @@
1
1
  from collections.abc import AsyncGenerator, Awaitable, Callable
2
2
  from dataclasses import dataclass, field
3
+ from functools import wraps
3
4
  from inspect import isasyncgenfunction
4
5
  from typing import Any, Concatenate, Self, TypeGuard
5
6
 
@@ -23,6 +24,13 @@ class MiddlewareGroup[**P, T]:
23
24
  init=False,
24
25
  )
25
26
 
27
+ def __call__(self, wrapped: Callable[P, Awaitable[T]]) -> Callable[P, Awaitable[T]]:
28
+ @wraps(wrapped)
29
+ async def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
30
+ return await self.invoke(wrapped, *args, **kwargs)
31
+
32
+ return wrapper
33
+
26
34
  def add(self, *middlewares: Middleware[P, T]) -> Self:
27
35
  classic_middlewares = reversed(
28
36
  tuple(self.__normalize(middleware) for middleware in middlewares)
@@ -48,6 +56,10 @@ class MiddlewareGroup[**P, T]:
48
56
 
49
57
  return handler
50
58
 
59
+ @classmethod
60
+ def from_middlewares(cls, *middlewares: Middleware[P, T]) -> Self:
61
+ return cls().add(*middlewares)
62
+
51
63
  @staticmethod
52
64
  def __normalize(middleware: Middleware[P, T]) -> ClassicMiddleware[P, T]:
53
65
  if _is_gen_middleware(middleware):
@@ -56,6 +68,14 @@ class MiddlewareGroup[**P, T]:
56
68
  return middleware # type: ignore[return-value]
57
69
 
58
70
 
71
+ def through_middlewares[**P, T](
72
+ first_middleware: Middleware[P, T],
73
+ /,
74
+ *middlewares: Middleware[P, T],
75
+ ) -> MiddlewareGroup[P, T]:
76
+ return MiddlewareGroup.from_middlewares(first_middleware, *middlewares)
77
+
78
+
59
79
  @dataclass(repr=False, eq=False, frozen=True, slots=True)
60
80
  class _BoundMiddleware[**P, T]:
61
81
  call_next: Callable[P, Awaitable[T]]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: python-cq
3
- Version: 0.25.2
3
+ Version: 0.26.0
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,9 @@
1
- cq/__init__.py,sha256=cIQ_uYKh4vIM_hRt2TCIMpyA35hybQfXqX52QwFpeZk,2011
1
+ cq/__init__.py,sha256=4hCNk_2bwYt-VS2VdyNoPO-tSxWYB8IuB1eAveCI1x0,2080
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
5
  cq/_core/message.py,sha256=uyFgiFCm3kVhWFzJ2gBtWNub_cgfCdyXXSJirBW05OQ,286
6
- cq/_core/middleware.py,sha256=cckYp7gTsCFH76-DnT2yOTv8QPYH2IlGWtpmDuDcupo,3706
6
+ cq/_core/middleware.py,sha256=1Nb-4YtO1jR196s9185PReQQx1gi90zLF3KDdmBs3JU,4352
7
7
  cq/_core/related_events.py,sha256=msJ0J-ydtxJ5My8qPLhMIFuCCvzbB_WBDD0CTwOEC-0,1369
8
8
  cq/_core/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  cq/_core/common/typing.py,sha256=xtXsqzyATZ0LTVfjB-J4sB6dPKHKrpXqd1bZIkwVljA,504
@@ -29,7 +29,7 @@ cq/middlewares/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
29
  cq/middlewares/contextlib.py,sha256=_kwbXteGADGuzD-o2pPoPWOeTKiXcPCNuDmpG-f-YnY,875
30
30
  cq/middlewares/exc.py,sha256=ecAMoksj6B4osySSZ9g_cBR35_tiABQdpII-Drxkz44,1604
31
31
  cq/middlewares/retry.py,sha256=WkpMYfAVUR8bnZ1NejX8zeKuPtfCIJlDEj8r4ZkqGBU,1054
32
- python_cq-0.25.2.dist-info/METADATA,sha256=vFbIJUJ02nNrYB8Wx4CbZwwC5OSvPm4Y-tel5ytHeY0,5032
33
- python_cq-0.25.2.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
34
- python_cq-0.25.2.dist-info/licenses/LICENSE,sha256=oC77BOa9kaaQni5rW-Z-ytz3E5h4EVg248BHg9UFgyg,1063
35
- python_cq-0.25.2.dist-info/RECORD,,
32
+ python_cq-0.26.0.dist-info/METADATA,sha256=PVlImM4K3EMJkcl9m7i82lE_XwDODtN_Fkj5NNDDktE,5032
33
+ python_cq-0.26.0.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
34
+ python_cq-0.26.0.dist-info/licenses/LICENSE,sha256=oC77BOa9kaaQni5rW-Z-ytz3E5h4EVg248BHg9UFgyg,1063
35
+ python_cq-0.26.0.dist-info/RECORD,,