diff --git a/docs/intro.rst b/docs/intro.rst index f47166f6..a4281abb 100644 --- a/docs/intro.rst +++ b/docs/intro.rst @@ -51,7 +51,7 @@ The corresponding between extra dependencies required and the GQL classes is: +---------------------+------------------------------------------------------------------+ | requests | :ref:`RequestsHTTPTransport ` | +---------------------+------------------------------------------------------------------+ -| httpx | :ref:`HTTPTXTransport ` | +| httpx2 or httpx | :ref:`HTTPTXTransport ` | | | | | | :ref:`HTTPXAsyncTransport ` | +---------------------+------------------------------------------------------------------+ diff --git a/docs/transports/httpx.rst b/docs/transports/httpx.rst index 25796621..7058b198 100644 --- a/docs/transports/httpx.rst +++ b/docs/transports/httpx.rst @@ -3,7 +3,7 @@ HTTPXTransport ============== -The HTTPXTransport is a sync transport using the `httpx`_ library +The HTTPXTransport is a sync transport using the `httpx2`_ or `httpx`_ library and allows you to send GraphQL queries using the HTTP protocol. Reference: :class:`gql.transport.httpx.HTTPXTransport` @@ -11,3 +11,4 @@ Reference: :class:`gql.transport.httpx.HTTPXTransport` .. literalinclude:: ../code_examples/httpx_sync.py .. _httpx: https://www.python-httpx.org +.. _httpx2: https://httpx2.pydantic.dev diff --git a/docs/transports/httpx_async.rst b/docs/transports/httpx_async.rst index c09d0cdc..2da0f204 100644 --- a/docs/transports/httpx_async.rst +++ b/docs/transports/httpx_async.rst @@ -3,7 +3,7 @@ HTTPXAsyncTransport =================== -This transport uses the `httpx`_ library and allows you to send GraphQL queries using the HTTP protocol. +This transport uses the `httpx2`_ or `httpx`_ library and allows you to send GraphQL queries using the HTTP protocol. Reference: :class:`gql.transport.httpx.HTTPXAsyncTransport` @@ -37,3 +37,4 @@ You can manually set the cookies which will be sent with each connection: transport = HTTPXAsyncTransport(url=url, cookies={"cookie1": "val1"}) .. _httpx: https://www.python-httpx.org +.. _httpx2: https://httpx2.pydantic.dev diff --git a/gql/transport/httpx.py b/gql/transport/httpx.py index 7143f263..fb0688b9 100644 --- a/gql/transport/httpx.py +++ b/gql/transport/httpx.py @@ -14,7 +14,11 @@ Union, ) -import httpx +try: + import httpx2 as httpx +except ModuleNotFoundError: # pragma: no cover + import httpx # type: ignore[no-redef] + from graphql import ExecutionResult from ..graphql_request import GraphQLRequest diff --git a/setup.py b/setup.py index af1d6a56..d7e9a926 100644 --- a/setup.py +++ b/setup.py @@ -52,6 +52,10 @@ "httpx>=0.27.0,<1", ] +install_httpx2_requires = [ + "httpx2>=2.0.0,<3", +] + install_websockets_requires = [ "websockets>=14.2,<16", ] @@ -65,7 +69,7 @@ ] install_all_requires = ( - install_aiohttp_requires + install_requests_requires + install_httpx_requires + install_websockets_requires + install_botocore_requires + install_aiofiles_requires + install_aiohttp_requires + install_requests_requires + install_httpx2_requires + install_websockets_requires + install_botocore_requires + install_aiofiles_requires ) # Get version from __version__.py file @@ -110,6 +114,7 @@ "aiohttp": install_aiohttp_requires, "requests": install_requests_requires, "httpx": install_httpx_requires, + "httpx2": install_httpx2_requires, "websockets": install_websockets_requires, "botocore": install_botocore_requires, "aiofiles": install_aiofiles_requires, diff --git a/tests/test_httpx.py b/tests/test_httpx.py index aa25edc2..88612464 100644 --- a/tests/test_httpx.py +++ b/tests/test_httpx.py @@ -216,19 +216,24 @@ def test_code(): query = gql(query1_str) - expected_error = "certificate verify failed: self-signed certificate" + expected_errors = [ + # Linux / OpenSSL error message + "certificate verify failed: self-signed certificate", + # Windows error message + "not trusted by the trust provider", + ] with pytest.raises(TransportConnectionFailed) as exc_info: with Client(transport=transport) as session: session.execute(query) - assert expected_error in str(exc_info.value) + assert any(err in str(exc_info.value) for err in expected_errors) with pytest.raises(TransportConnectionFailed) as exc_info: with Client(transport=transport) as session: session.execute_batch([query]) - assert expected_error in str(exc_info.value) + assert any(err in str(exc_info.value) for err in expected_errors) await run_sync_test(server, test_code) diff --git a/tests/test_httpx_async.py b/tests/test_httpx_async.py index 278d3c46..5effea79 100644 --- a/tests/test_httpx_async.py +++ b/tests/test_httpx_async.py @@ -436,7 +436,11 @@ async def handler(request): @pytest.mark.aiohttp @pytest.mark.asyncio async def test_httpx_extra_args(aiohttp_server): - import httpx + try: + import httpx2 as httpx + except ModuleNotFoundError: # pragma: no cover + import httpx # type: ignore[no-redef] + from aiohttp import web from gql.transport.httpx import HTTPXAsyncTransport @@ -1179,19 +1183,24 @@ async def handler(request): query = gql(query1_str) - expected_error = "certificate verify failed: self-signed certificate" + expected_errors = [ + # Linux / OpenSSL error message + "certificate verify failed: self-signed certificate", + # Windows error message + "not trusted by the trust provider", + ] with pytest.raises(TransportConnectionFailed) as exc_info: async with Client(transport=transport) as session: await session.execute(query) - assert expected_error in str(exc_info.value) + assert any(err in str(exc_info.value) for err in expected_errors) with pytest.raises(TransportConnectionFailed) as exc_info: async with Client(transport=transport) as session: await session.execute_batch([query]) - assert expected_error in str(exc_info.value) + assert any(err in str(exc_info.value) for err in expected_errors) @pytest.mark.aiohttp diff --git a/tests/test_httpx_batch.py b/tests/test_httpx_batch.py index 2f05df99..9e42d432 100644 --- a/tests/test_httpx_batch.py +++ b/tests/test_httpx_batch.py @@ -325,7 +325,11 @@ async def handler(request): @pytest.mark.aiohttp @pytest.mark.asyncio async def test_httpx_async_batch_extra_args(aiohttp_server): - import httpx + try: + import httpx2 as httpx + except ModuleNotFoundError: # pragma: no cover + import httpx # type: ignore[no-redef] + from aiohttp import web from gql.transport.httpx import HTTPXAsyncTransport