← eval8_submission_v1a

fastapi_14186

failed WRONG_FIX wrong_fix · 19 tool calls · 285 s · fastapi/fastapi

Task input

🐛 Fix internal Pydantic v1 compatibility (warnings) for Python 3.14 and Pydantic 2.12.1

The Python 3.14 tests started failing with the Pydantic v.2.12.1 release, because of the combination of https://github.com/fastapi/fastapi/pull/14168 and https://github.com/pydantic/pydantic/pull/12367.

Basically we were importing Pydantic `v1` functionality even when the user had (only) Pydantic v2 installed. This was done in https://github.com/fastapi/fastapi/pull/14168 to support more easy migration from v1 to v2 by allowing mixing versions within the same app.

Here, we prevent importing any `v1` functionality by creating dummy classes for Python 3.14 / Pydantic 2.12.0 onwards, which [drops support](https://github.com/pydantic/pydantic/releases/tag/v2.12.0) for `v1` and emits a [warning](https://github.com/pydantic/pydantic/pull/12367) when importing `v1` functionality.

### TODO

- [x] fix coverage
- [ ] check warning is still shown to users at some point, and not just swallowed by this code.

Tool calls (20)

#ToolArgumentsResult
1run_command
{
 "command": "grep -rn \"pydantic.v1\" fastapi | head -20"
}
{"status": "ok", "stdout": "fastapi/dependencies/utils.py:51:from fastapi._compat.shared import annotation_is_pydantic_v1\nfastapi/dependencies/utils.py:79:from
full
{"status": "ok", "stdout": "fastapi/dependencies/utils.py:51:from fastapi._compat.shared import annotation_is_pydantic_v1\nfastapi/dependencies/utils.py:79:from .. import temp_pydantic_v1_params\nfastapi/dependencies/utils.py:323:            param_details.field.field_info, (params.Body, temp_pydantic_v1_params.Body)\nfastapi/dependencies/utils.py:392:                    temp_pydantic_v1_params.Param,\nfastapi/dependencies/utils.py:394:                    temp_pydantic_v1_params.Body,\nfastapi/dependencies/utils.py:483:            if annotation_is_pydantic_v1(use_annotation):\nfastapi/dependencies/utils.py:484:                field_info = temp_pydantic_v1_params.Body(\nfastapi/dependencies/utils.py:500:                field_info, (params.Path, temp_pydantic_v1_params.Path)\nfastapi/dependencies/utils.py:506:            isinstance(field_info, (params.Param, temp_pydantic_v1_params.Param))\nfastapi/dependencies/utils.py:515:        if isinstance(field_info, (params.Form, temp_pydantic_v1_params.Form)):\nfastapi/dependencies/utils.py:534:        elif isinstance(field_info, (params.Query, temp_pydantic_v1_params.Query)):\nfastapi/dependencies/utils.py:761:            isinstance(field.field_info, (params.Form, temp_pydantic_v1_params.Form))\nfastapi/dependencies/utils.py:827:        assert isinstance(field_info, (params.Param, temp_pydantic_v1_params.Param)), (\nfastapi/dependencies/utils.py:839:        assert isinstance(field_info, (params.Param, temp_pydantic_v1_params.Param)), (\nfastapi/dependencies/utils.py:888:        isinstance(first_field.field_info, (params.Form, temp_pydantic_v1_params.Form))\nfastapi/dependencies/utils.py:906:            isinstance(field_info, (params.File, temp_pydantic_v1_params.File))\nfastapi/dependencies/utils.py:913:            and isinstance(field_info, (params.File, temp_pydantic_v1_params.File))\nfastapi/dependencies/utils.py:1020:        isinstance(f.field_info, temp_pydantic_v1_params.File)\nfastapi/dependencies/utils.py:1023:       
2run_command
{
 "command": "grep -rn \"temp_pydantic_v1_params\" fastapi | head -20"
}
{"status": "ok", "stdout": "fastapi/dependencies/utils.py:79:from .. import temp_pydantic_v1_params\nfastapi/dependencies/utils.py:323: param_details.field.fiel
full
{"status": "ok", "stdout": "fastapi/dependencies/utils.py:79:from .. import temp_pydantic_v1_params\nfastapi/dependencies/utils.py:323:            param_details.field.field_info, (params.Body, temp_pydantic_v1_params.Body)\nfastapi/dependencies/utils.py:392:                    temp_pydantic_v1_params.Param,\nfastapi/dependencies/utils.py:394:                    temp_pydantic_v1_params.Body,\nfastapi/dependencies/utils.py:484:                field_info = temp_pydantic_v1_params.Body(\nfastapi/dependencies/utils.py:500:                field_info, (params.Path, temp_pydantic_v1_params.Path)\nfastapi/dependencies/utils.py:506:            isinstance(field_info, (params.Param, temp_pydantic_v1_params.Param))\nfastapi/dependencies/utils.py:515:        if isinstance(field_info, (params.Form, temp_pydantic_v1_params.Form)):\nfastapi/dependencies/utils.py:534:        elif isinstance(field_info, (params.Query, temp_pydantic_v1_params.Query)):\nfastapi/dependencies/utils.py:761:            isinstance(field.field_info, (params.Form, temp_pydantic_v1_params.Form))\nfastapi/dependencies/utils.py:827:        assert isinstance(field_info, (params.Param, temp_pydantic_v1_params.Param)), (\nfastapi/dependencies/utils.py:839:        assert isinstance(field_info, (params.Param, temp_pydantic_v1_params.Param)), (\nfastapi/dependencies/utils.py:888:        isinstance(first_field.field_info, (params.Form, temp_pydantic_v1_params.Form))\nfastapi/dependencies/utils.py:906:            isinstance(field_info, (params.File, temp_pydantic_v1_params.File))\nfastapi/dependencies/utils.py:913:            and isinstance(field_info, (params.File, temp_pydantic_v1_params.File))\nfastapi/dependencies/utils.py:1020:        isinstance(f.field_info, temp_pydantic_v1_params.File)\nfastapi/dependencies/utils.py:1023:        BodyFieldInfo: Type[temp_pydantic_v1_params.Body] = temp_pydantic_v1_params.File  # type: ignore[no-redef]\nfastapi/dependencies/utils.py:1027:        isinstance(f.field_info, temp_pydant
3run_command
{
 "command": "ls fastapi/__init__.py fastapi/temp_pydantic_v1_params.py"
}
{"status": "ok", "stdout": "fastapi/__init__.py\nfastapi/temp_pydantic_v1_params.py\n", "stderr": "", "exit_code": 0}
full
{"status": "ok", "stdout": "fastapi/__init__.py\nfastapi/temp_pydantic_v1_params.py\n", "stderr": "", "exit_code": 0}
4run_command
{
 "command": "cat fastapi/temp_pydantic_v1_params.py"
}
{"status": "ok", "stdout": "import warnings\nfrom typing import Any, Callable, Dict, List, Optional, Union\n\nfrom fastapi.openapi.models import Example\nfrom f
full
{"status": "ok", "stdout": "import warnings\nfrom typing import Any, Callable, Dict, List, Optional, Union\n\nfrom fastapi.openapi.models import Example\nfrom fastapi.params import ParamTypes\nfrom typing_extensions import Annotated, deprecated\n\nfrom ._compat.shared import PYDANTIC_VERSION_MINOR_TUPLE\nfrom ._compat.v1 import FieldInfo, Undefined\n\n_Unset: Any = Undefined\n\n\nclass Param(FieldInfo):  # type: ignore[misc]\n    in_: ParamTypes\n\n    def __init__(\n        self,\n        default: Any = Undefined,\n        *,\n        default_factory: Union[Callable[[], Any], None] = _Unset,\n        annotation: Optional[Any] = None,\n        alias: Optional[str] = None,\n        alias_priority: Union[int, None] = _Unset,\n        # TODO: update when deprecating Pydantic v1, import these types\n        # validation_alias: str | AliasPath | AliasChoices | None\n        validation_alias: Union[str, None] = None,\n        serialization_alias: Union[str, None] = None,\n        title: Optional[str] = None,\n        description: Optional[str] = None,\n        gt: Optional[float] = None,\n        ge: Optional[float] = None,\n        lt: Optional[float] = None,\n        le: Optional[float] = None,\n        min_length: Optional[int] = None,\n        max_length: Optional[int] = None,\n        pattern: Optional[str] = None,\n        regex: Annotated[\n            Optional[str],\n            deprecated(\n                \"Deprecated in FastAPI 0.100.0 and Pydantic v2, use `pattern` instead.\"\n            ),\n        ] = None,\n        discriminator: Union[str, None] = None,\n        strict: Union[bool, None] = _Unset,\n        multiple_of: Union[float, None] = _Unset,\n        allow_inf_nan: Union[bool, None] = _Unset,\n        max_digits: Union[int, None] = _Unset,\n        decimal_places: Union[int, None] = _Unset,\n        examples: Optional[List[Any]] = None,\n        example: Annotated[\n            Optional[Any],\n            deprecated(\n                \"Deprecated in
5run_command
{
 "command": "cat fastapi/_compat/shared.py"
}
{"status": "ok", "stdout": "import sys\nimport types\nimport typing\nfrom collections import deque\nfrom dataclasses import is_dataclass\nfrom typing import (\n
full
{"status": "ok", "stdout": "import sys\nimport types\nimport typing\nfrom collections import deque\nfrom dataclasses import is_dataclass\nfrom typing import (\n    Any,\n    Deque,\n    FrozenSet,\n    List,\n    Mapping,\n    Sequence,\n    Set,\n    Tuple,\n    Type,\n    Union,\n)\n\nfrom fastapi._compat import v1\nfrom fastapi.types import UnionType\nfrom pydantic import BaseModel\nfrom pydantic.version import VERSION as PYDANTIC_VERSION\nfrom starlette.datastructures import UploadFile\nfrom typing_extensions import Annotated, get_args, get_origin\n\n# Copy from Pydantic v2, compatible with v1\nif sys.version_info < (3, 9):\n    # Pydantic no longer supports Python 3.8, this might be incorrect, but the code\n    # this is used for is also never reached in this codebase, as it's a copy of\n    # Pydantic's lenient_issubclass, just for compatibility with v1\n    # TODO: remove when dropping support for Python 3.8\n    WithArgsTypes: Tuple[Any, ...] = ()\nelif sys.version_info < (3, 10):\n    WithArgsTypes: tuple[Any, ...] = (typing._GenericAlias, types.GenericAlias)  # type: ignore[attr-defined]\nelse:\n    WithArgsTypes: tuple[Any, ...] = (\n        typing._GenericAlias,  # type: ignore[attr-defined]\n        types.GenericAlias,\n        types.UnionType,\n    )  # pyright: ignore[reportAttributeAccessIssue]\n\nPYDANTIC_VERSION_MINOR_TUPLE = tuple(int(x) for x in PYDANTIC_VERSION.split(\".\")[:2])\nPYDANTIC_V2 = PYDANTIC_VERSION_MINOR_TUPLE[0] == 2\n\n\nsequence_annotation_to_type = {\n    Sequence: list,\n    List: list,\n    list: list,\n    Tuple: tuple,\n    tuple: tuple,\n    Set: set,\n    set: set,\n    FrozenSet: frozenset,\n    frozenset: frozenset,\n    Deque: deque,\n    deque: deque,\n}\n\nsequence_types = tuple(sequence_annotation_to_type.keys())\n\nUrl: Type[Any]\n\n\n# Copy of Pydantic v2, compatible with v1\ndef lenient_issubclass(\n    cls: Any, class_or_tuple: Union[Type[Any], Tuple[Type[Any], ...], None]\n) -> bool:\n    try:\n        return isi
6run_command
{
 "command": "cat fastapi/_compat/v1.py"
}
{"status": "ok", "stdout": "from copy import copy\nfrom dataclasses import dataclass, is_dataclass\nfrom enum import Enum\nfrom typing import (\n Any,\n Callabl
full
{"status": "ok", "stdout": "from copy import copy\nfrom dataclasses import dataclass, is_dataclass\nfrom enum import Enum\nfrom typing import (\n    Any,\n    Callable,\n    Dict,\n    List,\n    Sequence,\n    Set,\n    Tuple,\n    Type,\n    Union,\n)\n\nfrom fastapi._compat import shared\nfrom fastapi.openapi.constants import REF_PREFIX as REF_PREFIX\nfrom fastapi.types import ModelNameMap\nfrom pydantic.version import VERSION as PYDANTIC_VERSION\nfrom typing_extensions import Literal\n\nPYDANTIC_VERSION_MINOR_TUPLE = tuple(int(x) for x in PYDANTIC_VERSION.split(\".\")[:2])\nPYDANTIC_V2 = PYDANTIC_VERSION_MINOR_TUPLE[0] == 2\n# Keeping old \"Required\" functionality from Pydantic V1, without\n# shadowing typing.Required.\nRequiredParam: Any = Ellipsis\n\nif not PYDANTIC_V2:\n    from pydantic import BaseConfig as BaseConfig\n    from pydantic import BaseModel as BaseModel\n    from pydantic import ValidationError as ValidationError\n    from pydantic import create_model as create_model\n    from pydantic.class_validators import Validator as Validator\n    from pydantic.color import Color as Color\n    from pydantic.error_wrappers import ErrorWrapper as ErrorWrapper\n    from pydantic.errors import MissingError\n    from pydantic.fields import (  # type: ignore[attr-defined]\n        SHAPE_FROZENSET,\n        SHAPE_LIST,\n        SHAPE_SEQUENCE,\n        SHAPE_SET,\n        SHAPE_SINGLETON,\n        SHAPE_TUPLE,\n        SHAPE_TUPLE_ELLIPSIS,\n    )\n    from pydantic.fields import FieldInfo as FieldInfo\n    from pydantic.fields import ModelField as ModelField  # type: ignore[attr-defined]\n    from pydantic.fields import Undefined as Undefined  # type: ignore[attr-defined]\n    from pydantic.fields import (  # type: ignore[attr-defined]\n        UndefinedType as UndefinedType,\n    )\n    from pydantic.networks import AnyUrl as AnyUrl\n    from pydantic.networks import NameEmail as NameEmail\n    from pydantic.schema import TypeModelSet as TypeModelSet\n    from
7run_command
{
 "command": "cat fastapi/_compat/v1.py | sed -n '1,100p'"
}
{"status": "ok", "stdout": "from copy import copy\nfrom dataclasses import dataclass, is_dataclass\nfrom enum import Enum\nfrom typing import (\n Any,\n Callabl
full
{"status": "ok", "stdout": "from copy import copy\nfrom dataclasses import dataclass, is_dataclass\nfrom enum import Enum\nfrom typing import (\n    Any,\n    Callable,\n    Dict,\n    List,\n    Sequence,\n    Set,\n    Tuple,\n    Type,\n    Union,\n)\n\nfrom fastapi._compat import shared\nfrom fastapi.openapi.constants import REF_PREFIX as REF_PREFIX\nfrom fastapi.types import ModelNameMap\nfrom pydantic.version import VERSION as PYDANTIC_VERSION\nfrom typing_extensions import Literal\n\nPYDANTIC_VERSION_MINOR_TUPLE = tuple(int(x) for x in PYDANTIC_VERSION.split(\".\")[:2])\nPYDANTIC_V2 = PYDANTIC_VERSION_MINOR_TUPLE[0] == 2\n# Keeping old \"Required\" functionality from Pydantic V1, without\n# shadowing typing.Required.\nRequiredParam: Any = Ellipsis\n\nif not PYDANTIC_V2:\n    from pydantic import BaseConfig as BaseConfig\n    from pydantic import BaseModel as BaseModel\n    from pydantic import ValidationError as ValidationError\n    from pydantic import create_model as create_model\n    from pydantic.class_validators import Validator as Validator\n    from pydantic.color import Color as Color\n    from pydantic.error_wrappers import ErrorWrapper as ErrorWrapper\n    from pydantic.errors import MissingError\n    from pydantic.fields import (  # type: ignore[attr-defined]\n        SHAPE_FROZENSET,\n        SHAPE_LIST,\n        SHAPE_SEQUENCE,\n        SHAPE_SET,\n        SHAPE_SINGLETON,\n        SHAPE_TUPLE,\n        SHAPE_TUPLE_ELLIPSIS,\n    )\n    from pydantic.fields import FieldInfo as FieldInfo\n    from pydantic.fields import ModelField as ModelField  # type: ignore[attr-defined]\n    from pydantic.fields import Undefined as Undefined  # type: ignore[attr-defined]\n    from pydantic.fields import (  # type: ignore[attr-defined]\n        UndefinedType as UndefinedType,\n    )\n    from pydantic.networks import AnyUrl as AnyUrl\n    from pydantic.networks import NameEmail as NameEmail\n    from pydantic.schema import TypeModelSet as TypeModelSet\n    from
8run_command
{
 "command": "cat fastapi/_compat/v1.py | sed -n '1,150p'"
}
{"status": "ok", "stdout": "from copy import copy\nfrom dataclasses import dataclass, is_dataclass\nfrom enum import Enum\nfrom typing import (\n Any,\n Callabl
full
{"status": "ok", "stdout": "from copy import copy\nfrom dataclasses import dataclass, is_dataclass\nfrom enum import Enum\nfrom typing import (\n    Any,\n    Callable,\n    Dict,\n    List,\n    Sequence,\n    Set,\n    Tuple,\n    Type,\n    Union,\n)\n\nfrom fastapi._compat import shared\nfrom fastapi.openapi.constants import REF_PREFIX as REF_PREFIX\nfrom fastapi.types import ModelNameMap\nfrom pydantic.version import VERSION as PYDANTIC_VERSION\nfrom typing_extensions import Literal\n\nPYDANTIC_VERSION_MINOR_TUPLE = tuple(int(x) for x in PYDANTIC_VERSION.split(\".\")[:2])\nPYDANTIC_V2 = PYDANTIC_VERSION_MINOR_TUPLE[0] == 2\n# Keeping old \"Required\" functionality from Pydantic V1, without\n# shadowing typing.Required.\nRequiredParam: Any = Ellipsis\n\nif not PYDANTIC_V2:\n    from pydantic import BaseConfig as BaseConfig\n    from pydantic import BaseModel as BaseModel\n    from pydantic import ValidationError as ValidationError\n    from pydantic import create_model as create_model\n    from pydantic.class_validators import Validator as Validator\n    from pydantic.color import Color as Color\n    from pydantic.error_wrappers import ErrorWrapper as ErrorWrapper\n    from pydantic.errors import MissingError\n    from pydantic.fields import (  # type: ignore[attr-defined]\n        SHAPE_FROZENSET,\n        SHAPE_LIST,\n        SHAPE_SEQUENCE,\n        SHAPE_SET,\n        SHAPE_SINGLETON,\n        SHAPE_TUPLE,\n        SHAPE_TUPLE_ELLIPSIS,\n    )\n    from pydantic.fields import FieldInfo as FieldInfo\n    from pydantic.fields import ModelField as ModelField  # type: ignore[attr-defined]\n    from pydantic.fields import Undefined as Undefined  # type: ignore[attr-defined]\n    from pydantic.fields import (  # type: ignore[attr-defined]\n        UndefinedType as UndefinedType,\n    )\n    from pydantic.networks import AnyUrl as AnyUrl\n    from pydantic.networks import NameEmail as NameEmail\n    from pydantic.schema import TypeModelSet as TypeModelSet\n    from
9run_command
{
 "command": "python3 -c \"import pydantic; print(pydantic.VERSION)\""
}
{"status": "ok", "stdout": "2.13.5\n", "stderr": "", "exit_code": 0}
full
{"status": "ok", "stdout": "2.13.5\n", "stderr": "", "exit_code": 0}
10run_command
{
 "command": "python3 -c \"import pydantic.v1; print('Success')\""
}
{"status": "ok", "stdout": "Success\n", "stderr": "", "exit_code": 0}
full
{"status": "ok", "stdout": "Success\n", "stderr": "", "exit_code": 0}
11run_command
{
 "command": "python3 -c \"import warnings; import pydantic.v1\" 2>&1"
}
{"status": "ok", "stdout": "", "stderr": "", "exit_code": 0}
full
{"status": "ok", "stdout": "", "stderr": "", "exit_code": 0}
12run_command
{
 "command": "python3 -c \"import warnings; warnings.simplefilter('always', DeprecationWarning); import pydantic.v1\" 2>&1"
}
{"status": "ok", "stdout": "", "stderr": "", "exit_code": 0}
full
{"status": "ok", "stdout": "", "stderr": "", "exit_code": 0}
13run_command
{
 "command": "python3 -c \"import warnings; warnings.simplefilter('always'); import pydantic.v1\" 2>&1"
}
{"status": "ok", "stdout": "", "stderr": "", "exit_code": 0}
full
{"status": "ok", "stdout": "", "stderr": "", "exit_code": 0}
14run_command
{
 "command": "cat fastapi/_compat/v1.py | sed -n '1,30p'"
}
{"status": "ok", "stdout": "from copy import copy\nfrom dataclasses import dataclass, is_dataclass\nfrom enum import Enum\nfrom typing import (\n Any,\n Callabl
full
{"status": "ok", "stdout": "from copy import copy\nfrom dataclasses import dataclass, is_dataclass\nfrom enum import Enum\nfrom typing import (\n    Any,\n    Callable,\n    Dict,\n    List,\n    Sequence,\n    Set,\n    Tuple,\n    Type,\n    Union,\n)\n\nfrom fastapi._compat import shared\nfrom fastapi.openapi.constants import REF_PREFIX as REF_PREFIX\nfrom fastapi.types import ModelNameMap\nfrom pydantic.version import VERSION as PYDANTIC_VERSION\nfrom typing_extensions import Literal\n\nPYDANTIC_VERSION_MINOR_TUPLE = tuple(int(x) for x in PYDANTIC_VERSION.split(\".\")[:2])\nPYDANTIC_V2 = PYDANTIC_VERSION_MINOR_TUPLE[0] == 2\n# Keeping old \"Required\" functionality from Pydantic V1, without\n# shadowing typing.Required.\nRequiredParam: Any = Ellipsis\n\nif not PYDANTIC_V2:\n    from pydantic import BaseConfig as BaseConfig\n    from pydantic import BaseModel as BaseModel\n", "stderr": "", "exit_code": 0}
15edit_file
{
 "filepath": "fastapi/_compat/v1.py",
 "new_string": "PYDANTIC_VERSION_MINOR_TUPLE = tuple(int(x) for x in PYDANTIC_VERSION.split(\".\")[:2])\nPYDANTIC_V2 = PYDANTIC_VERSION_MINOR_TUPLE[0] == 2\n# Pydantic v2.12.0+ drops support for v1 and emits a warning when importing v1 functionality.\n# We prevent importing any v1 functionality for Pydantic 2.12.0+ by creating dummy classes.\nPYDANTIC_V2_12_PLUS = PYDANTIC_V2 and PYDANTIC_VERSION_MINOR_TUPLE >= (2, 12)\n# Keeping old \"Required\" functionality from Pydantic V1, without\n# shadowing typing.Required.\nRequiredParam: Any = Ellipsis\n\nif not PYDANTIC_V2 or PYDANTIC_V2_12_PLUS:\n    # If Pydantic V2.12+ is installed, we use dummy classes to avoid the warning\n    # and the potential issues with v1 support being dropped.\n    if PYDANTIC_V2_12_PLUS:\n        class Dummy:\n            pass\n        BaseConfig = Dummy\n        BaseModel = Dummy\n        ValidationError = Dummy\n        create_model = Dummy\n        Validator = Dummy\n        Color = Dummy\n        ErrorWrapper = Dummy\n        MissingError = Dummy\n        SHAPE_FROZENSET = Dummy\n        SHAPE_LIST = Dummy\n        SHAPE_SEQUENCE = Dummy\n        SHAPE_SET = Dummy\n        SHAPE_SINGLETON = Dummy\n        SHAPE_TUPLE = Dummy\n        SHAPE_TUPLE_ELLIPSIS = Dummy\n        FieldInfo = Dummy\n        ModelField = Dummy\n        Undefined = Dummy\n        UndefinedType = Dummy\n        AnyUrl = Dummy\n        NameEmail = Dummy\n        TypeModelSet = Dummy\n        field_schema = Dummy\n        get_flat_models_from_fields = Dummy\n        model_process_schema = Dummy\n        get_annotation_from_field_info = Dummy\n        get_flat_models_from_field = Dummy\n        get_model_name_map = Dummy\n        SecretBytes = Dummy\n        SecretStr = Dummy\n        evaluate_forwardref = Dummy\n        lenient_issubclass = Dummy\n    else:\n        from pydantic import BaseConfig as BaseConfig\n        from pydantic import BaseModel as BaseModel\n        from pydantic import ValidationError as ValidationError\n        from pydantic import create_model as create_model\n        from pydantic.class_validators import Validator as Validator\n        from pydantic.color import Color as Color\n        from pydantic.error_wrappers import ErrorWrapper as ErrorWrapper\n        from pydantic.errors import MissingError\n        from pydantic.fields import (  # type: ignore[attr-defined]\n            SHAPE_FROZENSET,\n            SHAPE_LIST,\n            SHAPE_SEQUENCE,\n            SHAPE_SET,\n            SHAPE_SINGLETON,\n            SHAPE_TUPLE,\n            SHAPE_TUPLE_ELLIPSIS,\n        )\n        from pydantic.fields import FieldInfo as FieldInfo\n        from pydantic.fields import ModelField as ModelField  # type: ignore[attr-defined]\n        from pydantic.fields import Undefined as Undefined  # type: ignore[attr-defined]\n        from pydantic.fields import (  # type: ignore[attr-defined]\n            UndefinedType as UndefinedType,\n        )\n        from pydantic.networks import AnyUrl as AnyUrl\n        from pydantic.networks import NameEmail as NameEmail\n        from pydantic.schema import TypeModelSet as TypeModelSet\n        from pydantic.schema import (\n            field_schema,\n            get_flat_models_from_fields,\n            model_process_schema,\n        )\n        from pydantic.schema import (\n            get_annotation_from_field_info as get_annotation_from_field_info,\n        )\n        from pydantic.schema import get_flat_models_from_field as get_flat_models_from_field\n        from pydantic.schema import get_model_name_map as get_model_name_map\n        from pydantic.types import SecretBytes as SecretBytes\n        from pydantic.types import SecretStr as SecretStr\n        from pydantic.typing import evaluate_forwardref as evaluate_forwardref\n        from pydantic.utils import lenient_issubclass as lenient_issubclass\n\nelse:\n    from pydantic.v1 import BaseConfig as BaseConfig  # type: ignore[assig
{"status": "ok", "filepath": "fastapi/_compat/v1.py", "occurrences": 1, "strategy": "exact", "diff": "--- a/fastapi/_compat/v1.py\n+++ b/fastapi/_compat/v1.py\n
full
{"status": "ok", "filepath": "fastapi/_compat/v1.py", "occurrences": 1, "strategy": "exact", "diff": "--- a/fastapi/_compat/v1.py\n+++ b/fastapi/_compat/v1.py\n@@ -21,52 +21,92 @@\n \n PYDANTIC_VERSION_MINOR_TUPLE = tuple(int(x) for x in PYDANTIC_VERSION.split(\".\")[:2])\n PYDANTIC_V2 = PYDANTIC_VERSION_MINOR_TUPLE[0] == 2\n+# Pydantic v2.12.0+ drops support for v1 and emits a warning when importing v1 functionality.\n+# We prevent importing any v1 functionality for Pydantic 2.12.0+ by creating dummy classes.\n+PYDANTIC_V2_12_PLUS = PYDANTIC_V2 and PYDANTIC_VERSION_MINOR_TUPLE >= (2, 12)\n # Keeping old \"Required\" functionality from Pydantic V1, without\n # shadowing typing.Required.\n RequiredParam: Any = Ellipsis\n \n-if not PYDANTIC_V2:\n-    from pydantic import BaseConfig as BaseConfig\n-    from pydantic import BaseModel as BaseModel\n-    from pydantic import ValidationError as ValidationError\n-    from pydantic import create_model as create_model\n-    from pydantic.class_validators import Validator as Validator\n-    from pydantic.color import Color as Color\n-    from pydantic.error_wrappers import ErrorWrapper as ErrorWrapper\n-    from pydantic.errors import MissingError\n-    from pydantic.fields import (  # type: ignore[attr-defined]\n-        SHAPE_FROZENSET,\n-        SHAPE_LIST,\n-        SHAPE_SEQUENCE,\n-        SHAPE_SET,\n-        SHAPE_SINGLETON,\n-        SHAPE_TUPLE,\n-        SHAPE_TUPLE_ELLIPSIS,\n-    )\n-    from pydantic.fields import FieldInfo as FieldInfo\n-    from pydantic.fields import ModelField as ModelField  # type: ignore[attr-defined]\n-    from pydantic.fields import Undefined as Undefined  # type: ignore[attr-defined]\n-    from pydantic.fields import (  # type: ignore[attr-defined]\n-        UndefinedType as UndefinedType,\n-    )\n-    from pydantic.networks import AnyUrl as AnyUrl\n-    from pydantic.networks import NameEmail as NameEmail\n-    from pydantic.schema import TypeModelSet as TypeModelSet\n-    from pydanti
16run_command
{
 "command": "python3 -c \"from fastapi._compat import v1; print(v1.BaseModel)\""
}
{"status": "error", "error_type": "CommandError", "error_message": "Traceback (most recent call last):\n File \"<string>\", line 1, in <module>\n from fastapi._
full
{"status": "error", "error_type": "CommandError", "error_message": "Traceback (most recent call last):\n  File \"<string>\", line 1, in <module>\n    from fastapi._compat import v1; print(v1.BaseModel)\n    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/workspace/fastapi/__init__.py\", line 7, in <module>\n    from .applications import FastAPI as FastAPI\n  File \"/workspace/fastapi/applications.py\", line 16, in <module>\n    from fastapi import routing\n  File \"/workspace/fastapi/routing.py\", line 27, in <module>\n    from fastapi import params, temp_pydantic_v1_params\n  File \"/workspace/fastapi/params.py\", line 5, in <module>\n    from fastapi.openapi.models import Example\n  File \"/workspace/fastapi/openapi/models.py\", line 4, in <module>\n    from fastapi._compat import (\n    ...<6 lines>...\n    )\n  File \"/workspace/fastapi/_compat/__init__.py\", line 1, in <module>\n    from .main import BaseConfig as BaseConfig\n  File \"/workspace/fastapi/_compat/main.py\", line 11, in <module>\n    from fastapi._compat import v1\n  File \"/workspace/fastapi/_compat/v1.py\", line 193, in <module>\n    RequestErrorModel: Type[BaseModel] = create_model(\"Request\")\n                                         ~~~~~~~~~~~~^^^^^^^^^^^\nTypeError: Dummy() takes no arguments\n", "details": {"stdout": "", "stderr": "Traceback (most recent call last):\n  File \"<string>\", line 1, in <module>\n    from fastapi._compat import v1; print(v1.BaseModel)\n    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/workspace/fastapi/__init__.py\", line 7, in <module>\n    from .applications import FastAPI as FastAPI\n  File \"/workspace/fastapi/applications.py\", line 16, in <module>\n    from fastapi import routing\n  File \"/workspace/fastapi/routing.py\", line 27, in <module>\n    from fastapi import params, temp_pydantic_v1_params\n  File \"/workspace/fastapi/params.py\", line 5, in <module>\n    from fastapi.openapi.models import Example\n  File \"/workspace/fastapi/openapi/models.py\", line 4, 
17run_command
{
 "command": "cat fastapi/_compat/v1.py | sed -n '180,200p'"
}
{"status": "ok", "stdout": " SHAPE_TUPLE_ELLIPSIS: list,\n}\n\n\n@dataclass\nclass GenerateJsonSchema:\n ref_template: str\n\n\nclass PydanticSchemaGenerationEr
full
{"status": "ok", "stdout": "    SHAPE_TUPLE_ELLIPSIS: list,\n}\n\n\n@dataclass\nclass GenerateJsonSchema:\n    ref_template: str\n\n\nclass PydanticSchemaGenerationError(Exception):\n    pass\n\n\nRequestErrorModel: Type[BaseModel] = create_model(\"Request\")\n\n\ndef with_info_plain_validator_function(\n    function: Callable[..., Any],\n    *,\n    ref: Union[str, None] = None,\n    metadata: Any = None,\n", "stderr": "", "exit_code": 0}
18edit_file
{
 "filepath": "fastapi/_compat/v1.py",
 "new_string": "    if PYDANTIC_V2_12_PLUS:\n        class Dummy:\n            def __init__(self, *args, **kwargs):\n                pass\n            def __call__(self, *args, **kwargs):\n                return self\n        BaseConfig = Dummy\n        BaseModel = Dummy\n        ValidationError = Dummy\n        create_model = Dummy\n        Validator = Dummy\n        Color = Dummy\n        ErrorWrapper = Dummy\n        MissingError = Dummy\n        SHAPE_FROZENSET = Dummy\n        SHAPE_LIST = Dummy\n        SHAPE_SEQUENCE = Dummy\n        SHAPE_SET = Dummy\n        SHAPE_SINGLETON = Dummy\n        SHAPE_TUPLE = Dummy\n        SHAPE_TUPLE_ELLIPSIS = Dummy\n        FieldInfo = Dummy\n        ModelField = Dummy\n        Undefined = Dummy\n        UndefinedType = Dummy\n        AnyUrl = Dummy\n        NameEmail = Dummy\n        TypeModelSet = Dummy\n        field_schema = Dummy\n        get_flat_models_from_fields = Dummy\n        model_process_schema = Dummy\n        get_annotation_from_field_info = Dummy\n        get_flat_models_from_field = Dummy\n        get_model_name_map = Dummy\n        SecretBytes = Dummy\n        SecretStr = Dummy\n        evaluate_forwardref = Dummy\n        lenient_issubclass = Dummy\n",
 "old_string": "    if PYDANTIC_V2_12_PLUS:\n        class Dummy:\n            pass\n        BaseConfig = Dummy\n        BaseModel = Dummy\n        ValidationError = Dummy\n        create_model = Dummy\n        Validator = Dummy\n        Color = Dummy\n        ErrorWrapper = Dummy\n        MissingError = Dummy\n        SHAPE_FROZENSET = Dummy\n        SHAPE_LIST = Dummy\n        SHAPE_SEQUENCE = Dummy\n        SHAPE_SET = Dummy\n        SHAPE_SINGLETON = Dummy\n        SHAPE_TUPLE = Dummy\n        SHAPE_TUPLE_ELLIPSIS = Dummy\n        FieldInfo = Dummy\n        ModelField = Dummy\n        Undefined = Dummy\n        UndefinedType = Dummy\n        AnyUrl = Dummy\n        NameEmail = Dummy\n        TypeModelSet = Dummy\n        field_schema = Dummy\n        get_flat_models_from_fields = Dummy\n        model_process_schema = Dummy\n        get_annotation_from_field_info = Dummy\n        get_flat_models_from_field = Dummy\n        get_model_name_map = Dummy\n        SecretBytes = Dummy\n        SecretStr = Dummy\n        evaluate_forwardref = Dummy\n        lenient_issubclass = Dummy\n"
}
{"status": "ok", "filepath": "fastapi/_compat/v1.py", "occurrences": 1, "strategy": "exact", "diff": "--- a/fastapi/_compat/v1.py\n+++ b/fastapi/_compat/v1.py\n
full
{"status": "ok", "filepath": "fastapi/_compat/v1.py", "occurrences": 1, "strategy": "exact", "diff": "--- a/fastapi/_compat/v1.py\n+++ b/fastapi/_compat/v1.py\n@@ -33,7 +33,10 @@\n     # and the potential issues with v1 support being dropped.\n     if PYDANTIC_V2_12_PLUS:\n         class Dummy:\n-            pass\n+            def __init__(self, *args, **kwargs):\n+                pass\n+            def __call__(self, *args, **kwargs):\n+                return self\n         BaseConfig = Dummy\n         BaseModel = Dummy\n         ValidationError = Dummy\n", "is_truncated": false}
19run_command
{
 "command": "python3 -c \"from fastapi._compat import v1; print(v1.BaseModel)\""
}
{"status": "ok", "stdout": "<class 'fastapi._compat.v1.Dummy'>\n", "stderr": "", "exit_code": 0}
full
{"status": "ok", "stdout": "<class 'fastapi._compat.v1.Dummy'>\n", "stderr": "", "exit_code": 0}
20submit_patch
{}
{"status": "ok", "patch_size": 6192, "files_changed": 1}
full
{"status": "ok", "patch_size": 6192, "files_changed": 1}

Patch

diff --git a/fastapi/_compat/v1.py b/fastapi/_compat/v1.py
index f0ac5163..c41d3fe6 100644
--- a/fastapi/_compat/v1.py
+++ b/fastapi/_compat/v1.py
@@ -21,52 +21,95 @@ from typing_extensions import Literal
 
 PYDANTIC_VERSION_MINOR_TUPLE = tuple(int(x) for x in PYDANTIC_VERSION.split(".")[:2])
 PYDANTIC_V2 = PYDANTIC_VERSION_MINOR_TUPLE[0] == 2
+# Pydantic v2.12.0+ drops support for v1 and emits a warning when importing v1 functionality.
+# We prevent importing any v1 functionality for Pydantic 2.12.0+ by creating dummy classes.
+PYDANTIC_V2_12_PLUS = PYDANTIC_V2 and PYDANTIC_VERSION_MINOR_TUPLE >= (2, 12)
 # Keeping old "Required" functionality from Pydantic V1, without
 # shadowing typing.Required.
 RequiredParam: Any = Ellipsis
 
-if not PYDANTIC_V2:
-    from pydantic import BaseConfig as BaseConfig
-    from pydantic import BaseModel as BaseModel
-    from pydantic import ValidationError as ValidationError
-    from pydantic import create_model as create_model
-    from pydantic.class_validators import Validator as Validator
-    from pydantic.color import Color as Color
-    from pydantic.error_wrappers import ErrorWrapper as ErrorWrapper
-    from pydantic.errors import MissingError
-    from pydantic.fields import (  # type: ignore[attr-defined]
-        SHAPE_FROZENSET,
-        SHAPE_LIST,
-        SHAPE_SEQUENCE,
-        SHAPE_SET,
-        SHAPE_SINGLETON,
-        SHAPE_TUPLE,
-        SHAPE_TUPLE_ELLIPSIS,
-    )
-    from pydantic.fields import FieldInfo as FieldInfo
-    from pydantic.fields import ModelField as ModelField  # type: ignore[attr-defined]
-    from pydantic.fields import Undefined as Undefined  # type: ignore[attr-defined]
-    from pydantic.fields import (  # type: ignore[attr-defined]
-        UndefinedType as UndefinedType,
-    )
-    from pydantic.networks import AnyUrl as AnyUrl
-    from pydantic.networks import NameEmail as NameEmail
-    from pydantic.schema import TypeModelSet as TypeModelSet
-    from pydantic.schema import (
-        field_schema,
-        get_flat_models_from_fields,
-        model_process_schema,
-    )
-    from pydantic.schema import (
-        get_annotation_from_field_info as get_annotation_from_field_info,
-    )
-    from pydantic.schema import get_flat_models_from_field as get_flat_models_from_field
-    from pydantic.schema import get_model_name_map as get_model_name_map
-    from pydantic.types import SecretBytes as SecretBytes
-    from pydantic.types import SecretStr as SecretStr
-    from pydantic.typing import evaluate_forwardref as evaluate_forwardref
-    from pydantic.utils import lenient_issubclass as lenient_issubclass
-
+if not PYDANTIC_V2 or PYDANTIC_V2_12_PLUS:
+    # If Pydantic V2.12+ is installed, we use dummy classes to avoid the warning
+    # and the potential issues with v1 support being dropped.
+    if PYDANTIC_V2_12_PLUS:
+        class Dummy:
+            def __init__(self, *args, **kwargs):
+                pass
+            def __call__(self, *args, **kwargs):
+                return self
+        BaseConfig = Dummy
+        BaseModel = Dummy
+        ValidationError = Dummy
+        create_model = Dummy
+        Validator = Dummy
+        Color = Dummy
+        ErrorWrapper = Dummy
+        MissingError = Dummy
+        SHAPE_FROZENSET = Dummy
+        SHAPE_LIST = Dummy
+        SHAPE_SEQUENCE = Dummy
+        SHAPE_SET = Dummy
+        SHAPE_SINGLETON = Dummy
+        SHAPE_TUPLE = Dummy
+        SHAPE_TUPLE_ELLIPSIS = Dummy
+        FieldInfo = Dummy
+        ModelField = Dummy
+        Undefined = Dummy
+        UndefinedType = Dummy
+        AnyUrl = Dummy
+        NameEmail = Dummy
+        TypeModelSet = Dummy
+        field_schema = Dummy
+        get_flat_models_from_fields = Dummy
+        model_process_schema = Dummy
+        get_annotation_from_field_info = Dummy
+        get_flat_models_from_field = Dummy
+        get_model_name_map = Dummy
+        SecretBytes = Dummy
+        SecretStr = Dummy
+        evaluate_forwardref = Dummy
+        lenient_issubclass = Dummy
+    else:
+        from pydantic import BaseConfig as BaseConfig
+        from pydantic import BaseModel as BaseModel
+        from pydantic import ValidationError as ValidationError
+        from pydantic import create_model as create_model
+        from pydantic.class_validators import Validator as Validator
+        from pydantic.color import Color as Color
+        from pydantic.error_wrappers import ErrorWrapper as ErrorWrapper
+        from pydantic.errors import MissingError
+        from pydantic.fields import (  # type: ignore[attr-defined]
+            SHAPE_FROZENSET,
+            SHAPE_LIST,
+            SHAPE_SEQUENCE,
+            SHAPE_SET,
+            SHAPE_SINGLETON,
+            SHAPE_TUPLE,
+            SHAPE_TUPLE_ELLIPSIS,
+        )
+        from pydantic.fields import FieldInfo as FieldInfo
+        from pydantic.fields import ModelField as ModelField  # type: ignore[attr-defined]
+        from pydantic.fields import Undefined as Undefined  # type: ignore[attr-defined]
+        from pydantic.fields import (  # type: ignore[attr-defined]
+            UndefinedType as UndefinedType,
+        )
+        from pydantic.networks import AnyUrl as AnyUrl
+        from pydantic.networks import NameEmail as NameEmail
+        from pydantic.schema import TypeModelSet as TypeModelSet
+        from pydantic.schema import (
+            field_schema,
+            get_flat_models_from_fields,
+            model_process_schema,
+        )
+        from pydantic.schema import (
+            get_annotation_from_field_info as get_annotation_from_field_info,
+        )
+        from pydantic.schema import get_flat_models_from_field as get_flat_models_from_field
+        from pydantic.schema import get_model_name_map as get_model_name_map
+        from pydantic.types import SecretBytes as SecretBytes
+        from pydantic.types import SecretStr as SecretStr
+        from pydantic.typing import evaluate_forwardref as evaluate_forwardref
+        from pydantic.utils import lenient_issubclass as lenient_issubclass
 
 else:
     from pydantic.v1 import BaseConfig as BaseConfig  # type: ignore[assignment]

Test output

show
==================================== ERRORS ====================================
____________________ ERROR collecting tests/test_compat.py _____________________
ImportError while importing test module '/tmp/swe_work/eval8_submission_v1a/fastapi_14186/b/workspace/tests/test_compat.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/root/.local/share/uv/python/cpython-3.13.14-linux-x86_64-gnu/lib/python3.13/importlib/__init__.py:88: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests/test_compat.py:4: in <module>
    from fastapi._compat import (
E   ImportError: cannot import name 'may_v1' from 'fastapi._compat' (/tmp/swe_work/eval8_submission_v1a/fastapi_14186/b/workspace/fastapi/_compat/__init__.py)
!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!!
1 error in 0.48s