← or20_qwen27b_v2

fastapi_14794

failed NO_PATCH NO_PATCH UNSUBMITTED agent_error · 9 tool calls · 263 s · fastapi/fastapi

Task input

✨ Allow `Response` type hint as dependency annotation

## Summary
Fixes #10127

Using `Response` as a type hint with `Depends` would fail with an assertion error:
```python
def endpoint(response: Annotated[Response, Depends(modify_response)]):
    # AssertionError: Cannot specify \`Depends\` for type Response
```

## Changes
Modified the type annotation handling in `analyze_param()` to check for `Depends` before applying special type handling. When a `Depends` is specified, the dependency is called normally and its return value used.

## Usage
Now supports:
- `response: Annotated[Response, Depends(modify_response)]`
- `response: Response = Depends(modify_response)`

While still supporting regular injection:
- `response: Response`

## Testing
Added comprehensive tests in `tests/test_response_dependency.py`

Tool calls (9)

#ToolArgumentsResult
1run_command
{
 "command": "grep -rn \"Cannot specify\" /workspace/fastapi --include=*.py"
}
{"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}}
2run_command
{
 "command": "grep -rn \"analyze_param\" /workspace/fastapi --include=*.py | head -20"
}
{"status": "ok", "stdout": "", "exit_code": 0}
full
{"status": "ok", "stdout": "", "exit_code": 0}
3run_command
{
 "command": "grep -rn \"Cannot specify\" /workspace --include=*.py | head; ls /workspace"
}
{"status": "error", "error_type": "CommandError", "error_message": "Command failed with exit code 1", "details": {"stdout": "", "stderr": "ls: /tmp/swe_work/or2
full
{"status": "error", "error_type": "CommandError", "error_message": "Command failed with exit code 1", "details": {"stdout": "", "stderr": "ls: /tmp/swe_work/or20_qwen27b_v2/fastapi_14794/a/workspace: No such file or directory\n", "exit_code": 1}}
4run_command
{
 "command": "pwd; ls"
}
{"status": "ok", "stdout": "/private/workspace\nCITATION.cff\nCONTRIBUTING.md\ndocs\ndocs_src\nfastapi\nLICENSE\npdm_build.py\npyproject.toml\npytest.ini\nREADM
full
{"status": "ok", "stdout": "/private/workspace\nCITATION.cff\nCONTRIBUTING.md\ndocs\ndocs_src\nfastapi\nLICENSE\npdm_build.py\npyproject.toml\npytest.ini\nREADME.md\nscripts\nSECURITY.md\ntests\nuv.lock\n", "exit_code": 0}
5run_command
{
 "command": "grep -rn \"Cannot specify\" fastapi --include=*.py | head"
}
{"status": "ok", "stdout": "fastapi/dependencies/utils.py:320: f\"Cannot specify multiple FastAPI annotations for {param_name!r}\"\nfastapi/dependencies/utils.p
full
{"status": "ok", "stdout": "fastapi/dependencies/utils.py:320:                f\"Cannot specify multiple FastAPI annotations for {param_name!r}\"\nfastapi/dependencies/utils.py:427:            \"Cannot specify `Depends` in `Annotated` and default value\"\nfastapi/dependencies/utils.py:431:            \"Cannot specify a FastAPI annotation in `Annotated` and `Depends` as a\"\nfastapi/dependencies/utils.py:438:            \"Cannot specify FastAPI annotations in `Annotated` and default value\"\nfastapi/dependencies/utils.py:463:        assert depends is None, f\"Cannot specify `Depends` for type {type_annotation!r}\"\nfastapi/dependencies/utils.py:465:            f\"Cannot specify FastAPI annotation for type {type_annotation!r}\"\n", "exit_code": 0}
6read_file
{
 "filepath": "fastapi/dependencies/utils.py",
 "start_line": 380,
 "end_line": 520
}
{"status": "ok", "filepath": "fastapi/dependencies/utils.py", "content": " fastapi_annotations = [\n arg\n for arg in annotated_args[1:]\n if isinstance(arg, (F
full
{"status": "ok", "filepath": "fastapi/dependencies/utils.py", "content": "        fastapi_annotations = [\n            arg\n            for arg in annotated_args[1:]\n            if isinstance(arg, (FieldInfo, params.Depends))\n        ]\n        fastapi_specific_annotations = [\n            arg\n            for arg in fastapi_annotations\n            if isinstance(\n                arg,\n                (\n                    params.Param,\n                    params.Body,\n                    params.Depends,\n                ),\n            )\n        ]\n        if fastapi_specific_annotations:\n            fastapi_annotation: Union[FieldInfo, params.Depends, None] = (\n                fastapi_specific_annotations[-1]\n            )\n        else:\n            fastapi_annotation = None\n        # Set default for Annotated FieldInfo\n        if isinstance(fastapi_annotation, FieldInfo):\n            # Copy `field_info` because we mutate `field_info.default` below.\n            field_info = copy_field_info(\n                field_info=fastapi_annotation,\n                annotation=use_annotation,\n            )\n            assert (\n                field_info.default == Undefined or field_info.default == RequiredParam\n            ), (\n                f\"`{field_info.__class__.__name__}` default value cannot be set in\"\n                f\" `Annotated` for {param_name!r}. Set the default value with `=` instead.\"\n            )\n            if value is not inspect.Signature.empty:\n                assert not is_path_param, \"Path parameters cannot have default values\"\n                field_info.default = value\n            else:\n                field_info.default = RequiredParam\n        # Get Annotated Depends\n        elif isinstance(fastapi_annotation, params.Depends):\n            depends = fastapi_annotation\n    # Get Depends from default value\n    if isinstance(value, params.Depends):\n        assert depends is None, (\n            \"Cannot specify `De
7read_file
{
 "filepath": "fastapi/dependencies/utils.py",
 "start_line": 520,
 "end_line": 640
}
{"status": "ok", "filepath": "fastapi/dependencies/utils.py", "content": " is_scalar_field(field)\n or is_scalar_sequence_field(field)\n or (\n lenient_issubcla
full
{"status": "ok", "filepath": "fastapi/dependencies/utils.py", "content": "                is_scalar_field(field)\n                or is_scalar_sequence_field(field)\n                or (\n                    lenient_issubclass(field.type_, BaseModel)\n                    # For Pydantic v1\n                    and getattr(field, \"shape\", 1) == 1\n                )\n            ), f\"Query parameter {param_name!r} must be one of the supported types\"\n\n    return ParamDetails(type_annotation=type_annotation, depends=depends, field=field)\n\n\ndef add_param_to_fields(*, field: ModelField, dependant: Dependant) -> None:\n    field_info = field.field_info\n    field_info_in = getattr(field_info, \"in_\", None)\n    if field_info_in == params.ParamTypes.path:\n        dependant.path_params.append(field)\n    elif field_info_in == params.ParamTypes.query:\n        dependant.query_params.append(field)\n    elif field_info_in == params.ParamTypes.header:\n        dependant.header_params.append(field)\n    else:\n        assert field_info_in == params.ParamTypes.cookie, (\n            f\"non-body parameters must be in path, query, header or cookie: {field.name}\"\n        )\n        dependant.cookie_params.append(field)\n\n\nasync def _solve_generator(\n    *, dependant: Dependant, stack: AsyncExitStack, sub_values: dict[str, Any]\n) -> Any:\n    assert dependant.call\n    if dependant.is_async_gen_callable:\n        cm = asynccontextmanager(dependant.call)(**sub_values)\n    elif dependant.is_gen_callable:\n        cm = contextmanager_in_threadpool(contextmanager(dependant.call)(**sub_values))\n    return await stack.enter_async_context(cm)\n\n\n@dataclass\nclass SolvedDependency:\n    values: dict[str, Any]\n    errors: list[Any]\n    background_tasks: Optional[StarletteBackgroundTasks]\n    response: Response\n    dependency_cache: dict[DependencyCacheKey, Any]\n\n\nasync def solve_dependencies(\n    *,\n    request: Union[Request, WebSocket],\n    dependant: Dependant,
8read_file
{
 "filepath": "fastapi/dependencies/utils.py",
 "start_line": 640,
 "end_line": 760
}
{"status": "ok", "filepath": "fastapi/dependencies/utils.py", "content": " if sub_dependant.scope == \"function\":\n use_astack = function_astack\n solved = awa
full
{"status": "ok", "filepath": "fastapi/dependencies/utils.py", "content": "            if sub_dependant.scope == \"function\":\n                use_astack = function_astack\n            solved = await _solve_generator(\n                dependant=use_sub_dependant,\n                stack=use_astack,\n                sub_values=solved_result.values,\n            )\n        elif use_sub_dependant.is_coroutine_callable:\n            solved = await call(**solved_result.values)\n        else:\n            solved = await run_in_threadpool(call, **solved_result.values)\n        if sub_dependant.name is not None:\n            values[sub_dependant.name] = solved\n        if sub_dependant.cache_key not in dependency_cache:\n            dependency_cache[sub_dependant.cache_key] = solved\n    path_values, path_errors = request_params_to_args(\n        dependant.path_params, request.path_params\n    )\n    query_values, query_errors = request_params_to_args(\n        dependant.query_params, request.query_params\n    )\n    header_values, header_errors = request_params_to_args(\n        dependant.header_params, request.headers\n    )\n    cookie_values, cookie_errors = request_params_to_args(\n        dependant.cookie_params, request.cookies\n    )\n    values.update(path_values)\n    values.update(query_values)\n    values.update(header_values)\n    values.update(cookie_values)\n    errors += path_errors + query_errors + header_errors + cookie_errors\n    if dependant.body_params:\n        (\n            body_values,\n            body_errors,\n        ) = await request_body_to_args(  # body_params checked above\n            body_fields=dependant.body_params,\n            received_body=body,\n            embed_body_fields=embed_body_fields,\n        )\n        values.update(body_values)\n        errors.extend(body_errors)\n    if dependant.http_connection_param_name:\n        values[dependant.http_connection_param_name] = request\n    if dependant.request_param_name and isinstance(
9read_file
{
 "filepath": "fastapi/dependencies/utils.py",
 "start_line": 280,
 "end_line": 380
}
{"status": "ok", "filepath": "fastapi/dependencies/utils.py", "content": " is_path_param = param_name in path_param_names\n param_details = analyze_param(\n par
full
{"status": "ok", "filepath": "fastapi/dependencies/utils.py", "content": "        is_path_param = param_name in path_param_names\n        param_details = analyze_param(\n            param_name=param_name,\n            annotation=param.annotation,\n            value=param.default,\n            is_path_param=is_path_param,\n        )\n        if param_details.depends is not None:\n            assert param_details.depends.dependency\n            if (\n                (dependant.is_gen_callable or dependant.is_async_gen_callable)\n                and dependant.computed_scope == \"request\"\n                and param_details.depends.scope == \"function\"\n            ):\n                assert dependant.call\n                raise DependencyScopeError(\n                    f'The dependency \"{dependant.call.__name__}\" has a scope of '\n                    '\"request\", it cannot depend on dependencies with scope \"function\".'\n                )\n            sub_own_oauth_scopes: list[str] = []\n            if isinstance(param_details.depends, params.Security):\n                if param_details.depends.scopes:\n                    sub_own_oauth_scopes = list(param_details.depends.scopes)\n            sub_dependant = get_dependant(\n                path=path,\n                call=param_details.depends.dependency,\n                name=param_name,\n                own_oauth_scopes=sub_own_oauth_scopes,\n                parent_oauth_scopes=current_scopes,\n                use_cache=param_details.depends.use_cache,\n                scope=param_details.depends.scope,\n            )\n            dependant.dependencies.append(sub_dependant)\n            continue\n        if add_non_field_param_to_dependency(\n            param_name=param_name,\n            type_annotation=param_details.type_annotation,\n            dependant=dependant,\n        ):\n            assert param_details.field is None, (\n                f\"Cannot specify multiple FastAPI annotations for {param_name