mirror of
https://github.com/nonebot/nonebot2.git
synced 2024-11-27 18:45:05 +08:00
✨ Feature: 优化 pydantic 兼容函数 model_dump
和 type_validate_json
(#2579)
Co-authored-by: Ju4tCode <42488585+yanyongyu@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
fbb8320a25
commit
a830346545
@ -16,6 +16,7 @@ from typing import (
|
|||||||
Dict,
|
Dict,
|
||||||
List,
|
List,
|
||||||
Type,
|
Type,
|
||||||
|
Union,
|
||||||
TypeVar,
|
TypeVar,
|
||||||
Callable,
|
Callable,
|
||||||
Optional,
|
Optional,
|
||||||
@ -54,6 +55,7 @@ __all__ = (
|
|||||||
"model_config",
|
"model_config",
|
||||||
"model_dump",
|
"model_dump",
|
||||||
"type_validate_python",
|
"type_validate_python",
|
||||||
|
"type_validate_json",
|
||||||
"custom_validation",
|
"custom_validation",
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -195,13 +197,27 @@ if PYDANTIC_V2: # pragma: pydantic-v2
|
|||||||
include: Optional[Set[str]] = None,
|
include: Optional[Set[str]] = None,
|
||||||
exclude: Optional[Set[str]] = None,
|
exclude: Optional[Set[str]] = None,
|
||||||
by_alias: bool = False,
|
by_alias: bool = False,
|
||||||
|
exclude_unset: bool = False,
|
||||||
|
exclude_defaults: bool = False,
|
||||||
|
exclude_none: bool = False,
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
return model.model_dump(include=include, exclude=exclude, by_alias=by_alias)
|
return model.model_dump(
|
||||||
|
include=include,
|
||||||
|
exclude=exclude,
|
||||||
|
by_alias=by_alias,
|
||||||
|
exclude_unset=exclude_unset,
|
||||||
|
exclude_defaults=exclude_defaults,
|
||||||
|
exclude_none=exclude_none,
|
||||||
|
)
|
||||||
|
|
||||||
def type_validate_python(type_: Type[T], data: Any) -> T:
|
def type_validate_python(type_: Type[T], data: Any) -> T:
|
||||||
"""Validate data with given type."""
|
"""Validate data with given type."""
|
||||||
return TypeAdapter(type_).validate_python(data)
|
return TypeAdapter(type_).validate_python(data)
|
||||||
|
|
||||||
|
def type_validate_json(type_: Type[T], data: Union[str, bytes]) -> T:
|
||||||
|
"""Validate JSON with given type."""
|
||||||
|
return TypeAdapter(type_).validate_json(data)
|
||||||
|
|
||||||
def __get_pydantic_core_schema__(
|
def __get_pydantic_core_schema__(
|
||||||
cls: Type["_CustomValidationClass"],
|
cls: Type["_CustomValidationClass"],
|
||||||
source_type: Any,
|
source_type: Any,
|
||||||
@ -226,7 +242,7 @@ if PYDANTIC_V2: # pragma: pydantic-v2
|
|||||||
|
|
||||||
else: # pragma: pydantic-v1
|
else: # pragma: pydantic-v1
|
||||||
from pydantic import Extra
|
from pydantic import Extra
|
||||||
from pydantic import parse_obj_as
|
from pydantic import parse_obj_as, parse_raw_as
|
||||||
from pydantic import BaseConfig as PydanticConfig
|
from pydantic import BaseConfig as PydanticConfig
|
||||||
from pydantic.fields import FieldInfo as BaseFieldInfo
|
from pydantic.fields import FieldInfo as BaseFieldInfo
|
||||||
from pydantic.fields import ModelField as BaseModelField
|
from pydantic.fields import ModelField as BaseModelField
|
||||||
@ -341,13 +357,27 @@ else: # pragma: pydantic-v1
|
|||||||
include: Optional[Set[str]] = None,
|
include: Optional[Set[str]] = None,
|
||||||
exclude: Optional[Set[str]] = None,
|
exclude: Optional[Set[str]] = None,
|
||||||
by_alias: bool = False,
|
by_alias: bool = False,
|
||||||
|
exclude_unset: bool = False,
|
||||||
|
exclude_defaults: bool = False,
|
||||||
|
exclude_none: bool = False,
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
return model.dict(include=include, exclude=exclude, by_alias=by_alias)
|
return model.dict(
|
||||||
|
include=include,
|
||||||
|
exclude=exclude,
|
||||||
|
by_alias=by_alias,
|
||||||
|
exclude_unset=exclude_unset,
|
||||||
|
exclude_defaults=exclude_defaults,
|
||||||
|
exclude_none=exclude_none,
|
||||||
|
)
|
||||||
|
|
||||||
def type_validate_python(type_: Type[T], data: Any) -> T:
|
def type_validate_python(type_: Type[T], data: Any) -> T:
|
||||||
"""Validate data with given type."""
|
"""Validate data with given type."""
|
||||||
return parse_obj_as(type_, data)
|
return parse_obj_as(type_, data)
|
||||||
|
|
||||||
|
def type_validate_json(type_: Type[T], data: Union[str, bytes]) -> T:
|
||||||
|
"""Validate JSON with given type."""
|
||||||
|
return parse_raw_as(type_, data)
|
||||||
|
|
||||||
def custom_validation(class_: Type["CVC"]) -> Type["CVC"]:
|
def custom_validation(class_: Type["CVC"]) -> Type["CVC"]:
|
||||||
"""Do nothing in pydantic v1"""
|
"""Do nothing in pydantic v1"""
|
||||||
return class_
|
return class_
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from typing import Any
|
from typing import Any, Optional
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
@ -11,6 +11,7 @@ from nonebot.compat import (
|
|||||||
PydanticUndefined,
|
PydanticUndefined,
|
||||||
model_dump,
|
model_dump,
|
||||||
custom_validation,
|
custom_validation,
|
||||||
|
type_validate_json,
|
||||||
type_validate_python,
|
type_validate_python,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -66,3 +67,26 @@ async def test_custom_validation():
|
|||||||
|
|
||||||
assert type_validate_python(TestModel, {"test": 1}) == TestModel(test=1)
|
assert type_validate_python(TestModel, {"test": 1}) == TestModel(test=1)
|
||||||
assert called == [1, 2]
|
assert called == [1, 2]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_validate_json():
|
||||||
|
class TestModel(BaseModel):
|
||||||
|
test1: int
|
||||||
|
test2: str
|
||||||
|
test3: bool
|
||||||
|
test4: dict
|
||||||
|
test5: list
|
||||||
|
test6: Optional[int]
|
||||||
|
|
||||||
|
assert type_validate_json(
|
||||||
|
TestModel,
|
||||||
|
"{"
|
||||||
|
' "test1": 1,'
|
||||||
|
' "test2": "2",'
|
||||||
|
' "test3": true,'
|
||||||
|
' "test4": {},'
|
||||||
|
' "test5": [],'
|
||||||
|
' "test6": null'
|
||||||
|
"}",
|
||||||
|
) == TestModel(test1=1, test2="2", test3=True, test4={}, test5=[], test6=None)
|
||||||
|
Loading…
Reference in New Issue
Block a user