diff --git a/requirements.txt b/requirements.txt index 941877d2b3..b2e32385dd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -31,8 +31,6 @@ isort==5.11.4 mypy==0.982 types-certifi==2021.10.8.2 pytest==7.2.0 -pytest-asyncio==0.20.3 -pytest-trio==0.7.0 trio==0.21.0 trio-typing==0.7.0 trustme==0.9.0 diff --git a/setup.cfg b/setup.cfg index 8077a27542..d9b822c1e0 100644 --- a/setup.cfg +++ b/setup.cfg @@ -18,7 +18,7 @@ combine_as_imports = True addopts = -rxXs filterwarnings = error -asyncio_mode = strict + ignore: You seem to already have a custom sys.excepthook handler installed. I'll skip installing Trio's custom handler, but this means MultiErrors will not show full tracebacks.:RuntimeWarning markers = copied_from(source, changes=None): mark test as copied from somewhere else, along with a description of changes made to accodomate e.g. our test setup network: marks tests which require network connection. Used in 3rd-party build environments that have network disabled. diff --git a/tests/client/test_async_client.py b/tests/client/test_async_client.py index cd34022e91..61ad5101dd 100644 --- a/tests/client/test_async_client.py +++ b/tests/client/test_async_client.py @@ -6,7 +6,7 @@ import httpx -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_get(server): url = server.url async with httpx.AsyncClient(http2=True) as client: @@ -27,14 +27,14 @@ async def test_get(server): pytest.param("http://", id="no-host"), ], ) -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_get_invalid_url(server, url): async with httpx.AsyncClient() as client: with pytest.raises((httpx.UnsupportedProtocol, httpx.LocalProtocolError)): await client.get(url) -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_build_request(server): url = server.url.copy_with(path="/echo_headers") headers = {"Custom-header": "value"} @@ -49,7 +49,7 @@ async def test_build_request(server): assert response.json()["Custom-header"] == "value" -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_post(server): url = server.url async with httpx.AsyncClient() as client: @@ -57,7 +57,7 @@ async def test_post(server): assert response.status_code == 200 -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_post_json(server): url = server.url async with httpx.AsyncClient() as client: @@ -65,7 +65,7 @@ async def test_post_json(server): assert response.status_code == 200 -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_stream_response(server): async with httpx.AsyncClient() as client: async with client.stream("GET", server.url) as response: @@ -76,7 +76,7 @@ async def test_stream_response(server): assert response.content == b"Hello, world!" -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_access_content_stream_response(server): async with httpx.AsyncClient() as client: async with client.stream("GET", server.url) as response: @@ -87,7 +87,7 @@ async def test_access_content_stream_response(server): response.content -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_stream_request(server): async def hello_world() -> typing.AsyncIterator[bytes]: yield b"Hello, " @@ -98,7 +98,7 @@ async def hello_world() -> typing.AsyncIterator[bytes]: assert response.status_code == 200 -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_cannot_stream_sync_request(server): def hello_world() -> typing.Iterator[bytes]: # pragma: no cover yield b"Hello, " @@ -109,7 +109,7 @@ def hello_world() -> typing.Iterator[bytes]: # pragma: no cover await client.post(server.url, content=hello_world()) -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_raise_for_status(server): async with httpx.AsyncClient() as client: for status_code in (200, 400, 404, 500, 505): @@ -125,7 +125,7 @@ async def test_raise_for_status(server): assert response.raise_for_status() is None # type: ignore -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_options(server): async with httpx.AsyncClient() as client: response = await client.options(server.url) @@ -133,7 +133,7 @@ async def test_options(server): assert response.text == "Hello, world!" -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_head(server): async with httpx.AsyncClient() as client: response = await client.head(server.url) @@ -141,21 +141,21 @@ async def test_head(server): assert response.text == "" -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_put(server): async with httpx.AsyncClient() as client: response = await client.put(server.url, content=b"Hello, world!") assert response.status_code == 200 -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_patch(server): async with httpx.AsyncClient() as client: response = await client.patch(server.url, content=b"Hello, world!") assert response.status_code == 200 -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_delete(server): async with httpx.AsyncClient() as client: response = await client.delete(server.url) @@ -163,7 +163,7 @@ async def test_delete(server): assert response.text == "Hello, world!" -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_100_continue(server): headers = {"Expect": "100-continue"} content = b"Echo request body" @@ -177,7 +177,7 @@ async def test_100_continue(server): assert response.content == content -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_context_managed_transport(): class Transport(httpx.AsyncBaseTransport): def __init__(self) -> None: @@ -209,7 +209,7 @@ async def __aexit__(self, *args): ] -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_context_managed_transport_and_mount(): class Transport(httpx.AsyncBaseTransport): def __init__(self, name: str): @@ -254,7 +254,7 @@ def hello_world(request): return httpx.Response(200, text="Hello, world!") -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_client_closed_state_using_implicit_open(): client = httpx.AsyncClient(transport=httpx.MockTransport(hello_world)) @@ -275,7 +275,7 @@ async def test_client_closed_state_using_implicit_open(): pass # pragma: no cover -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_client_closed_state_using_with_block(): async with httpx.AsyncClient(transport=httpx.MockTransport(hello_world)) as client: assert not client.is_closed @@ -296,7 +296,7 @@ def mounted(request: httpx.Request) -> httpx.Response: return httpx.Response(200, json=data) -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_mounted_transport(): transport = httpx.MockTransport(unmounted) mounts = {"custom://": httpx.MockTransport(mounted)} @@ -311,7 +311,7 @@ async def test_mounted_transport(): assert response.json() == {"app": "mounted"} -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_async_mock_transport(): async def hello_world(request): return httpx.Response(200, text="Hello, world!") @@ -324,7 +324,7 @@ async def hello_world(request): assert response.text == "Hello, world!" -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_cancellation_during_stream(): """ If any BaseException is raised during streaming the response, then the @@ -364,7 +364,7 @@ async def aclose(self) -> None: assert stream_was_closed -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_server_extensions(server): url = server.url async with httpx.AsyncClient(http2=True) as client: diff --git a/tests/client/test_auth.py b/tests/client/test_auth.py index e889d8ef48..cce3495517 100644 --- a/tests/client/test_auth.py +++ b/tests/client/test_auth.py @@ -3,13 +3,13 @@ Unit tests for auth classes also exist in tests/test_auth.py """ -import asyncio import hashlib import os import threading import typing from urllib.request import parse_keqv_list +import anyio import pytest import httpx @@ -135,7 +135,7 @@ class SyncOrAsyncAuth(httpx.Auth): def __init__(self) -> None: self._lock = threading.Lock() - self._async_lock = asyncio.Lock() + self._async_lock = anyio.Lock() def sync_auth_flow( self, request: httpx.Request @@ -152,7 +152,7 @@ async def async_auth_flow( yield request -@pytest.mark.asyncio +@pytest.mark.anyio async def test_basic_auth() -> None: url = "https://example.org/" auth = ("user", "password123") @@ -165,7 +165,7 @@ async def test_basic_auth() -> None: assert response.json() == {"auth": "Basic dXNlcjpwYXNzd29yZDEyMw=="} -@pytest.mark.asyncio +@pytest.mark.anyio async def test_basic_auth_with_stream() -> None: """ See: https://github.com/encode/httpx/pull/1312 @@ -184,7 +184,7 @@ async def test_basic_auth_with_stream() -> None: assert response.json() == {"auth": "Basic dXNlcjpwYXNzd29yZDEyMw=="} -@pytest.mark.asyncio +@pytest.mark.anyio async def test_basic_auth_in_url() -> None: url = "https://user:password123@example.org/" app = App() @@ -196,7 +196,7 @@ async def test_basic_auth_in_url() -> None: assert response.json() == {"auth": "Basic dXNlcjpwYXNzd29yZDEyMw=="} -@pytest.mark.asyncio +@pytest.mark.anyio async def test_basic_auth_on_session() -> None: url = "https://example.org/" auth = ("user", "password123") @@ -211,7 +211,7 @@ async def test_basic_auth_on_session() -> None: assert response.json() == {"auth": "Basic dXNlcjpwYXNzd29yZDEyMw=="} -@pytest.mark.asyncio +@pytest.mark.anyio async def test_custom_auth() -> None: url = "https://example.org/" app = App() @@ -227,7 +227,7 @@ def auth(request: httpx.Request) -> httpx.Request: assert response.json() == {"auth": "Token 123"} -@pytest.mark.asyncio +@pytest.mark.anyio async def test_netrc_auth() -> None: os.environ["NETRC"] = str(FIXTURES_DIR / ".netrc") url = "http://netrcexample.org" @@ -242,7 +242,7 @@ async def test_netrc_auth() -> None: } -@pytest.mark.asyncio +@pytest.mark.anyio async def test_auth_header_has_priority_over_netrc() -> None: os.environ["NETRC"] = str(FIXTURES_DIR / ".netrc") url = "http://netrcexample.org" @@ -255,7 +255,7 @@ async def test_auth_header_has_priority_over_netrc() -> None: assert response.json() == {"auth": "Override"} -@pytest.mark.asyncio +@pytest.mark.anyio async def test_trust_env_auth() -> None: os.environ["NETRC"] = str(FIXTURES_DIR / ".netrc") url = "http://netrcexample.org" @@ -280,7 +280,7 @@ async def test_trust_env_auth() -> None: } -@pytest.mark.asyncio +@pytest.mark.anyio async def test_auth_disable_per_request() -> None: url = "https://example.org/" auth = ("user", "password123") @@ -302,7 +302,7 @@ def test_auth_hidden_url() -> None: assert expected == repr(httpx.URL(url)) -@pytest.mark.asyncio +@pytest.mark.anyio async def test_auth_hidden_header() -> None: url = "https://example.org/" auth = ("example-username", "example-password") @@ -314,7 +314,7 @@ async def test_auth_hidden_header() -> None: assert "'authorization': '[secure]'" in str(response.request.headers) -@pytest.mark.asyncio +@pytest.mark.anyio async def test_auth_property() -> None: app = App() @@ -330,7 +330,7 @@ async def test_auth_property() -> None: assert response.json() == {"auth": "Basic dXNlcjpwYXNzd29yZDEyMw=="} -@pytest.mark.asyncio +@pytest.mark.anyio async def test_auth_invalid_type() -> None: app = App() @@ -348,7 +348,7 @@ async def test_auth_invalid_type() -> None: client.auth = "not a tuple, not a callable" # type: ignore -@pytest.mark.asyncio +@pytest.mark.anyio async def test_digest_auth_returns_no_auth_if_no_digest_header_in_response() -> None: url = "https://example.org/" auth = httpx.DigestAuth(username="user", password="password123") @@ -376,7 +376,7 @@ def test_digest_auth_returns_no_auth_if_alternate_auth_scheme() -> None: assert len(response.history) == 0 -@pytest.mark.asyncio +@pytest.mark.anyio async def test_digest_auth_200_response_including_digest_auth_header() -> None: url = "https://example.org/" auth = httpx.DigestAuth(username="user", password="password123") @@ -391,7 +391,7 @@ async def test_digest_auth_200_response_including_digest_auth_header() -> None: assert len(response.history) == 0 -@pytest.mark.asyncio +@pytest.mark.anyio async def test_digest_auth_401_response_without_digest_auth_header() -> None: url = "https://example.org/" auth = httpx.DigestAuth(username="user", password="password123") @@ -418,7 +418,7 @@ async def test_digest_auth_401_response_without_digest_auth_header() -> None: ("SHA-512-SESS", 64, 128), ], ) -@pytest.mark.asyncio +@pytest.mark.anyio async def test_digest_auth( algorithm: str, expected_hash_length: int, expected_response_length: int ) -> None: @@ -451,7 +451,7 @@ async def test_digest_auth( assert len(digest_data["cnonce"]) == 16 + 2 -@pytest.mark.asyncio +@pytest.mark.anyio async def test_digest_auth_no_specified_qop() -> None: url = "https://example.org/" auth = httpx.DigestAuth(username="user", password="password123") @@ -483,7 +483,7 @@ async def test_digest_auth_no_specified_qop() -> None: @pytest.mark.parametrize("qop", ("auth, auth-int", "auth,auth-int", "unknown,auth")) -@pytest.mark.asyncio +@pytest.mark.anyio async def test_digest_auth_qop_including_spaces_and_auth_returns_auth(qop: str) -> None: url = "https://example.org/" auth = httpx.DigestAuth(username="user", password="password123") @@ -496,7 +496,7 @@ async def test_digest_auth_qop_including_spaces_and_auth_returns_auth(qop: str) assert len(response.history) == 1 -@pytest.mark.asyncio +@pytest.mark.anyio async def test_digest_auth_qop_auth_int_not_implemented() -> None: url = "https://example.org/" auth = httpx.DigestAuth(username="user", password="password123") @@ -507,7 +507,7 @@ async def test_digest_auth_qop_auth_int_not_implemented() -> None: await client.get(url, auth=auth) -@pytest.mark.asyncio +@pytest.mark.anyio async def test_digest_auth_qop_must_be_auth_or_auth_int() -> None: url = "https://example.org/" auth = httpx.DigestAuth(username="user", password="password123") @@ -518,7 +518,7 @@ async def test_digest_auth_qop_must_be_auth_or_auth_int() -> None: await client.get(url, auth=auth) -@pytest.mark.asyncio +@pytest.mark.anyio async def test_digest_auth_incorrect_credentials() -> None: url = "https://example.org/" auth = httpx.DigestAuth(username="user", password="password123") @@ -531,7 +531,7 @@ async def test_digest_auth_incorrect_credentials() -> None: assert len(response.history) == 1 -@pytest.mark.asyncio +@pytest.mark.anyio async def test_digest_auth_reuses_challenge() -> None: url = "https://example.org/" auth = httpx.DigestAuth(username="user", password="password123") @@ -548,7 +548,7 @@ async def test_digest_auth_reuses_challenge() -> None: assert len(response_2.history) == 0 -@pytest.mark.asyncio +@pytest.mark.anyio async def test_digest_auth_resets_nonce_count_after_401() -> None: url = "https://example.org/" auth = httpx.DigestAuth(username="user", password="password123") @@ -594,7 +594,7 @@ async def test_digest_auth_resets_nonce_count_after_401() -> None: 'Digest realm="httpx@example.org", qop="auth,au', # malformed fields list ], ) -@pytest.mark.asyncio +@pytest.mark.anyio async def test_async_digest_auth_raises_protocol_error_on_malformed_header( auth_header: str, ) -> None: @@ -626,7 +626,7 @@ def test_sync_digest_auth_raises_protocol_error_on_malformed_header( client.get(url, auth=auth) -@pytest.mark.asyncio +@pytest.mark.anyio async def test_async_auth_history() -> None: """ Test that intermediate requests sent as part of an authentication flow @@ -686,7 +686,7 @@ async def handle_async_request(self, request: httpx.Request) -> httpx.Response: return self.handler(request) -@pytest.mark.asyncio +@pytest.mark.anyio async def test_digest_auth_unavailable_streaming_body(): url = "https://example.org/" auth = httpx.DigestAuth(username="user", password="password123") @@ -700,7 +700,7 @@ async def streaming_body() -> typing.AsyncIterator[bytes]: await client.post(url, content=streaming_body(), auth=auth) -@pytest.mark.asyncio +@pytest.mark.anyio async def test_async_auth_reads_response_body() -> None: """ Test that we can read the response body in an auth flow if `requires_response_body` @@ -733,7 +733,7 @@ def test_sync_auth_reads_response_body() -> None: assert response.json() == {"auth": '{"auth": "xyz"}'} -@pytest.mark.asyncio +@pytest.mark.anyio async def test_async_auth() -> None: """ Test that we can use an auth implementation specific to the async case, to diff --git a/tests/client/test_event_hooks.py b/tests/client/test_event_hooks.py index 7c7ce55d48..6604dd31a3 100644 --- a/tests/client/test_event_hooks.py +++ b/tests/client/test_event_hooks.py @@ -63,7 +63,7 @@ def raise_on_4xx_5xx(response): assert exc.response.is_closed -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_async_event_hooks(): events = [] @@ -99,7 +99,7 @@ async def on_response(response): ] -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_async_event_hooks_raising_exception(): async def raise_on_4xx_5xx(response): response.raise_for_status() @@ -171,7 +171,7 @@ def on_response(response): ] -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_async_event_hooks_with_redirect(): """ A redirect request should trigger additional 'request' and 'response' event hooks. diff --git a/tests/client/test_proxies.py b/tests/client/test_proxies.py index 98dfafab26..3070022fa1 100644 --- a/tests/client/test_proxies.py +++ b/tests/client/test_proxies.py @@ -132,7 +132,7 @@ def test_transport_for_request(url, proxies, expected): assert transport._pool._proxy_url == url_to_origin(expected) -@pytest.mark.asyncio +@pytest.mark.anyio @pytest.mark.network async def test_async_proxy_close(): try: diff --git a/tests/client/test_redirects.py b/tests/client/test_redirects.py index 726572f918..b83e667879 100644 --- a/tests/client/test_redirects.py +++ b/tests/client/test_redirects.py @@ -151,7 +151,7 @@ def test_next_request(): assert response.next_request is None -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_async_next_request(): async with httpx.AsyncClient(transport=httpx.MockTransport(redirects)) as client: request = client.build_request("POST", "https://example.org/redirect_303") @@ -240,7 +240,7 @@ def test_multiple_redirects(): assert len(response.history[1].history) == 1 -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_async_too_many_redirects(): async with httpx.AsyncClient(transport=httpx.MockTransport(redirects)) as client: with pytest.raises(httpx.TooManyRedirects): @@ -438,7 +438,7 @@ def test_redirect_custom_scheme(): assert str(e.value) == "Scheme 'market' not supported." -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_async_invalid_redirect(): async with httpx.AsyncClient(transport=httpx.MockTransport(redirects)) as client: with pytest.raises(httpx.RemoteProtocolError): diff --git a/tests/conftest.py b/tests/conftest.py index 1cf08af230..4479b2b084 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -34,30 +34,6 @@ } -@pytest.fixture( - params=[ - pytest.param("asyncio", marks=pytest.mark.asyncio), - pytest.param("trio", marks=pytest.mark.trio), - ] -) -def async_environment(request: typing.Any) -> str: - """ - Mark a test function to be run on both asyncio and trio. - - Equivalent to having a pair of tests, each respectively marked with - '@pytest.mark.asyncio' and '@pytest.mark.trio'. - - Intended usage: - - ``` - @pytest.mark.usefixtures("async_environment") - async def my_async_test(): - ... - ``` - """ - return typing.cast(str, request.param) - - @pytest.fixture(scope="function", autouse=True) def clean_environ(): """Keeps os.environ clean for every test without having to mock os.environ""" diff --git a/tests/models/test_requests.py b/tests/models/test_requests.py index 85594942b3..690b0e17df 100644 --- a/tests/models/test_requests.py +++ b/tests/models/test_requests.py @@ -86,7 +86,7 @@ def test_read_and_stream_data(): assert content == request.content -@pytest.mark.asyncio +@pytest.mark.anyio async def test_aread_and_stream_data(): # Ensure a request may still be streamed if it has been read. # Needed for cases such as authentication classes that read the request body. @@ -192,7 +192,7 @@ def test_request_picklable(): } -@pytest.mark.asyncio +@pytest.mark.anyio async def test_request_async_streaming_content_picklable(): async def streaming_body(data: bytes) -> typing.AsyncIterator[bytes]: yield data diff --git a/tests/models/test_responses.py b/tests/models/test_responses.py index acb9bd4514..cbd71e8b52 100644 --- a/tests/models/test_responses.py +++ b/tests/models/test_responses.py @@ -331,7 +331,7 @@ def test_empty_read(): assert response.is_closed -@pytest.mark.asyncio +@pytest.mark.anyio async def test_aread(): response = httpx.Response( 200, @@ -350,7 +350,7 @@ async def test_aread(): assert response.is_closed -@pytest.mark.asyncio +@pytest.mark.anyio async def test_empty_aread(): response = httpx.Response(200) @@ -449,7 +449,7 @@ def test_iter_raw_increments_updates_counter(): num_downloaded = response.num_bytes_downloaded -@pytest.mark.asyncio +@pytest.mark.anyio async def test_aiter_raw(): response = httpx.Response(200, content=async_streaming_body()) @@ -459,7 +459,7 @@ async def test_aiter_raw(): assert raw == b"Hello, world!" -@pytest.mark.asyncio +@pytest.mark.anyio async def test_aiter_raw_with_chunksize(): response = httpx.Response(200, content=async_streaming_body()) @@ -477,7 +477,7 @@ async def test_aiter_raw_with_chunksize(): assert parts == [b"Hello, world!"] -@pytest.mark.asyncio +@pytest.mark.anyio async def test_aiter_raw_on_sync(): response = httpx.Response( 200, @@ -488,7 +488,7 @@ async def test_aiter_raw_on_sync(): [part async for part in response.aiter_raw()] -@pytest.mark.asyncio +@pytest.mark.anyio async def test_aclose_on_sync(): response = httpx.Response( 200, @@ -499,7 +499,7 @@ async def test_aclose_on_sync(): await response.aclose() -@pytest.mark.asyncio +@pytest.mark.anyio async def test_aiter_raw_increments_updates_counter(): response = httpx.Response(200, content=async_streaming_body()) @@ -551,7 +551,7 @@ def streaming_body_with_empty_chunks() -> typing.Iterator[bytes]: assert parts == [b"Hello, ", b"world!"] -@pytest.mark.asyncio +@pytest.mark.anyio async def test_aiter_bytes(): response = httpx.Response( 200, @@ -564,7 +564,7 @@ async def test_aiter_bytes(): assert content == b"Hello, world!" -@pytest.mark.asyncio +@pytest.mark.anyio async def test_aiter_bytes_with_chunk_size(): response = httpx.Response(200, content=async_streaming_body()) parts = [part async for part in response.aiter_bytes(chunk_size=5)] @@ -605,7 +605,7 @@ def test_iter_text_with_chunk_size(): assert parts == ["Hello, world!"] -@pytest.mark.asyncio +@pytest.mark.anyio async def test_aiter_text(): response = httpx.Response( 200, @@ -618,7 +618,7 @@ async def test_aiter_text(): assert content == "Hello, world!" -@pytest.mark.asyncio +@pytest.mark.anyio async def test_aiter_text_with_chunk_size(): response = httpx.Response(200, content=b"Hello, world!") parts = [part async for part in response.aiter_text(chunk_size=5)] @@ -642,7 +642,7 @@ def test_iter_lines(): assert content == ["Hello,\n", "world!"] -@pytest.mark.asyncio +@pytest.mark.anyio async def test_aiter_lines(): response = httpx.Response( 200, @@ -671,7 +671,7 @@ def test_sync_streaming_response(): assert response.is_closed -@pytest.mark.asyncio +@pytest.mark.anyio async def test_async_streaming_response(): response = httpx.Response( 200, @@ -702,7 +702,7 @@ def test_cannot_read_after_stream_consumed(): response.read() -@pytest.mark.asyncio +@pytest.mark.anyio async def test_cannot_aread_after_stream_consumed(): response = httpx.Response( 200, @@ -728,7 +728,7 @@ def test_cannot_read_after_response_closed(): response.read() -@pytest.mark.asyncio +@pytest.mark.anyio async def test_cannot_aread_after_response_closed(): response = httpx.Response( 200, @@ -740,7 +740,7 @@ async def test_cannot_aread_after_response_closed(): await response.aread() -@pytest.mark.asyncio +@pytest.mark.anyio async def test_elapsed_not_available_until_closed(): response = httpx.Response( 200, @@ -947,7 +947,7 @@ def test_response_picklable(): assert pickle_response.history == [] -@pytest.mark.asyncio +@pytest.mark.anyio async def test_response_async_streaming_picklable(): response = httpx.Response(200, content=async_streaming_body()) pickle_response = pickle.loads(pickle.dumps(response)) diff --git a/tests/test_asgi.py b/tests/test_asgi.py index 60f55dfd6f..9c877deaf9 100644 --- a/tests/test_asgi.py +++ b/tests/test_asgi.py @@ -70,7 +70,7 @@ async def raise_exc_after_response(scope, receive, send): raise RuntimeError() -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_asgi_transport(): async with httpx.ASGITransport(app=hello_world) as transport: request = httpx.Request("GET", "http://www.example.com/") @@ -80,7 +80,7 @@ async def test_asgi_transport(): assert response.content == b"Hello, World!" -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_asgi_transport_no_body(): async with httpx.ASGITransport(app=echo_body) as transport: request = httpx.Request("GET", "http://www.example.com/") @@ -90,7 +90,7 @@ async def test_asgi_transport_no_body(): assert response.content == b"" -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_asgi(): async with httpx.AsyncClient(app=hello_world) as client: response = await client.get("http://www.example.org/") @@ -99,7 +99,7 @@ async def test_asgi(): assert response.text == "Hello, World!" -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_asgi_urlencoded_path(): async with httpx.AsyncClient(app=echo_path) as client: url = httpx.URL("http://www.example.org/").copy_with(path="/user@example.org") @@ -109,7 +109,7 @@ async def test_asgi_urlencoded_path(): assert response.json() == {"path": "/user@example.org"} -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_asgi_raw_path(): async with httpx.AsyncClient(app=echo_raw_path) as client: url = httpx.URL("http://www.example.org/").copy_with(path="/user@example.org") @@ -119,7 +119,7 @@ async def test_asgi_raw_path(): assert response.json() == {"raw_path": "/user%40example.org"} -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_asgi_upload(): async with httpx.AsyncClient(app=echo_body) as client: response = await client.post("http://www.example.org/", content=b"example") @@ -128,7 +128,7 @@ async def test_asgi_upload(): assert response.text == "example" -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_asgi_headers(): async with httpx.AsyncClient(app=echo_headers) as client: response = await client.get("http://www.example.org/") @@ -145,21 +145,21 @@ async def test_asgi_headers(): } -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_asgi_exc(): async with httpx.AsyncClient(app=raise_exc) as client: with pytest.raises(RuntimeError): await client.get("http://www.example.org/") -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_asgi_exc_after_response(): async with httpx.AsyncClient(app=raise_exc_after_response) as client: with pytest.raises(RuntimeError): await client.get("http://www.example.org/") -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_asgi_disconnect_after_response_complete(): disconnect = False diff --git a/tests/test_content.py b/tests/test_content.py index 6a1303cc80..a4d5f7a1fc 100644 --- a/tests/test_content.py +++ b/tests/test_content.py @@ -9,7 +9,7 @@ url = "https://www.example.com" -@pytest.mark.asyncio +@pytest.mark.anyio async def test_empty_content(): request = httpx.Request(method, url) assert isinstance(request.stream, httpx.SyncByteStream) @@ -23,7 +23,7 @@ async def test_empty_content(): assert async_content == b"" -@pytest.mark.asyncio +@pytest.mark.anyio async def test_bytes_content(): request = httpx.Request(method, url, content=b"Hello, world!") assert isinstance(request.stream, typing.Iterable) @@ -50,7 +50,7 @@ async def test_bytes_content(): assert async_content == b"Hello, world!" -@pytest.mark.asyncio +@pytest.mark.anyio async def test_bytesio_content(): request = httpx.Request(method, url, content=io.BytesIO(b"Hello, world!")) assert isinstance(request.stream, typing.Iterable) @@ -62,7 +62,7 @@ async def test_bytesio_content(): assert content == b"Hello, world!" -@pytest.mark.asyncio +@pytest.mark.anyio async def test_async_bytesio_content(): class AsyncBytesIO: def __init__(self, content: bytes) -> None: @@ -90,7 +90,7 @@ async def __aiter__(self): assert content == b"Hello, world!" -@pytest.mark.asyncio +@pytest.mark.anyio async def test_iterator_content(): def hello_world() -> typing.Iterator[bytes]: yield b"Hello, " @@ -126,7 +126,7 @@ def hello_world() -> typing.Iterator[bytes]: assert content == b"Hello, world!" -@pytest.mark.asyncio +@pytest.mark.anyio async def test_aiterator_content(): async def hello_world() -> typing.AsyncIterator[bytes]: yield b"Hello, " @@ -162,7 +162,7 @@ async def hello_world() -> typing.AsyncIterator[bytes]: assert content == b"Hello, world!" -@pytest.mark.asyncio +@pytest.mark.anyio async def test_json_content(): request = httpx.Request(method, url, json={"Hello": "world!"}) assert isinstance(request.stream, typing.Iterable) @@ -180,7 +180,7 @@ async def test_json_content(): assert async_content == b'{"Hello": "world!"}' -@pytest.mark.asyncio +@pytest.mark.anyio async def test_urlencoded_content(): request = httpx.Request(method, url, data={"Hello": "world!"}) assert isinstance(request.stream, typing.Iterable) @@ -198,7 +198,7 @@ async def test_urlencoded_content(): assert async_content == b"Hello=world%21" -@pytest.mark.asyncio +@pytest.mark.anyio async def test_urlencoded_boolean(): request = httpx.Request(method, url, data={"example": True}) assert isinstance(request.stream, typing.Iterable) @@ -216,7 +216,7 @@ async def test_urlencoded_boolean(): assert async_content == b"example=true" -@pytest.mark.asyncio +@pytest.mark.anyio async def test_urlencoded_none(): request = httpx.Request(method, url, data={"example": None}) assert isinstance(request.stream, typing.Iterable) @@ -234,7 +234,7 @@ async def test_urlencoded_none(): assert async_content == b"example=" -@pytest.mark.asyncio +@pytest.mark.anyio async def test_urlencoded_list(): request = httpx.Request(method, url, data={"example": ["a", 1, True]}) assert isinstance(request.stream, typing.Iterable) @@ -252,7 +252,7 @@ async def test_urlencoded_list(): assert async_content == b"example=a&example=1&example=true" -@pytest.mark.asyncio +@pytest.mark.anyio async def test_multipart_files_content(): files = {"file": io.BytesIO(b"")} headers = {"Content-Type": "multipart/form-data; boundary=+++"} @@ -295,7 +295,7 @@ async def test_multipart_files_content(): ) -@pytest.mark.asyncio +@pytest.mark.anyio async def test_multipart_data_and_files_content(): data = {"message": "Hello, world!"} files = {"file": io.BytesIO(b"")} @@ -342,7 +342,7 @@ async def test_multipart_data_and_files_content(): ) -@pytest.mark.asyncio +@pytest.mark.anyio async def test_empty_request(): request = httpx.Request(method, url, data={}, files={}) assert isinstance(request.stream, typing.Iterable) @@ -364,7 +364,7 @@ def test_invalid_argument(): httpx.Request(method, url, content={"a": "b"}) # type: ignore -@pytest.mark.asyncio +@pytest.mark.anyio async def test_multipart_multiple_files_single_input_content(): files = [ ("file", io.BytesIO(b"")), @@ -415,7 +415,7 @@ async def test_multipart_multiple_files_single_input_content(): ) -@pytest.mark.asyncio +@pytest.mark.anyio async def test_response_empty_content(): response = httpx.Response(200) assert isinstance(response.stream, typing.Iterable) @@ -429,7 +429,7 @@ async def test_response_empty_content(): assert async_content == b"" -@pytest.mark.asyncio +@pytest.mark.anyio async def test_response_bytes_content(): response = httpx.Response(200, content=b"Hello, world!") assert isinstance(response.stream, typing.Iterable) @@ -443,7 +443,7 @@ async def test_response_bytes_content(): assert async_content == b"Hello, world!" -@pytest.mark.asyncio +@pytest.mark.anyio async def test_response_iterator_content(): def hello_world() -> typing.Iterator[bytes]: yield b"Hello, " @@ -462,7 +462,7 @@ def hello_world() -> typing.Iterator[bytes]: [part for part in response.stream] -@pytest.mark.asyncio +@pytest.mark.anyio async def test_response_aiterator_content(): async def hello_world() -> typing.AsyncIterator[bytes]: yield b"Hello, " diff --git a/tests/test_decoders.py b/tests/test_decoders.py index 359c1c4b19..35ddad2a82 100644 --- a/tests/test_decoders.py +++ b/tests/test_decoders.py @@ -114,7 +114,7 @@ def test_multi_with_identity(): assert response.content == body -@pytest.mark.asyncio +@pytest.mark.anyio async def test_streaming(): body = b"test 123" compressor = zlib.compressobj(9, zlib.DEFLATED, zlib.MAX_WBITS | 16) @@ -173,7 +173,7 @@ def test_decoding_errors(header_value): ((b"Accented: \xd6sterreich abcdefghijklmnopqrstuvwxyz", b""), "iso-8859-1"), ], ) -@pytest.mark.asyncio +@pytest.mark.anyio async def test_text_decoder_with_autodetect(data, encoding): async def iterator() -> typing.AsyncIterator[bytes]: nonlocal data @@ -196,7 +196,7 @@ def autodetect(content): assert text == (b"".join(data)).decode(encoding) -@pytest.mark.asyncio +@pytest.mark.anyio async def test_text_decoder_known_encoding(): async def iterator() -> typing.AsyncIterator[bytes]: yield b"\x83g" diff --git a/tests/test_timeouts.py b/tests/test_timeouts.py index dee17df2f7..09b25160e7 100644 --- a/tests/test_timeouts.py +++ b/tests/test_timeouts.py @@ -3,7 +3,7 @@ import httpx -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_read_timeout(server): timeout = httpx.Timeout(None, read=1e-6) @@ -12,7 +12,7 @@ async def test_read_timeout(server): await client.get(server.url.copy_with(path="/slow_response")) -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_write_timeout(server): timeout = httpx.Timeout(None, write=1e-6) @@ -22,7 +22,7 @@ async def test_write_timeout(server): await client.put(server.url.copy_with(path="/slow_response"), content=data) -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio @pytest.mark.network async def test_connect_timeout(server): timeout = httpx.Timeout(None, connect=1e-6) @@ -33,7 +33,7 @@ async def test_connect_timeout(server): await client.get("http://10.255.255.1/") -@pytest.mark.usefixtures("async_environment") +@pytest.mark.anyio async def test_pool_timeout(server): limits = httpx.Limits(max_connections=1) timeout = httpx.Timeout(None, pool=1e-4) diff --git a/tests/test_utils.py b/tests/test_utils.py index e4bbb6ba2c..859c4e4199 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -98,7 +98,7 @@ def test_parse_header_links(value, expected): assert parse_header_links(value) == expected -@pytest.mark.asyncio +@pytest.mark.anyio async def test_logs_debug(server, capsys): with override_log_level("debug"): async with httpx.AsyncClient() as client: @@ -108,7 +108,7 @@ async def test_logs_debug(server, capsys): assert 'HTTP Request: GET http://127.0.0.1:8000/ "HTTP/1.1 200 OK"' in stderr -@pytest.mark.asyncio +@pytest.mark.anyio async def test_logs_trace(server, capsys): with override_log_level("trace"): async with httpx.AsyncClient() as client: @@ -118,7 +118,7 @@ async def test_logs_trace(server, capsys): assert 'HTTP Request: GET http://127.0.0.1:8000/ "HTTP/1.1 200 OK"' in stderr -@pytest.mark.asyncio +@pytest.mark.anyio async def test_logs_redirect_chain(server, capsys): with override_log_level("debug"): async with httpx.AsyncClient(follow_redirects=True) as client: