1
0
mirror of https://github.com/home-assistant/supervisor.git synced 2026-02-15 07:27:13 +00:00

Use session.request() instead of getattr dispatch in HomeAssistantAPI (#6541)

Replace the dynamic `getattr(self.sys_websession, method)(...)` pattern
with the explicit `self.sys_websession.request(method, ...)` call. This
is type-safe and avoids runtime failures from typos in method names.

Also wrap the timeout parameter in `aiohttp.ClientTimeout` for
consistency with the typed `request()` signature.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Stefan Agner
2026-02-10 09:43:55 +01:00
committed by GitHub
parent 74da5cdaf7
commit 66228f976d
4 changed files with 25 additions and 16 deletions

View File

@@ -135,6 +135,7 @@ class HomeAssistantAPI(CoreSysAttributes):
""" """
url = f"{self.sys_homeassistant.api_url}/{path}" url = f"{self.sys_homeassistant.api_url}/{path}"
headers = headers or {} headers = headers or {}
client_timeout = aiohttp.ClientTimeout(total=timeout)
# Passthrough content type # Passthrough content type
if content_type is not None: if content_type is not None:
@@ -144,10 +145,11 @@ class HomeAssistantAPI(CoreSysAttributes):
try: try:
await self.ensure_access_token() await self.ensure_access_token()
headers[hdrs.AUTHORIZATION] = f"Bearer {self.access_token}" headers[hdrs.AUTHORIZATION] = f"Bearer {self.access_token}"
async with getattr(self.sys_websession, method)( async with self.sys_websession.request(
method,
url, url,
data=data, data=data,
timeout=timeout, timeout=client_timeout,
json=json, json=json,
headers=headers, headers=headers,
params=params, params=params,

View File

@@ -210,12 +210,17 @@ async def test_addon_uninstall_removes_discovery(
await coresys.addons.uninstall(TEST_ADDON_SLUG) await coresys.addons.uninstall(TEST_ADDON_SLUG)
await asyncio.sleep(0) await asyncio.sleep(0)
coresys.websession.delete.assert_called_once()
# Find the delete call among all request calls (send also uses request)
delete_calls = [
c for c in coresys.websession.request.call_args_list if c.args[0] == "delete"
]
assert len(delete_calls) == 1
assert ( assert (
coresys.websession.delete.call_args.args[0] delete_calls[0].args[1]
== f"http://172.30.32.1:8123/api/hassio_push/discovery/{message.uuid}" == f"http://172.30.32.1:8123/api/hassio_push/discovery/{message.uuid}"
) )
assert coresys.websession.delete.call_args.kwargs["json"] == { assert delete_calls[0].kwargs["json"] == {
"addon": TEST_ADDON_SLUG, "addon": TEST_ADDON_SLUG,
"service": "mqtt", "service": "mqtt",
"uuid": message.uuid, "uuid": message.uuid,

View File

@@ -95,7 +95,7 @@ async def test_password_reset(
days=1 days=1
) )
websession.post = MagicMock(return_value=MockResponse(status=200)) websession.request = MagicMock(return_value=MockResponse(status=200))
resp = await api_client.post( resp = await api_client.post(
"/auth/reset", json={"username": "john", "password": "doe"} "/auth/reset", json={"username": "john", "password": "doe"}
) )
@@ -104,7 +104,7 @@ async def test_password_reset(
@pytest.mark.parametrize( @pytest.mark.parametrize(
("post_mock", "expected_log"), ("request_mock", "expected_log"),
[ [
( (
MagicMock(return_value=MockResponse(status=400)), MagicMock(return_value=MockResponse(status=400)),
@@ -121,7 +121,7 @@ async def test_failed_password_reset(
coresys: CoreSys, coresys: CoreSys,
caplog: pytest.LogCaptureFixture, caplog: pytest.LogCaptureFixture,
websession: MagicMock, websession: MagicMock,
post_mock: MagicMock, request_mock: MagicMock,
expected_log: str, expected_log: str,
): ):
"""Test failed password reset.""" """Test failed password reset."""
@@ -131,7 +131,7 @@ async def test_failed_password_reset(
days=1 days=1
) )
websession.post = post_mock websession.request = request_mock
resp = await api_client.post( resp = await api_client.post(
"/auth/reset", json={"username": "john", "password": "doe"} "/auth/reset", json={"username": "john", "password": "doe"}
) )

View File

@@ -97,12 +97,13 @@ async def test_api_send_del_discovery(
assert resp.status == 200 assert resp.status == 200
result = await resp.json() result = await resp.json()
uuid = result["data"]["uuid"] uuid = result["data"]["uuid"]
coresys.websession.post.assert_called_once() coresys.websession.request.assert_called_once()
assert coresys.websession.request.call_args.args[0] == "post"
assert ( assert (
coresys.websession.post.call_args.args[0] coresys.websession.request.call_args.args[1]
== f"http://172.30.32.1:8123/api/hassio_push/discovery/{uuid}" == f"http://172.30.32.1:8123/api/hassio_push/discovery/{uuid}"
) )
assert coresys.websession.post.call_args.kwargs["json"] == { assert coresys.websession.request.call_args.kwargs["json"] == {
"addon": TEST_ADDON_SLUG, "addon": TEST_ADDON_SLUG,
"service": "test", "service": "test",
"uuid": uuid, "uuid": uuid,
@@ -113,15 +114,16 @@ async def test_api_send_del_discovery(
assert message.service == "test" assert message.service == "test"
assert message.config == {} assert message.config == {}
coresys.websession.delete = MagicMock() coresys.websession.request.reset_mock()
resp = await api_client.delete(f"/discovery/{uuid}") resp = await api_client.delete(f"/discovery/{uuid}")
assert resp.status == 200 assert resp.status == 200
coresys.websession.delete.assert_called_once() coresys.websession.request.assert_called_once()
assert coresys.websession.request.call_args.args[0] == "delete"
assert ( assert (
coresys.websession.delete.call_args.args[0] coresys.websession.request.call_args.args[1]
== f"http://172.30.32.1:8123/api/hassio_push/discovery/{uuid}" == f"http://172.30.32.1:8123/api/hassio_push/discovery/{uuid}"
) )
assert coresys.websession.delete.call_args.kwargs["json"] == { assert coresys.websession.request.call_args.kwargs["json"] == {
"addon": TEST_ADDON_SLUG, "addon": TEST_ADDON_SLUG,
"service": "test", "service": "test",
"uuid": uuid, "uuid": uuid,