forked from home-assistant/core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhttpx_client.py
99 lines (71 loc) · 2.74 KB
/
httpx_client.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
"""Helper for httpx."""
from __future__ import annotations
from collections.abc import Callable
import sys
from typing import Any
import httpx
from homeassistant.const import EVENT_HOMEASSISTANT_CLOSE, __version__
from homeassistant.core import Event, HomeAssistant, callback
from homeassistant.loader import bind_hass
from .frame import warn_use
DATA_ASYNC_CLIENT = "httpx_async_client"
DATA_ASYNC_CLIENT_NOVERIFY = "httpx_async_client_noverify"
SERVER_SOFTWARE = "HomeAssistant/{0} httpx/{1} Python/{2[0]}.{2[1]}".format(
__version__, httpx.__version__, sys.version_info
)
USER_AGENT = "User-Agent"
@callback
@bind_hass
def get_async_client(hass: HomeAssistant, verify_ssl: bool = True) -> httpx.AsyncClient:
"""Return default httpx AsyncClient.
This method must be run in the event loop.
"""
key = DATA_ASYNC_CLIENT if verify_ssl else DATA_ASYNC_CLIENT_NOVERIFY
client: httpx.AsyncClient | None = hass.data.get(key)
if client is None:
client = hass.data[key] = create_async_httpx_client(hass, verify_ssl)
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:
"""Prevent an integration from close of the client via context manager."""
@callback
def create_async_httpx_client(
hass: HomeAssistant,
verify_ssl: bool = True,
auto_cleanup: bool = True,
**kwargs: Any,
) -> httpx.AsyncClient:
"""Create a new httpx.AsyncClient with kwargs, i.e. for cookies.
If auto_cleanup is False, the client will be
automatically closed on homeassistant_stop.
This method must be run in the event loop.
"""
client = HassHttpXAsyncClient(
verify=verify_ssl,
headers={USER_AGENT: SERVER_SOFTWARE},
**kwargs,
)
original_aclose = client.aclose
client.aclose = warn_use( # type: ignore[assignment]
client.aclose, "closes the Home Assistant httpx client"
)
if auto_cleanup:
_async_register_async_client_shutdown(hass, client, original_aclose)
return client
@callback
def _async_register_async_client_shutdown(
hass: HomeAssistant,
client: httpx.AsyncClient,
original_aclose: Callable[..., Any],
) -> None:
"""Register httpx AsyncClient aclose on Home Assistant shutdown.
This method must be run in the event loop.
"""
async def _async_close_client(event: Event) -> None:
"""Close httpx client."""
await original_aclose()
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_CLOSE, _async_close_client)