diff --git a/tests/test_http_client.py b/tests/test_http_client.py new file mode 100644 index 0000000..c5f9ec1 --- /dev/null +++ b/tests/test_http_client.py @@ -0,0 +1,41 @@ +"""HTTPClient had zero test coverage before this: connect() hardcoded +http2=True in the httpx.AsyncClient(...) call, which raises ImportError +unless the optional 'h2' package is installed -- never declared as a +dependency anywhere, so the default constructor was unusable out of the +box for anyone who only installed velocix's declared requirements. +""" + +import asyncio + +from velocix.http.client import HTTPClient + + +def _run(coro): + return asyncio.run(coro) + + +def test_default_client_connects_without_h2_installed(): + async def scenario(): + client = HTTPClient() + await client.connect() + assert not client.is_closed + await client.close() + + _run(scenario()) + + +def test_default_client_as_context_manager(): + async def scenario(): + async with HTTPClient() as client: + assert not client.is_closed + + _run(scenario()) + + +def test_http2_is_opt_in(): + async def scenario(): + client = HTTPClient(http2=False) + await client.connect() + await client.close() + + _run(scenario()) diff --git a/velocix/http/client.py b/velocix/http/client.py index 4f855ae..156239f 100644 --- a/velocix/http/client.py +++ b/velocix/http/client.py @@ -48,6 +48,7 @@ class HTTPClient: "_limits", "_verify_ssl", "_follow_redirects", + "_http2", ) def __init__( @@ -60,6 +61,7 @@ def __init__( max_keepalive: int = 20, verify_ssl: bool = True, follow_redirects: bool = True, + http2: bool = False, ) -> None: self._client: httpx.AsyncClient | None = None self._timeout = timeout @@ -71,6 +73,11 @@ def __init__( ) self._verify_ssl = verify_ssl self._follow_redirects = follow_redirects + # Opt-in: httpx raises ImportError from AsyncClient(http2=True) unless + # the optional 'h2' package is installed, so defaulting this to True + # made HTTPClient unusable out of the box for anyone who only + # installed velocix's declared dependencies (just httpx, no h2). + self._http2 = http2 async def __aenter__(self) -> "HTTPClient": await self.connect() @@ -94,7 +101,7 @@ async def connect(self) -> None: limits=self._limits, verify=self._verify_ssl, follow_redirects=self._follow_redirects, - http2=True, # Enable HTTP/2 support + http2=self._http2, ) async def close(self) -> None: