All over the AsyncClient invocation is made using context manager or with try-finally block
This commit is contained in:
parent
aad8209928
commit
fa7661b306
@ -5,12 +5,11 @@ import typing
|
||||
import httpcore
|
||||
import pytest
|
||||
|
||||
import httpx
|
||||
from httpx import (
|
||||
URL,
|
||||
AsyncClient,
|
||||
Auth,
|
||||
BasicAuth,
|
||||
Client,
|
||||
DigestAuth,
|
||||
ProtocolError,
|
||||
Request,
|
||||
@ -189,8 +188,8 @@ async def test_basic_auth() -> None:
|
||||
url = "https://example.org/"
|
||||
auth = ("tomchristie", "password123")
|
||||
|
||||
client = AsyncClient(transport=AsyncMockTransport())
|
||||
response = await client.get(url, auth=auth)
|
||||
async with httpx.AsyncClient(transport=AsyncMockTransport()) as client:
|
||||
response = await client.get(url, auth=auth)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"auth": "Basic dG9tY2hyaXN0aWU6cGFzc3dvcmQxMjM="}
|
||||
@ -200,8 +199,8 @@ async def test_basic_auth() -> None:
|
||||
async def test_basic_auth_in_url() -> None:
|
||||
url = "https://tomchristie:password123@example.org/"
|
||||
|
||||
client = AsyncClient(transport=AsyncMockTransport())
|
||||
response = await client.get(url)
|
||||
async with httpx.AsyncClient(transport=AsyncMockTransport()) as client:
|
||||
response = await client.get(url)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"auth": "Basic dG9tY2hyaXN0aWU6cGFzc3dvcmQxMjM="}
|
||||
@ -212,8 +211,8 @@ async def test_basic_auth_on_session() -> None:
|
||||
url = "https://example.org/"
|
||||
auth = ("tomchristie", "password123")
|
||||
|
||||
client = AsyncClient(transport=AsyncMockTransport(), auth=auth)
|
||||
response = await client.get(url)
|
||||
async with httpx.AsyncClient(transport=AsyncMockTransport(), auth=auth) as client:
|
||||
response = await client.get(url)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"auth": "Basic dG9tY2hyaXN0aWU6cGFzc3dvcmQxMjM="}
|
||||
@ -227,8 +226,8 @@ async def test_custom_auth() -> None:
|
||||
request.headers["Authorization"] = "Token 123"
|
||||
return request
|
||||
|
||||
client = AsyncClient(transport=AsyncMockTransport())
|
||||
response = await client.get(url, auth=auth)
|
||||
async with httpx.AsyncClient(transport=AsyncMockTransport()) as client:
|
||||
response = await client.get(url, auth=auth)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"auth": "Token 123"}
|
||||
@ -239,8 +238,8 @@ async def test_netrc_auth() -> None:
|
||||
os.environ["NETRC"] = str(FIXTURES_DIR / ".netrc")
|
||||
url = "http://netrcexample.org"
|
||||
|
||||
client = AsyncClient(transport=AsyncMockTransport())
|
||||
response = await client.get(url)
|
||||
async with httpx.AsyncClient(transport=AsyncMockTransport()) as client:
|
||||
response = await client.get(url)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
@ -253,8 +252,8 @@ async def test_auth_header_has_priority_over_netrc() -> None:
|
||||
os.environ["NETRC"] = str(FIXTURES_DIR / ".netrc")
|
||||
url = "http://netrcexample.org"
|
||||
|
||||
client = AsyncClient(transport=AsyncMockTransport())
|
||||
response = await client.get(url, headers={"Authorization": "Override"})
|
||||
async with httpx.AsyncClient(transport=AsyncMockTransport()) as client:
|
||||
response = await client.get(url, headers={"Authorization": "Override"})
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"auth": "Override"}
|
||||
@ -265,14 +264,18 @@ async def test_trust_env_auth() -> None:
|
||||
os.environ["NETRC"] = str(FIXTURES_DIR / ".netrc")
|
||||
url = "http://netrcexample.org"
|
||||
|
||||
client = AsyncClient(transport=AsyncMockTransport(), trust_env=False)
|
||||
response = await client.get(url)
|
||||
async with httpx.AsyncClient(
|
||||
transport=AsyncMockTransport(), trust_env=False
|
||||
) as client:
|
||||
response = await client.get(url)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"auth": None}
|
||||
|
||||
client = AsyncClient(transport=AsyncMockTransport(), trust_env=True)
|
||||
response = await client.get(url)
|
||||
async with httpx.AsyncClient(
|
||||
transport=AsyncMockTransport(), trust_env=True
|
||||
) as client:
|
||||
response = await client.get(url)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
@ -285,8 +288,8 @@ async def test_auth_disable_per_request() -> None:
|
||||
url = "https://example.org/"
|
||||
auth = ("tomchristie", "password123")
|
||||
|
||||
client = AsyncClient(transport=AsyncMockTransport(), auth=auth)
|
||||
response = await client.get(url, auth=None)
|
||||
async with httpx.AsyncClient(transport=AsyncMockTransport(), auth=auth) as client:
|
||||
response = await client.get(url, auth=None)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"auth": None}
|
||||
@ -304,41 +307,40 @@ async def test_auth_hidden_header() -> None:
|
||||
url = "https://example.org/"
|
||||
auth = ("example-username", "example-password")
|
||||
|
||||
client = AsyncClient(transport=AsyncMockTransport())
|
||||
response = await client.get(url, auth=auth)
|
||||
async with httpx.AsyncClient(transport=AsyncMockTransport()) as client:
|
||||
response = await client.get(url, auth=auth)
|
||||
|
||||
assert "'authorization': '[secure]'" in str(response.request.headers)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_auth_property() -> None:
|
||||
client = AsyncClient(transport=AsyncMockTransport())
|
||||
assert client.auth is None
|
||||
async with httpx.AsyncClient(transport=AsyncMockTransport()) as client:
|
||||
assert client.auth is None
|
||||
|
||||
client.auth = ("tomchristie", "password123") # type: ignore
|
||||
assert isinstance(client.auth, BasicAuth)
|
||||
client.auth = ("tomchristie", "password123") # type: ignore
|
||||
assert isinstance(client.auth, BasicAuth)
|
||||
|
||||
url = "https://example.org/"
|
||||
response = await client.get(url)
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"auth": "Basic dG9tY2hyaXN0aWU6cGFzc3dvcmQxMjM="}
|
||||
url = "https://example.org/"
|
||||
response = await client.get(url)
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"auth": "Basic dG9tY2hyaXN0aWU6cGFzc3dvcmQxMjM="}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_auth_invalid_type() -> None:
|
||||
with pytest.raises(TypeError):
|
||||
client = AsyncClient(
|
||||
client = httpx.AsyncClient(
|
||||
transport=AsyncMockTransport(),
|
||||
auth="not a tuple, not a callable", # type: ignore
|
||||
)
|
||||
|
||||
client = AsyncClient(transport=AsyncMockTransport())
|
||||
async with httpx.AsyncClient(transport=AsyncMockTransport()) as client:
|
||||
with pytest.raises(TypeError):
|
||||
await client.get(auth="not a tuple, not a callable") # type: ignore
|
||||
|
||||
with pytest.raises(TypeError):
|
||||
await client.get(auth="not a tuple, not a callable") # type: ignore
|
||||
|
||||
with pytest.raises(TypeError):
|
||||
client.auth = "not a tuple, not a callable" # type: ignore
|
||||
with pytest.raises(TypeError):
|
||||
client.auth = "not a tuple, not a callable" # type: ignore
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@ -346,8 +348,8 @@ async def test_digest_auth_returns_no_auth_if_no_digest_header_in_response() ->
|
||||
url = "https://example.org/"
|
||||
auth = DigestAuth(username="tomchristie", password="password123")
|
||||
|
||||
client = AsyncClient(transport=AsyncMockTransport())
|
||||
response = await client.get(url, auth=auth)
|
||||
async with httpx.AsyncClient(transport=AsyncMockTransport()) as client:
|
||||
response = await client.get(url, auth=auth)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"auth": None}
|
||||
@ -360,10 +362,10 @@ async def test_digest_auth_200_response_including_digest_auth_header() -> None:
|
||||
auth = DigestAuth(username="tomchristie", password="password123")
|
||||
auth_header = b'Digest realm="realm@host.com",qop="auth",nonce="abc",opaque="xyz"'
|
||||
|
||||
client = AsyncClient(
|
||||
async with httpx.AsyncClient(
|
||||
transport=AsyncMockTransport(auth_header=auth_header, status_code=200)
|
||||
)
|
||||
response = await client.get(url, auth=auth)
|
||||
) as client:
|
||||
response = await client.get(url, auth=auth)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"auth": None}
|
||||
@ -375,8 +377,10 @@ async def test_digest_auth_401_response_without_digest_auth_header() -> None:
|
||||
url = "https://example.org/"
|
||||
auth = DigestAuth(username="tomchristie", password="password123")
|
||||
|
||||
client = AsyncClient(transport=AsyncMockTransport(auth_header=b"", status_code=401))
|
||||
response = await client.get(url, auth=auth)
|
||||
async with httpx.AsyncClient(
|
||||
transport=AsyncMockTransport(auth_header=b"", status_code=401)
|
||||
) as client:
|
||||
response = await client.get(url, auth=auth)
|
||||
|
||||
assert response.status_code == 401
|
||||
assert response.json() == {"auth": None}
|
||||
@ -403,8 +407,10 @@ async def test_digest_auth(
|
||||
url = "https://example.org/"
|
||||
auth = DigestAuth(username="tomchristie", password="password123")
|
||||
|
||||
client = AsyncClient(transport=MockDigestAuthTransport(algorithm=algorithm))
|
||||
response = await client.get(url, auth=auth)
|
||||
async with httpx.AsyncClient(
|
||||
transport=MockDigestAuthTransport(algorithm=algorithm)
|
||||
) as client:
|
||||
response = await client.get(url, auth=auth)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert len(response.history) == 1
|
||||
@ -433,8 +439,8 @@ async def test_digest_auth_no_specified_qop() -> None:
|
||||
url = "https://example.org/"
|
||||
auth = DigestAuth(username="tomchristie", password="password123")
|
||||
|
||||
client = AsyncClient(transport=MockDigestAuthTransport(qop=""))
|
||||
response = await client.get(url, auth=auth)
|
||||
async with httpx.AsyncClient(transport=MockDigestAuthTransport(qop="")) as client:
|
||||
response = await client.get(url, auth=auth)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert len(response.history) == 1
|
||||
@ -464,8 +470,8 @@ async def test_digest_auth_qop_including_spaces_and_auth_returns_auth(qop: str)
|
||||
url = "https://example.org/"
|
||||
auth = DigestAuth(username="tomchristie", password="password123")
|
||||
|
||||
client = AsyncClient(transport=MockDigestAuthTransport(qop=qop))
|
||||
response = await client.get(url, auth=auth)
|
||||
async with httpx.AsyncClient(transport=MockDigestAuthTransport(qop=qop)) as client:
|
||||
response = await client.get(url, auth=auth)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert len(response.history) == 1
|
||||
@ -475,20 +481,24 @@ async def test_digest_auth_qop_including_spaces_and_auth_returns_auth(qop: str)
|
||||
async def test_digest_auth_qop_auth_int_not_implemented() -> None:
|
||||
url = "https://example.org/"
|
||||
auth = DigestAuth(username="tomchristie", password="password123")
|
||||
client = AsyncClient(transport=MockDigestAuthTransport(qop="auth-int"))
|
||||
|
||||
with pytest.raises(NotImplementedError):
|
||||
await client.get(url, auth=auth)
|
||||
async with httpx.AsyncClient(
|
||||
transport=MockDigestAuthTransport(qop="auth-int")
|
||||
) as client:
|
||||
with pytest.raises(NotImplementedError):
|
||||
await client.get(url, auth=auth)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_digest_auth_qop_must_be_auth_or_auth_int() -> None:
|
||||
url = "https://example.org/"
|
||||
auth = DigestAuth(username="tomchristie", password="password123")
|
||||
client = AsyncClient(transport=MockDigestAuthTransport(qop="not-auth"))
|
||||
|
||||
with pytest.raises(ProtocolError):
|
||||
await client.get(url, auth=auth)
|
||||
async with httpx.AsyncClient(
|
||||
transport=MockDigestAuthTransport(qop="not-auth")
|
||||
) as client:
|
||||
with pytest.raises(ProtocolError):
|
||||
await client.get(url, auth=auth)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@ -496,10 +506,10 @@ async def test_digest_auth_incorrect_credentials() -> None:
|
||||
url = "https://example.org/"
|
||||
auth = DigestAuth(username="tomchristie", password="password123")
|
||||
|
||||
client = AsyncClient(
|
||||
async with httpx.AsyncClient(
|
||||
transport=MockDigestAuthTransport(send_response_after_attempt=2)
|
||||
)
|
||||
response = await client.get(url, auth=auth)
|
||||
) as client:
|
||||
response = await client.get(url, auth=auth)
|
||||
|
||||
assert response.status_code == 401
|
||||
assert len(response.history) == 1
|
||||
@ -521,12 +531,11 @@ async def test_async_digest_auth_raises_protocol_error_on_malformed_header(
|
||||
) -> None:
|
||||
url = "https://example.org/"
|
||||
auth = DigestAuth(username="tomchristie", password="password123")
|
||||
client = AsyncClient(
|
||||
async with httpx.AsyncClient(
|
||||
transport=AsyncMockTransport(auth_header=auth_header, status_code=401)
|
||||
)
|
||||
|
||||
with pytest.raises(ProtocolError):
|
||||
await client.get(url, auth=auth)
|
||||
) as client:
|
||||
with pytest.raises(ProtocolError):
|
||||
await client.get(url, auth=auth)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@ -544,12 +553,12 @@ def test_sync_digest_auth_raises_protocol_error_on_malformed_header(
|
||||
) -> None:
|
||||
url = "https://example.org/"
|
||||
auth = DigestAuth(username="tomchristie", password="password123")
|
||||
client = Client(
|
||||
transport=SyncMockTransport(auth_header=auth_header, status_code=401)
|
||||
)
|
||||
|
||||
with pytest.raises(ProtocolError):
|
||||
client.get(url, auth=auth)
|
||||
with httpx.Client(
|
||||
transport=SyncMockTransport(auth_header=auth_header, status_code=401)
|
||||
) as client:
|
||||
with pytest.raises(ProtocolError):
|
||||
client.get(url, auth=auth)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@ -560,9 +569,12 @@ async def test_async_auth_history() -> None:
|
||||
"""
|
||||
url = "https://example.org/"
|
||||
auth = RepeatAuth(repeat=2)
|
||||
client = AsyncClient(transport=AsyncMockTransport(auth_header=b"abc"))
|
||||
|
||||
response = await client.get(url, auth=auth)
|
||||
async with httpx.AsyncClient(
|
||||
transport=AsyncMockTransport(auth_header=b"abc")
|
||||
) as client:
|
||||
response = await client.get(url, auth=auth)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"auth": "Repeat abc.abc"}
|
||||
|
||||
@ -584,9 +596,10 @@ def test_sync_auth_history() -> None:
|
||||
"""
|
||||
url = "https://example.org/"
|
||||
auth = RepeatAuth(repeat=2)
|
||||
client = Client(transport=SyncMockTransport(auth_header=b"abc"))
|
||||
|
||||
response = client.get(url, auth=auth)
|
||||
with httpx.Client(transport=SyncMockTransport(auth_header=b"abc")) as client:
|
||||
response = client.get(url, auth=auth)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"auth": "Repeat abc.abc"}
|
||||
|
||||
@ -605,13 +618,13 @@ def test_sync_auth_history() -> None:
|
||||
async def test_digest_auth_unavailable_streaming_body():
|
||||
url = "https://example.org/"
|
||||
auth = DigestAuth(username="tomchristie", password="password123")
|
||||
client = AsyncClient(transport=AsyncMockTransport())
|
||||
|
||||
async def streaming_body():
|
||||
yield b"Example request body" # pragma: nocover
|
||||
|
||||
with pytest.raises(RequestBodyUnavailable):
|
||||
await client.post(url, data=streaming_body(), auth=auth)
|
||||
async with httpx.AsyncClient(transport=AsyncMockTransport()) as client:
|
||||
with pytest.raises(RequestBodyUnavailable):
|
||||
await client.post(url, data=streaming_body(), auth=auth)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@ -622,9 +635,9 @@ async def test_async_auth_reads_response_body() -> None:
|
||||
"""
|
||||
url = "https://example.org/"
|
||||
auth = ResponseBodyAuth("xyz")
|
||||
client = AsyncClient(transport=AsyncMockTransport())
|
||||
async with httpx.AsyncClient(transport=AsyncMockTransport()) as client:
|
||||
response = await client.get(url, auth=auth)
|
||||
|
||||
response = await client.get(url, auth=auth)
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"auth": '{"auth": "xyz"}'}
|
||||
|
||||
@ -636,8 +649,9 @@ def test_sync_auth_reads_response_body() -> None:
|
||||
"""
|
||||
url = "https://example.org/"
|
||||
auth = ResponseBodyAuth("xyz")
|
||||
client = Client(transport=SyncMockTransport())
|
||||
|
||||
response = client.get(url, auth=auth)
|
||||
with httpx.Client(transport=SyncMockTransport()) as client:
|
||||
response = client.get(url, auth=auth)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {"auth": '{"auth": "xyz"}'}
|
||||
|
||||
@ -43,39 +43,41 @@ async def raise_exc_after_response(scope, receive, send):
|
||||
|
||||
@pytest.mark.usefixtures("async_environment")
|
||||
async def test_asgi():
|
||||
client = httpx.AsyncClient(app=hello_world)
|
||||
response = await client.get("http://www.example.org/")
|
||||
async with httpx.AsyncClient(app=hello_world) as client:
|
||||
response = await client.get("http://www.example.org/")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.text == "Hello, World!"
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("async_environment")
|
||||
async def test_asgi_upload():
|
||||
client = httpx.AsyncClient(app=echo_body)
|
||||
response = await client.post("http://www.example.org/", data=b"example")
|
||||
async with httpx.AsyncClient(app=echo_body) as client:
|
||||
response = await client.post("http://www.example.org/", data=b"example")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.text == "example"
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("async_environment")
|
||||
async def test_asgi_exc():
|
||||
client = httpx.AsyncClient(app=raise_exc)
|
||||
with pytest.raises(ValueError):
|
||||
await client.get("http://www.example.org/")
|
||||
async with httpx.AsyncClient(app=raise_exc) as client:
|
||||
with pytest.raises(ValueError):
|
||||
await client.get("http://www.example.org/")
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("async_environment")
|
||||
async def test_asgi_http_error():
|
||||
client = httpx.AsyncClient(app=partial(raise_exc, exc=RuntimeError))
|
||||
with pytest.raises(RuntimeError):
|
||||
await client.get("http://www.example.org/")
|
||||
async with httpx.AsyncClient(app=partial(raise_exc, exc=RuntimeError)) as client:
|
||||
with pytest.raises(RuntimeError):
|
||||
await client.get("http://www.example.org/")
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("async_environment")
|
||||
async def test_asgi_exc_after_response():
|
||||
client = httpx.AsyncClient(app=raise_exc_after_response)
|
||||
with pytest.raises(ValueError):
|
||||
await client.get("http://www.example.org/")
|
||||
async with httpx.AsyncClient(app=raise_exc_after_response) as client:
|
||||
with pytest.raises(ValueError):
|
||||
await client.get("http://www.example.org/")
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("async_environment")
|
||||
@ -105,7 +107,8 @@ async def test_asgi_disconnect_after_response_complete():
|
||||
message = await receive()
|
||||
disconnect = message.get("type") == "http.disconnect"
|
||||
|
||||
client = httpx.AsyncClient(app=read_body)
|
||||
response = await client.post("http://www.example.org/", data=b"example")
|
||||
async with httpx.AsyncClient(app=read_body) as client:
|
||||
response = await client.post("http://www.example.org/", data=b"example")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert disconnect
|
||||
|
||||
@ -35,76 +35,79 @@ class MockTransport(httpcore.AsyncHTTPTransport):
|
||||
@pytest.mark.parametrize(("value,output"), (("abc", b"abc"), (b"abc", b"abc")))
|
||||
@pytest.mark.asyncio
|
||||
async def test_multipart(value, output):
|
||||
client = httpx.AsyncClient(transport=MockTransport())
|
||||
async with httpx.AsyncClient(transport=MockTransport()) as client:
|
||||
# Test with a single-value 'data' argument, and a plain file 'files' argument.
|
||||
data = {"text": value}
|
||||
files = {"file": io.BytesIO(b"<file content>")}
|
||||
response = await client.post("http://127.0.0.1:8000/", data=data, files=files)
|
||||
assert response.status_code == 200
|
||||
|
||||
# Test with a single-value 'data' argument, and a plain file 'files' argument.
|
||||
data = {"text": value}
|
||||
files = {"file": io.BytesIO(b"<file content>")}
|
||||
response = await client.post("http://127.0.0.1:8000/", data=data, files=files)
|
||||
assert response.status_code == 200
|
||||
# We're using the cgi module to verify the behavior here, which is a
|
||||
# bit grungy, but sufficient just for our testing purposes.
|
||||
boundary = response.request.headers["Content-Type"].split("boundary=")[-1]
|
||||
content_length = response.request.headers["Content-Length"]
|
||||
pdict: dict = {
|
||||
"boundary": boundary.encode("ascii"),
|
||||
"CONTENT-LENGTH": content_length,
|
||||
}
|
||||
multipart = cgi.parse_multipart(io.BytesIO(response.content), pdict)
|
||||
|
||||
# We're using the cgi module to verify the behavior here, which is a
|
||||
# bit grungy, but sufficient just for our testing purposes.
|
||||
boundary = response.request.headers["Content-Type"].split("boundary=")[-1]
|
||||
content_length = response.request.headers["Content-Length"]
|
||||
pdict: dict = {
|
||||
"boundary": boundary.encode("ascii"),
|
||||
"CONTENT-LENGTH": content_length,
|
||||
}
|
||||
multipart = cgi.parse_multipart(io.BytesIO(response.content), pdict)
|
||||
|
||||
# Note that the expected return type for text fields
|
||||
# appears to differs from 3.6 to 3.7+
|
||||
assert multipart["text"] == [output.decode()] or multipart["text"] == [output]
|
||||
assert multipart["file"] == [b"<file content>"]
|
||||
# Note that the expected return type for text fields
|
||||
# appears to differs from 3.6 to 3.7+
|
||||
assert multipart["text"] == [output.decode()] or multipart["text"] == [output]
|
||||
assert multipart["file"] == [b"<file content>"]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("key"), (b"abc", 1, 2.3, None))
|
||||
@pytest.mark.asyncio
|
||||
async def test_multipart_invalid_key(key):
|
||||
client = httpx.AsyncClient(transport=MockTransport())
|
||||
data = {key: "abc"}
|
||||
files = {"file": io.BytesIO(b"<file content>")}
|
||||
with pytest.raises(TypeError) as e:
|
||||
await client.post("http://127.0.0.1:8000/", data=data, files=files)
|
||||
assert "Invalid type for name" in str(e.value)
|
||||
async with httpx.AsyncClient(transport=MockTransport()) as client:
|
||||
data = {key: "abc"}
|
||||
files = {"file": io.BytesIO(b"<file content>")}
|
||||
with pytest.raises(TypeError) as e:
|
||||
await client.post(
|
||||
"http://127.0.0.1:8000/",
|
||||
data=data,
|
||||
files=files,
|
||||
)
|
||||
assert "Invalid type for name" in str(e.value)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("value"), (1, 2.3, None, [None, "abc"], {None: "abc"}))
|
||||
@pytest.mark.asyncio
|
||||
async def test_multipart_invalid_value(value):
|
||||
client = httpx.AsyncClient(transport=MockTransport())
|
||||
data = {"text": value}
|
||||
files = {"file": io.BytesIO(b"<file content>")}
|
||||
with pytest.raises(TypeError) as e:
|
||||
await client.post("http://127.0.0.1:8000/", data=data, files=files)
|
||||
assert "Invalid type for value" in str(e.value)
|
||||
async with httpx.AsyncClient(transport=MockTransport()) as client:
|
||||
data = {"text": value}
|
||||
files = {"file": io.BytesIO(b"<file content>")}
|
||||
with pytest.raises(TypeError) as e:
|
||||
await client.post("http://127.0.0.1:8000/", data=data, files=files)
|
||||
assert "Invalid type for value" in str(e.value)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_multipart_file_tuple():
|
||||
client = httpx.AsyncClient(transport=MockTransport())
|
||||
async with httpx.AsyncClient(transport=MockTransport()) as client:
|
||||
# Test with a list of values 'data' argument,
|
||||
# and a tuple style 'files' argument.
|
||||
data = {"text": ["abc"]}
|
||||
files = {"file": ("name.txt", io.BytesIO(b"<file content>"))}
|
||||
response = await client.post("http://127.0.0.1:8000/", data=data, files=files)
|
||||
assert response.status_code == 200
|
||||
|
||||
# Test with a list of values 'data' argument, and a tuple style 'files' argument.
|
||||
data = {"text": ["abc"]}
|
||||
files = {"file": ("name.txt", io.BytesIO(b"<file content>"))}
|
||||
response = await client.post("http://127.0.0.1:8000/", data=data, files=files)
|
||||
assert response.status_code == 200
|
||||
# We're using the cgi module to verify the behavior here, which is a
|
||||
# bit grungy, but sufficient just for our testing purposes.
|
||||
boundary = response.request.headers["Content-Type"].split("boundary=")[-1]
|
||||
content_length = response.request.headers["Content-Length"]
|
||||
pdict: dict = {
|
||||
"boundary": boundary.encode("ascii"),
|
||||
"CONTENT-LENGTH": content_length,
|
||||
}
|
||||
multipart = cgi.parse_multipart(io.BytesIO(response.content), pdict)
|
||||
|
||||
# We're using the cgi module to verify the behavior here, which is a
|
||||
# bit grungy, but sufficient just for our testing purposes.
|
||||
boundary = response.request.headers["Content-Type"].split("boundary=")[-1]
|
||||
content_length = response.request.headers["Content-Length"]
|
||||
pdict: dict = {
|
||||
"boundary": boundary.encode("ascii"),
|
||||
"CONTENT-LENGTH": content_length,
|
||||
}
|
||||
multipart = cgi.parse_multipart(io.BytesIO(response.content), pdict)
|
||||
|
||||
# Note that the expected return type for text fields
|
||||
# appears to differs from 3.6 to 3.7+
|
||||
assert multipart["text"] == ["abc"] or multipart["text"] == [b"abc"]
|
||||
assert multipart["file"] == [b"<file content>"]
|
||||
# Note that the expected return type for text fields
|
||||
# appears to differs from 3.6 to 3.7+
|
||||
assert multipart["text"] == ["abc"] or multipart["text"] == [b"abc"]
|
||||
assert multipart["file"] == [b"<file content>"]
|
||||
|
||||
|
||||
def test_multipart_encode(tmp_path: typing.Any) -> None:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user