mirror of
https://github.com/nonebot/nonebot2.git
synced 2025-09-07 04:26:45 +00:00
✨ Feature: 依赖注入支持 Generic TypeVar 和 Matcher 重载 (#2089)
This commit is contained in:
@ -317,7 +317,17 @@ class MatcherParam(Param):
|
||||
|
||||
# param type is Matcher(s) or subclass(es) of Matcher or None
|
||||
if generic_check_issubclass(param.annotation, Matcher):
|
||||
return cls(Required)
|
||||
checker: Optional[ModelField] = None
|
||||
if param.annotation is not Matcher:
|
||||
checker = ModelField(
|
||||
name=param.name,
|
||||
type_=param.annotation,
|
||||
class_validators=None,
|
||||
model_config=CustomConfig,
|
||||
default=None,
|
||||
required=True,
|
||||
)
|
||||
return cls(Required, checker=checker)
|
||||
# legacy: param is named "matcher" and has no type annotation
|
||||
elif param.annotation == param.empty and param.name == "matcher":
|
||||
return cls(Required)
|
||||
@ -325,6 +335,10 @@ class MatcherParam(Param):
|
||||
async def _solve(self, matcher: "Matcher", **kwargs: Any) -> Any:
|
||||
return matcher
|
||||
|
||||
async def _check(self, matcher: "Matcher", **kwargs: Any) -> Any:
|
||||
if checker := self.extra.get("checker", None):
|
||||
check_field_type(checker, matcher)
|
||||
|
||||
|
||||
class ArgInner:
|
||||
def __init__(
|
||||
|
@ -58,8 +58,12 @@ def generic_check_issubclass(
|
||||
) -> bool:
|
||||
"""检查 cls 是否是 class_or_tuple 中的一个类型子类。
|
||||
|
||||
特别的,如果 cls 是 `typing.Union` 或 `types.UnionType` 类型,
|
||||
则会检查其中的所有类型是否是 class_or_tuple 中一个类型的子类或 None。
|
||||
特别的:
|
||||
|
||||
- 如果 cls 是 `typing.Union` 或 `types.UnionType` 类型,
|
||||
则会检查其中的所有类型是否是 class_or_tuple 中一个类型的子类或 None。
|
||||
- 如果 cls 是 `typing.TypeVar` 类型,
|
||||
则会检查其 `__bound__` 或 `__constraints__` 是否是 class_or_tuple 中一个类型的子类或 None。
|
||||
"""
|
||||
try:
|
||||
return issubclass(cls, class_or_tuple)
|
||||
@ -70,8 +74,18 @@ def generic_check_issubclass(
|
||||
is_none_type(type_) or generic_check_issubclass(type_, class_or_tuple)
|
||||
for type_ in get_args(cls)
|
||||
)
|
||||
# ensure generic List, Dict can be checked
|
||||
elif origin:
|
||||
return issubclass(origin, class_or_tuple)
|
||||
elif isinstance(cls, TypeVar):
|
||||
if cls.__constraints__:
|
||||
return all(
|
||||
is_none_type(type_)
|
||||
or generic_check_issubclass(type_, class_or_tuple)
|
||||
for type_ in cls.__constraints__
|
||||
)
|
||||
elif cls.__bound__:
|
||||
return generic_check_issubclass(cls.__bound__, class_or_tuple)
|
||||
return False
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user