Complete typing on TwenteMilieu integration (#47480)

This commit is contained in:
Franck Nijhof
2021-03-06 00:33:26 +01:00
committed by GitHub
parent 2472dad1fa
commit 8f31b09b55
4 changed files with 51 additions and 34 deletions

View File

@@ -1,7 +1,8 @@
"""Support for Twente Milieu.""" """Support for Twente Milieu."""
from __future__ import annotations
import asyncio import asyncio
from datetime import timedelta from datetime import timedelta
from typing import Optional
from twentemilieu import TwenteMilieu from twentemilieu import TwenteMilieu
import voluptuous as vol import voluptuous as vol
@@ -15,11 +16,12 @@ from homeassistant.components.twentemilieu.const import (
) )
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_ID from homeassistant.const import CONF_ID
from homeassistant.core import HomeAssistant
from homeassistant.helpers import config_validation as cv from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.dispatcher import async_dispatcher_send from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.helpers.event import async_track_time_interval from homeassistant.helpers.event import async_track_time_interval
from homeassistant.helpers.typing import ConfigType, HomeAssistantType from homeassistant.helpers.typing import ConfigType
SCAN_INTERVAL = timedelta(seconds=3600) SCAN_INTERVAL = timedelta(seconds=3600)
@@ -27,9 +29,7 @@ SERVICE_UPDATE = "update"
SERVICE_SCHEMA = vol.Schema({vol.Optional(CONF_ID): cv.string}) SERVICE_SCHEMA = vol.Schema({vol.Optional(CONF_ID): cv.string})
async def _update_twentemilieu( async def _update_twentemilieu(hass: HomeAssistant, unique_id: str | None) -> None:
hass: HomeAssistantType, unique_id: Optional[str]
) -> None:
"""Update Twente Milieu.""" """Update Twente Milieu."""
if unique_id is not None: if unique_id is not None:
twentemilieu = hass.data[DOMAIN].get(unique_id) twentemilieu = hass.data[DOMAIN].get(unique_id)
@@ -37,16 +37,15 @@ async def _update_twentemilieu(
await twentemilieu.update() await twentemilieu.update()
async_dispatcher_send(hass, DATA_UPDATE, unique_id) async_dispatcher_send(hass, DATA_UPDATE, unique_id)
else: else:
tasks = [] await asyncio.wait(
for twentemilieu in hass.data[DOMAIN].values(): [twentemilieu.update() for twentemilieu in hass.data[DOMAIN].values()]
tasks.append(twentemilieu.update()) )
await asyncio.wait(tasks)
for uid in hass.data[DOMAIN]: for uid in hass.data[DOMAIN]:
async_dispatcher_send(hass, DATA_UPDATE, uid) async_dispatcher_send(hass, DATA_UPDATE, uid)
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool: async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the Twente Milieu components.""" """Set up the Twente Milieu components."""
async def update(call) -> None: async def update(call) -> None:
@@ -59,7 +58,7 @@ async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool:
return True return True
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool: async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up Twente Milieu from a config entry.""" """Set up Twente Milieu from a config entry."""
session = async_get_clientsession(hass) session = async_get_clientsession(hass)
twentemilieu = TwenteMilieu( twentemilieu = TwenteMilieu(
@@ -85,7 +84,7 @@ async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool
return True return True
async def async_unload_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool: async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload Twente Milieu config entry.""" """Unload Twente Milieu config entry."""
await hass.config_entries.async_forward_entry_unload(entry, "sensor") await hass.config_entries.async_forward_entry_unload(entry, "sensor")

View File

@@ -1,4 +1,8 @@
"""Config flow to configure the Twente Milieu integration.""" """Config flow to configure the Twente Milieu integration."""
from __future__ import annotations
from typing import Any
from twentemilieu import ( from twentemilieu import (
TwenteMilieu, TwenteMilieu,
TwenteMilieuAddressError, TwenteMilieuAddressError,
@@ -7,25 +11,23 @@ from twentemilieu import (
import voluptuous as vol import voluptuous as vol
from homeassistant import config_entries from homeassistant import config_entries
from homeassistant.components.twentemilieu.const import (
CONF_HOUSE_LETTER,
CONF_HOUSE_NUMBER,
CONF_POST_CODE,
DOMAIN,
)
from homeassistant.config_entries import ConfigFlow from homeassistant.config_entries import ConfigFlow
from homeassistant.const import CONF_ID from homeassistant.const import CONF_ID
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
from .const import CONF_HOUSE_LETTER, CONF_HOUSE_NUMBER, CONF_POST_CODE
from .const import DOMAIN # pylint: disable=unused-import
@config_entries.HANDLERS.register(DOMAIN)
class TwenteMilieuFlowHandler(ConfigFlow): class TwenteMilieuFlowHandler(ConfigFlow, domain=DOMAIN):
"""Handle a Twente Milieu config flow.""" """Handle a Twente Milieu config flow."""
VERSION = 1 VERSION = 1
CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_POLL CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_POLL
async def _show_setup_form(self, errors=None): async def _show_setup_form(
self, errors: dict[str, str] | None = None
) -> dict[str, Any]:
"""Show the setup form to the user.""" """Show the setup form to the user."""
return self.async_show_form( return self.async_show_form(
step_id="user", step_id="user",
@@ -39,7 +41,9 @@ class TwenteMilieuFlowHandler(ConfigFlow):
errors=errors or {}, errors=errors or {},
) )
async def async_step_user(self, user_input=None): async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> dict[str, Any]:
"""Handle a flow initiated by the user.""" """Handle a flow initiated by the user."""
if user_input is None: if user_input is None:
return await self._show_setup_form(user_input) return await self._show_setup_form(user_input)
@@ -70,7 +74,7 @@ class TwenteMilieuFlowHandler(ConfigFlow):
return self.async_abort(reason="already_configured") return self.async_abort(reason="already_configured")
return self.async_create_entry( return self.async_create_entry(
title=unique_id, title=str(unique_id),
data={ data={
CONF_ID: unique_id, CONF_ID: unique_id,
CONF_POST_CODE: user_input[CONF_POST_CODE], CONF_POST_CODE: user_input[CONF_POST_CODE],

View File

@@ -1,5 +1,7 @@
"""Support for Twente Milieu sensors.""" """Support for Twente Milieu sensors."""
from typing import Any, Dict from __future__ import annotations
from typing import Any, Callable
from twentemilieu import ( from twentemilieu import (
WASTE_TYPE_NON_RECYCLABLE, WASTE_TYPE_NON_RECYCLABLE,
@@ -10,20 +12,22 @@ from twentemilieu import (
TwenteMilieuConnectionError, TwenteMilieuConnectionError,
) )
from homeassistant.components.twentemilieu.const import DATA_UPDATE, DOMAIN
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_ID from homeassistant.const import CONF_ID
from homeassistant.core import callback from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import PlatformNotReady from homeassistant.exceptions import PlatformNotReady
from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
from homeassistant.helpers.typing import HomeAssistantType
from .const import DATA_UPDATE, DOMAIN
PARALLEL_UPDATES = 1 PARALLEL_UPDATES = 1
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistantType, entry: ConfigEntry, async_add_entities hass: HomeAssistant,
entry: ConfigEntry,
async_add_entities: Callable[[list[Entity], bool], None],
) -> None: ) -> None:
"""Set up Twente Milieu sensor based on a config entry.""" """Set up Twente Milieu sensor based on a config entry."""
twentemilieu = hass.data[DOMAIN][entry.data[CONF_ID]] twentemilieu = hass.data[DOMAIN][entry.data[CONF_ID]]
@@ -142,7 +146,7 @@ class TwenteMilieuSensor(Entity):
self._state = next_pickup.date().isoformat() self._state = next_pickup.date().isoformat()
@property @property
def device_info(self) -> Dict[str, Any]: def device_info(self) -> dict[str, Any]:
"""Return device information about Twente Milieu.""" """Return device information about Twente Milieu."""
return { return {
"identifiers": {(DOMAIN, self._unique_id)}, "identifiers": {(DOMAIN, self._unique_id)},

View File

@@ -10,8 +10,10 @@ from homeassistant.components.twentemilieu.const import (
DOMAIN, DOMAIN,
) )
from homeassistant.const import CONF_ID, CONTENT_TYPE_JSON from homeassistant.const import CONF_ID, CONTENT_TYPE_JSON
from homeassistant.core import HomeAssistant
from tests.common import MockConfigEntry from tests.common import MockConfigEntry
from tests.test_util.aiohttp import AiohttpClientMocker
FIXTURE_USER_INPUT = { FIXTURE_USER_INPUT = {
CONF_ID: "12345", CONF_ID: "12345",
@@ -21,7 +23,7 @@ FIXTURE_USER_INPUT = {
} }
async def test_show_set_form(hass): async def test_show_set_form(hass: HomeAssistant) -> None:
"""Test that the setup form is served.""" """Test that the setup form is served."""
flow = config_flow.TwenteMilieuFlowHandler() flow = config_flow.TwenteMilieuFlowHandler()
flow.hass = hass flow.hass = hass
@@ -31,7 +33,9 @@ async def test_show_set_form(hass):
assert result["step_id"] == "user" assert result["step_id"] == "user"
async def test_connection_error(hass, aioclient_mock): async def test_connection_error(
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
) -> None:
"""Test we show user form on Twente Milieu connection error.""" """Test we show user form on Twente Milieu connection error."""
aioclient_mock.post( aioclient_mock.post(
"https://twentemilieuapi.ximmio.com/api/FetchAdress", exc=aiohttp.ClientError "https://twentemilieuapi.ximmio.com/api/FetchAdress", exc=aiohttp.ClientError
@@ -46,7 +50,9 @@ async def test_connection_error(hass, aioclient_mock):
assert result["errors"] == {"base": "cannot_connect"} assert result["errors"] == {"base": "cannot_connect"}
async def test_invalid_address(hass, aioclient_mock): async def test_invalid_address(
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
) -> None:
"""Test we show user form on Twente Milieu invalid address error.""" """Test we show user form on Twente Milieu invalid address error."""
aioclient_mock.post( aioclient_mock.post(
"https://twentemilieuapi.ximmio.com/api/FetchAdress", "https://twentemilieuapi.ximmio.com/api/FetchAdress",
@@ -63,7 +69,9 @@ async def test_invalid_address(hass, aioclient_mock):
assert result["errors"] == {"base": "invalid_address"} assert result["errors"] == {"base": "invalid_address"}
async def test_address_already_set_up(hass, aioclient_mock): async def test_address_already_set_up(
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
) -> None:
"""Test we abort if address has already been set up.""" """Test we abort if address has already been set up."""
MockConfigEntry(domain=DOMAIN, data=FIXTURE_USER_INPUT, title="12345").add_to_hass( MockConfigEntry(domain=DOMAIN, data=FIXTURE_USER_INPUT, title="12345").add_to_hass(
hass hass
@@ -83,7 +91,9 @@ async def test_address_already_set_up(hass, aioclient_mock):
assert result["reason"] == "already_configured" assert result["reason"] == "already_configured"
async def test_full_flow_implementation(hass, aioclient_mock): async def test_full_flow_implementation(
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
) -> None:
"""Test registering an integration and finishing flow works.""" """Test registering an integration and finishing flow works."""
aioclient_mock.post( aioclient_mock.post(
"https://twentemilieuapi.ximmio.com/api/FetchAdress", "https://twentemilieuapi.ximmio.com/api/FetchAdress",