From 5fe7833bb74851ec3e99a03e7ee4462b9468c075 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Thu, 12 Mar 2026 22:10:53 +0100 Subject: [PATCH 01/14] use Pydantic's try_eval_type if available (otherwise deprecation warning) --- fastapi/_compat/v2.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py index 79fba93188..76acbe5c5d 100644 --- a/fastapi/_compat/v2.py +++ b/fastapi/_compat/v2.py @@ -22,10 +22,10 @@ from pydantic import BaseModel, ConfigDict, Field, TypeAdapter, create_model from pydantic import PydanticSchemaGenerationError as PydanticSchemaGenerationError from pydantic import PydanticUndefinedAnnotation as PydanticUndefinedAnnotation from pydantic import ValidationError as ValidationError +from pydantic._internal import _typing_extra as _pydantic_typing_extra from pydantic._internal._schema_generation_shared import ( # type: ignore[attr-defined] GetJsonSchemaHandler as GetJsonSchemaHandler, ) -from pydantic._internal._typing_extra import eval_type_lenient from pydantic.fields import FieldInfo as FieldInfo from pydantic.json_schema import GenerateJsonSchema as _GenerateJsonSchema from pydantic.json_schema import JsonSchemaValue as JsonSchemaValue @@ -38,7 +38,11 @@ from pydantic_core.core_schema import ( RequiredParam = PydanticUndefined Undefined = PydanticUndefined -evaluate_forwardref = eval_type_lenient + +# eval_type_lenient has been deprecated since Pydantic v2.10.0b1 (PR #10530) +evaluate_forwardref = getattr(_pydantic_typing_extra, "try_eval_type", None) +if evaluate_forwardref is None: + evaluate_forwardref = getattr(_pydantic_typing_extra, "eval_type_lenient") class GenerateJsonSchema(_GenerateJsonSchema): From 94bd71371eb4264fd40279f8b7f32e8f80b55d7e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Thu, 12 Mar 2026 21:14:26 +0000 Subject: [PATCH 02/14] =?UTF-8?q?=F0=9F=8E=A8=20Auto=20format?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/_compat/v2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py index 76acbe5c5d..38ca8ba7a3 100644 --- a/fastapi/_compat/v2.py +++ b/fastapi/_compat/v2.py @@ -42,7 +42,7 @@ Undefined = PydanticUndefined # eval_type_lenient has been deprecated since Pydantic v2.10.0b1 (PR #10530) evaluate_forwardref = getattr(_pydantic_typing_extra, "try_eval_type", None) if evaluate_forwardref is None: - evaluate_forwardref = getattr(_pydantic_typing_extra, "eval_type_lenient") + evaluate_forwardref = _pydantic_typing_extra.eval_type_lenient class GenerateJsonSchema(_GenerateJsonSchema): From a1abbce3a51035e96c9c60be850a24378cf0a8d2 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Thu, 12 Mar 2026 22:17:00 +0100 Subject: [PATCH 03/14] assert evaluate_forwardref is not None --- fastapi/_compat/v2.py | 1 + 1 file changed, 1 insertion(+) diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py index 38ca8ba7a3..11b17b9fa0 100644 --- a/fastapi/_compat/v2.py +++ b/fastapi/_compat/v2.py @@ -43,6 +43,7 @@ Undefined = PydanticUndefined evaluate_forwardref = getattr(_pydantic_typing_extra, "try_eval_type", None) if evaluate_forwardref is None: evaluate_forwardref = _pydantic_typing_extra.eval_type_lenient +assert evaluate_forwardref is not None class GenerateJsonSchema(_GenerateJsonSchema): From 97ce5de0bf309ea0c096088247c06545c7400bf6 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Thu, 12 Mar 2026 22:35:11 +0100 Subject: [PATCH 04/14] make mypy happy --- fastapi/_compat/v2.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py index 11b17b9fa0..6cf5c67f7c 100644 --- a/fastapi/_compat/v2.py +++ b/fastapi/_compat/v2.py @@ -1,6 +1,6 @@ import re import warnings -from collections.abc import Sequence +from collections.abc import Callable, Sequence from copy import copy from dataclasses import dataclass, is_dataclass from enum import Enum @@ -39,11 +39,16 @@ from pydantic_core.core_schema import ( RequiredParam = PydanticUndefined Undefined = PydanticUndefined -# eval_type_lenient has been deprecated since Pydantic v2.10.0b1 (PR #10530) -evaluate_forwardref = getattr(_pydantic_typing_extra, "try_eval_type", None) -if evaluate_forwardref is None: - evaluate_forwardref = _pydantic_typing_extra.eval_type_lenient -assert evaluate_forwardref is not None + +def define_forwardref() -> Callable[..., Any]: + # eval_type_lenient has been deprecated since Pydantic v2.10.0b1 (PR #10530) + eval_type = getattr(_pydantic_typing_extra, "try_eval_type", None) + if eval_type is not None: + return cast(Callable[..., Any], eval_type) + return _pydantic_typing_extra.eval_type_lenient + + +evaluate_forwardref = define_forwardref() class GenerateJsonSchema(_GenerateJsonSchema): From 8e5d327aca80d9c0fa84c9aefcddef77fed37ea9 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 13 Mar 2026 10:18:40 +0100 Subject: [PATCH 05/14] fix return type of eval_type --- fastapi/_compat/v2.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py index 6cf5c67f7c..d075c49822 100644 --- a/fastapi/_compat/v2.py +++ b/fastapi/_compat/v2.py @@ -42,9 +42,9 @@ Undefined = PydanticUndefined def define_forwardref() -> Callable[..., Any]: # eval_type_lenient has been deprecated since Pydantic v2.10.0b1 (PR #10530) - eval_type = getattr(_pydantic_typing_extra, "try_eval_type", None) - if eval_type is not None: - return cast(Callable[..., Any], eval_type) + try_eval_type = getattr(_pydantic_typing_extra, "try_eval_type", None) + if try_eval_type is not None: + return lambda *args: try_eval_type(*args)[0] return _pydantic_typing_extra.eval_type_lenient From 2d2fe3ebf389dd68dfbb01a97f01c1b88a036076 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 13 Mar 2026 10:27:29 +0100 Subject: [PATCH 06/14] add no cover for now --- fastapi/_compat/v2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py index d075c49822..c6137e17c8 100644 --- a/fastapi/_compat/v2.py +++ b/fastapi/_compat/v2.py @@ -45,7 +45,7 @@ def define_forwardref() -> Callable[..., Any]: try_eval_type = getattr(_pydantic_typing_extra, "try_eval_type", None) if try_eval_type is not None: return lambda *args: try_eval_type(*args)[0] - return _pydantic_typing_extra.eval_type_lenient + return _pydantic_typing_extra.eval_type_lenient # pragma: no cover evaluate_forwardref = define_forwardref() From bbf15294ebb2d2cd8a0825ad382844c54668197e Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 13 Mar 2026 10:54:24 +0100 Subject: [PATCH 07/14] coditional import of Color to avoid deprecation warning --- fastapi/_compat/__init__.py | 1 + fastapi/_compat/v2.py | 6 ++++++ fastapi/encoders.py | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/fastapi/_compat/__init__.py b/fastapi/_compat/__init__.py index 4581c38c88..225e79d9f4 100644 --- a/fastapi/_compat/__init__.py +++ b/fastapi/_compat/__init__.py @@ -19,6 +19,7 @@ from .shared import ( from .shared import lenient_issubclass as lenient_issubclass from .shared import sequence_types as sequence_types from .shared import value_is_sequence as value_is_sequence +from .v2 import Color as Color from .v2 import ModelField as ModelField from .v2 import PydanticSchemaGenerationError as PydanticSchemaGenerationError from .v2 import RequiredParam as RequiredParam diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py index c6137e17c8..d2ef4a8b85 100644 --- a/fastapi/_compat/v2.py +++ b/fastapi/_compat/v2.py @@ -39,6 +39,12 @@ from pydantic_core.core_schema import ( RequiredParam = PydanticUndefined Undefined = PydanticUndefined +# pydantic.color.Color is deprecated since v2.0b3 +try: + from pydantic_extra_types import Color +except ImportError: + from pydantic.color import Color # noqa: F401 + def define_forwardref() -> Callable[..., Any]: # eval_type_lenient has been deprecated since Pydantic v2.10.0b1 (PR #10530) diff --git a/fastapi/encoders.py b/fastapi/encoders.py index e20255c110..863b5d4531 100644 --- a/fastapi/encoders.py +++ b/fastapi/encoders.py @@ -22,12 +22,12 @@ from annotated_doc import Doc from fastapi.exceptions import PydanticV1NotSupportedError from fastapi.types import IncEx from pydantic import BaseModel -from pydantic.color import Color from pydantic.networks import AnyUrl, NameEmail from pydantic.types import SecretBytes, SecretStr from pydantic_core import PydanticUndefinedType from ._compat import ( + Color, Url, is_pydantic_v1_model_instance, ) From 171f062dd5b7218de11a065a9784fb9226b9e461 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 13 Mar 2026 11:03:09 +0100 Subject: [PATCH 08/14] fix import --- fastapi/_compat/v2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py index d2ef4a8b85..f98013a0b9 100644 --- a/fastapi/_compat/v2.py +++ b/fastapi/_compat/v2.py @@ -41,7 +41,7 @@ Undefined = PydanticUndefined # pydantic.color.Color is deprecated since v2.0b3 try: - from pydantic_extra_types import Color + from pydantic_extra_types.color import Color except ImportError: from pydantic.color import Color # noqa: F401 From e86753477a60b29a2d3df935313ca812c905c1eb Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 13 Mar 2026 11:05:27 +0100 Subject: [PATCH 09/14] appease mypy --- fastapi/_compat/v2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py index f98013a0b9..732ed9eca7 100644 --- a/fastapi/_compat/v2.py +++ b/fastapi/_compat/v2.py @@ -43,7 +43,7 @@ Undefined = PydanticUndefined try: from pydantic_extra_types.color import Color except ImportError: - from pydantic.color import Color # noqa: F401 + from pydantic.color import Color # type: ignore[assignment] # noqa: F401 def define_forwardref() -> Callable[..., Any]: From 6851dad91c090875955c44be8da11f5d3d8ec370 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 13 Mar 2026 11:10:05 +0100 Subject: [PATCH 10/14] appease mypy more --- fastapi/_compat/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastapi/_compat/__init__.py b/fastapi/_compat/__init__.py index 225e79d9f4..a0bede3471 100644 --- a/fastapi/_compat/__init__.py +++ b/fastapi/_compat/__init__.py @@ -19,7 +19,7 @@ from .shared import ( from .shared import lenient_issubclass as lenient_issubclass from .shared import sequence_types as sequence_types from .shared import value_is_sequence as value_is_sequence -from .v2 import Color as Color +from .v2 import Color as Color # type: ignore[attr-defined] from .v2 import ModelField as ModelField from .v2 import PydanticSchemaGenerationError as PydanticSchemaGenerationError from .v2 import RequiredParam as RequiredParam From f57b166f56b8196062d388df466b0de000ccec53 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 13 Mar 2026 11:20:16 +0100 Subject: [PATCH 11/14] add pragma no cover again --- fastapi/_compat/v2.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py index 732ed9eca7..9c6462dbfc 100644 --- a/fastapi/_compat/v2.py +++ b/fastapi/_compat/v2.py @@ -43,7 +43,9 @@ Undefined = PydanticUndefined try: from pydantic_extra_types.color import Color except ImportError: - from pydantic.color import Color # type: ignore[assignment] # noqa: F401 + from pydantic.color import ( + Color, # type: ignore[assignment] # noqa: F401 # pragma: no cover + ) def define_forwardref() -> Callable[..., Any]: From 926156f36076353a869c35c2f3cbece7478f6186 Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 13 Mar 2026 11:25:55 +0100 Subject: [PATCH 12/14] appease mypy once more --- fastapi/_compat/v2.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py index 9c6462dbfc..207dbe16b5 100644 --- a/fastapi/_compat/v2.py +++ b/fastapi/_compat/v2.py @@ -43,8 +43,8 @@ Undefined = PydanticUndefined try: from pydantic_extra_types.color import Color except ImportError: - from pydantic.color import ( - Color, # type: ignore[assignment] # noqa: F401 # pragma: no cover + from pydantic.color import ( # type: ignore[assignment] + Color, # noqa: F401 # pragma: no cover ) From 4f4491a14ea236c41a70fb94581322f42605b7be Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 13 Mar 2026 11:31:01 +0100 Subject: [PATCH 13/14] more pragma omg --- fastapi/_compat/v2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py index 207dbe16b5..a02a989079 100644 --- a/fastapi/_compat/v2.py +++ b/fastapi/_compat/v2.py @@ -43,7 +43,7 @@ Undefined = PydanticUndefined try: from pydantic_extra_types.color import Color except ImportError: - from pydantic.color import ( # type: ignore[assignment] + from pydantic.color import ( # type: ignore[assignment] # pragma: no cover Color, # noqa: F401 # pragma: no cover ) From 1f676f1889a5c5f27472f400336f5e8c6762232a Mon Sep 17 00:00:00 2001 From: svlandeg Date: Fri, 13 Mar 2026 11:50:30 +0100 Subject: [PATCH 14/14] cleanup --- fastapi/_compat/v2.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fastapi/_compat/v2.py b/fastapi/_compat/v2.py index a02a989079..0a83934752 100644 --- a/fastapi/_compat/v2.py +++ b/fastapi/_compat/v2.py @@ -42,9 +42,9 @@ Undefined = PydanticUndefined # pydantic.color.Color is deprecated since v2.0b3 try: from pydantic_extra_types.color import Color -except ImportError: - from pydantic.color import ( # type: ignore[assignment] # pragma: no cover - Color, # noqa: F401 # pragma: no cover +except ImportError: # pragma: no cover + from pydantic.color import ( # type: ignore[assignment] + Color, # noqa: F401 )