mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 12:17:07 +00:00
Type hint additions (#26831)
* Type hint additions * Remove optional from sidebar_icon comment Co-Authored-By: Franck Nijhof <frenck@frenck.nl> * Remove optional from sidebar_title comment Co-Authored-By: Franck Nijhof <frenck@frenck.nl> * Fix issues after rebase and mypy 0.730
This commit is contained in:
parent
4f55235aa2
commit
f259ff17d5
@ -1,16 +1,19 @@
|
||||
"""Offer state listening automation rules."""
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
from typing import Dict
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import exceptions
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.core import HomeAssistant, CALLBACK_TYPE, callback
|
||||
from homeassistant.const import MATCH_ALL, CONF_PLATFORM, CONF_FOR
|
||||
from homeassistant.helpers import config_validation as cv, template
|
||||
from homeassistant.helpers.event import async_track_state_change, async_track_same_state
|
||||
|
||||
|
||||
# mypy: allow-untyped-calls, allow-untyped-defs, no-check-untyped-defs
|
||||
# mypy: allow-incomplete-defs, allow-untyped-calls, allow-untyped-defs
|
||||
# mypy: no-check-untyped-defs
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@ -38,8 +41,13 @@ TRIGGER_SCHEMA = vol.All(
|
||||
|
||||
|
||||
async def async_attach_trigger(
|
||||
hass, config, action, automation_info, *, platform_type="state"
|
||||
):
|
||||
hass: HomeAssistant,
|
||||
config,
|
||||
action,
|
||||
automation_info,
|
||||
*,
|
||||
platform_type: str = "state",
|
||||
) -> CALLBACK_TYPE:
|
||||
"""Listen for state changes based on configuration."""
|
||||
entity_id = config.get(CONF_ENTITY_ID)
|
||||
from_state = config.get(CONF_FROM, MATCH_ALL)
|
||||
@ -48,7 +56,7 @@ async def async_attach_trigger(
|
||||
template.attach(hass, time_delta)
|
||||
match_all = from_state == MATCH_ALL and to_state == MATCH_ALL
|
||||
unsub_track_same = {}
|
||||
period = {}
|
||||
period: Dict[str, timedelta] = {}
|
||||
|
||||
@callback
|
||||
def state_automation_listener(entity, from_s, to_s):
|
||||
|
@ -1,6 +1,7 @@
|
||||
"""Helpers for device automations."""
|
||||
import asyncio
|
||||
import logging
|
||||
from typing import Any, List, MutableMapping
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
@ -11,6 +12,9 @@ from homeassistant.loader import async_get_integration, IntegrationNotFound
|
||||
|
||||
from .exceptions import InvalidDeviceAutomationConfig
|
||||
|
||||
|
||||
# mypy: allow-untyped-calls, allow-untyped-defs
|
||||
|
||||
DOMAIN = "device_automation"
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@ -96,7 +100,7 @@ async def _async_get_device_automations(hass, automation_type, device_id):
|
||||
)
|
||||
|
||||
domains = set()
|
||||
automations = []
|
||||
automations: List[MutableMapping[str, Any]] = []
|
||||
device = device_registry.async_get(device_id)
|
||||
for entry_id in device.config_entries:
|
||||
config_entry = hass.config_entries.async_get_entry(entry_id)
|
||||
|
@ -1,5 +1,5 @@
|
||||
"""Device automation helpers for toggle entity."""
|
||||
from typing import List
|
||||
from typing import Any, Dict, List
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.core import Context, HomeAssistant, CALLBACK_TYPE
|
||||
@ -19,6 +19,9 @@ from homeassistant.helpers import condition, config_validation as cv, service
|
||||
from homeassistant.helpers.typing import ConfigType, TemplateVarsType
|
||||
from . import TRIGGER_BASE_SCHEMA
|
||||
|
||||
|
||||
# mypy: allow-untyped-calls, allow-untyped-defs
|
||||
|
||||
ENTITY_ACTIONS = [
|
||||
{
|
||||
# Turn entity off
|
||||
@ -88,7 +91,7 @@ async def async_call_action_from_config(
|
||||
variables: TemplateVarsType,
|
||||
context: Context,
|
||||
domain: str,
|
||||
):
|
||||
) -> None:
|
||||
"""Change state based on configuration."""
|
||||
config = ACTION_SCHEMA(config)
|
||||
action_type = config[CONF_TYPE]
|
||||
@ -156,7 +159,7 @@ async def _async_get_automations(
|
||||
hass: HomeAssistant, device_id: str, automation_templates: List[dict], domain: str
|
||||
) -> List[dict]:
|
||||
"""List device automations."""
|
||||
automations = []
|
||||
automations: List[Dict[str, Any]] = []
|
||||
entity_registry = await hass.helpers.entity_registry.async_get_registry()
|
||||
|
||||
entries = [
|
||||
|
@ -4,7 +4,7 @@ import logging
|
||||
import mimetypes
|
||||
import os
|
||||
import pathlib
|
||||
from typing import Optional, Set, Tuple
|
||||
from typing import Any, Dict, Optional, Set, Tuple
|
||||
|
||||
from aiohttp import web, web_urldispatcher, hdrs
|
||||
import voluptuous as vol
|
||||
@ -122,19 +122,19 @@ class Panel:
|
||||
"""Abstract class for panels."""
|
||||
|
||||
# Name of the webcomponent
|
||||
component_name = None
|
||||
component_name: Optional[str] = None
|
||||
|
||||
# Icon to show in the sidebar (optional)
|
||||
sidebar_icon = None
|
||||
# Icon to show in the sidebar
|
||||
sidebar_icon: Optional[str] = None
|
||||
|
||||
# Title to show in the sidebar (optional)
|
||||
sidebar_title = None
|
||||
# Title to show in the sidebar
|
||||
sidebar_title: Optional[str] = None
|
||||
|
||||
# Url to show the panel in the frontend
|
||||
frontend_url_path = None
|
||||
frontend_url_path: Optional[str] = None
|
||||
|
||||
# Config to pass to the webcomponent
|
||||
config = None
|
||||
config: Optional[Dict[str, Any]] = None
|
||||
|
||||
# If the panel should only be visible to admins
|
||||
require_admin = False
|
||||
|
@ -1,6 +1,7 @@
|
||||
"""Provide the functionality to group entities."""
|
||||
import asyncio
|
||||
import logging
|
||||
from typing import Any, Iterable, List, Optional, cast
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
@ -32,9 +33,12 @@ from homeassistant.helpers.entity_component import EntityComponent
|
||||
from homeassistant.helpers.event import async_track_state_change
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.config_validation import ENTITY_SERVICE_SCHEMA
|
||||
from homeassistant.helpers.typing import HomeAssistantType
|
||||
from homeassistant.util.async_ import run_coroutine_threadsafe
|
||||
|
||||
|
||||
# mypy: allow-untyped-calls, allow-untyped-defs
|
||||
|
||||
DOMAIN = "group"
|
||||
|
||||
ENTITY_ID_FORMAT = DOMAIN + ".{}"
|
||||
@ -143,12 +147,12 @@ def is_on(hass, entity_id):
|
||||
|
||||
|
||||
@bind_hass
|
||||
def expand_entity_ids(hass, entity_ids):
|
||||
def expand_entity_ids(hass: HomeAssistantType, entity_ids: Iterable[Any]) -> List[str]:
|
||||
"""Return entity_ids with group entity ids replaced by their members.
|
||||
|
||||
Async friendly.
|
||||
"""
|
||||
found_ids = []
|
||||
found_ids: List[str] = []
|
||||
for entity_id in entity_ids:
|
||||
if not isinstance(entity_id, str):
|
||||
continue
|
||||
@ -182,7 +186,9 @@ def expand_entity_ids(hass, entity_ids):
|
||||
|
||||
|
||||
@bind_hass
|
||||
def get_entity_ids(hass, entity_id, domain_filter=None):
|
||||
def get_entity_ids(
|
||||
hass: HomeAssistantType, entity_id: str, domain_filter: Optional[str] = None
|
||||
) -> List[str]:
|
||||
"""Get members of this group.
|
||||
|
||||
Async friendly.
|
||||
@ -194,7 +200,7 @@ def get_entity_ids(hass, entity_id, domain_filter=None):
|
||||
|
||||
entity_ids = group.attributes[ATTR_ENTITY_ID]
|
||||
if not domain_filter:
|
||||
return entity_ids
|
||||
return cast(List[str], entity_ids)
|
||||
|
||||
domain_filter = domain_filter.lower() + "."
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
"""This platform allows several cover to be grouped into one cover."""
|
||||
import logging
|
||||
from typing import Dict, Optional, Set
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
@ -11,7 +12,7 @@ from homeassistant.const import (
|
||||
CONF_NAME,
|
||||
STATE_CLOSED,
|
||||
)
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.core import callback, State
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.event import async_track_state_change
|
||||
|
||||
@ -41,6 +42,9 @@ from homeassistant.components.cover import (
|
||||
CoverDevice,
|
||||
)
|
||||
|
||||
|
||||
# mypy: allow-incomplete-defs, allow-untyped-calls, allow-untyped-defs
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
KEY_OPEN_CLOSE = "open_close"
|
||||
@ -76,13 +80,25 @@ class CoverGroup(CoverDevice):
|
||||
self._assumed_state = True
|
||||
|
||||
self._entities = entities
|
||||
self._covers = {KEY_OPEN_CLOSE: set(), KEY_STOP: set(), KEY_POSITION: set()}
|
||||
self._tilts = {KEY_OPEN_CLOSE: set(), KEY_STOP: set(), KEY_POSITION: set()}
|
||||
self._covers: Dict[str, Set[str]] = {
|
||||
KEY_OPEN_CLOSE: set(),
|
||||
KEY_STOP: set(),
|
||||
KEY_POSITION: set(),
|
||||
}
|
||||
self._tilts: Dict[str, Set[str]] = {
|
||||
KEY_OPEN_CLOSE: set(),
|
||||
KEY_STOP: set(),
|
||||
KEY_POSITION: set(),
|
||||
}
|
||||
|
||||
@callback
|
||||
def update_supported_features(
|
||||
self, entity_id, old_state, new_state, update_state=True
|
||||
):
|
||||
self,
|
||||
entity_id: str,
|
||||
old_state: Optional[State],
|
||||
new_state: Optional[State],
|
||||
update_state: bool = True,
|
||||
) -> None:
|
||||
"""Update dictionaries with supported features."""
|
||||
if not new_state:
|
||||
for values in self._covers.values():
|
||||
|
@ -3,7 +3,7 @@ import asyncio
|
||||
from collections import Counter
|
||||
import itertools
|
||||
import logging
|
||||
from typing import Any, Callable, Iterator, List, Optional, Tuple
|
||||
from typing import Any, Callable, Iterator, List, Optional, Tuple, cast
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
@ -43,6 +43,9 @@ from homeassistant.components.light import (
|
||||
SUPPORT_WHITE_VALUE,
|
||||
)
|
||||
|
||||
|
||||
# mypy: allow-incomplete-defs, allow-untyped-calls, allow-untyped-defs
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DEFAULT_NAME = "Light Group"
|
||||
@ -69,7 +72,9 @@ async def async_setup_platform(
|
||||
hass: HomeAssistantType, config: ConfigType, async_add_entities, discovery_info=None
|
||||
) -> None:
|
||||
"""Initialize light.group platform."""
|
||||
async_add_entities([LightGroup(config.get(CONF_NAME), config[CONF_ENTITIES])])
|
||||
async_add_entities(
|
||||
[LightGroup(cast(str, config.get(CONF_NAME)), config[CONF_ENTITIES])]
|
||||
)
|
||||
|
||||
|
||||
class LightGroup(light.Light):
|
||||
@ -263,7 +268,7 @@ class LightGroup(light.Light):
|
||||
async def async_update(self):
|
||||
"""Query all members and determine the light group state."""
|
||||
all_states = [self.hass.states.get(x) for x in self._entity_ids]
|
||||
states = list(filter(None, all_states))
|
||||
states: List[State] = list(filter(None, all_states))
|
||||
on_states = [state for state in states if state.state == STATE_ON]
|
||||
|
||||
self._is_on = len(on_states) > 0
|
||||
|
@ -17,6 +17,9 @@ from homeassistant.components.notify import (
|
||||
BaseNotificationService,
|
||||
)
|
||||
|
||||
|
||||
# mypy: allow-untyped-calls, allow-untyped-defs
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
CONF_SERVICES = "services"
|
||||
|
@ -7,6 +7,7 @@ import functools as ft
|
||||
import hashlib
|
||||
import logging
|
||||
from random import SystemRandom
|
||||
from typing import Optional
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from aiohttp import web
|
||||
@ -347,7 +348,7 @@ async def async_unload_entry(hass, entry):
|
||||
class MediaPlayerDevice(Entity):
|
||||
"""ABC for media player devices."""
|
||||
|
||||
_access_token = None
|
||||
_access_token: Optional[str] = None
|
||||
|
||||
# Implement these for your media player
|
||||
@property
|
||||
@ -356,7 +357,7 @@ class MediaPlayerDevice(Entity):
|
||||
return None
|
||||
|
||||
@property
|
||||
def access_token(self):
|
||||
def access_token(self) -> str:
|
||||
"""Access token for this media player."""
|
||||
if self._access_token is None:
|
||||
self._access_token = hashlib.sha256(
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""Support for displaying persistent notifications."""
|
||||
from collections import OrderedDict
|
||||
import logging
|
||||
from typing import Awaitable
|
||||
from typing import Any, Mapping, MutableMapping, Optional
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
@ -14,6 +14,9 @@ from homeassistant.loader import bind_hass
|
||||
from homeassistant.util import slugify
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
||||
|
||||
# mypy: allow-untyped-calls, allow-untyped-defs
|
||||
|
||||
ATTR_CREATED_AT = "created_at"
|
||||
ATTR_MESSAGE = "message"
|
||||
ATTR_NOTIFICATION_ID = "notification_id"
|
||||
@ -70,7 +73,10 @@ def dismiss(hass, notification_id):
|
||||
@callback
|
||||
@bind_hass
|
||||
def async_create(
|
||||
hass: HomeAssistant, message: str, title: str = None, notification_id: str = None
|
||||
hass: HomeAssistant,
|
||||
message: str,
|
||||
title: Optional[str] = None,
|
||||
notification_id: Optional[str] = None,
|
||||
) -> None:
|
||||
"""Generate a notification."""
|
||||
data = {
|
||||
@ -95,9 +101,9 @@ def async_dismiss(hass: HomeAssistant, notification_id: str) -> None:
|
||||
hass.async_create_task(hass.services.async_call(DOMAIN, SERVICE_DISMISS, data))
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: dict) -> Awaitable[bool]:
|
||||
async def async_setup(hass: HomeAssistant, config: dict) -> bool:
|
||||
"""Set up the persistent notification component."""
|
||||
persistent_notifications = OrderedDict()
|
||||
persistent_notifications: MutableMapping[str, MutableMapping] = OrderedDict()
|
||||
hass.data[DOMAIN] = {"notifications": persistent_notifications}
|
||||
|
||||
@callback
|
||||
@ -201,8 +207,10 @@ async def async_setup(hass: HomeAssistant, config: dict) -> Awaitable[bool]:
|
||||
|
||||
@callback
|
||||
def websocket_get_notifications(
|
||||
hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg
|
||||
):
|
||||
hass: HomeAssistant,
|
||||
connection: websocket_api.ActiveConnection,
|
||||
msg: Mapping[str, Any],
|
||||
) -> None:
|
||||
"""Return a list of persistent_notifications."""
|
||||
connection.send_message(
|
||||
websocket_api.result_message(
|
||||
|
@ -17,6 +17,9 @@ from homeassistant.helpers.sun import (
|
||||
)
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
|
||||
# mypy: allow-untyped-calls, allow-untyped-defs
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DOMAIN = "sun"
|
||||
|
@ -4,6 +4,9 @@ from homeassistant.loader import bind_hass
|
||||
|
||||
from . import commands, connection, const, decorators, http, messages
|
||||
|
||||
|
||||
# mypy: allow-untyped-calls, allow-untyped-defs
|
||||
|
||||
DOMAIN = const.DOMAIN
|
||||
|
||||
DEPENDENCIES = ("http",)
|
||||
|
@ -2,6 +2,7 @@
|
||||
import voluptuous as vol
|
||||
from voluptuous.humanize import humanize_error
|
||||
|
||||
from homeassistant.auth.models import RefreshToken, User
|
||||
from homeassistant.auth.providers import legacy_api_password
|
||||
from homeassistant.components.http.ban import process_wrong_login, process_success_login
|
||||
from homeassistant.const import __version__
|
||||
@ -9,6 +10,9 @@ from homeassistant.const import __version__
|
||||
from .connection import ActiveConnection
|
||||
from .error import Disconnect
|
||||
|
||||
|
||||
# mypy: allow-untyped-calls, allow-untyped-defs
|
||||
|
||||
TYPE_AUTH = "auth"
|
||||
TYPE_AUTH_INVALID = "auth_invalid"
|
||||
TYPE_AUTH_OK = "auth_ok"
|
||||
@ -87,7 +91,9 @@ class AuthPhase:
|
||||
await process_wrong_login(self._request)
|
||||
raise Disconnect
|
||||
|
||||
async def _async_finish_auth(self, user, refresh_token) -> ActiveConnection:
|
||||
async def _async_finish_auth(
|
||||
self, user: User, refresh_token: RefreshToken
|
||||
) -> ActiveConnection:
|
||||
"""Create an active connection."""
|
||||
self._logger.debug("Auth OK")
|
||||
await process_success_login(self._request)
|
||||
|
@ -12,6 +12,9 @@ from homeassistant.helpers.event import async_track_state_change
|
||||
from . import const, decorators, messages
|
||||
|
||||
|
||||
# mypy: allow-untyped-calls, allow-untyped-defs
|
||||
|
||||
|
||||
@callback
|
||||
def async_register_commands(hass, async_reg):
|
||||
"""Register commands."""
|
||||
|
@ -1,5 +1,7 @@
|
||||
"""Connection session."""
|
||||
import asyncio
|
||||
from typing import Any, Callable, Dict, Hashable
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.core import callback, Context
|
||||
@ -8,6 +10,9 @@ from homeassistant.exceptions import Unauthorized
|
||||
from . import const, messages
|
||||
|
||||
|
||||
# mypy: allow-untyped-calls, allow-untyped-defs
|
||||
|
||||
|
||||
class ActiveConnection:
|
||||
"""Handle an active websocket client connection."""
|
||||
|
||||
@ -22,7 +27,7 @@ class ActiveConnection:
|
||||
else:
|
||||
self.refresh_token_id = None
|
||||
|
||||
self.subscriptions = {}
|
||||
self.subscriptions: Dict[Hashable, Callable[[], Any]] = {}
|
||||
self.last_id = 0
|
||||
|
||||
def context(self, msg):
|
||||
|
@ -8,6 +8,8 @@ from homeassistant.exceptions import Unauthorized
|
||||
from . import messages
|
||||
|
||||
|
||||
# mypy: allow-untyped-calls, allow-untyped-defs
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
@ -25,6 +25,9 @@ from .error import Disconnect
|
||||
from .messages import error_message
|
||||
|
||||
|
||||
# mypy: allow-untyped-calls, allow-untyped-defs
|
||||
|
||||
|
||||
class WebsocketAPIView(HomeAssistantView):
|
||||
"""View to serve a websockets endpoint."""
|
||||
|
||||
@ -45,7 +48,7 @@ class WebSocketHandler:
|
||||
self.hass = hass
|
||||
self.request = request
|
||||
self.wsock = None
|
||||
self._to_write = asyncio.Queue(maxsize=MAX_PENDING_MSG)
|
||||
self._to_write: asyncio.Queue = asyncio.Queue(maxsize=MAX_PENDING_MSG)
|
||||
self._handle_task = None
|
||||
self._writer_task = None
|
||||
self._logger = logging.getLogger("{}.connection.{}".format(__name__, id(self)))
|
||||
@ -106,7 +109,7 @@ class WebSocketHandler:
|
||||
# Py3.7+
|
||||
if hasattr(asyncio, "current_task"):
|
||||
# pylint: disable=no-member
|
||||
self._handle_task = asyncio.current_task()
|
||||
self._handle_task = asyncio.current_task() # type: ignore
|
||||
else:
|
||||
self._handle_task = asyncio.Task.current_task()
|
||||
|
||||
@ -144,13 +147,13 @@ class WebSocketHandler:
|
||||
raise Disconnect
|
||||
|
||||
try:
|
||||
msg = msg.json()
|
||||
msg_data = msg.json()
|
||||
except ValueError:
|
||||
disconnect_warn = "Received invalid JSON."
|
||||
raise Disconnect
|
||||
|
||||
self._logger.debug("Received %s", msg)
|
||||
connection = await auth.async_handle(msg)
|
||||
self._logger.debug("Received %s", msg_data)
|
||||
connection = await auth.async_handle(msg_data)
|
||||
self.hass.data[DATA_CONNECTIONS] = (
|
||||
self.hass.data.get(DATA_CONNECTIONS, 0) + 1
|
||||
)
|
||||
@ -170,13 +173,13 @@ class WebSocketHandler:
|
||||
break
|
||||
|
||||
try:
|
||||
msg = msg.json()
|
||||
msg_data = msg.json()
|
||||
except ValueError:
|
||||
disconnect_warn = "Received invalid JSON."
|
||||
break
|
||||
|
||||
self._logger.debug("Received %s", msg)
|
||||
connection.async_handle(msg)
|
||||
self._logger.debug("Received %s", msg_data)
|
||||
connection.async_handle(msg_data)
|
||||
|
||||
except asyncio.CancelledError:
|
||||
self._logger.info("Connection closed by client")
|
||||
|
@ -7,6 +7,8 @@ from homeassistant.helpers import config_validation as cv
|
||||
from . import const
|
||||
|
||||
|
||||
# mypy: allow-untyped-defs
|
||||
|
||||
# Minimal requirements of a message
|
||||
MINIMAL_MESSAGE_SCHEMA = vol.Schema(
|
||||
{vol.Required("id"): cv.positive_int, vol.Required("type"): cv.string},
|
||||
|
@ -10,6 +10,9 @@ from .const import (
|
||||
)
|
||||
|
||||
|
||||
# mypy: allow-untyped-calls, allow-untyped-defs
|
||||
|
||||
|
||||
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
|
||||
"""Set up the API streams platform."""
|
||||
entity = APICount()
|
||||
|
@ -1,9 +1,10 @@
|
||||
"""Support for the definition of zones."""
|
||||
import logging
|
||||
from typing import Set, cast
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.core import callback, State
|
||||
from homeassistant.loader import bind_hass
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.const import (
|
||||
@ -25,6 +26,9 @@ from .config_flow import configured_zones
|
||||
from .const import CONF_PASSIVE, DOMAIN, HOME_ZONE, ATTR_PASSIVE, ATTR_RADIUS
|
||||
from .zone import Zone
|
||||
|
||||
|
||||
# mypy: allow-untyped-calls, allow-untyped-defs
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DEFAULT_NAME = "Unnamed zone"
|
||||
@ -78,10 +82,11 @@ def async_active_zone(hass, latitude, longitude, radius=0):
|
||||
)
|
||||
|
||||
within_zone = zone_dist - radius < zone.attributes[ATTR_RADIUS]
|
||||
closer_zone = closest is None or zone_dist < min_dist
|
||||
closer_zone = closest is None or zone_dist < min_dist # type: ignore
|
||||
smaller_zone = (
|
||||
zone_dist == min_dist
|
||||
and zone.attributes[ATTR_RADIUS] < closest.attributes[ATTR_RADIUS]
|
||||
and zone.attributes[ATTR_RADIUS]
|
||||
< cast(State, closest).attributes[ATTR_RADIUS]
|
||||
)
|
||||
|
||||
if within_zone and (closer_zone or smaller_zone):
|
||||
@ -94,7 +99,7 @@ def async_active_zone(hass, latitude, longitude, radius=0):
|
||||
async def async_setup(hass, config):
|
||||
"""Set up configured zones as well as home assistant zone if necessary."""
|
||||
hass.data[DOMAIN] = {}
|
||||
entities = set()
|
||||
entities: Set[str] = set()
|
||||
zone_entries = configured_zones(hass)
|
||||
for _, entry in config_per_platform(config, DOMAIN):
|
||||
if slugify(entry[CONF_NAME]) not in zone_entries:
|
||||
|
@ -1,5 +1,7 @@
|
||||
"""Config flow to configure zone component."""
|
||||
|
||||
from typing import Set
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
@ -12,17 +14,23 @@ from homeassistant.const import (
|
||||
CONF_RADIUS,
|
||||
)
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.typing import HomeAssistantType
|
||||
from homeassistant.util import slugify
|
||||
|
||||
from .const import CONF_PASSIVE, DOMAIN, HOME_ZONE
|
||||
|
||||
|
||||
# mypy: allow-untyped-defs
|
||||
|
||||
|
||||
@callback
|
||||
def configured_zones(hass):
|
||||
def configured_zones(hass: HomeAssistantType) -> Set[str]:
|
||||
"""Return a set of the configured zones."""
|
||||
return set(
|
||||
(slugify(entry.data[CONF_NAME]))
|
||||
for entry in hass.config_entries.async_entries(DOMAIN)
|
||||
for entry in (
|
||||
hass.config_entries.async_entries(DOMAIN) if hass.config_entries else []
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
@ -1,5 +1,9 @@
|
||||
"""Zone entity and functionality."""
|
||||
|
||||
from typing import cast
|
||||
|
||||
from homeassistant.const import ATTR_HIDDEN, ATTR_LATITUDE, ATTR_LONGITUDE
|
||||
from homeassistant.core import State
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.util.location import distance
|
||||
|
||||
@ -8,7 +12,10 @@ from .const import ATTR_PASSIVE, ATTR_RADIUS
|
||||
STATE = "zoning"
|
||||
|
||||
|
||||
def in_zone(zone, latitude, longitude, radius=0) -> bool:
|
||||
# mypy: allow-untyped-defs
|
||||
|
||||
|
||||
def in_zone(zone: State, latitude: float, longitude: float, radius: float = 0) -> bool:
|
||||
"""Test if given latitude, longitude is in given zone.
|
||||
|
||||
Async friendly.
|
||||
@ -20,7 +27,9 @@ def in_zone(zone, latitude, longitude, radius=0) -> bool:
|
||||
zone.attributes[ATTR_LONGITUDE],
|
||||
)
|
||||
|
||||
return zone_dist - radius < zone.attributes[ATTR_RADIUS]
|
||||
if zone_dist is None or zone.attributes[ATTR_RADIUS] is None:
|
||||
return False
|
||||
return zone_dist - radius < cast(float, zone.attributes[ATTR_RADIUS])
|
||||
|
||||
|
||||
class Zone(Entity):
|
||||
|
@ -28,6 +28,7 @@ from typing import (
|
||||
Set,
|
||||
TYPE_CHECKING,
|
||||
Awaitable,
|
||||
Mapping,
|
||||
)
|
||||
|
||||
from async_timeout import timeout
|
||||
@ -704,7 +705,7 @@ class State:
|
||||
self,
|
||||
entity_id: str,
|
||||
state: str,
|
||||
attributes: Optional[Dict] = None,
|
||||
attributes: Optional[Mapping] = None,
|
||||
last_changed: Optional[datetime.datetime] = None,
|
||||
last_updated: Optional[datetime.datetime] = None,
|
||||
context: Optional[Context] = None,
|
||||
|
@ -170,7 +170,7 @@ class FlowHandler:
|
||||
# Set by flow manager
|
||||
flow_id: Optional[str] = None
|
||||
hass: Optional[HomeAssistant] = None
|
||||
handler = None
|
||||
handler: Optional[Hashable] = None
|
||||
cur_step: Optional[Dict[str, str]] = None
|
||||
context: Dict
|
||||
|
||||
@ -188,7 +188,7 @@ class FlowHandler:
|
||||
data_schema: vol.Schema = None,
|
||||
errors: Optional[Dict] = None,
|
||||
description_placeholders: Optional[Dict] = None,
|
||||
) -> Dict:
|
||||
) -> Dict[str, Any]:
|
||||
"""Return the definition of a form to gather user input."""
|
||||
return {
|
||||
"type": RESULT_TYPE_FORM,
|
||||
@ -208,7 +208,7 @@ class FlowHandler:
|
||||
data: Dict,
|
||||
description: Optional[str] = None,
|
||||
description_placeholders: Optional[Dict] = None,
|
||||
) -> Dict:
|
||||
) -> Dict[str, Any]:
|
||||
"""Finish config flow and create a config entry."""
|
||||
return {
|
||||
"version": self.VERSION,
|
||||
@ -224,7 +224,7 @@ class FlowHandler:
|
||||
@callback
|
||||
def async_abort(
|
||||
self, *, reason: str, description_placeholders: Optional[Dict] = None
|
||||
) -> Dict:
|
||||
) -> Dict[str, Any]:
|
||||
"""Abort the config flow."""
|
||||
return {
|
||||
"type": RESULT_TYPE_ABORT,
|
||||
@ -237,7 +237,7 @@ class FlowHandler:
|
||||
@callback
|
||||
def async_external_step(
|
||||
self, *, step_id: str, url: str, description_placeholders: Optional[Dict] = None
|
||||
) -> Dict:
|
||||
) -> Dict[str, Any]:
|
||||
"""Return the definition of an external step for the user to take."""
|
||||
return {
|
||||
"type": RESULT_TYPE_EXTERNAL_STEP,
|
||||
@ -249,7 +249,7 @@ class FlowHandler:
|
||||
}
|
||||
|
||||
@callback
|
||||
def async_external_step_done(self, *, next_step_id: str) -> Dict:
|
||||
def async_external_step_done(self, *, next_step_id: str) -> Dict[str, Any]:
|
||||
"""Return the definition of an external step for the user to take."""
|
||||
return {
|
||||
"type": RESULT_TYPE_EXTERNAL_STEP_DONE,
|
||||
|
@ -1,5 +1,7 @@
|
||||
"""An abstract class for entities."""
|
||||
from datetime import timedelta
|
||||
|
||||
import asyncio
|
||||
from datetime import datetime, timedelta
|
||||
import logging
|
||||
import functools as ft
|
||||
from timeit import default_timer as timer
|
||||
@ -22,6 +24,7 @@ from homeassistant.const import (
|
||||
ATTR_SUPPORTED_FEATURES,
|
||||
ATTR_DEVICE_CLASS,
|
||||
)
|
||||
from homeassistant.helpers.entity_platform import EntityPlatform
|
||||
from homeassistant.helpers.entity_registry import (
|
||||
EVENT_ENTITY_REGISTRY_UPDATED,
|
||||
RegistryEntry,
|
||||
@ -94,7 +97,7 @@ class Entity:
|
||||
hass: Optional[HomeAssistant] = None
|
||||
|
||||
# Owning platform instance. Will be set by EntityPlatform
|
||||
platform = None
|
||||
platform: Optional[EntityPlatform] = None
|
||||
|
||||
# If we reported if this entity was slow
|
||||
_slow_reported = False
|
||||
@ -106,7 +109,7 @@ class Entity:
|
||||
_update_staged = False
|
||||
|
||||
# Process updates in parallel
|
||||
parallel_updates = None
|
||||
parallel_updates: Optional[asyncio.Semaphore] = None
|
||||
|
||||
# Entry in the entity registry
|
||||
registry_entry: Optional[RegistryEntry] = None
|
||||
@ -115,8 +118,8 @@ class Entity:
|
||||
_on_remove: Optional[List[CALLBACK_TYPE]] = None
|
||||
|
||||
# Context
|
||||
_context = None
|
||||
_context_set = None
|
||||
_context: Optional[Context] = None
|
||||
_context_set: Optional[datetime] = None
|
||||
|
||||
@property
|
||||
def should_poll(self) -> bool:
|
||||
|
@ -124,7 +124,7 @@ class IntentHandler:
|
||||
|
||||
intent_type: Optional[str] = None
|
||||
slot_schema: Optional[vol.Schema] = None
|
||||
_slot_schema = None
|
||||
_slot_schema: Optional[vol.Schema] = None
|
||||
platforms: Optional[Iterable[str]] = []
|
||||
|
||||
@callback
|
||||
|
6
mypyrc
6
mypyrc
@ -6,8 +6,10 @@ homeassistant/components/binary_sensor/
|
||||
homeassistant/components/calendar/
|
||||
homeassistant/components/camera/
|
||||
homeassistant/components/cover/
|
||||
homeassistant/components/device_automation/
|
||||
homeassistant/components/frontend/
|
||||
homeassistant/components/geo_location/
|
||||
homeassistant/components/group/
|
||||
homeassistant/components/history/
|
||||
homeassistant/components/http/
|
||||
homeassistant/components/image_processing/
|
||||
@ -17,16 +19,20 @@ homeassistant/components/lock/
|
||||
homeassistant/components/mailbox/
|
||||
homeassistant/components/media_player/
|
||||
homeassistant/components/notify/
|
||||
homeassistant/components/persistent_notification/
|
||||
homeassistant/components/proximity/
|
||||
homeassistant/components/remote/
|
||||
homeassistant/components/scene/
|
||||
homeassistant/components/sensor/
|
||||
homeassistant/components/sun/
|
||||
homeassistant/components/switch/
|
||||
homeassistant/components/systemmonitor/
|
||||
homeassistant/components/tts/
|
||||
homeassistant/components/vacuum/
|
||||
homeassistant/components/water_heater/
|
||||
homeassistant/components/weather/
|
||||
homeassistant/components/websocket_api/
|
||||
homeassistant/components/zone/
|
||||
homeassistant/helpers/
|
||||
homeassistant/scripts/
|
||||
homeassistant/util/
|
||||
|
Loading…
x
Reference in New Issue
Block a user