failed WRONG_FIX wrong_fix · 14 tool calls · 76 s · fastapi/fastapi
✨ Add support for PEP695 `TypeAliasType` This is a continuation of #11140 with the comment by @Viicos fixed by vendoring a copy of `is_typealiastype` from [`typing-inspection`](https://github.com/pydantic/typing-inspection).
| # | Tool | Arguments | Result |
|---|---|---|---|
| 1 | run_command | {
"command": "grep -rn \"TypeAlias\" . | head -20"
} | {"status": "ok", "stdout": "", "exit_code": 0}full{"status": "ok", "stdout": "", "exit_code": 0} |
| 2 | run_command | {
"command": "grep -rn \"get_type_hints\" . | head -20"
} | {"status": "ok", "stdout": "", "exit_code": 0}full{"status": "ok", "stdout": "", "exit_code": 0} |
| 3 | run_command | {
"command": "find . -maxdepth 3 -type d"
} | {"status": "ok", "stdout": ".\n./fastapi\n./fastapi/dependencies\n./fastapi/_compat\n./fastapi/security\n./fastapi/middleware\n./fastapi/openapi\n./scripts\n./sfull{"status": "ok", "stdout": ".\n./fastapi\n./fastapi/dependencies\n./fastapi/_compat\n./fastapi/security\n./fastapi/middleware\n./fastapi/openapi\n./scripts\n./scripts/tests\n./scripts/tests/test_translation_fixer\n./scripts/playwright\n./scripts/playwright/cookie_param_models\n./scripts/playwright/query_param_models\n./scripts/playwright/sql_databases\n./scripts/playwright/separate_openapi_schemas\n./scripts/playwright/header_param_models\n./scripts/playwright/request_form_models\n./tests\n./tests/test_request_params\n./tests/test_request_params/test_file\n./tests/test_request_params/test_form\n./tests/test_request_params/test_cookie\n./tests/test_request_params/test_path\n./tests/test_request_params/test_body\n./tests/test_request_params/test_query\n./tests/test_request_params/test_header\n./tests/test_modules_same_name_body\n./tests/test_modules_same_name_body/app\n./tests/benchmarks\n./tests/test_validate_response_recursive\n./tests/test_tutorial\n./tests/test_tutorial/test_request_forms_and_files\n./tests/test_tutorial/test_header_param_models\n./tests/test_tutorial/test_cookie_params\n./tests/test_tutorial/test_schema_extra_example\n./tests/test_tutorial/test_response_model\n./tests/test_tutorial/test_encoder\n./tests/test_tutorial/test_middleware\n./tests/test_tutorial/test_response_change_status_code\n./tests/test_tutorial/test_body_updates\n./tests/test_tutorial/test_body_multiple_params\n./tests/test_tutorial/test_events\n./tests/test_tutorial/test_openapi_webhooks\n./tests/test_tutorial/test_request_files\n./tests/test_tutorial/test_async_tests\n./tests/test_tutorial/test_settings\n./tests/test_tutorial/test_security\n./tests/test_tutorial/test_python_types\n./tests/test_tutorial/test_additional_status_codes\n./tests/test_tutorial/test_body_nested_models\n./tests/test_tutorial/test_path_operation_configurations\n./tests/test_tutorial/test_conditional_openapi\n./tests/test_tutorial/test_dependencies\n./tests/test_tutorial/test_header_params\n./tests/test_tu |
| 4 | run_command | {
"command": "grep -rn \"typing\" fastapi | head -20"
} | {"status": "ok", "stdout": "fastapi/datastructures.py:2:from typing import (\nfastapi/datastructures.py:39: from typing import Annotated\nfastapi/dependencies/mfull{"status": "ok", "stdout": "fastapi/datastructures.py:2:from typing import (\nfastapi/datastructures.py:39: from typing import Annotated\nfastapi/dependencies/models.py:5:from typing import Any, Callable, Optional, Union\nfastapi/dependencies/models.py:10:from typing_extensions import Literal\nfastapi/dependencies/utils.py:8:from typing import (\nfastapi/dependencies/utils.py:68:from typing_extensions import Literal, get_args, get_origin\nfastapi/dependencies/utils.py:838: # Check if it's a Union type (covers both typing.Union and types.UnionType in Python 3.10+)\nfastapi/_compat/shared.py:3:import typing\nfastapi/_compat/shared.py:8:from typing import (\nfastapi/_compat/shared.py:18:from typing_extensions import get_args, get_origin\nfastapi/_compat/shared.py:20:# Copy from Pydantic: pydantic/_internal/_typing_extra.py\nfastapi/_compat/shared.py:22: WithArgsTypes: tuple[Any, ...] = (typing._GenericAlias, types.GenericAlias) # type: ignore[attr-defined]\nfastapi/_compat/shared.py:25: typing._GenericAlias, # type: ignore[attr-defined]\nfastapi/_compat/v2.py:8:from typing import (\nfastapi/_compat/v2.py:25:from pydantic._internal._typing_extra import eval_type_lenient\nfastapi/_compat/v2.py:33:from typing_extensions import Literal, get_args, get_origin\nfastapi/applications.py:3:from typing import (\nfastapi/applications.py:43:from typing_extensions import deprecated\nfastapi/applications.py:4602: from typing import Awaitable, Callable\nfastapi/exceptions.py:2:from typing import Annotated, Any, Optional, TypedDict, Union\n", "exit_code": 0} |
| 5 | read_file | {
"filepath": "fastapi/_compat/shared.py",
"start_line": 1,
"end_line": 40
} | {"status": "ok", "filepath": "fastapi/_compat/shared.py", "content": "import sys\nimport types\nimport typing\nimport warnings\nfrom collections import deque\nffull{"status": "ok", "filepath": "fastapi/_compat/shared.py", "content": "import sys\nimport types\nimport typing\nimport warnings\nfrom collections import deque\nfrom collections.abc import Mapping, Sequence\nfrom dataclasses import is_dataclass\nfrom typing import (\n Annotated,\n Any,\n Union,\n)\n\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 get_args, get_origin\n\n# Copy from Pydantic: pydantic/_internal/_typing_extra.py\nif 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 tuple: tuple,\n set: set,\n frozenset: frozenset,\n deque: deque,\n", "start_line": 1, "end_line": 40, "total_lines": 206, "is_truncated": false} |
| 6 | run_command | {
"command": "grep -rn \"get_origin\" fastapi | head -20"
} | {"status": "ok", "stdout": "fastapi/dependencies/utils.py:68:from typing_extensions import Literal, get_args, get_origin\nfastapi/dependencies/utils.py:377: if full{"status": "ok", "stdout": "fastapi/dependencies/utils.py:68:from typing_extensions import Literal, get_args, get_origin\nfastapi/dependencies/utils.py:377: if get_origin(use_annotation) is Annotated:\nfastapi/dependencies/utils.py:836: origin = get_origin(field_type)\nfastapi/_compat/shared.py:18:from typing_extensions import get_args, get_origin\nfastapi/_compat/shared.py:67: origin = get_origin(annotation)\nfastapi/_compat/shared.py:74: get_origin(annotation)\nfastapi/_compat/shared.py:91: origin = get_origin(annotation)\nfastapi/_compat/shared.py:112: origin = get_origin(annotation)\nfastapi/_compat/shared.py:131: origin = get_origin(annotation)\nfastapi/_compat/shared.py:142: origin = get_origin(annotation)\nfastapi/_compat/shared.py:151: origin = get_origin(annotation)\nfastapi/_compat/shared.py:166: origin = get_origin(annotation)\nfastapi/_compat/shared.py:197: origin = get_origin(annotation)\nfastapi/_compat/v2.py:33:from typing_extensions import Literal, get_args, get_origin\nfastapi/_compat/v2.py:432: origin_type = get_origin(field.field_info.annotation) or field.field_info.annotation\nfastapi/_compat/v2.py:438: origin_type = get_origin(union_arg) or union_arg\nfastapi/_compat/v2.py:525: origin = get_origin(annotation)\n", "exit_code": 0} |
| 7 | read_file | {
"end_line": 206,
"filepath": "fastapi/_compat/shared.py",
"start_line": 41
} | {"status": "ok", "filepath": "fastapi/_compat/shared.py", "content": "}\n\nsequence_types = tuple(sequence_annotation_to_type.keys())\n\nUrl: type[Any]\n\n\n# Cfull{"status": "ok", "filepath": "fastapi/_compat/shared.py", "content": "}\n\nsequence_types = tuple(sequence_annotation_to_type.keys())\n\nUrl: type[Any]\n\n\n# Copy of Pydantic: pydantic/_internal/_utils.py\ndef lenient_issubclass(\n cls: Any, class_or_tuple: Union[type[Any], tuple[type[Any], ...], None]\n) -> bool:\n try:\n return isinstance(cls, type) and issubclass(cls, class_or_tuple) # type: ignore[arg-type]\n except TypeError: # pragma: no cover\n if isinstance(cls, WithArgsTypes):\n return False\n raise # pragma: no cover\n\n\ndef _annotation_is_sequence(annotation: Union[type[Any], None]) -> bool:\n if lenient_issubclass(annotation, (str, bytes)):\n return False\n return lenient_issubclass(annotation, sequence_types)\n\n\ndef field_annotation_is_sequence(annotation: Union[type[Any], None]) -> bool:\n origin = get_origin(annotation)\n if origin is Union or origin is UnionType:\n for arg in get_args(annotation):\n if field_annotation_is_sequence(arg):\n return True\n return False\n return _annotation_is_sequence(annotation) or _annotation_is_sequence(\n get_origin(annotation)\n )\n\n\ndef value_is_sequence(value: Any) -> bool:\n return isinstance(value, sequence_types) and not isinstance(value, (str, bytes))\n\n\ndef _annotation_is_complex(annotation: Union[type[Any], None]) -> bool:\n return (\n lenient_issubclass(annotation, (BaseModel, Mapping, UploadFile))\n or _annotation_is_sequence(annotation)\n or is_dataclass(annotation)\n )\n\n\ndef field_annotation_is_complex(annotation: Union[type[Any], None]) -> bool:\n origin = get_origin(annotation)\n if origin is Union or origin is UnionType:\n return any(field_annotation_is_complex(arg) for arg in get_args(annotation))\n\n if origin is Annotated:\n return field_annotation_is_complex(get_args(annotation)[0])\n\n return (\n _annotation_i |
| 8 | run_command | {
"command": "grep -rn \"is_typealiastype\" ."
} | {"status": "error", "error_type": "CommandError", "error_message": "Command failed with exit code 1", "details": {"stdout": "", "stderr": "", "exit_code": 1}}full{"status": "error", "error_type": "CommandError", "error_message": "Command failed with exit code 1", "details": {"stdout": "", "stderr": "", "exit_code": 1}} |
| 9 | run_command | {
"command": "grep -rn \"is_typealias\" ."
} | {"status": "error", "error_type": "CommandError", "error_message": "Command failed with exit code 1", "details": {"stdout": "", "stderr": "", "exit_code": 1}}full{"status": "error", "error_type": "CommandError", "error_message": "Command failed with exit code 1", "details": {"stdout": "", "stderr": "", "exit_code": 1}} |
| 10 | read_file | {
"filepath": "fastapi/_compat/shared.py"
} | {"status": "ok", "filepath": "fastapi/_compat/shared.py", "content": "import sys\nimport types\nimport typing\nimport warnings\nfrom collections import deque\nffull{"status": "ok", "filepath": "fastapi/_compat/shared.py", "content": "import sys\nimport types\nimport typing\nimport warnings\nfrom collections import deque\nfrom collections.abc import Mapping, Sequence\nfrom dataclasses import is_dataclass\nfrom typing import (\n Annotated,\n Any,\n Union,\n)\n\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 get_args, get_origin\n\n# Copy from Pydantic: pydantic/_internal/_typing_extra.py\nif 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 tuple: tuple,\n set: set,\n frozenset: frozenset,\n deque: deque,\n}\n\nsequence_types = tuple(sequence_annotation_to_type.keys())\n\nUrl: type[Any]\n\n\n# Copy of Pydantic: pydantic/_internal/_utils.py\ndef lenient_issubclass(\n cls: Any, class_or_tuple: Union[type[Any], tuple[type[Any], ...], None]\n) -> bool:\n try:\n return isinstance(cls, type) and issubclass(cls, class_or_tuple) # type: ignore[arg-type]\n except TypeError: # pragma: no cover\n if isinstance(cls, WithArgsTypes):\n return False\n raise # pragma: no cover\n\n\ndef _annotation_is_sequence(annotation: Union[type[Any], None]) -> bool:\n if lenient_issubclass(annotation, (str, bytes)):\n return False\n return lenient_issubclass(annotation, sequence_types)\n\n\ndef field_annotati |
| 11 | edit_file | {
"filepath": "fastapi/_compat/shared.py",
"new_string": "else:\n WithArgsTypes: tuple[Any, ...] = (\n typing._GenericAlias, # type: ignore[attr-defined]\n types.GenericAlias,\n types.UnionType,\n getattr(types, \"TypeAliasType\", types.GenericAlias),\n ) # pyright: ignore[reportAttributeAccessIssue]",
"old_string": "else:\n WithArgsTypes: tuple[Any, ...] = (\n typing._GenericAlias, # type: ignore[attr-defined]\n types.GenericAlias,\n types.UnionType,\n ) # pyright: ignore[reportAttributeAccessIssue]"
} | {"status": "ok", "filepath": "fastapi/_compat/shared.py", "occurrences": 1, "strategy": "exact", "diff": "--- a/fastapi/_compat/shared.py\n+++ b/fastapi/_compatfull{"status": "ok", "filepath": "fastapi/_compat/shared.py", "occurrences": 1, "strategy": "exact", "diff": "--- a/fastapi/_compat/shared.py\n+++ b/fastapi/_compat/shared.py\n@@ -25,6 +25,7 @@\n typing._GenericAlias, # type: ignore[attr-defined]\n types.GenericAlias,\n types.UnionType,\n+ getattr(types, \"TypeAliasType\", types.GenericAlias),\n ) # pyright: ignore[reportAttributeAccessIssue]\n \n PYDANTIC_VERSION_MINOR_TUPLE = tuple(int(x) for x in PYDANTIC_VERSION.split(\".\")[:2])\n", "is_truncated": false} |
| 12 | edit_file | {
"filepath": "fastapi/_compat/shared.py",
"new_string": "def is_typealiastype(annotation: Any) -> bool:\n return isinstance(annotation, getattr(types, \"TypeAliasType\", type(None)))\n\n\n# Copy of Pydantic: pydantic/_internal/_utils.py",
"old_string": "# Copy of Pydantic: pydantic/_internal/_utils.py"
} | {"status": "ok", "filepath": "fastapi/_compat/shared.py", "occurrences": 1, "strategy": "exact", "diff": "--- a/fastapi/_compat/shared.py\n+++ b/fastapi/_compatfull{"status": "ok", "filepath": "fastapi/_compat/shared.py", "occurrences": 1, "strategy": "exact", "diff": "--- a/fastapi/_compat/shared.py\n+++ b/fastapi/_compat/shared.py\n@@ -46,6 +46,10 @@\n Url: type[Any]\n \n \n+def is_typealiastype(annotation: Any) -> bool:\n+ return isinstance(annotation, getattr(types, \"TypeAliasType\", type(None)))\n+\n+\n # Copy of Pydantic: pydantic/_internal/_utils.py\n def lenient_issubclass(\n cls: Any, class_or_tuple: Union[type[Any], tuple[type[Any], ...], None]\n", "is_truncated": false} |
| 13 | edit_file | {
"filepath": "fastapi/_compat/shared.py",
"new_string": "def field_annotation_is_sequence(annotation: Union[type[Any], None]) -> bool:\n if is_typealiastype(annotation):\n return field_annotation_is_sequence(annotation.__value__)\n origin = get_origin(annotation)\n if origin is Union or origin is UnionType:",
"old_string": "def field_annotation_is_sequence(annotation: Union[type[Any], None]) -> bool:\n origin = get_origin(annotation)\n if origin is Union or origin is UnionType:"
} | {"status": "ok", "filepath": "fastapi/_compat/shared.py", "occurrences": 1, "strategy": "exact", "diff": "--- a/fastapi/_compat/shared.py\n+++ b/fastapi/_compatfull{"status": "ok", "filepath": "fastapi/_compat/shared.py", "occurrences": 1, "strategy": "exact", "diff": "--- a/fastapi/_compat/shared.py\n+++ b/fastapi/_compat/shared.py\n@@ -69,6 +69,8 @@\n \n \n def field_annotation_is_sequence(annotation: Union[type[Any], None]) -> bool:\n+ if is_typealiastype(annotation):\n+ return field_annotation_is_sequence(annotation.__value__)\n origin = get_origin(annotation)\n if origin is Union or origin is UnionType:\n for arg in get_args(annotation):\n", "is_truncated": false} |
| 14 | edit_file | {
"filepath": "fastapi/_compat/shared.py",
"new_string": "def field_annotation_is_complex(annotation: Union[type[Any], None]) -> bool:\n if is_typealiastype(annotation):\n return field_annotation_is_complex(annotation.__value__)\n origin = get_origin(annotation)\n if origin is Union or origin is UnionType:",
"old_string": "def field_annotation_is_complex(annotation: Union[type[Any], None]) -> bool:\n origin = get_origin(annotation)\n if origin is Union or origin is UnionType:"
} | {"status": "ok", "filepath": "fastapi/_compat/shared.py", "occurrences": 1, "strategy": "exact", "diff": "--- a/fastapi/_compat/shared.py\n+++ b/fastapi/_compatfull{"status": "ok", "filepath": "fastapi/_compat/shared.py", "occurrences": 1, "strategy": "exact", "diff": "--- a/fastapi/_compat/shared.py\n+++ b/fastapi/_compat/shared.py\n@@ -95,6 +95,8 @@\n \n \n def field_annotation_is_complex(annotation: Union[type[Any], None]) -> bool:\n+ if is_typealiastype(annotation):\n+ return field_annotation_is_complex(annotation.__value__)\n origin = get_origin(annotation)\n if origin is Union or origin is UnionType:\n return any(field_annotation_is_complex(arg) for arg in get_args(annotation))\n", "is_truncated": false} |
| 15 | submit_patch | [] | {"status": "ok", "patch_size": 1743, "files_changed": 1}full{"status": "ok", "patch_size": 1743, "files_changed": 1} |
diff --git a/fastapi/_compat/shared.py b/fastapi/_compat/shared.py
index 68b9bbdf..9850f5f3 100644
--- a/fastapi/_compat/shared.py
+++ b/fastapi/_compat/shared.py
@@ -25,6 +25,7 @@ else:
typing._GenericAlias, # type: ignore[attr-defined]
types.GenericAlias,
types.UnionType,
+ getattr(types, "TypeAliasType", types.GenericAlias),
) # pyright: ignore[reportAttributeAccessIssue]
PYDANTIC_VERSION_MINOR_TUPLE = tuple(int(x) for x in PYDANTIC_VERSION.split(".")[:2])
@@ -45,6 +46,10 @@ sequence_types = tuple(sequence_annotation_to_type.keys())
Url: type[Any]
+def is_typealiastype(annotation: Any) -> bool:
+ return isinstance(annotation, getattr(types, "TypeAliasType", type(None)))
+
+
# Copy of Pydantic: pydantic/_internal/_utils.py
def lenient_issubclass(
cls: Any, class_or_tuple: Union[type[Any], tuple[type[Any], ...], None]
@@ -64,6 +69,8 @@ def _annotation_is_sequence(annotation: Union[type[Any], None]) -> bool:
def field_annotation_is_sequence(annotation: Union[type[Any], None]) -> bool:
+ if is_typealiastype(annotation):
+ return field_annotation_is_sequence(annotation.__value__)
origin = get_origin(annotation)
if origin is Union or origin is UnionType:
for arg in get_args(annotation):
@@ -88,6 +95,8 @@ def _annotation_is_complex(annotation: Union[type[Any], None]) -> bool:
def field_annotation_is_complex(annotation: Union[type[Any], None]) -> bool:
+ if is_typealiastype(annotation):
+ return field_annotation_is_complex(annotation.__value__)
origin = get_origin(annotation)
if origin is Union or origin is UnionType:
return any(field_annotation_is_complex(arg) for arg in get_args(annotation))
F
=================================== FAILURES ===================================
________________________ test_pep695_type_dependencies _________________________
def test_pep695_type_dependencies():
app = FastAPI()
@app.get("/")
async def get_with_dep(value: DependedValue) -> str: # noqa
return f"value: {value}"
client = TestClient(app)
response = client.get("/")
> assert response.status_code == 200
E assert 422 == 200
E + where 422 = <Response [422 Unprocessable Entity]>.status_code
tests/test_dependency_pep695.py:26: AssertionError
=============================== warnings summary ===============================
../../../../../../kaggle/tmp/envs/overlays/starlette-0.50.0-py3-none-any/starlette/testclient.py:45
/kaggle/tmp/envs/overlays/starlette-0.50.0-py3-none-any/starlette/testclient.py:45: DeprecationWarning: The anyio.abc.BlockingPortal alias is deprecated, use anyio.from_thread.BlockingPortal instead.
_PortalFactoryType = Callable[[], AbstractContextManager[anyio.abc.BlockingPortal]]
-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!!
1 failed, 1 warning in 0.73s