diff --git a/homeassistant/helpers/httpx_client.py b/homeassistant/helpers/httpx_client.py index dfac0694a074..44045a7abeb0 100644 --- a/homeassistant/helpers/httpx_client.py +++ b/homeassistant/helpers/httpx_client.py @@ -39,6 +39,17 @@ def get_async_client( return client +class HassHttpXAsyncClient(httpx.AsyncClient): + """httpx AsyncClient that suppresses context management.""" + + async def __aenter__(self: HassHttpXAsyncClient) -> HassHttpXAsyncClient: + """Prevent an integration from reopen of the client via context manager.""" + return self + + async def __aexit__(self, *args: Any) -> None: # pylint: disable=signature-differs + """Prevent an integration from close of the client via context manager.""" + + @callback def create_async_httpx_client( hass: HomeAssistantType, @@ -53,7 +64,7 @@ def create_async_httpx_client( This method must be run in the event loop. """ - client = httpx.AsyncClient( + client = HassHttpXAsyncClient( verify=verify_ssl, headers={USER_AGENT: SERVER_SOFTWARE}, **kwargs, diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 86269b9da06b..4d1d53b85d12 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -16,7 +16,7 @@ distro==1.5.0 emoji==1.2.0 hass-nabucasa==0.42.0 home-assistant-frontend==20210324.0 -httpx==0.16.1 +httpx==0.17.1 jinja2>=2.11.3 netdisco==2.8.2 paho-mqtt==1.5.1 diff --git a/requirements.txt b/requirements.txt index dafb5686e4a0..5f633eaeb691 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,7 +9,7 @@ awesomeversion==21.2.3 bcrypt==3.1.7 certifi>=2020.12.5 ciso8601==2.1.3 -httpx==0.16.1 +httpx==0.17.1 jinja2>=2.11.3 PyJWT==1.7.1 cryptography==3.3.2 diff --git a/setup.py b/setup.py index d3a8a5aea707..56e56391489f 100755 --- a/setup.py +++ b/setup.py @@ -40,7 +40,7 @@ REQUIRES = [ "bcrypt==3.1.7", "certifi>=2020.12.5", "ciso8601==2.1.3", - "httpx==0.16.1", + "httpx==0.17.1", "jinja2>=2.11.3", "PyJWT==1.7.1", # PyJWT has loose dependency. We want the latest one. diff --git a/tests/helpers/test_httpx_client.py b/tests/helpers/test_httpx_client.py index 53a6985f5cc7..a47463b6b989 100644 --- a/tests/helpers/test_httpx_client.py +++ b/tests/helpers/test_httpx_client.py @@ -80,6 +80,19 @@ async def test_get_async_client_patched_close(hass): assert mock_aclose.call_count == 0 +async def test_get_async_client_context_manager(hass): + """Test using the async client with a context manager does not close the session.""" + + with patch("httpx.AsyncClient.aclose") as mock_aclose: + httpx_session = client.get_async_client(hass) + assert isinstance(hass.data[client.DATA_ASYNC_CLIENT], httpx.AsyncClient) + + async with httpx_session: + pass + + assert mock_aclose.call_count == 0 + + async def test_warning_close_session_integration(hass, caplog): """Test log warning message when closing the session from integration context.""" with patch(