From f07b39b7eef039ec0652f59bdd899e6b1e45b92271682d51e8c7b8166d756497 Mon Sep 17 00:00:00 2001 From: Daniel Garcia Date: Mon, 23 Jun 2025 06:57:01 +0000 Subject: [PATCH] - Add patch bump-pydantic-core-2.35.1.patch to support latest pydantic-core, gh#pydantic/pydantic#11963 - Add patch field-name-validator-core-schemas.patch to remove deprecation warning, gh#pydantic/pydantic#11761 - Update to 2.11.7 * Copy FieldInfo instance if necessary during FieldInfo build by @Viicos in #11980 2.11.6 * Rebuild dataclass fields before schema generation by @Viicos in #11949 * Always store the original field assignment on FieldInfo by @Viicos in #11946 2.11.5 * Check if FieldInfo is complete after applying type variable map by @Viicos in #11855 * Do not delete mock validator/serializer in model_rebuild() by @Viicos in #11890 * Do not duplicate metadata on model rebuild by @Viicos in #11902 OBS-URL: https://build.opensuse.org/package/show/devel:languages:python/python-pydantic?expand=0&rev=73 --- bump-pydantic-core-2.35.1.patch | 424 ++++++++++++++++++++++++ field-name-validator-core-schemas.patch | 233 +++++++++++++ pydantic-2.11.4.tar.gz | 3 - pydantic-2.11.7.tar.gz | 3 + python-pydantic.changes | 17 + python-pydantic.spec | 10 +- 6 files changed, 684 insertions(+), 6 deletions(-) create mode 100644 bump-pydantic-core-2.35.1.patch create mode 100644 field-name-validator-core-schemas.patch delete mode 100644 pydantic-2.11.4.tar.gz create mode 100644 pydantic-2.11.7.tar.gz diff --git a/bump-pydantic-core-2.35.1.patch b/bump-pydantic-core-2.35.1.patch new file mode 100644 index 0000000..18f11dd --- /dev/null +++ b/bump-pydantic-core-2.35.1.patch @@ -0,0 +1,424 @@ +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: ... diff --git a/field-name-validator-core-schemas.patch b/field-name-validator-core-schemas.patch new file mode 100644 index 0000000..760e5b4 --- /dev/null +++ b/field-name-validator-core-schemas.patch @@ -0,0 +1,233 @@ +From cd0d37c4c18f24b5624ae86cfe5288cd82edf2c1 Mon Sep 17 00:00:00 2001 +From: Douwe Maan +Date: Wed, 16 Apr 2025 18:01:58 +0000 +Subject: [PATCH 1/4] Stop using deprecated field_name argument on validation + function schemas + +--- + docs/concepts/types.md | 2 +- + pydantic/_internal/_generate_schema.py | 45 ++++++++++---------------- + pydantic/functional_validators.py | 5 +-- + tests/test_validators.py | 2 +- + 4 files changed, 20 insertions(+), 34 deletions(-) + +Index: pydantic-2.11.7/docs/concepts/types.md +=================================================================== +--- pydantic-2.11.7.orig/docs/concepts/types.md ++++ pydantic-2.11.7/docs/concepts/types.md +@@ -979,7 +979,7 @@ class CustomType: + cls, source_type: Any, handler: GetCoreSchemaHandler + ) -> core_schema.CoreSchema: + return core_schema.with_info_after_validator_function( +- cls.validate, handler(int), field_name=handler.field_name ++ cls.validate, handler(int) + ) + + +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 +@@ -222,7 +222,6 @@ def filter_field_decorator_info_by_field + def apply_each_item_validators( + schema: core_schema.CoreSchema, + each_item_validators: list[Decorator[ValidatorDecoratorInfo]], +- field_name: str | None, + ) -> core_schema.CoreSchema: + # This V1 compatibility shim should eventually be removed + +@@ -234,21 +233,20 @@ def apply_each_item_validators( + # note that this won't work for any Annotated types that get wrapped by a function validator + # but that's okay because that didn't exist in V1 + if schema['type'] == 'nullable': +- schema['schema'] = apply_each_item_validators(schema['schema'], each_item_validators, field_name) ++ schema['schema'] = apply_each_item_validators(schema['schema'], each_item_validators) + return schema + elif schema['type'] == 'tuple': + if (variadic_item_index := schema.get('variadic_item_index')) is not None: + schema['items_schema'][variadic_item_index] = apply_validators( + schema['items_schema'][variadic_item_index], + each_item_validators, +- field_name, + ) + elif is_list_like_schema_with_items_schema(schema): + inner_schema = schema.get('items_schema', core_schema.any_schema()) +- schema['items_schema'] = apply_validators(inner_schema, each_item_validators, field_name) ++ schema['items_schema'] = apply_validators(inner_schema, each_item_validators) + elif schema['type'] == 'dict': + inner_schema = schema.get('values_schema', core_schema.any_schema()) +- schema['values_schema'] = apply_validators(inner_schema, each_item_validators, field_name) ++ schema['values_schema'] = apply_validators(inner_schema, each_item_validators) + else: + raise TypeError( + f'`@validator(..., each_item=True)` cannot be applied to fields with a schema of {schema["type"]}' +@@ -840,7 +838,7 @@ class GenerateSchema: + extras_keys_schema=extras_keys_schema, + model_name=cls.__name__, + ) +- inner_schema = apply_validators(fields_schema, decorators.root_validators.values(), None) ++ inner_schema = apply_validators(fields_schema, decorators.root_validators.values()) + inner_schema = apply_model_validators(inner_schema, model_validators, 'inner') + + model_schema = core_schema.model_schema( +@@ -1380,9 +1378,9 @@ class GenerateSchema: + field_info.validate_default = True + each_item_validators = [v for v in this_field_validators if v.info.each_item is True] + this_field_validators = [v for v in this_field_validators if v not in each_item_validators] +- schema = apply_each_item_validators(schema, each_item_validators, name) ++ schema = apply_each_item_validators(schema, each_item_validators) + +- schema = apply_validators(schema, this_field_validators, name) ++ schema = apply_validators(schema, this_field_validators) + + # the default validator needs to go outside of any other validators + # so that it is the topmost validator for the field validator +@@ -1972,7 +1970,7 @@ class GenerateSchema: + collect_init_only=has_post_init, + ) + +- inner_schema = apply_validators(args_schema, decorators.root_validators.values(), None) ++ inner_schema = apply_validators(args_schema, decorators.root_validators.values()) + + model_validators = decorators.model_validators.values() + inner_schema = apply_model_validators(inner_schema, model_validators, 'inner') +@@ -2484,24 +2482,16 @@ class GenerateSchema: + + _VALIDATOR_F_MATCH: Mapping[ + tuple[FieldValidatorModes, Literal['no-info', 'with-info']], +- Callable[[Callable[..., Any], core_schema.CoreSchema, str | None], core_schema.CoreSchema], ++ Callable[[Callable[..., Any], core_schema.CoreSchema], core_schema.CoreSchema], + ] = { +- ('before', 'no-info'): lambda f, schema, _: core_schema.no_info_before_validator_function(f, schema), +- ('after', 'no-info'): lambda f, schema, _: core_schema.no_info_after_validator_function(f, schema), +- ('plain', 'no-info'): lambda f, _1, _2: core_schema.no_info_plain_validator_function(f), +- ('wrap', 'no-info'): lambda f, schema, _: core_schema.no_info_wrap_validator_function(f, schema), +- ('before', 'with-info'): lambda f, schema, field_name: core_schema.with_info_before_validator_function( +- f, schema, field_name=field_name +- ), +- ('after', 'with-info'): lambda f, schema, field_name: core_schema.with_info_after_validator_function( +- f, schema, field_name=field_name +- ), +- ('plain', 'with-info'): lambda f, _, field_name: core_schema.with_info_plain_validator_function( +- f, field_name=field_name +- ), +- ('wrap', 'with-info'): lambda f, schema, field_name: core_schema.with_info_wrap_validator_function( +- f, schema, field_name=field_name +- ), ++ ('before', 'no-info'): lambda f, schema: core_schema.no_info_before_validator_function(f, schema), ++ ('after', 'no-info'): lambda f, schema: core_schema.no_info_after_validator_function(f, schema), ++ ('plain', 'no-info'): lambda f, _: core_schema.no_info_plain_validator_function(f), ++ ('wrap', 'no-info'): lambda f, schema: core_schema.no_info_wrap_validator_function(f, schema), ++ ('before', 'with-info'): lambda f, schema: core_schema.with_info_before_validator_function(f, schema), ++ ('after', 'with-info'): lambda f, schema: core_schema.with_info_after_validator_function(f, schema), ++ ('plain', 'with-info'): lambda f, _: core_schema.with_info_plain_validator_function(f), ++ ('wrap', 'with-info'): lambda f, schema: core_schema.with_info_wrap_validator_function(f, schema), + } + + +@@ -2512,7 +2502,6 @@ def apply_validators( + validators: Iterable[Decorator[RootValidatorDecoratorInfo]] + | Iterable[Decorator[ValidatorDecoratorInfo]] + | Iterable[Decorator[FieldValidatorDecoratorInfo]], +- field_name: str | None, + ) -> core_schema.CoreSchema: + """Apply validators to a schema. + +@@ -2528,7 +2517,7 @@ def apply_validators( + info_arg = inspect_validator(validator.func, validator.info.mode) + val_type = 'with-info' if info_arg else 'no-info' + +- schema = _VALIDATOR_F_MATCH[(validator.info.mode, val_type)](validator.func, schema, field_name) ++ schema = _VALIDATOR_F_MATCH[(validator.info.mode, val_type)](validator.func, schema) + return schema + + +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 +@@ -75,7 +75,7 @@ class AfterValidator: + info_arg = _inspect_validator(self.func, 'after') + if info_arg: + func = cast(core_schema.WithInfoValidatorFunction, self.func) +- return core_schema.with_info_after_validator_function(func, schema=schema, field_name=handler.field_name) ++ return core_schema.with_info_after_validator_function(func, schema=schema) + else: + func = cast(core_schema.NoInfoValidatorFunction, self.func) + return core_schema.no_info_after_validator_function(func, schema=schema) +@@ -136,7 +136,6 @@ class BeforeValidator: + return core_schema.with_info_before_validator_function( + func, + schema=schema, +- field_name=handler.field_name, + json_schema_input_schema=input_schema, + ) + else: +@@ -230,7 +229,6 @@ class PlainValidator: + func = cast(core_schema.WithInfoValidatorFunction, self.func) + return core_schema.with_info_plain_validator_function( + func, +- field_name=handler.field_name, + serialization=serialization, # pyright: ignore[reportArgumentType] + json_schema_input_schema=input_schema, + ) +@@ -307,7 +305,6 @@ class WrapValidator: + return core_schema.with_info_wrap_validator_function( + func, + schema=schema, +- field_name=handler.field_name, + json_schema_input_schema=input_schema, + ) + else: +Index: pydantic-2.11.7/tests/test_validators.py +=================================================================== +--- pydantic-2.11.7.orig/tests/test_validators.py ++++ pydantic-2.11.7/tests/test_validators.py +@@ -21,7 +21,7 @@ from unittest.mock import MagicMock + import pytest + from dirty_equals import HasRepr, IsInstance + from pydantic_core import core_schema +-from typing_extensions import TypedDict ++from typing_extensions import TypeAliasType, TypedDict + + from pydantic import ( + BaseModel, +@@ -2684,7 +2684,7 @@ def foobar_validate(value: Any, info: co + class Foobar: + @classmethod + def __get_pydantic_core_schema__(cls, source_type: Any, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema: +- return core_schema.with_info_plain_validator_function(foobar_validate, field_name=handler.field_name) ++ return core_schema.with_info_plain_validator_function(foobar_validate) + + + def test_custom_type_field_name_model(): +@@ -2779,6 +2779,29 @@ def test_plain_validator_field_name(): + assert m.foobar == {'value': '1', 'field_name': 'foobar', 'data': {'x': 123}} + + ++def test_validator_field_name_with_reused_type_alias(): ++ calls = [] ++ ++ def validate_my_field(value: str, info: ValidationInfo): ++ calls.append((info.field_name, value)) ++ return value ++ ++ MyField = TypeAliasType('MyField', Annotated[str, AfterValidator(validate_my_field)]) ++ ++ class MyModel(BaseModel): ++ field1: MyField ++ field2: MyField ++ ++ MyModel.model_validate( ++ { ++ 'field1': 'value1', ++ 'field2': 'value2', ++ } ++ ) ++ ++ assert calls == [('field1', 'value1'), ('field2', 'value2')] ++ ++ + def validate_wrap(value: Any, handler: core_schema.ValidatorFunctionWrapHandler, info: core_schema.ValidationInfo): + data = info.data + if isinstance(data, dict): diff --git a/pydantic-2.11.4.tar.gz b/pydantic-2.11.4.tar.gz deleted file mode 100644 index 6f0fe2b..0000000 --- a/pydantic-2.11.4.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:aad186cc4b1d4de2c3f83ea62c93a3939c9681bea655d794846934dbf306571e -size 3087324 diff --git a/pydantic-2.11.7.tar.gz b/pydantic-2.11.7.tar.gz new file mode 100644 index 0000000..8d5db9e --- /dev/null +++ b/pydantic-2.11.7.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d1a46d39c3e10114cf192d4989dd279ec2574e14e9a2902195d62948c3a16d7b +size 3090119 diff --git a/python-pydantic.changes b/python-pydantic.changes index 7165527..b305261 100644 --- a/python-pydantic.changes +++ b/python-pydantic.changes @@ -1,3 +1,20 @@ +------------------------------------------------------------------- +Mon Jun 23 05:56:23 UTC 2025 - Daniel Garcia + +- Add patch bump-pydantic-core-2.35.1.patch to support latest + pydantic-core, gh#pydantic/pydantic#11963 +- Add patch field-name-validator-core-schemas.patch to remove + deprecation warning, gh#pydantic/pydantic#11761 +- Update to 2.11.7 + * Copy FieldInfo instance if necessary during FieldInfo build by @Viicos in #11980 +2.11.6 + * Rebuild dataclass fields before schema generation by @Viicos in #11949 + * Always store the original field assignment on FieldInfo by @Viicos in #11946 +2.11.5 + * Check if FieldInfo is complete after applying type variable map by @Viicos in #11855 + * Do not delete mock validator/serializer in model_rebuild() by @Viicos in #11890 + * Do not duplicate metadata on model rebuild by @Viicos in #11902 + ------------------------------------------------------------------- Mon May 5 08:19:26 UTC 2025 - John Paul Adrian Glaubitz diff --git a/python-pydantic.spec b/python-pydantic.spec index 42843e5..6d98bcd 100644 --- a/python-pydantic.spec +++ b/python-pydantic.spec @@ -27,17 +27,21 @@ %endif %{?sle15_python_module_pythons} Name: python-pydantic%{psuffix} -Version: 2.11.4 +Version: 2.11.7 Release: 0 Summary: Data validation and settings management using python type hinting License: MIT URL: https://github.com/pydantic/pydantic Source: https://github.com/pydantic/pydantic/archive/v%{version}.tar.gz#/pydantic-%{version}.tar.gz +# PATCH-FIX-UPSTREAM bump-pydantic-core-2.35.1.patch gh#pydantic/pydantic#11963 +Patch0: bump-pydantic-core-2.35.1.patch +# PATCH-FIX-UPSTREAM field-name-validator-core-schemas.patch gh#pydantic/pydantic#11761 +Patch1: field-name-validator-core-schemas.patch BuildRequires: %{python_module hatch-fancy-pypi-readme} BuildRequires: %{python_module hatchling} BuildRequires: %{python_module packaging} BuildRequires: %{python_module pip} -BuildRequires: %{python_module pydantic-core >= 2.33.2} +BuildRequires: %{python_module pydantic-core = 2.35.1} BuildRequires: %{python_module wheel} BuildRequires: fdupes BuildRequires: python-rpm-macros @@ -61,7 +65,7 @@ Requires: python-annotated-types >= 0.4.0 %if 0%{?python_version_nodots} < 310 Requires: python-eval-type-backport %endif -Requires: python-pydantic-core >= 2.33.2 +Requires: python-pydantic-core = 2.35.1 Requires: python-typing-extensions >= 4.12.2 Requires: python-typing-inspection BuildArch: noarch