From 9305fe7875230cba0f4c31ef3b3e737bbac339af Mon Sep 17 00:00:00 2001 From: Ju4tCode <42488585+yanyongyu@users.noreply.github.com> Date: Fri, 27 Oct 2023 23:09:32 +0800 Subject: [PATCH] =?UTF-8?q?:bug:=20=E4=BF=AE=E5=A4=8D=E4=BE=9D=E8=B5=96?= =?UTF-8?q?=E6=B3=A8=E5=85=A5=E5=AF=B9=20Literal=20=E6=A3=80=E6=9F=A5?= =?UTF-8?q?=E6=8A=A5=E9=94=99=20(#2433)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nonebot/utils.py | 13 +++++++++++-- tests/test_utils.py | 5 ++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/nonebot/utils.py b/nonebot/utils.py index b4eb9aba..984662aa 100644 --- a/nonebot/utils.py +++ b/nonebot/utils.py @@ -31,7 +31,7 @@ from typing import ( overload, ) -from pydantic.typing import is_union, is_none_type +from pydantic.typing import is_union, is_none_type, is_literal_type, all_literal_values from nonebot.log import logger @@ -75,9 +75,18 @@ def generic_check_issubclass( is_none_type(type_) or generic_check_issubclass(type_, class_or_tuple) for type_ in get_args(cls) ) + elif is_literal_type(cls): + return all( + is_none_type(value) or isinstance(value, class_or_tuple) + for value in all_literal_values(cls) + ) # ensure generic List, Dict can be checked elif origin: - return issubclass(origin, class_or_tuple) + # avoid class check error (typing.Final, typing.ClassVar, etc...) + try: + return issubclass(origin, class_or_tuple) + except TypeError: + return False elif isinstance(cls, TypeVar): if cls.__constraints__: return all( diff --git a/tests/test_utils.py b/tests/test_utils.py index fbcdeaff..7db3f7b5 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,5 +1,5 @@ import json -from typing import Dict, List, Union, TypeVar +from typing import Dict, List, Union, Literal, TypeVar, ClassVar from utils import FakeMessage, FakeMessageSegment from nonebot.utils import ( @@ -24,8 +24,11 @@ def test_generic_check_issubclass(): assert generic_check_issubclass(int, (int, float)) assert not generic_check_issubclass(str, (int, float)) assert generic_check_issubclass(Union[int, float, None], (int, float)) + assert generic_check_issubclass(Literal[1, 2, 3], int) + assert not generic_check_issubclass(Literal[1, 2, "3"], int) assert generic_check_issubclass(List[int], list) assert generic_check_issubclass(Dict[str, int], dict) + assert not generic_check_issubclass(ClassVar[int], int) assert generic_check_issubclass(TypeVar("T", int, float), (int, float)) assert generic_check_issubclass(TypeVar("T", bound=int), (int, float))