Enable basic type checking in template (#66222)

* Fix binary_sensor

* Adjust button

* Adjust fan

* Adjust select

* Adjust template_entity

* Adjust trigger_entity

* Adjust weather

* Adjust init

* Adjust number

* Adjust None check
This commit is contained in:
epenet 2022-02-10 10:59:54 +01:00 committed by GitHub
parent 8760cb035a
commit 47d6f75c17
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 31 additions and 62 deletions

View File

@ -61,7 +61,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
return True return True
async def _process_config(hass, hass_config): async def _process_config(hass: HomeAssistant, hass_config: ConfigType) -> None:
"""Process config.""" """Process config."""
coordinators: list[TriggerUpdateCoordinator] | None = hass.data.pop(DOMAIN, None) coordinators: list[TriggerUpdateCoordinator] | None = hass.data.pop(DOMAIN, None)
@ -126,7 +126,7 @@ class TriggerUpdateCoordinator(update_coordinator.DataUpdateCoordinator):
if self._unsub_trigger: if self._unsub_trigger:
self._unsub_trigger() self._unsub_trigger()
async def async_setup(self: HomeAssistant, hass_config: ConfigType) -> bool: async def async_setup(self, hass_config: ConfigType) -> None:
"""Set up the trigger and create entities.""" """Set up the trigger and create entities."""
if self.hass.state == CoreState.running: if self.hass.state == CoreState.running:
await self._attach_triggers() await self._attach_triggers()

View File

@ -31,7 +31,7 @@ from homeassistant.const import (
CONF_UNIT_OF_MEASUREMENT, CONF_UNIT_OF_MEASUREMENT,
CONF_VALUE_TEMPLATE, CONF_VALUE_TEMPLATE,
) )
from homeassistant.core import HomeAssistant, callback from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback
from homeassistant.exceptions import TemplateError from homeassistant.exceptions import TemplateError
from homeassistant.helpers import template from homeassistant.helpers import template
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
@ -300,12 +300,12 @@ class TriggerBinarySensorEntity(TriggerEntity, BinarySensorEntity):
self._to_render_simple.append(key) self._to_render_simple.append(key)
self._parse_result.add(key) self._parse_result.add(key)
self._delay_cancel = None self._delay_cancel: CALLBACK_TYPE | None = None
self._auto_off_cancel = None self._auto_off_cancel = None
self._state = None self._state: bool | None = None
@property @property
def is_on(self) -> bool: def is_on(self) -> bool | None:
"""Return state of the sensor.""" """Return state of the sensor."""
return self._state return self._state

View File

@ -63,7 +63,7 @@ async def async_setup_platform(
discovery_info: DiscoveryInfoType | None = None, discovery_info: DiscoveryInfoType | None = None,
) -> None: ) -> None:
"""Set up the template button.""" """Set up the template button."""
if "coordinator" in discovery_info: if not discovery_info or "coordinator" in discovery_info:
raise PlatformNotReady( raise PlatformNotReady(
"The template button platform doesn't support trigger entities" "The template button platform doesn't support trigger entities"
) )
@ -86,6 +86,7 @@ class TemplateButtonEntity(TemplateEntity, ButtonEntity):
) -> None: ) -> None:
"""Initialize the button.""" """Initialize the button."""
super().__init__(hass, config=config, unique_id=unique_id) super().__init__(hass, config=config, unique_id=unique_id)
assert self._attr_name is not None
self._command_press = Script(hass, config[CONF_PRESS], self._attr_name, DOMAIN) self._command_press = Script(hass, config[CONF_PRESS], self._attr_name, DOMAIN)
self._attr_device_class = config.get(CONF_DEVICE_CLASS) self._attr_device_class = config.get(CONF_DEVICE_CLASS)
self._attr_state = None self._attr_state = None

View File

@ -2,6 +2,7 @@
from __future__ import annotations from __future__ import annotations
import logging import logging
from typing import Any
import voluptuous as vol import voluptuous as vol
@ -63,7 +64,6 @@ CONF_SET_DIRECTION_ACTION = "set_direction"
CONF_SET_PRESET_MODE_ACTION = "set_preset_mode" CONF_SET_PRESET_MODE_ACTION = "set_preset_mode"
_VALID_STATES = [STATE_ON, STATE_OFF] _VALID_STATES = [STATE_ON, STATE_OFF]
_VALID_OSC = [True, False]
_VALID_DIRECTIONS = [DIRECTION_FORWARD, DIRECTION_REVERSE] _VALID_DIRECTIONS = [DIRECTION_FORWARD, DIRECTION_REVERSE]
FAN_SCHEMA = vol.All( FAN_SCHEMA = vol.All(
@ -273,8 +273,7 @@ class TemplateFan(TemplateEntity, FanEntity):
elif speed is not None: elif speed is not None:
await self.async_set_speed(speed) await self.async_set_speed(speed)
# pylint: disable=arguments-differ async def async_turn_off(self, **kwargs: Any) -> None:
async def async_turn_off(self) -> None:
"""Turn off the fan.""" """Turn off the fan."""
await self._off_script.async_run(context=self._context) await self._off_script.async_run(context=self._context)
self._state = STATE_OFF self._state = STATE_OFF
@ -316,17 +315,10 @@ class TemplateFan(TemplateEntity, FanEntity):
if self._set_oscillating_script is None: if self._set_oscillating_script is None:
return return
if oscillating in _VALID_OSC:
self._oscillating = oscillating self._oscillating = oscillating
await self._set_oscillating_script.async_run( await self._set_oscillating_script.async_run(
{ATTR_OSCILLATING: oscillating}, context=self._context {ATTR_OSCILLATING: oscillating}, context=self._context
) )
else:
_LOGGER.error(
"Received invalid oscillating value: %s. Expected: %s",
oscillating,
", ".join(_VALID_OSC),
)
async def async_set_direction(self, direction: str) -> None: async def async_set_direction(self, direction: str) -> None:
"""Set the direction of the fan.""" """Set the direction of the fan."""

View File

@ -108,6 +108,7 @@ class TemplateNumber(TemplateEntity, NumberEntity):
) -> None: ) -> None:
"""Initialize the number.""" """Initialize the number."""
super().__init__(hass, config=config, unique_id=unique_id) super().__init__(hass, config=config, unique_id=unique_id)
assert self._attr_name is not None
self._value_template = config[CONF_STATE] self._value_template = config[CONF_STATE]
self._command_set_value = Script( self._command_set_value = Script(
hass, config[CONF_SET_VALUE], self._attr_name, DOMAIN hass, config[CONF_SET_VALUE], self._attr_name, DOMAIN

View File

@ -102,13 +102,14 @@ class TemplateSelect(TemplateEntity, SelectEntity):
) -> None: ) -> None:
"""Initialize the select.""" """Initialize the select."""
super().__init__(hass, config=config, unique_id=unique_id) super().__init__(hass, config=config, unique_id=unique_id)
assert self._attr_name is not None
self._value_template = config[CONF_STATE] self._value_template = config[CONF_STATE]
self._command_select_option = Script( self._command_select_option = Script(
hass, config[CONF_SELECT_OPTION], self._attr_name, DOMAIN hass, config[CONF_SELECT_OPTION], self._attr_name, DOMAIN
) )
self._options_template = config[ATTR_OPTIONS] self._options_template = config[ATTR_OPTIONS]
self._attr_assumed_state = self._optimistic = config[CONF_OPTIMISTIC] self._attr_assumed_state = self._optimistic = config[CONF_OPTIMISTIC]
self._attr_options = None self._attr_options = []
self._attr_current_option = None self._attr_current_option = None
async def async_added_to_hass(self) -> None: async def async_added_to_hass(self) -> None:

View File

@ -16,13 +16,13 @@ from homeassistant.const import (
CONF_ICON, CONF_ICON,
CONF_ICON_TEMPLATE, CONF_ICON_TEMPLATE,
CONF_NAME, CONF_NAME,
EVENT_HOMEASSISTANT_START,
) )
from homeassistant.core import EVENT_HOMEASSISTANT_START, CoreState, callback from homeassistant.core import CoreState, Event, callback
from homeassistant.exceptions import TemplateError from homeassistant.exceptions import TemplateError
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
from homeassistant.helpers.event import ( from homeassistant.helpers.event import (
Event,
TrackTemplate, TrackTemplate,
TrackTemplateResult, TrackTemplateResult,
async_track_template_result, async_track_template_result,
@ -94,7 +94,7 @@ LEGACY_FIELDS = {
def rewrite_common_legacy_to_modern_conf( def rewrite_common_legacy_to_modern_conf(
entity_cfg: dict[str, Any], extra_legacy_fields: dict[str, str] = None entity_cfg: dict[str, Any], extra_legacy_fields: dict[str, str] = None
) -> list[dict]: ) -> dict[str, Any]:
"""Rewrite legacy config.""" """Rewrite legacy config."""
entity_cfg = {**entity_cfg} entity_cfg = {**entity_cfg}
if extra_legacy_fields is None: if extra_legacy_fields is None:
@ -176,10 +176,12 @@ class _TemplateAttribute:
if self.none_on_template_error: if self.none_on_template_error:
self._default_update(result) self._default_update(result)
else: else:
assert self.on_update
self.on_update(result) self.on_update(result)
return return
if not self.validator: if not self.validator:
assert self.on_update
self.on_update(result) self.on_update(result)
return return
@ -197,9 +199,11 @@ class _TemplateAttribute:
self._entity.entity_id, self._entity.entity_id,
ex.msg, ex.msg,
) )
assert self.on_update
self.on_update(None) self.on_update(None)
return return
assert self.on_update
self.on_update(validated) self.on_update(validated)
return return
@ -321,11 +325,11 @@ class TemplateEntity(Entity):
""" """
assert self.hass is not None, "hass cannot be None" assert self.hass is not None, "hass cannot be None"
template.hass = self.hass template.hass = self.hass
attribute = _TemplateAttribute( template_attribute = _TemplateAttribute(
self, attribute, template, validator, on_update, none_on_template_error self, attribute, template, validator, on_update, none_on_template_error
) )
self._template_attrs.setdefault(template, []) self._template_attrs.setdefault(template, [])
self._template_attrs[template].append(attribute) self._template_attrs[template].append(template_attribute)
@callback @callback
def _handle_results( def _handle_results(
@ -362,7 +366,7 @@ class TemplateEntity(Entity):
self.async_write_ha_state() self.async_write_ha_state()
async def _async_template_startup(self, *_) -> None: async def _async_template_startup(self, *_) -> None:
template_var_tups = [] template_var_tups: list[TrackTemplate] = []
has_availability_template = False has_availability_template = False
for template, attributes in self._template_attrs.items(): for template, attributes in self._template_attrs.items():
template_var_tup = TrackTemplate(template, None) template_var_tup = TrackTemplate(template, None)

View File

@ -12,6 +12,7 @@ from homeassistant.const import (
CONF_UNIT_OF_MEASUREMENT, CONF_UNIT_OF_MEASUREMENT,
) )
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import TemplateError
from homeassistant.helpers import template, update_coordinator from homeassistant.helpers import template, update_coordinator
from . import TriggerUpdateCoordinator from . import TriggerUpdateCoordinator
@ -36,6 +37,7 @@ class TriggerEntity(update_coordinator.CoordinatorEntity):
entity_unique_id = config.get(CONF_UNIQUE_ID) entity_unique_id = config.get(CONF_UNIQUE_ID)
self._unique_id: str | None
if entity_unique_id and coordinator.unique_id: if entity_unique_id and coordinator.unique_id:
self._unique_id = f"{coordinator.unique_id}-{entity_unique_id}" self._unique_id = f"{coordinator.unique_id}-{entity_unique_id}"
else: else:
@ -45,7 +47,7 @@ class TriggerEntity(update_coordinator.CoordinatorEntity):
self._static_rendered = {} self._static_rendered = {}
self._to_render_simple = [] self._to_render_simple = []
self._to_render_complex = [] self._to_render_complex: list[str] = []
for itm in ( for itm in (
CONF_NAME, CONF_NAME,
@ -148,7 +150,7 @@ class TriggerEntity(update_coordinator.CoordinatorEntity):
) )
self._rendered = rendered self._rendered = rendered
except template.TemplateError as err: except TemplateError as err:
logging.getLogger(f"{__package__}.{self.entity_id.split('.')[0]}").error( logging.getLogger(f"{__package__}.{self.entity_id.split('.')[0]}").error(
"Error rendering %s template for %s: %s", key, self.entity_id, err "Error rendering %s template for %s: %s", key, self.entity_id, err
) )

View File

@ -2619,36 +2619,12 @@ ignore_errors = true
[mypy-homeassistant.components.telegram_bot.polling] [mypy-homeassistant.components.telegram_bot.polling]
ignore_errors = true ignore_errors = true
[mypy-homeassistant.components.template]
ignore_errors = true
[mypy-homeassistant.components.template.binary_sensor]
ignore_errors = true
[mypy-homeassistant.components.template.button]
ignore_errors = true
[mypy-homeassistant.components.template.fan]
ignore_errors = true
[mypy-homeassistant.components.template.number] [mypy-homeassistant.components.template.number]
ignore_errors = true ignore_errors = true
[mypy-homeassistant.components.template.select]
ignore_errors = true
[mypy-homeassistant.components.template.sensor] [mypy-homeassistant.components.template.sensor]
ignore_errors = true ignore_errors = true
[mypy-homeassistant.components.template.template_entity]
ignore_errors = true
[mypy-homeassistant.components.template.trigger_entity]
ignore_errors = true
[mypy-homeassistant.components.template.weather]
ignore_errors = true
[mypy-homeassistant.components.toon] [mypy-homeassistant.components.toon]
ignore_errors = true ignore_errors = true

View File

@ -179,16 +179,8 @@ IGNORED_MODULES: Final[list[str]] = [
"homeassistant.components.sonos.statistics", "homeassistant.components.sonos.statistics",
"homeassistant.components.system_health", "homeassistant.components.system_health",
"homeassistant.components.telegram_bot.polling", "homeassistant.components.telegram_bot.polling",
"homeassistant.components.template",
"homeassistant.components.template.binary_sensor",
"homeassistant.components.template.button",
"homeassistant.components.template.fan",
"homeassistant.components.template.number", "homeassistant.components.template.number",
"homeassistant.components.template.select",
"homeassistant.components.template.sensor", "homeassistant.components.template.sensor",
"homeassistant.components.template.template_entity",
"homeassistant.components.template.trigger_entity",
"homeassistant.components.template.weather",
"homeassistant.components.toon", "homeassistant.components.toon",
"homeassistant.components.toon.config_flow", "homeassistant.components.toon.config_flow",
"homeassistant.components.toon.models", "homeassistant.components.toon.models",