From 0a1efc8415f1e95f7737a183f1333ba18410692a Mon Sep 17 00:00:00 2001 From: Marcelo Trylesinski Date: Sat, 10 Oct 2026 08:34:31 -0400 Subject: [PATCH 1/2] Finalize transfer decoding before callbacks --- python_multipart/multipart.py | 9 ++++----- tests/test_multipart.py | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/python_multipart/multipart.py b/python_multipart/multipart.py index 5237786..c863a80 100644 --- a/python_multipart/multipart.py +++ b/python_multipart/multipart.py @@ -1759,9 +1759,11 @@ def on_part_data(data: bytes, start: int, end: int) -> None: # TODO: check for error here. def on_part_end() -> None: - nonlocal f_multi, is_file + nonlocal f_multi, is_file, writer assert f_multi is not None - f_multi.finalize() + assert writer is not None + writer.finalize() + writer = None if is_file: if on_file: assert isinstance(f_multi, File) @@ -1833,9 +1835,6 @@ def on_headers_finished() -> None: writer = f_multi def _on_end() -> None: - nonlocal writer - if writer is not None: - writer.finalize() if self.on_end is not None: self.on_end() diff --git a/tests/test_multipart.py b/tests/test_multipart.py index 9ad3fdc..de220eb 100644 --- a/tests/test_multipart.py +++ b/tests/test_multipart.py @@ -854,6 +854,20 @@ def test_content_transfer_encoding_is_case_insensitive(content_transfer_encoding assert file.file_object.read() == b"Test" +def test_finalizes_transfer_encoding_before_callback() -> None: + data = ( + b'--b\r\nContent-Disposition: form-data; name="f"\r\n' + b"Content-Transfer-Encoding: quoted-printable\r\n\r\n=4\r\n--b--\r\n" + ) + values: list[bytes | None] = [] + parser = FormParser("multipart/form-data", lambda field: values.append(field.value), None, boundary=b"b") + + parser.write(data) + parser.finalize() + + assert values == [b"=4"] + + def test_parser_states_remain_enum_members() -> None: multipart_parser = MultipartParser(b"boundary") multipart_parser.write(b"--boundary--\r\n") From 79fb73a3ef4ee5543363922434b967f69d80f731 Mon Sep 17 00:00:00 2001 From: Marcelo Trylesinski Date: Sun, 11 Oct 2026 15:33:15 +0200 Subject: [PATCH 2/2] Simplify transfer decoder finalization --- python_multipart/multipart.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/python_multipart/multipart.py b/python_multipart/multipart.py index c863a80..cfc3220 100644 --- a/python_multipart/multipart.py +++ b/python_multipart/multipart.py @@ -1759,11 +1759,9 @@ def on_part_data(data: bytes, start: int, end: int) -> None: # TODO: check for error here. def on_part_end() -> None: - nonlocal f_multi, is_file, writer assert f_multi is not None assert writer is not None writer.finalize() - writer = None if is_file: if on_file: assert isinstance(f_multi, File)