← oracle_full

fastapi_11194

failed WRONG_FIX UNSUBMITTED wrong_fix_unsubmitted(None) · None tool calls · 0 s · fastapi/fastapi

Task input

🐛 Fix validation error when `File` is declared after `Form` parameter

This PR updates the fix (6185a92) from @jsg921019 so that tests pass with the latest FastAPI code (0.110.0).
It also adds a test to cover the case with multiple files, and another to ensure the order of parameters in an endpoint definition does not affect the way FastAPI handles the request.

**Problem**
When declaring an endpoint which accepts a `File` but also a `Form` parameter, the `File` parameter must be declared first or the endpoint would respond with error 422.

**Context**
- See discussion #9116
- And probably also #4625

Tool calls (0)

#ToolArgumentsResult
No trace captured.

Patch

--- a/fastapi/dependencies/utils.py
+++ b/fastapi/dependencies/utils.py
@@ -872,20 +872,19 @@ async def _extract_form_body(
     received_body: FormData,
 ) -> Dict[str, Any]:
     values = {}
-    first_field = body_fields[0]
-    first_field_info = first_field.field_info
 
     for field in body_fields:
         value = _get_multidict_value(field, received_body)
+        field_info = field.field_info
         if (
-            isinstance(first_field_info, params.File)
+            isinstance(field_info, params.File)
             and is_bytes_field(field)
             and isinstance(value, UploadFile)
         ):
             value = await value.read()
         elif (
             is_bytes_sequence_field(field)
-            and isinstance(first_field_info, params.File)
+            and isinstance(field_info, params.File)
             and value_is_sequence(value)
         ):
             # For types

Test output

show
==================================== ERRORS ====================================
________ ERROR collecting tests/test_file_and_form_order_issue_9116.py _________
tests/test_file_and_form_order_issue_9116.py:17: in <module>
    @app.post("/file_before_form")
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
fastapi/routing.py:1001: in decorator
    self.add_api_route(
fastapi/routing.py:940: in add_api_route
    route = route_class(
fastapi/routing.py:561: in __init__
    self.dependant = get_dependant(path=self.path_format, call=self.endpoint)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
fastapi/dependencies/utils.py:293: in get_dependant
    param_details = analyze_param(
fastapi/dependencies/utils.py:490: in analyze_param
    ensure_multipart_is_installed()
fastapi/dependencies/utils.py:121: in ensure_multipart_is_installed
    raise RuntimeError(multipart_not_installed_error) from None
E   RuntimeError: Form data requires "python-multipart" to be installed. 
E   You can install "python-multipart" with: 
E   
E   pip install python-multipart
=============================== warnings summary ===============================
../../../../../../../Users/jp/repos/kaggle-gemini-coding-agent-post-training/.envs/overlays/starlette-0.48.0-py3-none-any/starlette/testclient.py:51
  /Users/jp/repos/kaggle-gemini-coding-agent-post-training/.envs/overlays/starlette-0.48.0-py3-none-any/starlette/testclient.py:51: 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 !!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!
1 warning, 1 error in 0.54s