diff --git a/.strict-typing b/.strict-typing index 0a634e31ad4..1641398a8cb 100644 --- a/.strict-typing +++ b/.strict-typing @@ -247,6 +247,7 @@ homeassistant.components.recorder.* homeassistant.components.remote.* homeassistant.components.renault.* homeassistant.components.repairs.* +homeassistant.components.rest.* homeassistant.components.rfxtrx.* homeassistant.components.rhasspy.* homeassistant.components.ridwell.* diff --git a/homeassistant/components/rest/__init__.py b/homeassistant/components/rest/__init__.py index 4ec519dd709..37c483505b8 100644 --- a/homeassistant/components/rest/__init__.py +++ b/homeassistant/components/rest/__init__.py @@ -6,7 +6,7 @@ from collections.abc import Coroutine import contextlib from datetime import timedelta import logging -from typing import Any +from typing import Any, cast import httpx import voluptuous as vol @@ -149,8 +149,12 @@ def _rest_coordinator( """Wrap a DataUpdateCoordinator around the rest object.""" if resource_template: - async def _async_refresh_with_resource_template(): - rest.set_url(resource_template.async_render(parse_result=False)) + async def _async_refresh_with_resource_template() -> None: + rest.set_url( + cast(template.Template, resource_template).async_render( + parse_result=False + ) + ) await rest.async_update() update_method = _async_refresh_with_resource_template diff --git a/homeassistant/components/rest/binary_sensor.py b/homeassistant/components/rest/binary_sensor.py index fc40d76a21d..320413a10a0 100644 --- a/homeassistant/components/rest/binary_sensor.py +++ b/homeassistant/components/rest/binary_sensor.py @@ -20,11 +20,14 @@ from homeassistant.core import HomeAssistant from homeassistant.exceptions import PlatformNotReady import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.helpers.template import Template from homeassistant.helpers.template_entity import TemplateEntity from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType +from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from . import async_get_config_and_coordinator, create_rest_data_from_config from .const import DEFAULT_BINARY_SENSOR_NAME +from .data import RestData from .entity import RestEntity from .schema import BINARY_SENSOR_SCHEMA, RESOURCE_SCHEMA @@ -79,19 +82,19 @@ class RestBinarySensor(RestEntity, TemplateEntity, BinarySensorEntity): def __init__( self, - hass, - coordinator, - rest, - config, - unique_id, - ): + hass: HomeAssistant, + coordinator: DataUpdateCoordinator[None] | None, + rest: RestData, + config: ConfigType, + unique_id: str | None, + ) -> None: """Initialize a REST binary sensor.""" RestEntity.__init__( self, coordinator, rest, config.get(CONF_RESOURCE_TEMPLATE), - config.get(CONF_FORCE_UPDATE), + config[CONF_FORCE_UPDATE], ) TemplateEntity.__init__( self, @@ -101,16 +104,17 @@ class RestBinarySensor(RestEntity, TemplateEntity, BinarySensorEntity): unique_id=unique_id, ) self._previous_data = None - self._value_template = config.get(CONF_VALUE_TEMPLATE) + self._value_template: Template | None = config.get(CONF_VALUE_TEMPLATE) if (value_template := self._value_template) is not None: value_template.hass = hass self._attr_device_class = config.get(CONF_DEVICE_CLASS) - def _update_from_rest_data(self): + def _update_from_rest_data(self) -> None: """Update state from the rest data.""" if self.rest.data is None: self._attr_is_on = False + return response = self.rest.data diff --git a/homeassistant/components/rest/notify.py b/homeassistant/components/rest/notify.py index 91f76d836d7..f1d4152b4b4 100644 --- a/homeassistant/components/rest/notify.py +++ b/homeassistant/components/rest/notify.py @@ -3,6 +3,7 @@ from __future__ import annotations from http import HTTPStatus import logging +from typing import Any import requests from requests.auth import AuthBase, HTTPBasicAuth, HTTPDigestAuth @@ -77,18 +78,18 @@ def get_service( discovery_info: DiscoveryInfoType | None = None, ) -> RestNotificationService: """Get the RESTful notification service.""" - resource = config.get(CONF_RESOURCE) - method = config.get(CONF_METHOD) - headers = config.get(CONF_HEADERS) - params = config.get(CONF_PARAMS) - message_param_name = config.get(CONF_MESSAGE_PARAMETER_NAME) - title_param_name = config.get(CONF_TITLE_PARAMETER_NAME) - target_param_name = config.get(CONF_TARGET_PARAMETER_NAME) - data = config.get(CONF_DATA) - data_template = config.get(CONF_DATA_TEMPLATE) - username = config.get(CONF_USERNAME) - password = config.get(CONF_PASSWORD) - verify_ssl = config.get(CONF_VERIFY_SSL) + resource: str = config[CONF_RESOURCE] + method: str = config[CONF_METHOD] + headers: dict[str, str] | None = config.get(CONF_HEADERS) + params: dict[str, str] | None = config.get(CONF_PARAMS) + message_param_name: str = config[CONF_MESSAGE_PARAMETER_NAME] + title_param_name: str | None = config.get(CONF_TITLE_PARAMETER_NAME) + target_param_name: str | None = config.get(CONF_TARGET_PARAMETER_NAME) + data: dict[str, Any] | None = config.get(CONF_DATA) + data_template: dict[str, Any] | None = config.get(CONF_DATA_TEMPLATE) + username: str | None = config.get(CONF_USERNAME) + password: str | None = config.get(CONF_PASSWORD) + verify_ssl: bool = config[CONF_VERIFY_SSL] auth: AuthBase | None = None if username and password: @@ -118,19 +119,19 @@ class RestNotificationService(BaseNotificationService): def __init__( self, - hass, - resource, - method, - headers, - params, - message_param_name, - title_param_name, - target_param_name, - data, - data_template, - auth, - verify_ssl, - ): + hass: HomeAssistant, + resource: str, + method: str, + headers: dict[str, str] | None, + params: dict[str, str] | None, + message_param_name: str, + title_param_name: str | None, + target_param_name: str | None, + data: dict[str, Any] | None, + data_template: dict[str, Any] | None, + auth: AuthBase | None, + verify_ssl: bool, + ) -> None: """Initialize the service.""" self._resource = resource self._hass = hass @@ -145,7 +146,7 @@ class RestNotificationService(BaseNotificationService): self._auth = auth self._verify_ssl = verify_ssl - def send_message(self, message="", **kwargs): + def send_message(self, message: str = "", **kwargs: Any) -> None: """Send a message to a user.""" data = {self._message_param_name: message} @@ -160,7 +161,7 @@ class RestNotificationService(BaseNotificationService): if self._data_template or self._data: kwargs[ATTR_MESSAGE] = message - def _data_template_creator(value): + def _data_template_creator(value: Any) -> Any: """Recursive template creator helper function.""" if isinstance(value, list): return [_data_template_creator(item) for item in value] diff --git a/homeassistant/components/rest/sensor.py b/homeassistant/components/rest/sensor.py index ff571b0c9dc..9f14dea076c 100644 --- a/homeassistant/components/rest/sensor.py +++ b/homeassistant/components/rest/sensor.py @@ -28,9 +28,11 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.json import json_dumps, json_loads from homeassistant.helpers.template_entity import TemplateSensor from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType +from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from . import async_get_config_and_coordinator, create_rest_data_from_config from .const import CONF_JSON_ATTRS, CONF_JSON_ATTRS_PATH, DEFAULT_SENSOR_NAME +from .data import RestData from .entity import RestEntity from .schema import RESOURCE_SCHEMA, SENSOR_SCHEMA @@ -67,7 +69,7 @@ async def async_setup_platform( raise PlatformNotReady from rest.last_exception raise PlatformNotReady - unique_id = conf.get(CONF_UNIQUE_ID) + unique_id: str | None = conf.get(CONF_UNIQUE_ID) async_add_entities( [ @@ -87,19 +89,19 @@ class RestSensor(RestEntity, TemplateSensor): def __init__( self, - hass, - coordinator, - rest, - config, - unique_id, - ): + hass: HomeAssistant, + coordinator: DataUpdateCoordinator[None] | None, + rest: RestData, + config: ConfigType, + unique_id: str | None, + ) -> None: """Initialize the REST sensor.""" RestEntity.__init__( self, coordinator, rest, config.get(CONF_RESOURCE_TEMPLATE), - config.get(CONF_FORCE_UPDATE), + config[CONF_FORCE_UPDATE], ) TemplateSensor.__init__( self, @@ -108,25 +110,13 @@ class RestSensor(RestEntity, TemplateSensor): fallback_name=DEFAULT_SENSOR_NAME, unique_id=unique_id, ) - self._state = None self._value_template = config.get(CONF_VALUE_TEMPLATE) if (value_template := self._value_template) is not None: value_template.hass = hass self._json_attrs = config.get(CONF_JSON_ATTRS) - self._attributes = None self._json_attrs_path = config.get(CONF_JSON_ATTRS_PATH) - @property - def native_value(self): - """Return the state of the device.""" - return self._state - - @property - def extra_state_attributes(self): - """Return the state attributes.""" - return self._attributes - - def _update_from_rest_data(self): + def _update_from_rest_data(self) -> None: """Update state from the rest data.""" value = self.rest.data _LOGGER.debug("Data fetched from resource: %s", value) @@ -150,7 +140,7 @@ class RestSensor(RestEntity, TemplateSensor): _LOGGER.debug("Erroneous XML: %s", value) if self._json_attrs: - self._attributes = {} + self._attr_extra_state_attributes = {} if value: try: json_dict = json_loads(value) @@ -165,7 +155,7 @@ class RestSensor(RestEntity, TemplateSensor): attrs = { k: json_dict[k] for k in self._json_attrs if k in json_dict } - self._attributes = attrs + self._attr_extra_state_attributes = attrs else: _LOGGER.warning( "JSON result was not a dictionary" @@ -187,9 +177,9 @@ class RestSensor(RestEntity, TemplateSensor): SensorDeviceClass.DATE, SensorDeviceClass.TIMESTAMP, ): - self._state = value + self._attr_native_value = value return - self._state = async_parse_date_datetime( + self._attr_native_value = async_parse_date_datetime( value, self.entity_id, self.device_class ) diff --git a/mypy.ini b/mypy.ini index 9e1b25d7ad4..5358346494c 100644 --- a/mypy.ini +++ b/mypy.ini @@ -2225,6 +2225,16 @@ disallow_untyped_defs = true warn_return_any = true warn_unreachable = true +[mypy-homeassistant.components.rest.*] +check_untyped_defs = true +disallow_incomplete_defs = true +disallow_subclassing_any = true +disallow_untyped_calls = true +disallow_untyped_decorators = true +disallow_untyped_defs = true +warn_return_any = true +warn_unreachable = true + [mypy-homeassistant.components.rfxtrx.*] check_untyped_defs = true disallow_incomplete_defs = true