425 lines
18 KiB
Diff
425 lines
18 KiB
Diff
From 4494c31a4834bdc2301cfa3d94f4bbc62c2774dc Mon Sep 17 00:00:00 2001
|
|
From: Viicos <65306057+Viicos@users.noreply.github.com>
|
|
Date: Wed, 11 Jun 2025 14:52:26 +0200
|
|
Subject: [PATCH] Bump `pydantic-core` to v2.35.1
|
|
|
|
Make use of `ensure_ascii` option
|
|
Update typechecking tests
|
|
Remove core schema validation hook
|
|
---
|
|
docs/api/standard_library_types.md | 2 +-
|
|
docs/why.md | 2 +-
|
|
pydantic/_internal/_core_utils.py | 8 -
|
|
pydantic/_internal/_generate_schema.py | 5 +-
|
|
pydantic/functional_serializers.py | 4 +-
|
|
pydantic/functional_validators.py | 10 +-
|
|
pydantic/main.py | 4 +
|
|
pydantic/type_adapter.py | 3 +
|
|
pydantic/version.py | 2 +-
|
|
pyproject.toml | 4 +-
|
|
tests/typechecking/decorators.py | 79 +++++++--
|
|
12 files changed, 203 insertions(+), 140 deletions(-)
|
|
|
|
Index: pydantic-2.11.7/docs/api/standard_library_types.md
|
|
===================================================================
|
|
--- pydantic-2.11.7.orig/docs/api/standard_library_types.md
|
|
+++ pydantic-2.11.7/docs/api/standard_library_types.md
|
|
@@ -81,7 +81,7 @@ event = Event(dt='2032-04-23T10:20:30.40
|
|
|
|
print(event.model_dump())
|
|
"""
|
|
-{'dt': datetime.datetime(2032, 4, 23, 10, 20, 30, 400000, tzinfo=TzInfo(+02:30))}
|
|
+{'dt': datetime.datetime(2032, 4, 23, 10, 20, 30, 400000, tzinfo=TzInfo(9000))}
|
|
"""
|
|
```
|
|
|
|
Index: pydantic-2.11.7/docs/why.md
|
|
===================================================================
|
|
--- pydantic-2.11.7.orig/docs/why.md
|
|
+++ pydantic-2.11.7/docs/why.md
|
|
@@ -363,7 +363,7 @@ Functional validators and serializers, a
|
|
|
|
|
|
print(Meeting(when='2020-01-01T12:00+01:00'))
|
|
- #> when=datetime.datetime(2020, 1, 1, 12, 0, tzinfo=TzInfo(+01:00))
|
|
+ #> when=datetime.datetime(2020, 1, 1, 12, 0, tzinfo=TzInfo(3600))
|
|
print(Meeting(when='now'))
|
|
#> when=datetime.datetime(2032, 1, 2, 3, 4, 5, 6)
|
|
print(Meeting(when='2020-01-01T12:00'))
|
|
Index: pydantic-2.11.7/pydantic/_internal/_core_utils.py
|
|
===================================================================
|
|
--- pydantic-2.11.7.orig/pydantic/_internal/_core_utils.py
|
|
+++ pydantic-2.11.7/pydantic/_internal/_core_utils.py
|
|
@@ -1,12 +1,10 @@
|
|
from __future__ import annotations
|
|
|
|
import inspect
|
|
-import os
|
|
from collections.abc import Mapping, Sequence
|
|
from typing import TYPE_CHECKING, Any, Union
|
|
|
|
from pydantic_core import CoreSchema, core_schema
|
|
-from pydantic_core import validate_core_schema as _validate_core_schema
|
|
from typing_extensions import TypeGuard, get_args, get_origin
|
|
from typing_inspection import typing_objects
|
|
|
|
@@ -109,12 +107,6 @@ def get_ref(s: core_schema.CoreSchema) -
|
|
return s.get('ref', None)
|
|
|
|
|
|
-def validate_core_schema(schema: CoreSchema) -> CoreSchema:
|
|
- if os.getenv('PYDANTIC_VALIDATE_CORE_SCHEMAS'):
|
|
- return _validate_core_schema(schema)
|
|
- return schema
|
|
-
|
|
-
|
|
def _clean_schema_for_pretty_print(obj: Any, strip_metadata: bool = True) -> Any: # pragma: no cover
|
|
"""A utility function to remove irrelevant information from a core schema."""
|
|
if isinstance(obj, Mapping):
|
|
Index: pydantic-2.11.7/pydantic/_internal/_generate_schema.py
|
|
===================================================================
|
|
--- pydantic-2.11.7.orig/pydantic/_internal/_generate_schema.py
|
|
+++ pydantic-2.11.7/pydantic/_internal/_generate_schema.py
|
|
@@ -70,7 +70,6 @@ from ._core_utils import (
|
|
get_ref,
|
|
get_type_ref,
|
|
is_list_like_schema_with_items_schema,
|
|
- validate_core_schema,
|
|
)
|
|
from ._decorators import (
|
|
Decorator,
|
|
@@ -666,9 +665,7 @@ class GenerateSchema:
|
|
return schema
|
|
|
|
def clean_schema(self, schema: CoreSchema) -> CoreSchema:
|
|
- schema = self.defs.finalize_schema(schema)
|
|
- schema = validate_core_schema(schema)
|
|
- return schema
|
|
+ return self.defs.finalize_schema(schema)
|
|
|
|
def _add_js_function(self, metadata_schema: CoreSchema, js_function: Callable[..., Any]) -> None:
|
|
metadata = metadata_schema.get('metadata', {})
|
|
Index: pydantic-2.11.7/pydantic/functional_serializers.py
|
|
===================================================================
|
|
--- pydantic-2.11.7.orig/pydantic/functional_serializers.py
|
|
+++ pydantic-2.11.7/pydantic/functional_serializers.py
|
|
@@ -300,7 +300,7 @@ def field_serializer(
|
|
if TYPE_CHECKING:
|
|
# The first argument in the following callables represent the `self` type:
|
|
|
|
- ModelPlainSerializerWithInfo: TypeAlias = Callable[[Any, SerializationInfo], Any]
|
|
+ ModelPlainSerializerWithInfo: TypeAlias = Callable[[Any, SerializationInfo[Any]], Any]
|
|
"""A model serializer method with the `info` argument, in `plain` mode."""
|
|
|
|
ModelPlainSerializerWithoutInfo: TypeAlias = Callable[[Any], Any]
|
|
@@ -309,7 +309,7 @@ if TYPE_CHECKING:
|
|
ModelPlainSerializer: TypeAlias = 'ModelPlainSerializerWithInfo | ModelPlainSerializerWithoutInfo'
|
|
"""A model serializer method in `plain` mode."""
|
|
|
|
- ModelWrapSerializerWithInfo: TypeAlias = Callable[[Any, SerializerFunctionWrapHandler, SerializationInfo], Any]
|
|
+ ModelWrapSerializerWithInfo: TypeAlias = Callable[[Any, SerializerFunctionWrapHandler, SerializationInfo[Any]], Any]
|
|
"""A model serializer method with the `info` argument, in `wrap` mode."""
|
|
|
|
ModelWrapSerializerWithoutInfo: TypeAlias = Callable[[Any, SerializerFunctionWrapHandler], Any]
|
|
Index: pydantic-2.11.7/pydantic/functional_validators.py
|
|
===================================================================
|
|
--- pydantic-2.11.7.orig/pydantic/functional_validators.py
|
|
+++ pydantic-2.11.7/pydantic/functional_validators.py
|
|
@@ -332,7 +332,7 @@ if TYPE_CHECKING:
|
|
def __call__(self, cls: Any, value: Any, /) -> Any: ...
|
|
|
|
class _V2ValidatorClsMethod(Protocol):
|
|
- def __call__(self, cls: Any, value: Any, info: _core_schema.ValidationInfo, /) -> Any: ...
|
|
+ def __call__(self, cls: Any, value: Any, info: core_schema.ValidationInfo[Any], /) -> Any: ...
|
|
|
|
class _OnlyValueWrapValidatorClsMethod(Protocol):
|
|
def __call__(self, cls: Any, value: Any, handler: _core_schema.ValidatorFunctionWrapHandler, /) -> Any: ...
|
|
@@ -343,7 +343,7 @@ if TYPE_CHECKING:
|
|
cls: Any,
|
|
value: Any,
|
|
handler: _core_schema.ValidatorFunctionWrapHandler,
|
|
- info: _core_schema.ValidationInfo,
|
|
+ info: core_schema.ValidationInfo[Any],
|
|
/,
|
|
) -> Any: ...
|
|
|
|
@@ -559,7 +559,7 @@ class ModelWrapValidator(Protocol[_Model
|
|
# thus validators _must_ handle all cases
|
|
value: Any,
|
|
handler: ModelWrapValidatorHandler[_ModelType],
|
|
- info: _core_schema.ValidationInfo,
|
|
+ info: core_schema.ValidationInfo[Any],
|
|
/,
|
|
) -> _ModelType: ...
|
|
|
|
@@ -604,7 +604,7 @@ class FreeModelBeforeValidator(Protocol)
|
|
# or anything else that gets passed to validate_python
|
|
# thus validators _must_ handle all cases
|
|
value: Any,
|
|
- info: _core_schema.ValidationInfo,
|
|
+ info: core_schema.ValidationInfo[Any],
|
|
/,
|
|
) -> Any: ...
|
|
|
|
@@ -619,7 +619,7 @@ class ModelBeforeValidator(Protocol):
|
|
# or anything else that gets passed to validate_python
|
|
# thus validators _must_ handle all cases
|
|
value: Any,
|
|
- info: _core_schema.ValidationInfo,
|
|
+ info: core_schema.ValidationInfo[Any],
|
|
/,
|
|
) -> Any: ...
|
|
|
|
@@ -629,7 +629,7 @@ ModelAfterValidatorWithoutInfo = Callabl
|
|
have info argument.
|
|
"""
|
|
|
|
-ModelAfterValidator = Callable[[_ModelType, _core_schema.ValidationInfo], _ModelType]
|
|
+ModelAfterValidator = Callable[[_ModelType, core_schema.ValidationInfo[Any]], _ModelType]
|
|
"""A `@model_validator` decorated function signature. This is used when `mode='after'`."""
|
|
|
|
_AnyModelWrapValidator = Union[ModelWrapValidator[_ModelType], ModelWrapValidatorWithoutInfo[_ModelType]]
|
|
Index: pydantic-2.11.7/pydantic/main.py
|
|
===================================================================
|
|
--- pydantic-2.11.7.orig/pydantic/main.py
|
|
+++ pydantic-2.11.7/pydantic/main.py
|
|
@@ -480,6 +480,7 @@ class BaseModel(metaclass=_model_constru
|
|
self,
|
|
*,
|
|
indent: int | None = None,
|
|
+ ensure_ascii: bool = False,
|
|
include: IncEx | None = None,
|
|
exclude: IncEx | None = None,
|
|
context: Any | None = None,
|
|
@@ -499,6 +500,8 @@ class BaseModel(metaclass=_model_constru
|
|
|
|
Args:
|
|
indent: Indentation to use in the JSON output. If None is passed, the output will be compact.
|
|
+ ensure_ascii: If `True`, the output is guaranteed to have all incoming non-ASCII characters escaped.
|
|
+ If `False` (the default), these characters will be output as-is.
|
|
include: Field(s) to include in the JSON output.
|
|
exclude: Field(s) to exclude from the JSON output.
|
|
context: Additional context to pass to the serializer.
|
|
@@ -519,6 +522,7 @@ class BaseModel(metaclass=_model_constru
|
|
return self.__pydantic_serializer__.to_json(
|
|
self,
|
|
indent=indent,
|
|
+ ensure_ascii=ensure_ascii,
|
|
include=include,
|
|
exclude=exclude,
|
|
context=context,
|
|
Index: pydantic-2.11.7/pydantic/type_adapter.py
|
|
===================================================================
|
|
--- pydantic-2.11.7.orig/pydantic/type_adapter.py
|
|
+++ pydantic-2.11.7/pydantic/type_adapter.py
|
|
@@ -591,6 +591,7 @@ class TypeAdapter(Generic[T]):
|
|
/,
|
|
*,
|
|
indent: int | None = None,
|
|
+ ensure_ascii: bool = False,
|
|
include: IncEx | None = None,
|
|
exclude: IncEx | None = None,
|
|
by_alias: bool | None = None,
|
|
@@ -611,6 +612,8 @@ class TypeAdapter(Generic[T]):
|
|
Args:
|
|
instance: The instance to be serialized.
|
|
indent: Number of spaces for JSON indentation.
|
|
+ ensure_ascii: If `True`, the output is guaranteed to have all incoming non-ASCII characters escaped.
|
|
+ If `False` (the default), these characters will be output as-is.
|
|
include: Fields to include.
|
|
exclude: Fields to exclude.
|
|
by_alias: Whether to use alias names for field names.
|
|
Index: pydantic-2.11.7/pydantic/version.py
|
|
===================================================================
|
|
--- pydantic-2.11.7.orig/pydantic/version.py
|
|
+++ pydantic-2.11.7/pydantic/version.py
|
|
@@ -66,7 +66,7 @@ def version_info() -> str:
|
|
def check_pydantic_core_version() -> bool:
|
|
"""Check that the installed `pydantic-core` dependency is compatible."""
|
|
# Keep this in sync with the version constraint in the `pyproject.toml` dependencies:
|
|
- return __pydantic_core_version__ == '2.33.2'
|
|
+ return __pydantic_core_version__ == '2.35.1'
|
|
|
|
|
|
def parse_mypy_version(version: str) -> tuple[int, int, int]:
|
|
Index: pydantic-2.11.7/pyproject.toml
|
|
===================================================================
|
|
--- pydantic-2.11.7.orig/pyproject.toml
|
|
+++ pydantic-2.11.7/pyproject.toml
|
|
@@ -43,10 +43,10 @@ classifiers = [
|
|
]
|
|
requires-python = '>=3.9'
|
|
dependencies = [
|
|
- 'typing-extensions>=4.12.2',
|
|
+ 'typing-extensions>=4.13.0',
|
|
'annotated-types>=0.6.0',
|
|
# Keep this in sync with the version in the `check_pydantic_core_version()` function:
|
|
- 'pydantic-core==2.33.2',
|
|
+ 'pydantic-core==2.35.1',
|
|
'typing-inspection>=0.4.0',
|
|
]
|
|
dynamic = ['version', 'readme']
|
|
Index: pydantic-2.11.7/tests/typechecking/decorators.py
|
|
===================================================================
|
|
--- pydantic-2.11.7.orig/tests/typechecking/decorators.py
|
|
+++ pydantic-2.11.7/tests/typechecking/decorators.py
|
|
@@ -31,13 +31,25 @@ class BeforeModelValidator(BaseModel):
|
|
"""TODO This shouldn't be valid. At runtime, `self` is the actual value and `value` is the `ValidationInfo` instance."""
|
|
|
|
@model_validator(mode='before')
|
|
- def valid_method_info(self, value: Any, info: ValidationInfo) -> Any: ...
|
|
+ def valid_method_info_default(self, value: Any, info: ValidationInfo) -> Any: ...
|
|
+
|
|
+ @model_validator(mode='before')
|
|
+ def valid_method_info(self, value: Any, info: ValidationInfo[int]) -> Any:
|
|
+ assert_type(info.context, int)
|
|
|
|
@model_validator(mode='before')
|
|
@classmethod
|
|
def valid_classmethod(cls, value: Any) -> Any: ...
|
|
|
|
@model_validator(mode='before')
|
|
+ @classmethod
|
|
+ def valid_classmethod_info_default(cls, value: Any, info: ValidationInfo) -> Any: ...
|
|
+
|
|
+ @model_validator(mode='before')
|
|
+ @classmethod
|
|
+ def valid_classmethod_info(cls, value: Any, info: ValidationInfo[int]) -> Any: ...
|
|
+
|
|
+ @model_validator(mode='before')
|
|
@staticmethod
|
|
def valid_staticmethod(value: Any) -> Any: ...
|
|
|
|
@@ -91,7 +103,10 @@ class AfterModelValidator(BaseModel):
|
|
def valid_method_no_info(self) -> Self: ...
|
|
|
|
@model_validator(mode='after')
|
|
- def valid_method_info(self, info: ValidationInfo) -> Self: ...
|
|
+ def valid_method_info_default(self, info: ValidationInfo) -> Self: ...
|
|
+
|
|
+ @model_validator(mode='after')
|
|
+ def valid_method_info(self, info: ValidationInfo[int]) -> Self: ...
|
|
|
|
|
|
class BeforeFieldValidator(BaseModel):
|
|
@@ -114,7 +129,11 @@ class BeforeFieldValidator(BaseModel):
|
|
|
|
@field_validator('foo', mode='before', json_schema_input_type=int) # `json_schema_input_type` allowed here.
|
|
@classmethod
|
|
- def valid_with_info(cls, value: Any, info: ValidationInfo) -> Any: ...
|
|
+ def valid_with_info_default(cls, value: Any, info: ValidationInfo) -> Any: ...
|
|
+
|
|
+ @field_validator('foo', mode='before', json_schema_input_type=int) # `json_schema_input_type` allowed here.
|
|
+ @classmethod
|
|
+ def valid_with_info(cls, value: Any, info: ValidationInfo[int]) -> Any: ...
|
|
|
|
|
|
class AfterFieldValidator(BaseModel):
|
|
@@ -122,6 +141,14 @@ class AfterFieldValidator(BaseModel):
|
|
@classmethod
|
|
def valid_classmethod(cls, value: Any) -> Any: ...
|
|
|
|
+ @field_validator('foo', mode='after')
|
|
+ @classmethod
|
|
+ def valid_classmethod_info_default(cls, value: Any, info: ValidationInfo) -> Any: ...
|
|
+
|
|
+ @field_validator('foo', mode='after')
|
|
+ @classmethod
|
|
+ def valid_classmethod_info(cls, value: Any, info: ValidationInfo[int]) -> Any: ...
|
|
+
|
|
@field_validator('foo', mode='after', json_schema_input_type=int) # type: ignore[call-overload] # pyright: ignore[reportCallIssue, reportArgumentType]
|
|
@classmethod
|
|
def invalid_input_type_not_allowed(cls, value: Any) -> Any: ...
|
|
@@ -148,7 +175,13 @@ class WrapFieldValidator(BaseModel):
|
|
|
|
@field_validator('foo', mode='wrap', json_schema_input_type=int) # `json_schema_input_type` allowed here.
|
|
@classmethod
|
|
- def valid_with_info(cls, value: Any, handler: ValidatorFunctionWrapHandler, info: ValidationInfo) -> Any: ...
|
|
+ def valid_with_info_default(
|
|
+ cls, value: Any, handler: ValidatorFunctionWrapHandler, info: ValidationInfo
|
|
+ ) -> Any: ...
|
|
+
|
|
+ @field_validator('foo', mode='wrap', json_schema_input_type=int) # `json_schema_input_type` allowed here.
|
|
+ @classmethod
|
|
+ def valid_with_info(cls, value: Any, handler: ValidatorFunctionWrapHandler, info: ValidationInfo[int]) -> Any: ...
|
|
|
|
|
|
class PlainModelSerializer(BaseModel):
|
|
@@ -162,7 +195,10 @@ class PlainModelSerializer(BaseModel):
|
|
def valid_plain_serializer_2(self) -> Any: ...
|
|
|
|
@model_serializer(mode='plain')
|
|
- def valid_plain_serializer_info(self, info: SerializationInfo) -> Any: ...
|
|
+ def valid_plain_serializer_info_default(self, info: SerializationInfo) -> Any: ...
|
|
+
|
|
+ @model_serializer(mode='plain')
|
|
+ def valid_plain_serializer_info(self, info: SerializationInfo[int]) -> Any: ...
|
|
|
|
|
|
class WrapModelSerializer(BaseModel):
|
|
@@ -175,7 +211,12 @@ class WrapModelSerializer(BaseModel):
|
|
return value
|
|
|
|
@model_serializer(mode='wrap')
|
|
- def valid_info(self, handler: SerializerFunctionWrapHandler, info: SerializationInfo) -> Any:
|
|
+ def valid_info_default(self, handler: SerializerFunctionWrapHandler, info: SerializationInfo) -> Any:
|
|
+ value = handler(self)
|
|
+ return value
|
|
+
|
|
+ @model_serializer(mode='wrap')
|
|
+ def valid_info(self, handler: SerializerFunctionWrapHandler, info: SerializationInfo[int]) -> Any:
|
|
value = handler(self)
|
|
return value
|
|
|
|
@@ -205,7 +246,10 @@ class PlainFieldSerializer(BaseModel):
|
|
"""
|
|
|
|
@field_serializer('a', mode='plain')
|
|
- def valid_method_info(self, value: Any, info: FieldSerializationInfo) -> Any: ...
|
|
+ def valid_method_info_default(self, value: Any, info: FieldSerializationInfo) -> Any: ...
|
|
+
|
|
+ @field_serializer('a', mode='plain')
|
|
+ def valid_method_info(self, value: Any, info: FieldSerializationInfo[int]) -> Any: ...
|
|
|
|
@field_serializer('a', mode='plain')
|
|
@staticmethod
|
|
@@ -213,7 +257,11 @@ class PlainFieldSerializer(BaseModel):
|
|
|
|
@field_serializer('a', mode='plain')
|
|
@staticmethod
|
|
- def valid_staticmethod_info(value: Any, info: FieldSerializationInfo) -> Any: ...
|
|
+ def valid_staticmethod_info_default(value: Any, info: FieldSerializationInfo) -> Any: ...
|
|
+
|
|
+ @field_serializer('a', mode='plain')
|
|
+ @staticmethod
|
|
+ def valid_staticmethod_info(value: Any, info: FieldSerializationInfo[int]) -> Any: ...
|
|
|
|
@field_serializer('a', mode='plain')
|
|
@classmethod
|
|
@@ -221,7 +269,11 @@ class PlainFieldSerializer(BaseModel):
|
|
|
|
@field_serializer('a', mode='plain')
|
|
@classmethod
|
|
- def valid_classmethod_info(cls, value: Any, info: FieldSerializationInfo) -> Any: ...
|
|
+ def valid_classmethod_info_default(cls, value: Any, info: FieldSerializationInfo) -> Any: ...
|
|
+
|
|
+ @field_serializer('a', mode='plain')
|
|
+ @classmethod
|
|
+ def valid_classmethod_info(cls, value: Any, info: FieldSerializationInfo[int]) -> Any: ...
|
|
|
|
partial_ = field_serializer('a', mode='plain')(partial(lambda v, x: v, x=1))
|
|
|
|
@@ -250,4 +302,11 @@ class WrapFieldSerializer(BaseModel):
|
|
def valid_no_info(self, value: Any, handler: SerializerFunctionWrapHandler) -> Any: ...
|
|
|
|
@field_serializer('a', mode='wrap')
|
|
- def valid_info(self, value: Any, handler: SerializerFunctionWrapHandler, info: FieldSerializationInfo) -> Any: ...
|
|
+ def valid_info_default(
|
|
+ self, value: Any, handler: SerializerFunctionWrapHandler, info: FieldSerializationInfo
|
|
+ ) -> Any: ...
|
|
+
|
|
+ @field_serializer('a', mode='wrap')
|
|
+ def valid_info(
|
|
+ self, value: Any, handler: SerializerFunctionWrapHandler, info: FieldSerializationInfo[int]
|
|
+ ) -> Any: ...
|