Exemple #1
0
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
Exemple #2
0
async def test_aiterator_content():
    async def hello_world():
        yield b"Hello, "
        yield b"world!"

    headers, stream = encode_request(content=hello_world())
    assert not isinstance(stream, typing.Iterable)
    assert isinstance(stream, typing.AsyncIterable)

    content = b"".join([part async for part in stream])

    assert headers == {"Transfer-Encoding": "chunked"}
    assert content == b"Hello, world!"

    with pytest.raises(StreamConsumed):
        [part async for part in stream]

    # Support 'data' for compat with requests.
    headers, stream = encode_request(data=hello_world())  # type: ignore
    assert not isinstance(stream, typing.Iterable)
    assert isinstance(stream, typing.AsyncIterable)

    content = b"".join([part async for part in stream])

    assert headers == {"Transfer-Encoding": "chunked"}
    assert content == b"Hello, world!"
Exemple #3
0
async def test_multipart_files_content():
    files = {"file": io.BytesIO(b"<file content>")}
    headers, stream = encode_request(files=files, boundary=b"+++")
    assert isinstance(stream, typing.Iterable)
    assert isinstance(stream, typing.AsyncIterable)

    sync_content = b"".join([part for part in stream])
    async_content = b"".join([part async for part in stream])

    assert headers == {
        "Content-Length": "138",
        "Content-Type": "multipart/form-data; boundary=+++",
    }
    assert sync_content == b"".join(
        [
            b"--+++\r\n",
            b'Content-Disposition: form-data; name="file"; filename="upload"\r\n',
            b"Content-Type: application/octet-stream\r\n",
            b"\r\n",
            b"<file content>\r\n",
            b"--+++--\r\n",
        ]
    )
    assert async_content == b"".join(
        [
            b"--+++\r\n",
            b'Content-Disposition: form-data; name="file"; filename="upload"\r\n',
            b"Content-Type: application/octet-stream\r\n",
            b"\r\n",
            b"<file content>\r\n",
            b"--+++--\r\n",
        ]
    )
Exemple #4
0
def test_multipart_file_tuple_headers(content_type: typing.Optional[str]):
    file_name = "test.txt"
    expected_content_type = "text/plain"
    headers = {"Expires": "0"}

    files = {
        "file":
        (file_name, io.BytesIO(b"<file content>"), content_type, headers)
    }
    with mock.patch("os.urandom", return_value=os.urandom(16)):
        boundary = os.urandom(16).hex()

        headers, stream = encode_request(data={}, files=files)
        assert isinstance(stream, typing.Iterable)

        content = (
            f'--{boundary}\r\nContent-Disposition: form-data; name="file"; '
            f'filename="{file_name}"\r\nExpires: 0\r\nContent-Type: '
            f"{expected_content_type}\r\n\r\n<file content>\r\n--{boundary}--\r\n"
            "".encode("ascii"))
        assert headers == {
            "Content-Type": f"multipart/form-data; boundary={boundary}",
            "Content-Length": str(len(content)),
        }
        assert content == b"".join(stream)
Exemple #5
0
def test_multipart_headers_include_content_type() -> None:
    """Content-Type from 4th tuple parameter (headers) should override the 3rd parameter (content_type)"""
    file_name = "test.txt"
    expected_content_type = "image/png"
    headers = {"Content-Type": "image/png"}

    files = {
        "file":
        (file_name, io.BytesIO(b"<file content>"), "text_plain", headers)
    }
    with mock.patch("os.urandom", return_value=os.urandom(16)):
        boundary = os.urandom(16).hex()

        headers, stream = encode_request(data={}, files=files)
        assert isinstance(stream, typing.Iterable)

        content = (
            f'--{boundary}\r\nContent-Disposition: form-data; name="file"; '
            f'filename="{file_name}"\r\nContent-Type: '
            f"{expected_content_type}\r\n\r\n<file content>\r\n--{boundary}--\r\n"
            "".encode("ascii"))
        assert headers == {
            "Content-Type": f"multipart/form-data; boundary={boundary}",
            "Content-Length": str(len(content)),
        }
        assert content == b"".join(stream)
Exemple #6
0
    def add_token_to_post_body(self, request: httpx.Request):
        data = dict(parse_qsl(request.content))
        data['token'] = self.access_token
        headers, request.stream = encode_request(data=data)

        # Ensure our Content-Length header is updated to new value
        request.headers.update(headers)
Exemple #7
0
def test_multipart_encode_non_seekable_filelike() -> None:
    """
    Test that special readable but non-seekable filelike objects are supported,
    at the cost of reading them into memory at most once.
    """

    class IteratorIO(io.IOBase):
        def __init__(self, iterator: typing.Iterator[bytes]) -> None:
            self._iterator = iterator

        def read(self, *args: typing.Any) -> bytes:
            return b"".join(self._iterator)

    def data() -> typing.Iterator[bytes]:
        yield b"Hello"
        yield b"World"

    fileobj: typing.Any = IteratorIO(data())
    files = {"file": fileobj}
    headers, stream = encode_request(files=files, boundary=b"+++")
    assert isinstance(stream, typing.Iterable)

    content = (
        b"--+++\r\n"
        b'Content-Disposition: form-data; name="file"; filename="upload"\r\n'
        b"Content-Type: application/octet-stream\r\n"
        b"\r\n"
        b"HelloWorld\r\n"
        b"--+++--\r\n"
    )
    assert headers == {
        "Content-Type": "multipart/form-data; boundary=+++",
        "Content-Length": str(len(content)),
    }
    assert content == b"".join(stream)
Exemple #8
0
async def test_bytesio_content():
    headers, stream = encode_request(content=io.BytesIO(b"Hello, world!"))
    assert isinstance(stream, typing.Iterable)
    assert not isinstance(stream, typing.AsyncIterable)

    content = b"".join([part for part in stream])

    assert headers == {"Content-Length": "13"}
    assert content == b"Hello, world!"
Exemple #9
0
async def test_empty_content():
    headers, stream = encode_request()
    assert isinstance(stream, httpx.SyncByteStream)
    assert isinstance(stream, httpx.AsyncByteStream)

    sync_content = stream.read()
    async_content = await stream.aread()

    assert headers == {}
    assert sync_content == b""
    assert async_content == b""
Exemple #10
0
async def test_empty_request():
    headers, stream = encode_request(data={}, files={})
    assert isinstance(stream, typing.Iterable)
    assert isinstance(stream, typing.AsyncIterable)

    sync_content = b"".join([part for part in stream])
    async_content = b"".join([part async for part in stream])

    assert headers == {}
    assert sync_content == b""
    assert async_content == b""
Exemple #11
0
async def test_bytes_content():
    headers, stream = encode_request(content=b"Hello, world!")
    assert isinstance(stream, typing.Iterable)
    assert isinstance(stream, typing.AsyncIterable)

    sync_content = b"".join([part for part in stream])
    async_content = b"".join([part async for part in stream])

    assert headers == {"Content-Length": "13"}
    assert sync_content == b"Hello, world!"
    assert async_content == b"Hello, world!"

    # Support 'data' for compat with requests.
    headers, stream = encode_request(data=b"Hello, world!")  # type: ignore
    assert isinstance(stream, typing.Iterable)
    assert isinstance(stream, typing.AsyncIterable)

    sync_content = b"".join([part for part in stream])
    async_content = b"".join([part async for part in stream])

    assert headers == {"Content-Length": "13"}
    assert sync_content == b"Hello, world!"
    assert async_content == b"Hello, world!"
Exemple #12
0
async def test_urlencoded_list():
    headers, stream = encode_request(data={"example": ["a", 1, True]})
    assert isinstance(stream, typing.Iterable)
    assert isinstance(stream, typing.AsyncIterable)

    sync_content = b"".join([part for part in stream])
    async_content = b"".join([part async for part in stream])

    assert headers == {
        "Content-Length": "32",
        "Content-Type": "application/x-www-form-urlencoded",
    }
    assert sync_content == b"example=a&example=1&example=true"
    assert async_content == b"example=a&example=1&example=true"
Exemple #13
0
async def test_urlencoded_content():
    headers, stream = encode_request(data={"Hello": "world!"})
    assert isinstance(stream, typing.Iterable)
    assert isinstance(stream, typing.AsyncIterable)

    sync_content = b"".join([part for part in stream])
    async_content = b"".join([part async for part in stream])

    assert headers == {
        "Content-Length": "14",
        "Content-Type": "application/x-www-form-urlencoded",
    }
    assert sync_content == b"Hello=world%21"
    assert async_content == b"Hello=world%21"
Exemple #14
0
async def test_json_content():
    headers, stream = encode_request(json={"Hello": "world!"})
    assert isinstance(stream, typing.Iterable)
    assert isinstance(stream, typing.AsyncIterable)

    sync_content = b"".join([part for part in stream])
    async_content = b"".join([part async for part in stream])

    assert headers == {
        "Content-Length": "19",
        "Content-Type": "application/json",
    }
    assert sync_content == b'{"Hello": "world!"}'
    assert async_content == b'{"Hello": "world!"}'
Exemple #15
0
def test_multipart_encode_files_allows_filenames_as_none() -> None:
    files = {"file": (None, io.BytesIO(b"<file content>"))}
    with mock.patch("os.urandom", return_value=os.urandom(16)):
        boundary = os.urandom(16).hex()

        headers, stream = encode_request(data={}, files=files)
        assert isinstance(stream, typing.Iterable)

        content = (
            '--{0}\r\nContent-Disposition: form-data; name="file"\r\n\r\n'
            "<file 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)
Exemple #16
0
def test_multipart_encode_unicode_file_contents() -> None:
    files = {"file": ("name.txt", "<únicode string>")}

    with mock.patch("os.urandom", return_value=os.urandom(16)):
        boundary = os.urandom(16).hex()

        headers, stream = encode_request(files=files)
        assert isinstance(stream, typing.Iterable)

        content = ('--{0}\r\nContent-Disposition: form-data; name="file";'
                   ' filename="name.txt"\r\n'
                   "Content-Type: text/plain\r\n\r\n<únicode string>\r\n"
                   "--{0}--\r\n"
                   "".format(boundary).encode("utf-8"))
        assert headers == {
            "Content-Type": f"multipart/form-data; boundary={boundary}",
            "Content-Length": str(len(content)),
        }
        assert content == b"".join(stream)
Exemple #17
0
def test_multipart_encode_files_guesses_correct_content_type(
        file_name: str, expected_content_type: str) -> None:
    files = {"file": (file_name, io.BytesIO(b"<file content>"))}
    with mock.patch("os.urandom", return_value=os.urandom(16)):
        boundary = os.urandom(16).hex()

        headers, stream = encode_request(data={}, files=files)
        assert isinstance(stream, typing.Iterable)

        content = (
            f'--{boundary}\r\nContent-Disposition: form-data; name="file"; '
            f'filename="{file_name}"\r\nContent-Type: '
            f"{expected_content_type}\r\n\r\n<file content>\r\n--{boundary}--\r\n"
            "".encode("ascii"))
        assert headers == {
            "Content-Type": f"multipart/form-data; boundary={boundary}",
            "Content-Length": str(len(content)),
        }
        assert content == b"".join(stream)
Exemple #18
0
def test_multipart_encode(tmp_path: typing.Any) -> None:
    path = str(tmp_path / "name.txt")
    with open(path, "wb") as f:
        f.write(b"<file content>")

    data = {
        "a": "1",
        "b": b"C",
        "c": ["11", "22", "33"],
        "d": "",
    }
    files: RequestFiles = {
        "file": ("name.txt", open(path, "rb")),
        "file2": ("file2.txt", "<únicode string>"),
    }

    with mock.patch("os.urandom", return_value=os.urandom(16)):
        boundary = os.urandom(16).hex()

        headers, stream = encode_request(data=data, files=files)
        assert isinstance(stream, typing.Iterable)

        content = (
            '--{0}\r\nContent-Disposition: form-data; name="a"\r\n\r\n1\r\n'
            '--{0}\r\nContent-Disposition: form-data; name="b"\r\n\r\nC\r\n'
            '--{0}\r\nContent-Disposition: form-data; name="c"\r\n\r\n11\r\n'
            '--{0}\r\nContent-Disposition: form-data; name="c"\r\n\r\n22\r\n'
            '--{0}\r\nContent-Disposition: form-data; name="c"\r\n\r\n33\r\n'
            '--{0}\r\nContent-Disposition: form-data; name="d"\r\n\r\n\r\n'
            '--{0}\r\nContent-Disposition: form-data; name="file";'
            ' filename="name.txt"\r\n'
            "Content-Type: text/plain\r\n\r\n<file content>\r\n"
            '--{0}\r\nContent-Disposition: form-data; name="file2";'
            ' filename="file2.txt"\r\n'
            "Content-Type: text/plain\r\n\r\n<únicode string>\r\n"
            "--{0}--\r\n"
            "".format(boundary).encode("utf-8")
        )
        assert headers == {
            "Content-Type": f"multipart/form-data; boundary={boundary}",
            "Content-Length": str(len(content)),
        }
        assert content == b"".join(stream)
Exemple #19
0
def test_multipart_encode_files_allows_bytes_or_str_content(
        value: typing.Union[str, bytes], output: str) -> None:
    files = {"file": ("test.txt", value, "text/plain")}
    with mock.patch("os.urandom", return_value=os.urandom(16)):
        boundary = os.urandom(16).hex()

        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{1}\r\n"
                   "--{0}--\r\n"
                   "".format(boundary, output).encode("ascii"))
        assert headers == {
            "Content-Type": f"multipart/form-data; boundary={boundary}",
            "Content-Length": str(len(content)),
        }
        assert content == b"".join(stream)
Exemple #20
0
async def test_async_bytesio_content():
    class AsyncBytesIO:
        def __init__(self, content):
            self._idx = 0
            self._content = content

        async def aread(self, chunk_size: int):
            chunk = self._content[self._idx : self._idx + chunk_size]
            self._idx = self._idx + chunk_size
            return chunk

        async def __aiter__(self):
            yield self._content  # pragma: nocover

    headers, stream = encode_request(content=AsyncBytesIO(b"Hello, world!"))
    assert not isinstance(stream, typing.Iterable)
    assert isinstance(stream, typing.AsyncIterable)

    content = b"".join([part async for part in stream])

    assert headers == {"Transfer-Encoding": "chunked"}
    assert content == b"Hello, world!"
Exemple #21
0
def test_invalid_argument():
    with pytest.raises(TypeError):
        encode_request(123)  # type: ignore