From 94880bf530f9e34bd6aeff8bd8c6bd628b844fba Mon Sep 17 00:00:00 2001 From: hungtsetse Date: Sat, 6 Jan 2024 09:55:59 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Fix=20File=20field=20cannot=20be?= =?UTF-8?q?=20defined=20after=20Form=20field?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/dependencies/utils.py | 1 + tests/test_datastructures.py | 42 ++++++++++++++++++++++++++++++----- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index b73473484..559b4621c 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -713,6 +713,7 @@ async def request_body_to_args( except AttributeError: errors.append(get_missing_field_error(loc)) continue + field_info = field.field_info if ( value is None or (isinstance(field_info, params.Form) and value == "") diff --git a/tests/test_datastructures.py b/tests/test_datastructures.py index 7e57d525c..8f1ee2f38 100644 --- a/tests/test_datastructures.py +++ b/tests/test_datastructures.py @@ -3,7 +3,7 @@ from pathlib import Path from typing import List import pytest -from fastapi import FastAPI, UploadFile +from fastapi import FastAPI, File, Form, UploadFile from fastapi.datastructures import Default from fastapi.testclient import TestClient @@ -33,10 +33,22 @@ def test_default_placeholder_bool(): assert not placeholder_b -def test_upload_file_is_closed(tmp_path: Path): - path = tmp_path / "test.txt" - path.write_bytes(b"") +@pytest.fixture(name="client", scope="module") +def get_client(): app = FastAPI() + client = TestClient(app) + return client + + +@pytest.fixture(scope="module") +def tmp_file(tmp_path_factory): + path = tmp_path_factory.getbasetemp() / "test.txt" + path.write_bytes(b"") + return path + + +def test_upload_file_is_closed(client: TestClient, tmp_file: Path): + app = client.app testing_file_store: List[UploadFile] = [] @@ -46,7 +58,7 @@ def test_upload_file_is_closed(tmp_path: Path): return {"filename": file.filename} client = TestClient(app) - with path.open("rb") as file: + with tmp_file.open("rb") as file: response = client.post("/uploadfile/", files={"file": file}) assert response.status_code == 200, response.text assert response.json() == {"filename": "test.txt"} @@ -55,6 +67,26 @@ def test_upload_file_is_closed(tmp_path: Path): assert testing_file_store[0].file.closed +def test_form_is_declared_before_file(client: TestClient, tmp_file: Path): + app = client.app + + @app.post("/uploadfile_checksum/") + def create_upload_file_with_checksum( + checksum: str = Form(), file: UploadFile = File() + ): + return {"checksum": checksum, "filename": file.filename} + + client = TestClient(app) + with tmp_file.open("rb") as file: + response = client.post( + "/uploadfile_checksum/", + data={"checksum": ""}, + files={"file": file}, + ) + assert response.status_code == 200, response.text + assert response.json() == {"checksum": "", "filename": "test.txt"} + + # For UploadFile coverage, segments copied from Starlette tests