Allow str content for multipart upload files (#2400)
This commit is contained in:
parent
770d4f2254
commit
0ebe9259ac
@ -122,8 +122,14 @@ class FileField:
|
||||
# requests does the opposite (it overwrites the header with the 3rd tuple element)
|
||||
headers["Content-Type"] = content_type
|
||||
|
||||
if isinstance(fileobj, (str, io.StringIO)):
|
||||
raise TypeError(f"Expected bytes or bytes-like object got: {type(fileobj)}")
|
||||
if "b" not in getattr(fileobj, "mode", "b"):
|
||||
raise TypeError(
|
||||
"Multipart file uploads must be opened in binary mode, not text mode."
|
||||
)
|
||||
if isinstance(fileobj, io.StringIO):
|
||||
raise TypeError(
|
||||
"Multipart file uploads require 'io.BytesIO', not 'io.StringIO'."
|
||||
)
|
||||
|
||||
self.filename = filename
|
||||
self.file = fileobj
|
||||
|
||||
@ -80,7 +80,7 @@ ResponseExtensions = Dict[str, Any]
|
||||
|
||||
RequestData = Mapping[str, Any]
|
||||
|
||||
FileContent = Union[IO[bytes], bytes]
|
||||
FileContent = Union[IO[bytes], bytes, str]
|
||||
FileTypes = Union[
|
||||
# file (or bytes)
|
||||
FileContent,
|
||||
|
||||
@ -339,18 +339,37 @@ def test_multipart_encode_files_allows_bytes_content() -> None:
|
||||
assert content == b"".join(stream)
|
||||
|
||||
|
||||
def test_multipart_encode_files_raises_exception_with_str_content() -> None:
|
||||
files = {"file": ("test.txt", "<bytes content>", "text/plain")}
|
||||
def test_multipart_encode_files_allows_str_content() -> None:
|
||||
files = {"file": ("test.txt", "<str content>", "text/plain")}
|
||||
with mock.patch("os.urandom", return_value=os.urandom(16)):
|
||||
boundary = os.urandom(16).hex()
|
||||
|
||||
with pytest.raises(TypeError):
|
||||
encode_request(data={}, files=files) # type: ignore
|
||||
headers, stream = encode_request(data={}, files=files)
|
||||
assert isinstance(stream, typing.Iterable)
|
||||
|
||||
content = (
|
||||
'--{0}\r\nContent-Disposition: form-data; name="file"; '
|
||||
'filename="test.txt"\r\n'
|
||||
"Content-Type: text/plain\r\n\r\n<str content>\r\n"
|
||||
"--{0}--\r\n"
|
||||
"".format(boundary).encode("ascii")
|
||||
)
|
||||
assert headers == {
|
||||
"Content-Type": f"multipart/form-data; boundary={boundary}",
|
||||
"Content-Length": str(len(content)),
|
||||
}
|
||||
assert content == b"".join(stream)
|
||||
|
||||
|
||||
def test_multipart_encode_files_raises_exception_with_StringIO_content() -> None:
|
||||
files = {"file": ("test.txt", io.StringIO("content"), "text/plain")}
|
||||
with mock.patch("os.urandom", return_value=os.urandom(16)):
|
||||
with pytest.raises(TypeError):
|
||||
encode_request(data={}, files=files) # type: ignore
|
||||
|
||||
|
||||
def test_multipart_encode_files_raises_exception_with_text_mode_file() -> None:
|
||||
with tempfile.TemporaryFile(mode="w") as upload:
|
||||
files = {"file": ("test.txt", upload, "text/plain")}
|
||||
with pytest.raises(TypeError):
|
||||
encode_request(data={}, files=files) # type: ignore
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user