From 74b50a80096f7c55c61ea7e94cc741c86e806f6f Mon Sep 17 00:00:00 2001 From: ollo69 <60491700+ollo69@users.noreply.github.com> Date: Fri, 22 Apr 2022 09:14:13 +0200 Subject: [PATCH] Enable AsusWRT strict typing (#70396) * Enable AsusWRT strict typing * Fix myPi errors --- .strict-typing | 1 + homeassistant/components/asuswrt/__init__.py | 4 +- .../components/asuswrt/config_flow.py | 61 +++++++++++-------- .../components/asuswrt/device_tracker.py | 2 +- homeassistant/components/asuswrt/router.py | 2 +- homeassistant/components/asuswrt/sensor.py | 7 +-- mypy.ini | 11 ++++ 7 files changed, 55 insertions(+), 33 deletions(-) diff --git a/.strict-typing b/.strict-typing index 81e754f9f00..ac60defda3f 100644 --- a/.strict-typing +++ b/.strict-typing @@ -46,6 +46,7 @@ homeassistant.components.ambient_station.* homeassistant.components.amcrest.* homeassistant.components.ampio.* homeassistant.components.aseko_pool_live.* +homeassistant.components.asuswrt.* homeassistant.components.automation.* homeassistant.components.backup.* homeassistant.components.binary_sensor.* diff --git a/homeassistant/components/asuswrt/__init__.py b/homeassistant/components/asuswrt/__init__.py index f735e520bdc..0532dd9c7cc 100644 --- a/homeassistant/components/asuswrt/__init__.py +++ b/homeassistant/components/asuswrt/__init__.py @@ -2,7 +2,7 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.const import EVENT_HOMEASSISTANT_STOP, Platform -from homeassistant.core import HomeAssistant +from homeassistant.core import Event, HomeAssistant from .const import DATA_ASUSWRT, DOMAIN from .router import AsusWrtRouter @@ -18,7 +18,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: router.async_on_close(entry.add_update_listener(update_listener)) - async def async_close_connection(event): + async def async_close_connection(event: Event) -> None: """Close AsusWrt connection on HA Stop.""" await router.close() diff --git a/homeassistant/components/asuswrt/config_flow.py b/homeassistant/components/asuswrt/config_flow.py index 578ee3f968b..c431b6789bd 100644 --- a/homeassistant/components/asuswrt/config_flow.py +++ b/homeassistant/components/asuswrt/config_flow.py @@ -1,15 +1,19 @@ """Config flow to configure the AsusWrt integration.""" + +from __future__ import annotations + import logging import os import socket +from typing import Any import voluptuous as vol -from homeassistant import config_entries from homeassistant.components.device_tracker.const import ( CONF_CONSIDER_HOME, DEFAULT_CONSIDER_HOME, ) +from homeassistant.config_entries import ConfigEntry, ConfigFlow, OptionsFlow from homeassistant.const import ( CONF_HOST, CONF_MODE, @@ -19,6 +23,7 @@ from homeassistant.const import ( CONF_USERNAME, ) from homeassistant.core import callback +from homeassistant.data_entry_flow import FlowResult from homeassistant.helpers import config_validation as cv from .const import ( @@ -45,13 +50,13 @@ RESULT_SUCCESS = "success" _LOGGER = logging.getLogger(__name__) -def _is_file(value) -> bool: +def _is_file(value: str) -> bool: """Validate that the value is an existing file.""" - file_in = os.path.expanduser(str(value)) + file_in = os.path.expanduser(value) return os.path.isfile(file_in) and os.access(file_in, os.R_OK) -def _get_ip(host): +def _get_ip(host: str) -> str | None: """Get the ip address from the host name.""" try: return socket.gethostbyname(host) @@ -59,17 +64,17 @@ def _get_ip(host): return None -class AsusWrtFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): +class AsusWrtFlowHandler(ConfigFlow, domain=DOMAIN): """Handle a config flow.""" VERSION = 1 - def __init__(self): - """Initialize AsusWrt config flow.""" - self._host = None - @callback - def _show_setup_form(self, user_input=None, errors=None): + def _show_setup_form( + self, + user_input: dict[str, Any] | None = None, + errors: dict[str, str] | None = None, + ) -> FlowResult: """Show the setup form to the user.""" if user_input is None: @@ -100,25 +105,27 @@ class AsusWrtFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): errors=errors or {}, ) - async def _async_check_connection(self, user_input): + @staticmethod + async def _async_check_connection(user_input: dict[str, Any]) -> str: """Attempt to connect the AsusWrt router.""" + host: str = user_input[CONF_HOST] api = get_api(user_input) try: await api.connection.async_connect() except OSError: - _LOGGER.error("Error connecting to the AsusWrt router at %s", self._host) + _LOGGER.error("Error connecting to the AsusWrt router at %s", host) return RESULT_CONN_ERROR except Exception: # pylint: disable=broad-except _LOGGER.exception( - "Unknown error connecting with AsusWrt router at %s", self._host + "Unknown error connecting with AsusWrt router at %s", host ) return RESULT_UNKNOWN if not api.is_connected: - _LOGGER.error("Error connecting to the AsusWrt router at %s", self._host) + _LOGGER.error("Error connecting to the AsusWrt router at %s", host) return RESULT_CONN_ERROR conf_protocol = user_input[CONF_PROTOCOL] @@ -126,7 +133,9 @@ class AsusWrtFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): api.connection.disconnect() return RESULT_SUCCESS - async def async_step_user(self, user_input=None): + async def async_step_user( + self, user_input: dict[str, Any] | None = None + ) -> FlowResult: """Handle a flow initiated by the user.""" if self._async_current_entries(): return self.async_abort(reason="single_instance_allowed") @@ -134,11 +143,11 @@ class AsusWrtFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): if user_input is None: return self._show_setup_form(user_input) - errors = {} - self._host = user_input[CONF_HOST] + errors: dict[str, str] = {} + host: str = user_input[CONF_HOST] - pwd = user_input.get(CONF_PASSWORD) - ssh = user_input.get(CONF_SSH_KEY) + pwd: str | None = user_input.get(CONF_PASSWORD) + ssh: str | None = user_input.get(CONF_SSH_KEY) if not (pwd or ssh): errors["base"] = "pwd_or_ssh" @@ -151,7 +160,7 @@ class AsusWrtFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): errors["base"] = "ssh_not_file" if not errors: - ip_address = await self.hass.async_add_executor_job(_get_ip, self._host) + ip_address = await self.hass.async_add_executor_job(_get_ip, host) if not ip_address: errors["base"] = "invalid_host" @@ -164,25 +173,27 @@ class AsusWrtFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): return self._show_setup_form(user_input, errors) return self.async_create_entry( - title=self._host, + title=host, data=user_input, ) @staticmethod @callback - def async_get_options_flow(config_entry): + def async_get_options_flow(config_entry: ConfigEntry) -> OptionsFlow: """Get the options flow for this handler.""" return OptionsFlowHandler(config_entry) -class OptionsFlowHandler(config_entries.OptionsFlow): +class OptionsFlowHandler(OptionsFlow): """Handle a option flow for AsusWrt.""" - def __init__(self, config_entry: config_entries.ConfigEntry) -> None: + def __init__(self, config_entry: ConfigEntry) -> None: """Initialize options flow.""" self.config_entry = config_entry - async def async_step_init(self, user_input=None): + async def async_step_init( + self, user_input: dict[str, Any] | None = None + ) -> FlowResult: """Handle options flow.""" if user_input is not None: return self.async_create_entry(title="", data=user_input) diff --git a/homeassistant/components/asuswrt/device_tracker.py b/homeassistant/components/asuswrt/device_tracker.py index a75cdbd9752..af43294c954 100644 --- a/homeassistant/components/asuswrt/device_tracker.py +++ b/homeassistant/components/asuswrt/device_tracker.py @@ -22,7 +22,7 @@ async def async_setup_entry( tracked: set = set() @callback - def update_router(): + def update_router() -> None: """Update the values of the router.""" add_entities(router, async_add_entities, tracked) diff --git a/homeassistant/components/asuswrt/router.py b/homeassistant/components/asuswrt/router.py index 70addb926ec..2484b9880c3 100644 --- a/homeassistant/components/asuswrt/router.py +++ b/homeassistant/components/asuswrt/router.py @@ -119,7 +119,7 @@ class AsusWrtSensorDataHandler: async def _get_temperatures(self) -> dict[str, Any]: """Fetch temperatures information from the router.""" try: - temperatures = await self._api.async_get_temperature() + temperatures: dict[str, Any] = await self._api.async_get_temperature() except (OSError, ValueError) as exc: raise UpdateFailed(exc) from exc diff --git a/homeassistant/components/asuswrt/sensor.py b/homeassistant/components/asuswrt/sensor.py index bc04dbb28a3..5c46b3e693c 100644 --- a/homeassistant/components/asuswrt/sensor.py +++ b/homeassistant/components/asuswrt/sensor.py @@ -2,7 +2,6 @@ from __future__ import annotations from dataclasses import dataclass -from numbers import Real from homeassistant.components.sensor import ( SensorDeviceClass, @@ -197,10 +196,10 @@ class AsusWrtSensor(CoordinatorEntity, SensorEntity): self._attr_extra_state_attributes = {"hostname": router.host} @property - def native_value(self) -> float | str | None: + def native_value(self) -> float | int | str | None: """Return current state.""" descr = self.entity_description - state = self.coordinator.data.get(descr.key) - if state is not None and descr.factor and isinstance(state, Real): + state: float | int | str | None = self.coordinator.data.get(descr.key) + if state is not None and descr.factor and isinstance(state, (float, int)): return round(state / descr.factor, descr.precision) return state diff --git a/mypy.ini b/mypy.ini index 2b08aa0cd1e..439f5e326ca 100644 --- a/mypy.ini +++ b/mypy.ini @@ -308,6 +308,17 @@ no_implicit_optional = true warn_return_any = true warn_unreachable = true +[mypy-homeassistant.components.asuswrt.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +no_implicit_optional = true +warn_return_any = true +warn_unreachable = true + [mypy-homeassistant.components.automation.*] check_untyped_defs = true disallow_incomplete_defs = true