@@ -21,74 +21,96 @@ class Handler[**P, T](Protocol):
2121 __slots__ = ()
2222
2323 @abstractmethod
24- async def handle (self , * args : P .args , ** kwargs : P .kwargs ) -> T :
24+ async def handle (self , / , * args : P .args , ** kwargs : P .kwargs ) -> T :
2525 raise NotImplementedError
2626
2727
28+ @dataclass (repr = False , eq = False , frozen = True , slots = True )
29+ class HandleFunction [** P , T ]:
30+ handler_factory : HandlerFactory [P , T ]
31+ handler_type : HandlerType [P , T ] | None = field (default = None )
32+ fail_silently : bool = field (default = False )
33+
34+ async def __call__ (self , / , * args : P .args , ** kwargs : P .kwargs ) -> T :
35+ handler = await self .handler_factory ()
36+ return await handler .handle (* args , ** kwargs )
37+
38+
2839@runtime_checkable
2940class HandlerRegistry [I , O ](Protocol ):
3041 __slots__ = ()
3142
3243 @abstractmethod
33- def handlers_from (
34- self ,
35- input_type : type [I ],
36- ) -> Iterator [Callable [[I ], Awaitable [O ]]]:
44+ def handlers_from (self , input_type : type [I ]) -> Iterator [HandleFunction [[I ], O ]]:
3745 raise NotImplementedError
3846
3947 @abstractmethod
40- def subscribe (self , input_type : type [I ], factory : HandlerFactory [[I ], O ]) -> Self :
48+ def subscribe (
49+ self ,
50+ input_type : type [I ],
51+ handler_factory : HandlerFactory [[I ], O ],
52+ handler_type : HandlerType [[I ], O ] | None = ...,
53+ fail_silently : bool = ...,
54+ ) -> Self :
4155 raise NotImplementedError
4256
4357
4458@dataclass (repr = False , eq = False , frozen = True , slots = True )
4559class MultipleHandlerRegistry [I , O ](HandlerRegistry [I , O ]):
46- __factories : dict [type [I ], list [HandlerFactory [[I ], O ]]] = field (
60+ __values : dict [type [I ], list [HandleFunction [[I ], O ]]] = field (
4761 default_factory = partial (defaultdict , list ),
4862 init = False ,
4963 )
5064
51- def handlers_from (
65+ def handlers_from (self , input_type : type [I ]) -> Iterator [HandleFunction [[I ], O ]]:
66+ for key_type in _iter_key_types (input_type ):
67+ yield from self .__values .get (key_type , ())
68+
69+ def subscribe (
5270 self ,
5371 input_type : type [I ],
54- ) -> Iterator [Callable [[I ], Awaitable [O ]]]:
55- for key_type in _iter_key_types (input_type ):
56- for factory in self .__factories .get (key_type , ()):
57- yield _make_handle_function (factory )
72+ handler_factory : HandlerFactory [[I ], O ],
73+ handler_type : HandlerType [[I ], O ] | None = None ,
74+ fail_silently : bool = False ,
75+ ) -> Self :
76+ function = HandleFunction (handler_factory , handler_type , fail_silently )
5877
59- def subscribe (self , input_type : type [I ], factory : HandlerFactory [[I ], O ]) -> Self :
6078 for key_type in _build_key_types (input_type ):
61- self .__factories [key_type ].append (factory )
79+ self .__values [key_type ].append (function )
6280
6381 return self
6482
6583
6684@dataclass (repr = False , eq = False , frozen = True , slots = True )
6785class SingleHandlerRegistry [I , O ](HandlerRegistry [I , O ]):
68- __factories : dict [type [I ], HandlerFactory [[I ], O ]] = field (
86+ __values : dict [type [I ], HandleFunction [[I ], O ]] = field (
6987 default_factory = dict ,
7088 init = False ,
7189 )
7290
73- def handlers_from (
74- self ,
75- input_type : type [I ],
76- ) -> Iterator [Callable [[I ], Awaitable [O ]]]:
91+ def handlers_from (self , input_type : type [I ]) -> Iterator [HandleFunction [[I ], O ]]:
7792 for key_type in _iter_key_types (input_type ):
78- factory = self .__factories .get (key_type , None )
79- if factory is not None :
80- yield _make_handle_function ( factory )
93+ function = self .__values .get (key_type , None )
94+ if function is not None :
95+ yield function
8196
82- def subscribe (self , input_type : type [I ], factory : HandlerFactory [[I ], O ]) -> Self :
83- entries = {key_type : factory for key_type in _build_key_types (input_type )}
97+ def subscribe (
98+ self ,
99+ input_type : type [I ],
100+ handler_factory : HandlerFactory [[I ], O ],
101+ handler_type : HandlerType [[I ], O ] | None = None ,
102+ fail_silently : bool = False ,
103+ ) -> Self :
104+ function = HandleFunction (handler_factory , handler_type , fail_silently )
105+ entries = {key_type : function for key_type in _build_key_types (input_type )}
84106
85107 for key_type in entries :
86- if key_type in self .__factories :
108+ if key_type in self .__values :
87109 raise RuntimeError (
88110 f"A handler is already registered for the input type: `{ key_type } `."
89111 )
90112
91- self .__factories .update (entries )
113+ self .__values .update (entries )
92114 return self
93115
94116
@@ -105,6 +127,7 @@ def __call__(
105127 input_or_handler_type : type [I ],
106128 / ,
107129 * ,
130+ fail_silently : bool = ...,
108131 threadsafe : bool | None = ...,
109132 ) -> Decorator : ...
110133
@@ -114,6 +137,7 @@ def __call__[T](
114137 input_or_handler_type : T ,
115138 / ,
116139 * ,
140+ fail_silently : bool = ...,
117141 threadsafe : bool | None = ...,
118142 ) -> T : ...
119143
@@ -123,6 +147,7 @@ def __call__(
123147 input_or_handler_type : None = ...,
124148 / ,
125149 * ,
150+ fail_silently : bool = ...,
126151 threadsafe : bool | None = ...,
127152 ) -> Decorator : ...
128153
@@ -131,18 +156,24 @@ def __call__[T](
131156 input_or_handler_type : type [I ] | T | None = None ,
132157 / ,
133158 * ,
159+ fail_silently : bool = False ,
134160 threadsafe : bool | None = None ,
135161 ) -> Any :
136162 if (
137163 input_or_handler_type is not None
138164 and isclass (input_or_handler_type )
139165 and issubclass (input_or_handler_type , Handler )
140166 ):
141- return self .__decorator (input_or_handler_type , threadsafe = threadsafe )
167+ return self .__decorator (
168+ input_or_handler_type ,
169+ fail_silently = fail_silently ,
170+ threadsafe = threadsafe ,
171+ )
142172
143173 return partial (
144174 self .__decorator ,
145175 input_type = input_or_handler_type , # type: ignore[arg-type]
176+ fail_silently = fail_silently ,
146177 threadsafe = threadsafe ,
147178 )
148179
@@ -152,11 +183,12 @@ def __decorator(
152183 / ,
153184 * ,
154185 input_type : type [I ] | None = None ,
186+ fail_silently : bool = False ,
155187 threadsafe : bool | None = None ,
156188 ) -> HandlerType [[I ], O ]:
157189 factory = self .injection_module .make_async_factory (wrapped , threadsafe )
158190 input_type = input_type or _resolve_input_type (wrapped )
159- self .registry .subscribe (input_type , factory )
191+ self .registry .subscribe (input_type , factory , wrapped , fail_silently )
160192 return wrapped
161193
162194
@@ -190,14 +222,3 @@ def _resolve_input_type[I, O](handler_type: HandlerType[[I], O]) -> type[I]:
190222 f"Unable to resolve input type for handler `{ handler_type } `, "
191223 "`handle` method must have a type annotation for its first parameter."
192224 )
193-
194-
195- def _make_handle_function [I , O ](
196- factory : HandlerFactory [[I ], O ],
197- ) -> Callable [[I ], Awaitable [O ]]:
198- return partial (__handle , factory = factory )
199-
200-
201- async def __handle [I , O ](input_value : I , * , factory : HandlerFactory [[I ], O ]) -> O :
202- handler = await factory ()
203- return await handler .handle (input_value )
0 commit comments