Feature: 优化 pydantic 兼容函数 model_dumptype_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:
MingxuanGame 2024-02-17 23:18:00 +08:00 committed by GitHub
parent fbb8320a25
commit a830346545
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 58 additions and 4 deletions

View File

@ -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_

View File

@ -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)