mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Fully type homeassistant integration (#107380)
This commit is contained in:
parent
5ae419367e
commit
78752264b3
@ -196,8 +196,7 @@ homeassistant.components.here_travel_time.*
|
|||||||
homeassistant.components.history.*
|
homeassistant.components.history.*
|
||||||
homeassistant.components.history_stats.*
|
homeassistant.components.history_stats.*
|
||||||
homeassistant.components.holiday.*
|
homeassistant.components.holiday.*
|
||||||
homeassistant.components.homeassistant.exposed_entities
|
homeassistant.components.homeassistant.*
|
||||||
homeassistant.components.homeassistant.triggers.event
|
|
||||||
homeassistant.components.homeassistant_alerts.*
|
homeassistant.components.homeassistant_alerts.*
|
||||||
homeassistant.components.homeassistant_green.*
|
homeassistant.components.homeassistant_green.*
|
||||||
homeassistant.components.homeassistant_hardware.*
|
homeassistant.components.homeassistant_hardware.*
|
||||||
|
@ -94,8 +94,8 @@ async def async_setup(hass: ha.HomeAssistant, config: ConfigType) -> bool: # no
|
|||||||
sorted(all_referenced), lambda item: ha.split_entity_id(item)[0]
|
sorted(all_referenced), lambda item: ha.split_entity_id(item)[0]
|
||||||
)
|
)
|
||||||
|
|
||||||
tasks = []
|
tasks: list[Coroutine[Any, Any, ha.ServiceResponse]] = []
|
||||||
unsupported_entities = set()
|
unsupported_entities: set[str] = set()
|
||||||
|
|
||||||
for domain, ent_ids in by_domain:
|
for domain, ent_ids in by_domain:
|
||||||
# This leads to endless loop.
|
# This leads to endless loop.
|
||||||
@ -298,7 +298,7 @@ async def async_setup(hass: ha.HomeAssistant, config: ConfigType) -> bool: # no
|
|||||||
|
|
||||||
async def async_handle_reload_config_entry(call: ha.ServiceCall) -> None:
|
async def async_handle_reload_config_entry(call: ha.ServiceCall) -> None:
|
||||||
"""Service handler for reloading a config entry."""
|
"""Service handler for reloading a config entry."""
|
||||||
reload_entries = set()
|
reload_entries: set[str] = set()
|
||||||
if ATTR_ENTRY_ID in call.data:
|
if ATTR_ENTRY_ID in call.data:
|
||||||
reload_entries.add(call.data[ATTR_ENTRY_ID])
|
reload_entries.add(call.data[ATTR_ENTRY_ID])
|
||||||
reload_entries.update(await async_extract_config_entry_ids(hass, call))
|
reload_entries.update(await async_extract_config_entry_ids(hass, call))
|
||||||
@ -376,7 +376,7 @@ async def async_setup(hass: ha.HomeAssistant, config: ConfigType) -> bool: # no
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
async def _async_stop(hass: ha.HomeAssistant, restart: bool):
|
async def _async_stop(hass: ha.HomeAssistant, restart: bool) -> None:
|
||||||
"""Stop home assistant."""
|
"""Stop home assistant."""
|
||||||
exit_code = RESTART_EXIT_CODE if restart else 0
|
exit_code = RESTART_EXIT_CODE if restart else 0
|
||||||
# Track trask in hass.data. No need to cleanup, we're stopping.
|
# Track trask in hass.data. No need to cleanup, we're stopping.
|
||||||
|
@ -475,7 +475,7 @@ def ws_expose_new_entities_get(
|
|||||||
def ws_expose_new_entities_set(
|
def ws_expose_new_entities_set(
|
||||||
hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: dict[str, Any]
|
hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: dict[str, Any]
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Expose new entities to an assistatant."""
|
"""Expose new entities to an assistant."""
|
||||||
exposed_entities: ExposedEntities = hass.data[DATA_EXPOSED_ENTITIES]
|
exposed_entities: ExposedEntities = hass.data[DATA_EXPOSED_ENTITIES]
|
||||||
exposed_entities.async_set_expose_new_entities(msg["assistant"], msg["expose_new"])
|
exposed_entities.async_set_expose_new_entities(msg["assistant"], msg["expose_new"])
|
||||||
connection.send_result(msg["id"])
|
connection.send_result(msg["id"])
|
||||||
|
@ -28,7 +28,7 @@ def async_describe_events(
|
|||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_describe_hass_event(event: Event) -> dict[str, str]:
|
def async_describe_hass_event(event: Event) -> dict[str, str]:
|
||||||
"""Describe homeassisant logbook event."""
|
"""Describe homeassistant logbook event."""
|
||||||
return {
|
return {
|
||||||
LOGBOOK_ENTRY_NAME: "Home Assistant",
|
LOGBOOK_ENTRY_NAME: "Home Assistant",
|
||||||
LOGBOOK_ENTRY_MESSAGE: EVENT_TO_NAME[event.event_type],
|
LOGBOOK_ENTRY_MESSAGE: EVENT_TO_NAME[event.event_type],
|
||||||
|
@ -135,7 +135,7 @@ class SceneConfig(NamedTuple):
|
|||||||
id: str | None
|
id: str | None
|
||||||
name: str
|
name: str
|
||||||
icon: str | None
|
icon: str | None
|
||||||
states: dict
|
states: dict[str, State]
|
||||||
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
"""Provide info to system health."""
|
"""Provide info to system health."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
from homeassistant.components import system_health
|
from homeassistant.components import system_health
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers import system_info
|
from homeassistant.helpers import system_info
|
||||||
@ -12,7 +16,7 @@ def async_register(
|
|||||||
register.async_register_info(system_health_info)
|
register.async_register_info(system_health_info)
|
||||||
|
|
||||||
|
|
||||||
async def system_health_info(hass):
|
async def system_health_info(hass: HomeAssistant) -> dict[str, Any]:
|
||||||
"""Get info for the info page."""
|
"""Get info for the info page."""
|
||||||
info = await system_info.async_get_system_info(hass)
|
info = await system_info.async_get_system_info(hass)
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ async def async_validate_trigger_config(
|
|||||||
if hasattr(platform, "async_validate_trigger_config"):
|
if hasattr(platform, "async_validate_trigger_config"):
|
||||||
return await platform.async_validate_trigger_config(hass, config)
|
return await platform.async_validate_trigger_config(hass, config)
|
||||||
|
|
||||||
return platform.TRIGGER_SCHEMA(config)
|
return platform.TRIGGER_SCHEMA(config) # type: ignore[no-any-return]
|
||||||
|
|
||||||
|
|
||||||
async def async_attach_trigger(
|
async def async_attach_trigger(
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
"""Offer numeric state listening automation rules."""
|
"""Offer numeric state listening automation rules."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections.abc import Callable
|
||||||
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
|
from typing import Any, TypeVar
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
@ -13,7 +18,7 @@ from homeassistant.const import (
|
|||||||
CONF_PLATFORM,
|
CONF_PLATFORM,
|
||||||
CONF_VALUE_TEMPLATE,
|
CONF_VALUE_TEMPLATE,
|
||||||
)
|
)
|
||||||
from homeassistant.core import CALLBACK_TYPE, HassJob, HomeAssistant, callback
|
from homeassistant.core import CALLBACK_TYPE, HassJob, HomeAssistant, State, callback
|
||||||
from homeassistant.helpers import (
|
from homeassistant.helpers import (
|
||||||
condition,
|
condition,
|
||||||
config_validation as cv,
|
config_validation as cv,
|
||||||
@ -21,14 +26,17 @@ from homeassistant.helpers import (
|
|||||||
template,
|
template,
|
||||||
)
|
)
|
||||||
from homeassistant.helpers.event import (
|
from homeassistant.helpers.event import (
|
||||||
|
EventStateChangedData,
|
||||||
async_track_same_state,
|
async_track_same_state,
|
||||||
async_track_state_change_event,
|
async_track_state_change_event,
|
||||||
)
|
)
|
||||||
from homeassistant.helpers.trigger import TriggerActionType, TriggerInfo
|
from homeassistant.helpers.trigger import TriggerActionType, TriggerInfo
|
||||||
from homeassistant.helpers.typing import ConfigType
|
from homeassistant.helpers.typing import ConfigType, EventType
|
||||||
|
|
||||||
|
_T = TypeVar("_T", bound=dict[str, Any])
|
||||||
|
|
||||||
|
|
||||||
def validate_above_below(value):
|
def validate_above_below(value: _T) -> _T:
|
||||||
"""Validate that above and below can co-exist."""
|
"""Validate that above and below can co-exist."""
|
||||||
above = value.get(CONF_ABOVE)
|
above = value.get(CONF_ABOVE)
|
||||||
below = value.get(CONF_BELOW)
|
below = value.get(CONF_BELOW)
|
||||||
@ -96,9 +104,9 @@ async def async_attach_trigger(
|
|||||||
time_delta = config.get(CONF_FOR)
|
time_delta = config.get(CONF_FOR)
|
||||||
template.attach(hass, time_delta)
|
template.attach(hass, time_delta)
|
||||||
value_template = config.get(CONF_VALUE_TEMPLATE)
|
value_template = config.get(CONF_VALUE_TEMPLATE)
|
||||||
unsub_track_same = {}
|
unsub_track_same: dict[str, Callable[[], None]] = {}
|
||||||
armed_entities = set()
|
armed_entities: set[str] = set()
|
||||||
period: dict = {}
|
period: dict[str, timedelta] = {}
|
||||||
attribute = config.get(CONF_ATTRIBUTE)
|
attribute = config.get(CONF_ATTRIBUTE)
|
||||||
job = HassJob(action, f"numeric state trigger {trigger_info}")
|
job = HassJob(action, f"numeric state trigger {trigger_info}")
|
||||||
|
|
||||||
@ -108,7 +116,7 @@ async def async_attach_trigger(
|
|||||||
if value_template is not None:
|
if value_template is not None:
|
||||||
value_template.hass = hass
|
value_template.hass = hass
|
||||||
|
|
||||||
def variables(entity_id):
|
def variables(entity_id: str) -> dict[str, Any]:
|
||||||
"""Return a dict with trigger variables."""
|
"""Return a dict with trigger variables."""
|
||||||
trigger_info = {
|
trigger_info = {
|
||||||
"trigger": {
|
"trigger": {
|
||||||
@ -122,7 +130,9 @@ async def async_attach_trigger(
|
|||||||
return {**_variables, **trigger_info}
|
return {**_variables, **trigger_info}
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def check_numeric_state(entity_id, from_s, to_s):
|
def check_numeric_state(
|
||||||
|
entity_id: str, from_s: State | None, to_s: str | State | None
|
||||||
|
) -> bool:
|
||||||
"""Return whether the criteria are met, raise ConditionError if unknown."""
|
"""Return whether the criteria are met, raise ConditionError if unknown."""
|
||||||
return condition.async_numeric_state(
|
return condition.async_numeric_state(
|
||||||
hass, to_s, below, above, value_template, variables(entity_id), attribute
|
hass, to_s, below, above, value_template, variables(entity_id), attribute
|
||||||
@ -141,14 +151,17 @@ async def async_attach_trigger(
|
|||||||
)
|
)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def state_automation_listener(event):
|
def state_automation_listener(event: EventType[EventStateChangedData]) -> None:
|
||||||
"""Listen for state changes and calls action."""
|
"""Listen for state changes and calls action."""
|
||||||
entity_id = event.data.get("entity_id")
|
entity_id = event.data["entity_id"]
|
||||||
from_s = event.data.get("old_state")
|
from_s = event.data["old_state"]
|
||||||
to_s = event.data.get("new_state")
|
to_s = event.data["new_state"]
|
||||||
|
|
||||||
|
if to_s is None:
|
||||||
|
return
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def call_action():
|
def call_action() -> None:
|
||||||
"""Call action with right context."""
|
"""Call action with right context."""
|
||||||
hass.async_run_hass_job(
|
hass.async_run_hass_job(
|
||||||
job,
|
job,
|
||||||
@ -169,7 +182,9 @@ async def async_attach_trigger(
|
|||||||
)
|
)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def check_numeric_state_no_raise(entity_id, from_s, to_s):
|
def check_numeric_state_no_raise(
|
||||||
|
entity_id: str, from_s: State | None, to_s: State | None
|
||||||
|
) -> bool:
|
||||||
"""Return True if the criteria are now met, False otherwise."""
|
"""Return True if the criteria are now met, False otherwise."""
|
||||||
try:
|
try:
|
||||||
return check_numeric_state(entity_id, from_s, to_s)
|
return check_numeric_state(entity_id, from_s, to_s)
|
||||||
@ -216,7 +231,7 @@ async def async_attach_trigger(
|
|||||||
unsub = async_track_state_change_event(hass, entity_ids, state_automation_listener)
|
unsub = async_track_state_change_event(hass, entity_ids, state_automation_listener)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_remove():
|
def async_remove() -> None:
|
||||||
"""Remove state listeners async."""
|
"""Remove state listeners async."""
|
||||||
unsub()
|
unsub()
|
||||||
for async_remove in unsub_track_same.values():
|
for async_remove in unsub_track_same.values():
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
"""Offer state listening automation rules."""
|
"""Offer state listening automation rules."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections.abc import Callable
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
@ -114,7 +115,7 @@ async def async_attach_trigger(
|
|||||||
match_all = all(
|
match_all = all(
|
||||||
item not in config for item in (CONF_FROM, CONF_NOT_FROM, CONF_NOT_TO, CONF_TO)
|
item not in config for item in (CONF_FROM, CONF_NOT_FROM, CONF_NOT_TO, CONF_TO)
|
||||||
)
|
)
|
||||||
unsub_track_same = {}
|
unsub_track_same: dict[str, Callable[[], None]] = {}
|
||||||
period: dict[str, timedelta] = {}
|
period: dict[str, timedelta] = {}
|
||||||
attribute = config.get(CONF_ATTRIBUTE)
|
attribute = config.get(CONF_ATTRIBUTE)
|
||||||
job = HassJob(action, f"state trigger {trigger_info}")
|
job = HassJob(action, f"state trigger {trigger_info}")
|
||||||
@ -158,7 +159,7 @@ async def async_attach_trigger(
|
|||||||
return
|
return
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def call_action():
|
def call_action() -> None:
|
||||||
"""Call action with right context."""
|
"""Call action with right context."""
|
||||||
hass.async_run_hass_job(
|
hass.async_run_hass_job(
|
||||||
job,
|
job,
|
||||||
@ -201,7 +202,7 @@ async def async_attach_trigger(
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
def _check_same_state(_, _2, new_st: State | None) -> bool:
|
def _check_same_state(_: str, _2: State | None, new_st: State | None) -> bool:
|
||||||
if new_st is None:
|
if new_st is None:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -227,7 +228,7 @@ async def async_attach_trigger(
|
|||||||
unsub = async_track_state_change_event(hass, entity_ids, state_automation_listener)
|
unsub = async_track_state_change_event(hass, entity_ids, state_automation_listener)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_remove():
|
def async_remove() -> None:
|
||||||
"""Remove state listeners async."""
|
"""Remove state listeners async."""
|
||||||
unsub()
|
unsub()
|
||||||
for async_remove in unsub_track_same.values():
|
for async_remove in unsub_track_same.values():
|
||||||
|
@ -53,7 +53,9 @@ async def async_attach_trigger(
|
|||||||
job = HassJob(action, f"time trigger {trigger_info}")
|
job = HassJob(action, f"time trigger {trigger_info}")
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def time_automation_listener(description, now, *, entity_id=None):
|
def time_automation_listener(
|
||||||
|
description: str, now: datetime, *, entity_id: str | None = None
|
||||||
|
) -> None:
|
||||||
"""Listen for time changes and calls action."""
|
"""Listen for time changes and calls action."""
|
||||||
hass.async_run_hass_job(
|
hass.async_run_hass_job(
|
||||||
job,
|
job,
|
||||||
@ -183,7 +185,7 @@ async def async_attach_trigger(
|
|||||||
)
|
)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def remove_track_time_changes():
|
def remove_track_time_changes() -> None:
|
||||||
"""Remove tracked time changes."""
|
"""Remove tracked time changes."""
|
||||||
for remove in entities.values():
|
for remove in entities.values():
|
||||||
remove()
|
remove()
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
"""Offer time listening automation rules."""
|
"""Offer time listening automation rules."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.const import CONF_PLATFORM
|
from homeassistant.const import CONF_PLATFORM
|
||||||
@ -19,15 +24,15 @@ class TimePattern:
|
|||||||
:raises Invalid: If the value has a wrong format or is outside the range.
|
:raises Invalid: If the value has a wrong format or is outside the range.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, maximum):
|
def __init__(self, maximum: int) -> None:
|
||||||
"""Initialize time pattern."""
|
"""Initialize time pattern."""
|
||||||
self.maximum = maximum
|
self.maximum = maximum
|
||||||
|
|
||||||
def __call__(self, value):
|
def __call__(self, value: Any) -> str | int:
|
||||||
"""Validate input."""
|
"""Validate input."""
|
||||||
try:
|
try:
|
||||||
if value == "*":
|
if value == "*":
|
||||||
return value
|
return value # type: ignore[no-any-return]
|
||||||
|
|
||||||
if isinstance(value, str) and value.startswith("/"):
|
if isinstance(value, str) and value.startswith("/"):
|
||||||
number = int(value[1:])
|
number = int(value[1:])
|
||||||
@ -39,7 +44,7 @@ class TimePattern:
|
|||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
raise vol.Invalid("invalid time_pattern value") from err
|
raise vol.Invalid("invalid time_pattern value") from err
|
||||||
|
|
||||||
return value
|
return value # type: ignore[no-any-return]
|
||||||
|
|
||||||
|
|
||||||
TRIGGER_SCHEMA = vol.All(
|
TRIGGER_SCHEMA = vol.All(
|
||||||
@ -75,7 +80,7 @@ async def async_attach_trigger(
|
|||||||
seconds = 0
|
seconds = 0
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def time_automation_listener(now):
|
def time_automation_listener(now: datetime) -> None:
|
||||||
"""Listen for time changes and calls action."""
|
"""Listen for time changes and calls action."""
|
||||||
hass.async_run_hass_job(
|
hass.async_run_hass_job(
|
||||||
job,
|
job,
|
||||||
|
@ -520,7 +520,7 @@ def async_extract_referenced_entity_ids(
|
|||||||
@bind_hass
|
@bind_hass
|
||||||
async def async_extract_config_entry_ids(
|
async def async_extract_config_entry_ids(
|
||||||
hass: HomeAssistant, service_call: ServiceCall, expand_group: bool = True
|
hass: HomeAssistant, service_call: ServiceCall, expand_group: bool = True
|
||||||
) -> set:
|
) -> set[str]:
|
||||||
"""Extract referenced config entry ids from a service call."""
|
"""Extract referenced config entry ids from a service call."""
|
||||||
referenced = async_extract_referenced_entity_ids(hass, service_call, expand_group)
|
referenced = async_extract_referenced_entity_ids(hass, service_call, expand_group)
|
||||||
ent_reg = entity_registry.async_get(hass)
|
ent_reg = entity_registry.async_get(hass)
|
||||||
|
12
mypy.ini
12
mypy.ini
@ -1721,17 +1721,7 @@ disallow_untyped_defs = true
|
|||||||
warn_return_any = true
|
warn_return_any = true
|
||||||
warn_unreachable = true
|
warn_unreachable = true
|
||||||
|
|
||||||
[mypy-homeassistant.components.homeassistant.exposed_entities]
|
[mypy-homeassistant.components.homeassistant.*]
|
||||||
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.homeassistant.triggers.event]
|
|
||||||
check_untyped_defs = true
|
check_untyped_defs = true
|
||||||
disallow_incomplete_defs = true
|
disallow_incomplete_defs = true
|
||||||
disallow_subclassing_any = true
|
disallow_subclassing_any = true
|
||||||
|
Loading…
x
Reference in New Issue
Block a user