From ed10856cc48239cfc64774cfb6d1872247004e2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Sat, 15 May 2021 07:49:41 +0300 Subject: [PATCH] UpCloud API and typing update (#50624) --- .strict-typing | 1 + homeassistant/components/upcloud/__init__.py | 25 +++++++++++-------- .../components/upcloud/binary_sensor.py | 9 ++++++- .../components/upcloud/config_flow.py | 25 +++++++++++++++---- .../components/upcloud/manifest.json | 2 +- homeassistant/components/upcloud/switch.py | 15 ++++++++--- homeassistant/helpers/entity.py | 2 +- mypy.ini | 14 ++++++++--- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- script/hassfest/mypy_config.py | 1 - 11 files changed, 71 insertions(+), 27 deletions(-) diff --git a/.strict-typing b/.strict-typing index 77e833bca7a..87bef3033c4 100644 --- a/.strict-typing +++ b/.strict-typing @@ -46,6 +46,7 @@ homeassistant.components.switch.* homeassistant.components.synology_dsm.* homeassistant.components.systemmonitor.* homeassistant.components.tts.* +homeassistant.components.upcloud.* homeassistant.components.vacuum.* homeassistant.components.water_heater.* homeassistant.components.weather.* diff --git a/homeassistant/components/upcloud/__init__.py b/homeassistant/components/upcloud/__init__.py index 21c99416673..a2bd2e6e88c 100644 --- a/homeassistant/components/upcloud/__init__.py +++ b/homeassistant/components/upcloud/__init__.py @@ -4,7 +4,7 @@ from __future__ import annotations import dataclasses from datetime import timedelta import logging -from typing import Dict +from typing import Any, Dict import requests.exceptions import upcloud_api @@ -28,6 +28,7 @@ from homeassistant.helpers.dispatcher import ( async_dispatcher_connect, async_dispatcher_send, ) +from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.update_coordinator import ( CoordinatorEntity, DataUpdateCoordinator, @@ -117,7 +118,7 @@ class UpCloudHassData: scan_interval_migrations: dict[str, int] = dataclasses.field(default_factory=dict) -async def async_setup(hass: HomeAssistant, config) -> bool: +async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: """Set up UpCloud component.""" domain_config = config.get(DOMAIN) if not domain_config: @@ -228,7 +229,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b return True -async def async_unload_entry(hass, config_entry): +async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool: """Unload the config entry.""" unload_ok = await hass.config_entries.async_unload_platforms( config_entry, CONFIG_ENTRY_DOMAINS @@ -242,7 +243,11 @@ async def async_unload_entry(hass, config_entry): class UpCloudServerEntity(CoordinatorEntity): """Entity class for UpCloud servers.""" - def __init__(self, coordinator, uuid): + def __init__( + self, + coordinator: DataUpdateCoordinator[dict[str, upcloud_api.Server]], + uuid: str, + ) -> None: """Initialize the UpCloud server entity.""" super().__init__(coordinator) self.uuid = uuid @@ -257,7 +262,7 @@ class UpCloudServerEntity(CoordinatorEntity): return self.uuid @property - def name(self): + def name(self) -> str: """Return the name of the component.""" try: return DEFAULT_COMPONENT_NAME.format(self._server.title) @@ -265,12 +270,12 @@ class UpCloudServerEntity(CoordinatorEntity): return DEFAULT_COMPONENT_NAME.format(self.uuid) @property - def icon(self): + def icon(self) -> str: """Return the icon of this server.""" return "mdi:server" if self.is_on else "mdi:server-off" @property - def state(self): + def state(self) -> str | None: """Return state of the server.""" try: return STATE_MAP.get(self._server.state, self._server.state) @@ -278,17 +283,17 @@ class UpCloudServerEntity(CoordinatorEntity): return None @property - def is_on(self): + def is_on(self) -> bool: """Return true if the server is on.""" return self.state == STATE_ON @property - def device_class(self): + def device_class(self) -> str: """Return the class of this server.""" return DEFAULT_COMPONENT_DEVICE_CLASS @property - def extra_state_attributes(self): + def extra_state_attributes(self) -> dict[str, Any]: """Return the state attributes of the UpCloud server.""" return { x: getattr(self._server, x, None) diff --git a/homeassistant/components/upcloud/binary_sensor.py b/homeassistant/components/upcloud/binary_sensor.py index d64dc0f7ea9..de55a577610 100644 --- a/homeassistant/components/upcloud/binary_sensor.py +++ b/homeassistant/components/upcloud/binary_sensor.py @@ -3,8 +3,11 @@ import voluptuous as vol from homeassistant.components.binary_sensor import PLATFORM_SCHEMA, BinarySensorEntity +from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_USERNAME +from homeassistant.core import HomeAssistant import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.entity_platform import AddEntitiesCallback from . import CONF_SERVERS, DATA_UPCLOUD, UpCloudServerEntity @@ -13,7 +16,11 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( ) -async def async_setup_entry(hass, config_entry, async_add_entities): +async def async_setup_entry( + hass: HomeAssistant, + config_entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: """Set up the UpCloud server binary sensor.""" coordinator = hass.data[DATA_UPCLOUD].coordinators[config_entry.data[CONF_USERNAME]] entities = [UpCloudBinarySensor(coordinator, uuid) for uuid in coordinator.data] diff --git a/homeassistant/components/upcloud/config_flow.py b/homeassistant/components/upcloud/config_flow.py index 62260ebc8ca..3ad5976df1f 100644 --- a/homeassistant/components/upcloud/config_flow.py +++ b/homeassistant/components/upcloud/config_flow.py @@ -1,6 +1,9 @@ """Config flow for UpCloud.""" +from __future__ import annotations + import logging +from typing import Any import requests.exceptions import upcloud_api @@ -9,6 +12,7 @@ import voluptuous as vol from homeassistant import config_entries from homeassistant.const import CONF_PASSWORD, CONF_SCAN_INTERVAL, CONF_USERNAME from homeassistant.core import callback +from homeassistant.data_entry_flow import FlowResult from .const import DEFAULT_SCAN_INTERVAL, DOMAIN @@ -23,7 +27,9 @@ class UpCloudConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): username: str password: str - async def async_step_user(self, user_input=None): + async def async_step_user( + self, user_input: dict[str, Any] | None = None + ) -> FlowResult: """Handle user initiated flow.""" if user_input is None: return self._async_show_form(step_id="user") @@ -51,7 +57,7 @@ class UpCloudConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): return self.async_create_entry(title=user_input[CONF_USERNAME], data=user_input) - async def async_step_import(self, user_input=None): + async def async_step_import(self, user_input: dict[str, Any]) -> FlowResult: """Handle import initiated flow.""" await self.async_set_unique_id(user_input[CONF_USERNAME]) self._abort_if_unique_id_configured() @@ -59,7 +65,12 @@ class UpCloudConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): return await self.async_step_user(user_input=user_input) @callback - def _async_show_form(self, step_id, user_input=None, errors=None): + def _async_show_form( + self, + step_id: str, + user_input: dict[str, Any] | None = None, + errors: dict[str, str] | None = None, + ) -> FlowResult: """Show our form.""" if user_input is None: user_input = {} @@ -80,7 +91,9 @@ class UpCloudConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): @staticmethod @callback - def async_get_options_flow(config_entry): + def async_get_options_flow( + config_entry: config_entries.ConfigEntry, + ) -> UpCloudOptionsFlow: """Get options flow.""" return UpCloudOptionsFlow(config_entry) @@ -92,7 +105,9 @@ class UpCloudOptionsFlow(config_entries.OptionsFlow): """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: diff --git a/homeassistant/components/upcloud/manifest.json b/homeassistant/components/upcloud/manifest.json index 064cfa224e1..a9e0f74462e 100644 --- a/homeassistant/components/upcloud/manifest.json +++ b/homeassistant/components/upcloud/manifest.json @@ -3,7 +3,7 @@ "name": "UpCloud", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/upcloud", - "requirements": ["upcloud-api==1.0.1"], + "requirements": ["upcloud-api==2.0.0"], "codeowners": ["@scop"], "iot_class": "cloud_polling" } diff --git a/homeassistant/components/upcloud/switch.py b/homeassistant/components/upcloud/switch.py index a9e4ab56dd1..91676ab1d5a 100644 --- a/homeassistant/components/upcloud/switch.py +++ b/homeassistant/components/upcloud/switch.py @@ -1,11 +1,16 @@ """Support for interacting with UpCloud servers.""" +from typing import Any + import voluptuous as vol from homeassistant.components.switch import PLATFORM_SCHEMA, SwitchEntity +from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_USERNAME, STATE_OFF +from homeassistant.core import HomeAssistant import homeassistant.helpers.config_validation as cv from homeassistant.helpers.dispatcher import dispatcher_send +from homeassistant.helpers.entity_platform import AddEntitiesCallback from . import CONF_SERVERS, DATA_UPCLOUD, SIGNAL_UPDATE_UPCLOUD, UpCloudServerEntity @@ -14,7 +19,11 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( ) -async def async_setup_entry(hass, config_entry, async_add_entities): +async def async_setup_entry( + hass: HomeAssistant, + config_entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: """Set up the UpCloud server switch.""" coordinator = hass.data[DATA_UPCLOUD].coordinators[config_entry.data[CONF_USERNAME]] entities = [UpCloudSwitch(coordinator, uuid) for uuid in coordinator.data] @@ -24,13 +33,13 @@ async def async_setup_entry(hass, config_entry, async_add_entities): class UpCloudSwitch(UpCloudServerEntity, SwitchEntity): """Representation of an UpCloud server switch.""" - def turn_on(self, **kwargs): + def turn_on(self, **kwargs: Any) -> None: """Start the server.""" if self.state == STATE_OFF: self._server.start() dispatcher_send(self.hass, SIGNAL_UPDATE_UPCLOUD) - def turn_off(self, **kwargs): + def turn_off(self, **kwargs: Any) -> None: """Stop the server.""" if self.is_on: self._server.stop() diff --git a/homeassistant/helpers/entity.py b/homeassistant/helpers/entity.py index a9843387fd9..2e2c1b3b3f9 100644 --- a/homeassistant/helpers/entity.py +++ b/homeassistant/helpers/entity.py @@ -749,7 +749,7 @@ class ToggleEntity(Entity): """An abstract class for entities that can be turned on and off.""" @property - def state(self) -> str: + def state(self) -> str | None: """Return the state.""" return STATE_ON if self.is_on else STATE_OFF diff --git a/mypy.ini b/mypy.ini index 3371658dc92..8bc55b0d82e 100644 --- a/mypy.ini +++ b/mypy.ini @@ -517,6 +517,17 @@ no_implicit_optional = true warn_return_any = true warn_unreachable = true +[mypy-homeassistant.components.upcloud.*] +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.vacuum.*] check_untyped_defs = true disallow_incomplete_defs = true @@ -1220,9 +1231,6 @@ ignore_errors = true [mypy-homeassistant.components.unifi.*] ignore_errors = true -[mypy-homeassistant.components.upcloud.*] -ignore_errors = true - [mypy-homeassistant.components.updater.*] ignore_errors = true diff --git a/requirements_all.txt b/requirements_all.txt index 494dac6d1e3..092f1ece333 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2286,7 +2286,7 @@ unifiled==0.11 upb_lib==0.4.12 # homeassistant.components.upcloud -upcloud-api==1.0.1 +upcloud-api==2.0.0 # homeassistant.components.huawei_lte # homeassistant.components.syncthru diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 6164462ceca..ba1b5c40889 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1228,7 +1228,7 @@ twinkly-client==0.0.2 upb_lib==0.4.12 # homeassistant.components.upcloud -upcloud-api==1.0.1 +upcloud-api==2.0.0 # homeassistant.components.huawei_lte # homeassistant.components.syncthru diff --git a/script/hassfest/mypy_config.py b/script/hassfest/mypy_config.py index 73752f4c51a..72bb8879312 100644 --- a/script/hassfest/mypy_config.py +++ b/script/hassfest/mypy_config.py @@ -219,7 +219,6 @@ IGNORED_MODULES: Final[list[str]] = [ "homeassistant.components.tradfri.*", "homeassistant.components.tuya.*", "homeassistant.components.unifi.*", - "homeassistant.components.upcloud.*", "homeassistant.components.updater.*", "homeassistant.components.upnp.*", "homeassistant.components.velbus.*",