Add rest to strict-typing (#86149)

* Add type hints to rest notify

* Add rest to strict-typing
This commit is contained in:
epenet 2023-02-07 15:48:16 +01:00 committed by GitHub
parent 59ca7780fa
commit b854dd99fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 74 additions and 64 deletions

View File

@ -247,6 +247,7 @@ homeassistant.components.recorder.*
homeassistant.components.remote.* homeassistant.components.remote.*
homeassistant.components.renault.* homeassistant.components.renault.*
homeassistant.components.repairs.* homeassistant.components.repairs.*
homeassistant.components.rest.*
homeassistant.components.rfxtrx.* homeassistant.components.rfxtrx.*
homeassistant.components.rhasspy.* homeassistant.components.rhasspy.*
homeassistant.components.ridwell.* homeassistant.components.ridwell.*

View File

@ -6,7 +6,7 @@ from collections.abc import Coroutine
import contextlib import contextlib
from datetime import timedelta from datetime import timedelta
import logging import logging
from typing import Any from typing import Any, cast
import httpx import httpx
import voluptuous as vol import voluptuous as vol
@ -149,8 +149,12 @@ def _rest_coordinator(
"""Wrap a DataUpdateCoordinator around the rest object.""" """Wrap a DataUpdateCoordinator around the rest object."""
if resource_template: if resource_template:
async def _async_refresh_with_resource_template(): async def _async_refresh_with_resource_template() -> None:
rest.set_url(resource_template.async_render(parse_result=False)) rest.set_url(
cast(template.Template, resource_template).async_render(
parse_result=False
)
)
await rest.async_update() await rest.async_update()
update_method = _async_refresh_with_resource_template update_method = _async_refresh_with_resource_template

View File

@ -20,11 +20,14 @@ from homeassistant.core import HomeAssistant
from homeassistant.exceptions import PlatformNotReady from homeassistant.exceptions import PlatformNotReady
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.template import Template
from homeassistant.helpers.template_entity import TemplateEntity from homeassistant.helpers.template_entity import TemplateEntity
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType 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 . import async_get_config_and_coordinator, create_rest_data_from_config
from .const import DEFAULT_BINARY_SENSOR_NAME from .const import DEFAULT_BINARY_SENSOR_NAME
from .data import RestData
from .entity import RestEntity from .entity import RestEntity
from .schema import BINARY_SENSOR_SCHEMA, RESOURCE_SCHEMA from .schema import BINARY_SENSOR_SCHEMA, RESOURCE_SCHEMA
@ -79,19 +82,19 @@ class RestBinarySensor(RestEntity, TemplateEntity, BinarySensorEntity):
def __init__( def __init__(
self, self,
hass, hass: HomeAssistant,
coordinator, coordinator: DataUpdateCoordinator[None] | None,
rest, rest: RestData,
config, config: ConfigType,
unique_id, unique_id: str | None,
): ) -> None:
"""Initialize a REST binary sensor.""" """Initialize a REST binary sensor."""
RestEntity.__init__( RestEntity.__init__(
self, self,
coordinator, coordinator,
rest, rest,
config.get(CONF_RESOURCE_TEMPLATE), config.get(CONF_RESOURCE_TEMPLATE),
config.get(CONF_FORCE_UPDATE), config[CONF_FORCE_UPDATE],
) )
TemplateEntity.__init__( TemplateEntity.__init__(
self, self,
@ -101,16 +104,17 @@ class RestBinarySensor(RestEntity, TemplateEntity, BinarySensorEntity):
unique_id=unique_id, unique_id=unique_id,
) )
self._previous_data = None 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: if (value_template := self._value_template) is not None:
value_template.hass = hass value_template.hass = hass
self._attr_device_class = config.get(CONF_DEVICE_CLASS) 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.""" """Update state from the rest data."""
if self.rest.data is None: if self.rest.data is None:
self._attr_is_on = False self._attr_is_on = False
return
response = self.rest.data response = self.rest.data

View File

@ -3,6 +3,7 @@ from __future__ import annotations
from http import HTTPStatus from http import HTTPStatus
import logging import logging
from typing import Any
import requests import requests
from requests.auth import AuthBase, HTTPBasicAuth, HTTPDigestAuth from requests.auth import AuthBase, HTTPBasicAuth, HTTPDigestAuth
@ -77,18 +78,18 @@ def get_service(
discovery_info: DiscoveryInfoType | None = None, discovery_info: DiscoveryInfoType | None = None,
) -> RestNotificationService: ) -> RestNotificationService:
"""Get the RESTful notification service.""" """Get the RESTful notification service."""
resource = config.get(CONF_RESOURCE) resource: str = config[CONF_RESOURCE]
method = config.get(CONF_METHOD) method: str = config[CONF_METHOD]
headers = config.get(CONF_HEADERS) headers: dict[str, str] | None = config.get(CONF_HEADERS)
params = config.get(CONF_PARAMS) params: dict[str, str] | None = config.get(CONF_PARAMS)
message_param_name = config.get(CONF_MESSAGE_PARAMETER_NAME) message_param_name: str = config[CONF_MESSAGE_PARAMETER_NAME]
title_param_name = config.get(CONF_TITLE_PARAMETER_NAME) title_param_name: str | None = config.get(CONF_TITLE_PARAMETER_NAME)
target_param_name = config.get(CONF_TARGET_PARAMETER_NAME) target_param_name: str | None = config.get(CONF_TARGET_PARAMETER_NAME)
data = config.get(CONF_DATA) data: dict[str, Any] | None = config.get(CONF_DATA)
data_template = config.get(CONF_DATA_TEMPLATE) data_template: dict[str, Any] | None = config.get(CONF_DATA_TEMPLATE)
username = config.get(CONF_USERNAME) username: str | None = config.get(CONF_USERNAME)
password = config.get(CONF_PASSWORD) password: str | None = config.get(CONF_PASSWORD)
verify_ssl = config.get(CONF_VERIFY_SSL) verify_ssl: bool = config[CONF_VERIFY_SSL]
auth: AuthBase | None = None auth: AuthBase | None = None
if username and password: if username and password:
@ -118,19 +119,19 @@ class RestNotificationService(BaseNotificationService):
def __init__( def __init__(
self, self,
hass, hass: HomeAssistant,
resource, resource: str,
method, method: str,
headers, headers: dict[str, str] | None,
params, params: dict[str, str] | None,
message_param_name, message_param_name: str,
title_param_name, title_param_name: str | None,
target_param_name, target_param_name: str | None,
data, data: dict[str, Any] | None,
data_template, data_template: dict[str, Any] | None,
auth, auth: AuthBase | None,
verify_ssl, verify_ssl: bool,
): ) -> None:
"""Initialize the service.""" """Initialize the service."""
self._resource = resource self._resource = resource
self._hass = hass self._hass = hass
@ -145,7 +146,7 @@ class RestNotificationService(BaseNotificationService):
self._auth = auth self._auth = auth
self._verify_ssl = verify_ssl 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.""" """Send a message to a user."""
data = {self._message_param_name: message} data = {self._message_param_name: message}
@ -160,7 +161,7 @@ class RestNotificationService(BaseNotificationService):
if self._data_template or self._data: if self._data_template or self._data:
kwargs[ATTR_MESSAGE] = message kwargs[ATTR_MESSAGE] = message
def _data_template_creator(value): def _data_template_creator(value: Any) -> Any:
"""Recursive template creator helper function.""" """Recursive template creator helper function."""
if isinstance(value, list): if isinstance(value, list):
return [_data_template_creator(item) for item in value] return [_data_template_creator(item) for item in value]

View File

@ -28,9 +28,11 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.json import json_dumps, json_loads from homeassistant.helpers.json import json_dumps, json_loads
from homeassistant.helpers.template_entity import TemplateSensor from homeassistant.helpers.template_entity import TemplateSensor
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType 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 . 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 .const import CONF_JSON_ATTRS, CONF_JSON_ATTRS_PATH, DEFAULT_SENSOR_NAME
from .data import RestData
from .entity import RestEntity from .entity import RestEntity
from .schema import RESOURCE_SCHEMA, SENSOR_SCHEMA from .schema import RESOURCE_SCHEMA, SENSOR_SCHEMA
@ -67,7 +69,7 @@ async def async_setup_platform(
raise PlatformNotReady from rest.last_exception raise PlatformNotReady from rest.last_exception
raise PlatformNotReady raise PlatformNotReady
unique_id = conf.get(CONF_UNIQUE_ID) unique_id: str | None = conf.get(CONF_UNIQUE_ID)
async_add_entities( async_add_entities(
[ [
@ -87,19 +89,19 @@ class RestSensor(RestEntity, TemplateSensor):
def __init__( def __init__(
self, self,
hass, hass: HomeAssistant,
coordinator, coordinator: DataUpdateCoordinator[None] | None,
rest, rest: RestData,
config, config: ConfigType,
unique_id, unique_id: str | None,
): ) -> None:
"""Initialize the REST sensor.""" """Initialize the REST sensor."""
RestEntity.__init__( RestEntity.__init__(
self, self,
coordinator, coordinator,
rest, rest,
config.get(CONF_RESOURCE_TEMPLATE), config.get(CONF_RESOURCE_TEMPLATE),
config.get(CONF_FORCE_UPDATE), config[CONF_FORCE_UPDATE],
) )
TemplateSensor.__init__( TemplateSensor.__init__(
self, self,
@ -108,25 +110,13 @@ class RestSensor(RestEntity, TemplateSensor):
fallback_name=DEFAULT_SENSOR_NAME, fallback_name=DEFAULT_SENSOR_NAME,
unique_id=unique_id, unique_id=unique_id,
) )
self._state = None
self._value_template = config.get(CONF_VALUE_TEMPLATE) self._value_template = config.get(CONF_VALUE_TEMPLATE)
if (value_template := self._value_template) is not None: if (value_template := self._value_template) is not None:
value_template.hass = hass value_template.hass = hass
self._json_attrs = config.get(CONF_JSON_ATTRS) self._json_attrs = config.get(CONF_JSON_ATTRS)
self._attributes = None
self._json_attrs_path = config.get(CONF_JSON_ATTRS_PATH) self._json_attrs_path = config.get(CONF_JSON_ATTRS_PATH)
@property def _update_from_rest_data(self) -> None:
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):
"""Update state from the rest data.""" """Update state from the rest data."""
value = self.rest.data value = self.rest.data
_LOGGER.debug("Data fetched from resource: %s", value) _LOGGER.debug("Data fetched from resource: %s", value)
@ -150,7 +140,7 @@ class RestSensor(RestEntity, TemplateSensor):
_LOGGER.debug("Erroneous XML: %s", value) _LOGGER.debug("Erroneous XML: %s", value)
if self._json_attrs: if self._json_attrs:
self._attributes = {} self._attr_extra_state_attributes = {}
if value: if value:
try: try:
json_dict = json_loads(value) json_dict = json_loads(value)
@ -165,7 +155,7 @@ class RestSensor(RestEntity, TemplateSensor):
attrs = { attrs = {
k: json_dict[k] for k in self._json_attrs if k in json_dict 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: else:
_LOGGER.warning( _LOGGER.warning(
"JSON result was not a dictionary" "JSON result was not a dictionary"
@ -187,9 +177,9 @@ class RestSensor(RestEntity, TemplateSensor):
SensorDeviceClass.DATE, SensorDeviceClass.DATE,
SensorDeviceClass.TIMESTAMP, SensorDeviceClass.TIMESTAMP,
): ):
self._state = value self._attr_native_value = value
return return
self._state = async_parse_date_datetime( self._attr_native_value = async_parse_date_datetime(
value, self.entity_id, self.device_class value, self.entity_id, self.device_class
) )

View File

@ -2225,6 +2225,16 @@ disallow_untyped_defs = true
warn_return_any = true warn_return_any = true
warn_unreachable = 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.*] [mypy-homeassistant.components.rfxtrx.*]
check_untyped_defs = true check_untyped_defs = true
disallow_incomplete_defs = true disallow_incomplete_defs = true