33from collections .abc import Awaitable , Callable , Iterator
44from dataclasses import dataclass , field
55from functools import partial
6- from inspect import Parameter , getmro , isclass
6+ from inspect import Parameter , isclass
77from inspect import signature as inspect_signature
88from typing import TYPE_CHECKING , Any , Protocol , Self , overload , runtime_checkable
99
1010import injection
11+ from type_analyzer import MatchingTypesConfig , iter_matching_types , matching_types
1112
1213type HandlerType [** P , T ] = type [Handler [P , T ]]
1314type HandlerFactory [** P , T ] = Callable [..., Awaitable [Handler [P , T ]]]
@@ -49,12 +50,14 @@ def handlers_from(
4950 self ,
5051 input_type : type [I ],
5152 ) -> Iterator [Callable [[I ], Awaitable [O ]]]:
52- for it in getmro (input_type ):
53- for factory in self .__factories .get (it , ()):
53+ for key_type in _iter_key_types (input_type ):
54+ for factory in self .__factories .get (key_type , ()):
5455 yield _make_handle_function (factory )
5556
5657 def subscribe (self , input_type : type [I ], factory : HandlerFactory [[I ], O ]) -> Self :
57- self .__factories [input_type ].append (factory )
58+ for key_type in _build_key_types (input_type ):
59+ self .__factories [key_type ].append (factory )
60+
5861 return self
5962
6063
@@ -69,18 +72,20 @@ def handlers_from(
6972 self ,
7073 input_type : type [I ],
7174 ) -> Iterator [Callable [[I ], Awaitable [O ]]]:
72- for it in getmro (input_type ):
73- factory = self .__factories .get (it , None )
75+ for key_type in _iter_key_types (input_type ):
76+ factory = self .__factories .get (key_type , None )
7477 if factory is not None :
7578 yield _make_handle_function (factory )
7679
7780 def subscribe (self , input_type : type [I ], factory : HandlerFactory [[I ], O ]) -> Self :
78- if input_type in self .__factories :
79- raise RuntimeError (
80- f"A handler is already registered for the input type: `{ input_type } `."
81- )
81+ for key_type in _build_key_types (input_type ):
82+ if key_type in self .__factories :
83+ raise RuntimeError (
84+ f"A handler is already registered for the input type: `{ key_type } `."
85+ )
86+
87+ self .__factories [key_type ] = factory
8288
83- self .__factories [input_type ] = factory
8489 return self
8590
8691
@@ -152,6 +157,20 @@ def __decorator(
152157 return wrapped
153158
154159
160+ def _build_key_types (input_type : Any ) -> tuple [Any , ...]:
161+ config = MatchingTypesConfig (ignore_none = True )
162+ return matching_types (input_type , config )
163+
164+
165+ def _iter_key_types (input_type : Any ) -> Iterator [Any ]:
166+ config = MatchingTypesConfig (
167+ with_bases = True ,
168+ with_origin = True ,
169+ with_type_alias_value = True ,
170+ )
171+ return iter_matching_types (input_type , config )
172+
173+
155174def _resolve_input_type [I , O ](handler_type : HandlerType [[I ], O ]) -> type [I ]:
156175 fake_method = handler_type .handle .__get__ (NotImplemented , handler_type )
157176 signature = inspect_signature (fake_method , eval_str = True )
0 commit comments