Skip to content

Commit ba7eb23

Browse files
authored
refactor: Now analyze type hints with type-analyzer
1 parent 3e75f29 commit ba7eb23

File tree

3 files changed

+177
-143
lines changed

3 files changed

+177
-143
lines changed

cq/_core/handler.py

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
from collections.abc import Awaitable, Callable, Iterator
44
from dataclasses import dataclass, field
55
from functools import partial
6-
from inspect import Parameter, getmro, isclass
6+
from inspect import Parameter, isclass
77
from inspect import signature as inspect_signature
88
from typing import TYPE_CHECKING, Any, Protocol, Self, overload, runtime_checkable
99

1010
import injection
11+
from type_analyzer import MatchingTypesConfig, iter_matching_types, matching_types
1112

1213
type HandlerType[**P, T] = type[Handler[P, T]]
1314
type 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+
155174
def _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)

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ classifiers = [
5050
dependencies = [
5151
"anyio",
5252
"python-injection",
53+
"type-analyzer",
5354
]
5455

5556
[project.urls]

0 commit comments

Comments
 (0)