From 439f1f2997412d4c3c1a3453af8111bb8120651c Mon Sep 17 00:00:00 2001 From: agape1225 <49804691+agape1225@users.noreply.github.com> Date: Wed, 23 Jul 2025 19:56:02 +0900 Subject: [PATCH] allow IO[bytes] for send_file argument --- CHANGES.rst | 8 ++++++++ src/flask/helpers.py | 2 +- tests/test_helpers.py | 28 ++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index d400ef3e..95feabcd 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,6 +1,14 @@ Version 3.1.1 ------------- +Unreleased + +- Fix ``helpers.send_file`` type hint to allow ``IO[bytes]``, not just + ``BinaryIO``. Fixes :issue:`5776`. + +Version 3.1.1 +------------- + Released 2025-05-13 - Fix signing key selection order when key rotation is enabled via diff --git a/src/flask/helpers.py b/src/flask/helpers.py index 90a0e0c6..081548a9 100644 --- a/src/flask/helpers.py +++ b/src/flask/helpers.py @@ -398,7 +398,7 @@ def _prepare_send_file_kwargs(**kwargs: t.Any) -> dict[str, t.Any]: def send_file( - path_or_file: os.PathLike[t.AnyStr] | str | t.BinaryIO, + path_or_file: os.PathLike[t.AnyStr] | str | t.IO[bytes], mimetype: str | None = None, as_attachment: bool = False, download_name: str | None = None, diff --git a/tests/test_helpers.py b/tests/test_helpers.py index ee77f176..dfafd238 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -98,6 +98,34 @@ class TestSendfile: assert rv.data.strip() == b"Hello Subdomain" rv.close() + def test_send_file_io_bytes(self, app, req_ctx): + """ + Tests that send_file can handle file-like objects typed as IO[bytes]. + This verifies the fix for issue #5776. + """ + file_content = b"this is file content" + file_obj: IO[bytes] = io.BytesIO(file_content) + + # 2. send_file 함수에 as_attachment=True 인자를 추가합니다. + rv = flask.send_file( + file_obj, + download_name="test.txt", + mimetype="text/plain", + as_attachment=True, # <-- 이 부분을 추가하세요. + ) + + # 3. 응답 검증 + assert rv.status_code == 200 + assert rv.direct_passthrough + + rv.direct_passthrough = False + + assert rv.data == file_content + assert rv.mimetype == "text/plain" + # 이제 이 assert문이 정상적으로 통과합니다. + assert "attachment; filename=test.txt" in rv.headers["Content-Disposition"] + rv.close() + class TestUrlFor: def test_url_for_with_anchor(self, app, req_ctx):