From 971ac015e7b1d1205e22fb3183fcfe699ae9e19b Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Wed, 19 Oct 2022 04:15:55 +0200 Subject: [PATCH] Add websocket type hints in config (#80532) --- homeassistant/components/config/auth.py | 27 +++++++++++-- .../config/auth_provider_homeassistant.py | 40 ++++++++++++++----- .../components/config/config_entries.py | 36 ++++++++++++----- homeassistant/components/config/core.py | 17 ++++++-- 4 files changed, 92 insertions(+), 28 deletions(-) diff --git a/homeassistant/components/config/auth.py b/homeassistant/components/config/auth.py index 15fc6634f5b..1699a4c8509 100644 --- a/homeassistant/components/config/auth.py +++ b/homeassistant/components/config/auth.py @@ -1,7 +1,10 @@ """Offer API to configure Home Assistant auth.""" +from typing import Any + import voluptuous as vol from homeassistant.components import websocket_api +from homeassistant.core import HomeAssistant WS_TYPE_LIST = "config/auth/list" SCHEMA_WS_LIST = websocket_api.BASE_COMMAND_MESSAGE_SCHEMA.extend( @@ -29,7 +32,11 @@ async def async_setup(hass): @websocket_api.require_admin @websocket_api.async_response -async def websocket_list(hass, connection, msg): +async def websocket_list( + hass: HomeAssistant, + connection: websocket_api.ActiveConnection, + msg: dict[str, Any], +) -> None: """Return a list of users.""" result = [_user_info(u) for u in await hass.auth.async_get_users()] @@ -38,7 +45,11 @@ async def websocket_list(hass, connection, msg): @websocket_api.require_admin @websocket_api.async_response -async def websocket_delete(hass, connection, msg): +async def websocket_delete( + hass: HomeAssistant, + connection: websocket_api.ActiveConnection, + msg: dict[str, Any], +) -> None: """Delete a user.""" if msg["user_id"] == connection.user.id: connection.send_message( @@ -69,7 +80,11 @@ async def websocket_delete(hass, connection, msg): } ) @websocket_api.async_response -async def websocket_create(hass, connection, msg): +async def websocket_create( + hass: HomeAssistant, + connection: websocket_api.ActiveConnection, + msg: dict[str, Any], +) -> None: """Create a user.""" user = await hass.auth.async_create_user( msg["name"], group_ids=msg.get("group_ids"), local_only=msg.get("local_only") @@ -92,7 +107,11 @@ async def websocket_create(hass, connection, msg): } ) @websocket_api.async_response -async def websocket_update(hass, connection, msg): +async def websocket_update( + hass: HomeAssistant, + connection: websocket_api.ActiveConnection, + msg: dict[str, Any], +) -> None: """Update a user.""" if not (user := await hass.auth.async_get_user(msg.pop("user_id"))): connection.send_message( diff --git a/homeassistant/components/config/auth_provider_homeassistant.py b/homeassistant/components/config/auth_provider_homeassistant.py index b6874720c47..d0606a748a9 100644 --- a/homeassistant/components/config/auth_provider_homeassistant.py +++ b/homeassistant/components/config/auth_provider_homeassistant.py @@ -1,9 +1,11 @@ """Offer API to configure the Home Assistant auth provider.""" +from typing import Any + import voluptuous as vol from homeassistant.auth.providers import homeassistant as auth_ha from homeassistant.components import websocket_api -from homeassistant.components.websocket_api import decorators +from homeassistant.core import HomeAssistant from homeassistant.exceptions import Unauthorized @@ -16,7 +18,7 @@ async def async_setup(hass): return True -@decorators.websocket_command( +@websocket_api.websocket_command( { vol.Required("type"): "config/auth_provider/homeassistant/create", vol.Required("user_id"): str, @@ -26,7 +28,11 @@ async def async_setup(hass): ) @websocket_api.require_admin @websocket_api.async_response -async def websocket_create(hass, connection, msg): +async def websocket_create( + hass: HomeAssistant, + connection: websocket_api.ActiveConnection, + msg: dict[str, Any], +) -> None: """Create credentials and attach to a user.""" provider = auth_ha.async_get_provider(hass) @@ -56,7 +62,7 @@ async def websocket_create(hass, connection, msg): connection.send_result(msg["id"]) -@decorators.websocket_command( +@websocket_api.websocket_command( { vol.Required("type"): "config/auth_provider/homeassistant/delete", vol.Required("username"): str, @@ -64,7 +70,11 @@ async def websocket_create(hass, connection, msg): ) @websocket_api.require_admin @websocket_api.async_response -async def websocket_delete(hass, connection, msg): +async def websocket_delete( + hass: HomeAssistant, + connection: websocket_api.ActiveConnection, + msg: dict[str, Any], +) -> None: """Delete username and related credential.""" provider = auth_ha.async_get_provider(hass) credentials = await provider.async_get_or_create_credentials( @@ -90,7 +100,7 @@ async def websocket_delete(hass, connection, msg): connection.send_result(msg["id"]) -@decorators.websocket_command( +@websocket_api.websocket_command( { vol.Required("type"): "config/auth_provider/homeassistant/change_password", vol.Required("current_password"): str, @@ -98,7 +108,11 @@ async def websocket_delete(hass, connection, msg): } ) @websocket_api.async_response -async def websocket_change_password(hass, connection, msg): +async def websocket_change_password( + hass: HomeAssistant, + connection: websocket_api.ActiveConnection, + msg: dict[str, Any], +) -> None: """Change current user password.""" if (user := connection.user) is None: connection.send_error(msg["id"], "user_not_found", "User not found") @@ -130,7 +144,7 @@ async def websocket_change_password(hass, connection, msg): connection.send_result(msg["id"]) -@decorators.websocket_command( +@websocket_api.websocket_command( { vol.Required( "type" @@ -139,9 +153,13 @@ async def websocket_change_password(hass, connection, msg): vol.Required("password"): str, } ) -@decorators.require_admin -@decorators.async_response -async def websocket_admin_change_password(hass, connection, msg): +@websocket_api.require_admin +@websocket_api.async_response +async def websocket_admin_change_password( + hass: HomeAssistant, + connection: websocket_api.ActiveConnection, + msg: dict[str, Any], +) -> None: """Change password of any user.""" if not connection.user.is_owner: raise Unauthorized(context=connection.context(msg)) diff --git a/homeassistant/components/config/config_entries.py b/homeassistant/components/config/config_entries.py index fb96a99827d..6f2320a2e93 100644 --- a/homeassistant/components/config/config_entries.py +++ b/homeassistant/components/config/config_entries.py @@ -13,7 +13,6 @@ from homeassistant import config_entries, data_entry_flow from homeassistant.auth.permissions.const import CAT_CONFIG_ENTRIES, POLICY_EDIT from homeassistant.components import websocket_api from homeassistant.components.http import HomeAssistantView -from homeassistant.components.websocket_api.connection import ActiveConnection from homeassistant.core import HomeAssistant, callback from homeassistant.exceptions import DependencyError, Unauthorized from homeassistant.helpers.data_entry_flow import ( @@ -291,7 +290,11 @@ def get_entry( } ) @websocket_api.async_response -async def config_entry_update(hass, connection, msg): +async def config_entry_update( + hass: HomeAssistant, + connection: websocket_api.ActiveConnection, + msg: dict[str, Any], +) -> None: """Update config entry.""" changes = dict(msg) changes.pop("id") @@ -311,9 +314,10 @@ async def config_entry_update(hass, connection, msg): "require_restart": False, } + initial_state = entry.state if ( old_disable_polling != entry.pref_disable_polling - and entry.state is config_entries.ConfigEntryState.LOADED + and initial_state is config_entries.ConfigEntryState.LOADED ): if not await hass.config_entries.async_reload(entry.entry_id): result["require_restart"] = ( @@ -334,14 +338,18 @@ async def config_entry_update(hass, connection, msg): } ) @websocket_api.async_response -async def config_entry_disable(hass, connection, msg): +async def config_entry_disable( + hass: HomeAssistant, + connection: websocket_api.ActiveConnection, + msg: dict[str, Any], +) -> None: """Disable config entry.""" if (disabled_by := msg["disabled_by"]) is not None: disabled_by = config_entries.ConfigEntryDisabler(disabled_by) - result = False + success = False try: - result = await hass.config_entries.async_set_disabled_by( + success = await hass.config_entries.async_set_disabled_by( msg["entry_id"], disabled_by ) except config_entries.OperationNotAllowed: @@ -351,7 +359,7 @@ async def config_entry_disable(hass, connection, msg): send_entry_not_found(connection, msg["id"]) return - result = {"require_restart": not result} + result = {"require_restart": not success} connection.send_result(msg["id"], result) @@ -361,7 +369,11 @@ async def config_entry_disable(hass, connection, msg): {"type": "config_entries/ignore_flow", "flow_id": str, "title": str} ) @websocket_api.async_response -async def ignore_config_flow(hass, connection, msg): +async def ignore_config_flow( + hass: HomeAssistant, + connection: websocket_api.ActiveConnection, + msg: dict[str, Any], +) -> None: """Ignore a config flow.""" flow = next( ( @@ -399,7 +411,9 @@ async def ignore_config_flow(hass, connection, msg): ) @websocket_api.async_response async def config_entries_get( - hass: HomeAssistant, connection: ActiveConnection, msg: dict[str, Any] + hass: HomeAssistant, + connection: websocket_api.ActiveConnection, + msg: dict[str, Any], ) -> None: """Return matching config entries by type and/or domain.""" connection.send_result( @@ -418,7 +432,9 @@ async def config_entries_get( ) @websocket_api.async_response async def config_entries_subscribe( - hass: HomeAssistant, connection: ActiveConnection, msg: dict[str, Any] + hass: HomeAssistant, + connection: websocket_api.ActiveConnection, + msg: dict[str, Any], ) -> None: """Subscribe to config entry updates.""" type_filter = msg.get("type_filter") diff --git a/homeassistant/components/config/core.py b/homeassistant/components/config/core.py index d6d97b5caca..5ffb2d4db99 100644 --- a/homeassistant/components/config/core.py +++ b/homeassistant/components/config/core.py @@ -1,10 +1,13 @@ """Component to interact with Hassbian tools.""" +from typing import Any + import voluptuous as vol from homeassistant.components import websocket_api from homeassistant.components.http import HomeAssistantView from homeassistant.config import async_check_ha_config_file +from homeassistant.core import HomeAssistant from homeassistant.helpers import config_validation as cv from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.util import location, unit_system @@ -49,7 +52,11 @@ class CheckConfigView(HomeAssistantView): } ) @websocket_api.async_response -async def websocket_update_config(hass, connection, msg): +async def websocket_update_config( + hass: HomeAssistant, + connection: websocket_api.ActiveConnection, + msg: dict[str, Any], +) -> None: """Handle update core config command.""" data = dict(msg) data.pop("id") @@ -65,12 +72,16 @@ async def websocket_update_config(hass, connection, msg): @websocket_api.require_admin @websocket_api.websocket_command({"type": "config/core/detect"}) @websocket_api.async_response -async def websocket_detect_config(hass, connection, msg): +async def websocket_detect_config( + hass: HomeAssistant, + connection: websocket_api.ActiveConnection, + msg: dict[str, Any], +) -> None: """Detect core config.""" session = async_get_clientsession(hass) location_info = await location.async_detect_location_info(session) - info = {} + info: dict[str, Any] = {} if location_info is None: connection.send_result(msg["id"], info)