mirror of
https://github.com/nonebot/nonebot2.git
synced 2025-10-14 14:46:58 +00:00
🐛 Fix: 兼容 pydantic v2.12 FieldInfo
改动 (#3722)
This commit is contained in:
@@ -55,7 +55,6 @@ __all__ = (
|
||||
"Required",
|
||||
"TypeAdapter",
|
||||
"custom_validation",
|
||||
"extract_field_info",
|
||||
"field_validator",
|
||||
"model_config",
|
||||
"model_dump",
|
||||
@@ -95,7 +94,7 @@ if PYDANTIC_V2: # pragma: pydantic-v2
|
||||
DEFAULT_CONFIG = ConfigDict(extra="allow", arbitrary_types_allowed=True)
|
||||
"""Default config for validations"""
|
||||
|
||||
class FieldInfo(BaseFieldInfo):
|
||||
class FieldInfo(BaseFieldInfo): # pyright: ignore[reportGeneralTypeIssues]
|
||||
"""FieldInfo class with extra property for compatibility with pydantic v1"""
|
||||
|
||||
# make default can be positional argument
|
||||
@@ -115,6 +114,20 @@ if PYDANTIC_V2: # pragma: pydantic-v2
|
||||
slots = super().__slots__
|
||||
return {k: v for k, v in self._attributes_set.items() if k not in slots}
|
||||
|
||||
@classmethod
|
||||
def _inherit_construct(
|
||||
cls, field_info: Optional[BaseFieldInfo] = None, **kwargs: Any
|
||||
) -> Self:
|
||||
init_kwargs = {}
|
||||
if field_info:
|
||||
init_kwargs.update(field_info._attributes_set)
|
||||
init_kwargs.update(kwargs)
|
||||
|
||||
instance = cls(**init_kwargs)
|
||||
if field_info:
|
||||
instance.metadata = field_info.metadata
|
||||
return instance
|
||||
|
||||
@dataclass
|
||||
class ModelField:
|
||||
"""ModelField class for compatibility with pydantic v1"""
|
||||
@@ -187,13 +200,6 @@ if PYDANTIC_V2: # pragma: pydantic-v2
|
||||
"""Validate the value pass to the field."""
|
||||
return self.type_adapter.validate_python(value)
|
||||
|
||||
def extract_field_info(field_info: BaseFieldInfo) -> dict[str, Any]:
|
||||
"""Get FieldInfo init kwargs from a FieldInfo instance."""
|
||||
|
||||
kwargs = field_info._attributes_set.copy()
|
||||
kwargs["annotation"] = field_info.rebuild_annotation()
|
||||
return kwargs
|
||||
|
||||
def model_fields(model: type[BaseModel]) -> list[ModelField]:
|
||||
"""Get field list of a model."""
|
||||
|
||||
@@ -201,7 +207,7 @@ if PYDANTIC_V2: # pragma: pydantic-v2
|
||||
ModelField._construct(
|
||||
name=name,
|
||||
annotation=field_info.rebuild_annotation(),
|
||||
field_info=FieldInfo(**extract_field_info(field_info)),
|
||||
field_info=FieldInfo._inherit_construct(field_info),
|
||||
)
|
||||
for name, field_info in model.model_fields.items()
|
||||
]
|
||||
@@ -294,6 +300,22 @@ else: # pragma: pydantic-v1
|
||||
default = PydanticUndefined
|
||||
super().__init__(default, **kwargs)
|
||||
|
||||
@classmethod
|
||||
def _inherit_construct(
|
||||
cls, field_info: Optional[BaseFieldInfo] = None, **kwargs: Any
|
||||
):
|
||||
if field_info:
|
||||
init_kwargs = {
|
||||
s: getattr(field_info, s)
|
||||
for s in field_info.__slots__
|
||||
if s != "extra"
|
||||
}
|
||||
init_kwargs.update(field_info.extra)
|
||||
else:
|
||||
init_kwargs = {}
|
||||
init_kwargs.update(kwargs)
|
||||
return cls(**init_kwargs)
|
||||
|
||||
class ModelField(BaseModelField):
|
||||
@classmethod
|
||||
def _construct(cls, name: str, annotation: Any, field_info: FieldInfo) -> Self:
|
||||
@@ -364,15 +386,6 @@ else: # pragma: pydantic-v1
|
||||
def validate_json(self, value: Union[str, bytes]) -> T:
|
||||
return type_validate_json(self.type, value)
|
||||
|
||||
def extract_field_info(field_info: BaseFieldInfo) -> dict[str, Any]:
|
||||
"""Get FieldInfo init kwargs from a FieldInfo instance."""
|
||||
|
||||
kwargs = {
|
||||
s: getattr(field_info, s) for s in field_info.__slots__ if s != "extra"
|
||||
}
|
||||
kwargs.update(field_info.extra)
|
||||
return kwargs
|
||||
|
||||
@overload
|
||||
def field_validator(
|
||||
field: str,
|
||||
@@ -419,9 +432,7 @@ else: # pragma: pydantic-v1
|
||||
ModelField._construct(
|
||||
name=model_field.name,
|
||||
annotation=model_field.annotation,
|
||||
field_info=FieldInfo(
|
||||
**extract_field_info(model_field.field_info),
|
||||
),
|
||||
field_info=FieldInfo._inherit_construct(model_field.field_info),
|
||||
)
|
||||
for model_field in model.__fields__.values()
|
||||
]
|
||||
|
@@ -17,7 +17,7 @@ import anyio
|
||||
from exceptiongroup import BaseExceptionGroup, catch
|
||||
from pydantic.fields import FieldInfo as PydanticFieldInfo
|
||||
|
||||
from nonebot.compat import FieldInfo, ModelField, PydanticUndefined, extract_field_info
|
||||
from nonebot.compat import FieldInfo, ModelField, PydanticUndefined
|
||||
from nonebot.consts import ARG_KEY, REJECT_PROMPT_RESULT_KEY
|
||||
from nonebot.dependencies import Dependent, Param
|
||||
from nonebot.dependencies.utils import check_field_type
|
||||
@@ -194,15 +194,12 @@ class DependParam(Param):
|
||||
use_cache: bool,
|
||||
validate: Union[bool, PydanticFieldInfo],
|
||||
) -> Self:
|
||||
kwargs = {}
|
||||
if isinstance(validate, PydanticFieldInfo):
|
||||
kwargs.update(extract_field_info(validate))
|
||||
|
||||
kwargs["validate"] = bool(validate)
|
||||
kwargs["dependent"] = sub_dependent
|
||||
kwargs["use_cache"] = use_cache
|
||||
|
||||
return cls(**kwargs)
|
||||
return cls._inherit_construct(
|
||||
validate if isinstance(validate, PydanticFieldInfo) else None,
|
||||
dependent=sub_dependent,
|
||||
use_cache=use_cache,
|
||||
validate=bool(validate),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
@override
|
||||
|
Reference in New Issue
Block a user