From 5bcf4fdcd42577fc6f2b61835c3289f44488dfac Mon Sep 17 00:00:00 2001 From: sbin Date: Tue, 6 Oct 2026 16:56:02 +0900 Subject: [PATCH] Accept a `str` `UPLOAD_DIR` when `UPLOAD_KEEP_FILENAME` is set `File._get_disk_file()` joined `UPLOAD_DIR` with the file name, which is always `bytes`, so a `str` directory (the documented type) raised `TypeError: Can't mix strings and bytes in path components` on the first write past `MAX_MEMORY_FILE_SIZE`. The temporary-file branch already accepts both types; run the directory through `os.fsencode()` here as well and drop the `type: ignore` that hid the mismatch. Co-Authored-By: Claude Opus 5.5 --- python_multipart/multipart.py | 2 +- tests/test_file.py | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/python_multipart/multipart.py b/python_multipart/multipart.py index 5237786..2a51d10 100644 --- a/python_multipart/multipart.py +++ b/python_multipart/multipart.py @@ -539,7 +539,7 @@ def _get_disk_file(self) -> BufferedRandom: # TODO: what happens if we don't have a filename? fname = self._file_base + self._ext if keep_extensions else self._file_base - path = os.path.join(file_dir, fname) # type: ignore[arg-type] + path = os.path.join(os.fsencode(file_dir), fname) try: self.logger.info("Opening file: %r", path) tmp_file = open(path, "w+b") diff --git a/tests/test_file.py b/tests/test_file.py index a2aa134..9fe570f 100644 --- a/tests/test_file.py +++ b/tests/test_file.py @@ -24,3 +24,21 @@ def test_upload_dir_with_leading_slash_in_filename(tmp_path: Path) -> None: assert not file.in_memory assert Path(upload_dir / "foo.txt").exists() assert Path(upload_dir / "foo.txt").read_bytes() == b"123456789012" + + +def test_str_upload_dir_with_keep_filename(tmp_path: Path) -> None: + file = File( + b"foo.txt", + config={ + "UPLOAD_DIR": str(tmp_path), + "UPLOAD_KEEP_FILENAME": True, + "UPLOAD_KEEP_EXTENSIONS": True, + "MAX_MEMORY_FILE_SIZE": 10, + }, + ) + file.write(b"123456789012") + file.close() + + assert not file.in_memory + assert file.actual_file_name == b"foo.txt" + assert (tmp_path / "foo.txt").read_bytes() == b"123456789012"