Skip to content

Commit f7902bb

Browse files
authored
🐛 Fix: log level 配置项无法使用 int 类型配置 (#3732)
1 parent 34d3f66 commit f7902bb

File tree

5 files changed

+28
-5
lines changed

5 files changed

+28
-5
lines changed

nonebot/compat.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
from collections.abc import Generator
1313
from dataclasses import dataclass, is_dataclass
14-
from functools import cached_property
14+
from functools import cached_property, wraps
1515
from typing import (
1616
TYPE_CHECKING,
1717
Annotated,
@@ -25,13 +25,14 @@
2525
Union,
2626
overload,
2727
)
28-
from typing_extensions import Self, get_args, get_origin, is_typeddict
28+
from typing_extensions import ParamSpec, Self, get_args, get_origin, is_typeddict
2929

3030
from pydantic import VERSION, BaseModel
3131

3232
from nonebot.typing import origin_is_annotated
3333

3434
T = TypeVar("T")
35+
P = ParamSpec("P")
3536

3637
PYDANTIC_V2 = int(VERSION.split(".", 1)[0]) == 2
3738

@@ -49,6 +50,7 @@ def __get_validators__(cls) -> Generator[Callable[..., Any], None, None]: ...
4950
"PYDANTIC_V2",
5051
"ConfigDict",
5152
"FieldInfo",
53+
"LegacyUnionField",
5254
"ModelField",
5355
"PydanticUndefined",
5456
"PydanticUndefinedType",
@@ -71,7 +73,7 @@ def __get_validators__(cls) -> Generator[Callable[..., Any], None, None]: ...
7173

7274

7375
if PYDANTIC_V2: # pragma: pydantic-v2
74-
from pydantic import GetCoreSchemaHandler
76+
from pydantic import Field, GetCoreSchemaHandler
7577
from pydantic import TypeAdapter as TypeAdapter
7678
from pydantic import field_validator as field_validator
7779
from pydantic import model_validator as model_validator
@@ -94,6 +96,17 @@ def __get_validators__(cls) -> Generator[Callable[..., Any], None, None]: ...
9496
DEFAULT_CONFIG = ConfigDict(extra="allow", arbitrary_types_allowed=True)
9597
"""Default config for validations"""
9698

99+
def _get_legacy_union_field(func: Callable[P, T]) -> Callable[P, T]:
100+
@wraps(func)
101+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
102+
kwargs["union_mode"] = "left_to_right"
103+
return func(*args, **kwargs)
104+
105+
return wrapper
106+
107+
LegacyUnionField = _get_legacy_union_field(Field)
108+
LegacyUnionField.__doc__ = "Mark field to use legacy left to right union mode"
109+
97110
class FieldInfo(BaseFieldInfo): # pyright: ignore[reportGeneralTypeIssues]
98111
"""FieldInfo class with extra property for compatibility with pydantic v1"""
99112

@@ -292,6 +305,8 @@ class DEFAULT_CONFIG(ConfigDict):
292305
extra = Extra.allow
293306
arbitrary_types_allowed = True
294307

308+
from pydantic.fields import Field as LegacyUnionField
309+
295310
class FieldInfo(BaseFieldInfo):
296311
def __init__(self, default: Any = PydanticUndefined, **kwargs: Any):
297312
# preprocess default value to make it compatible with pydantic v2

nonebot/config.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
from nonebot.compat import (
3131
PYDANTIC_V2,
3232
ConfigDict,
33+
LegacyUnionField,
3334
ModelField,
3435
PydanticUndefined,
3536
PydanticUndefinedType,
@@ -424,7 +425,7 @@ class Config(BaseSettings):
424425
"""NoneBot {ref}`nonebot.drivers.ReverseDriver` 服务端监听的 IP/主机名。"""
425426
port: int = Field(default=8080, ge=1, le=65535)
426427
"""NoneBot {ref}`nonebot.drivers.ReverseDriver` 服务端监听的端口。"""
427-
log_level: Union[int, str] = "INFO"
428+
log_level: Union[int, str] = LegacyUnionField(default="INFO")
428429
"""NoneBot 日志输出等级,可以为 `int` 类型等级或等级名称。
429430
430431
参考 [记录日志](https://nonebot.dev/docs/appendices/log),[loguru 日志等级](https://loguru.readthedocs.io/en/stable/api/logger.html#levels)。

tests/.env.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
SIMPLE=simple
2+
int_str=123
23
COMPLEX='
34
[1, 2, 3]
45
'

tests/test_config.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from pydantic import BaseModel, Field
44
import pytest
55

6-
from nonebot.compat import PYDANTIC_V2
6+
from nonebot.compat import PYDANTIC_V2, LegacyUnionField
77
from nonebot.config import DOTENV_TYPE, BaseSettings, SettingsConfig, SettingsError
88

99

@@ -32,6 +32,7 @@ class Config( # pyright: ignore[reportIncompatibleVariableOverride]
3232
env_nested_delimiter = "__"
3333

3434
simple: str = ""
35+
int_str: Union[int, str] = LegacyUnionField(default="")
3536
complex: list[int] = Field(default=[1])
3637
complex_none: Optional[list[int]] = None
3738
complex_union: Union[int, list[int]] = 1
@@ -62,6 +63,8 @@ def test_config_with_env():
6263
config = Example(_env_file=(".env", ".env.example"))
6364
assert config.simple == "simple"
6465

66+
assert config.int_str == 123
67+
6568
assert config.complex == [1, 2, 3]
6669

6770
assert config.complex_none is None

tests/uv.lock

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)