Various type hint improvements (#37952)

This commit is contained in:
Ville Skyttä 2020-07-22 18:06:37 +03:00 committed by GitHub
parent 3e2555e2c1
commit aa1c5fc43d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 30 additions and 27 deletions

View file

@ -7,7 +7,7 @@ from homeassistant.util.async_ import protect_loop
def enable() -> None: def enable() -> None:
"""Enable the detection of I/O in the event loop.""" """Enable the detection of I/O in the event loop."""
# Prevent urllib3 and requests doing I/O in event loop # Prevent urllib3 and requests doing I/O in event loop
HTTPConnection.putrequest = protect_loop(HTTPConnection.putrequest) HTTPConnection.putrequest = protect_loop(HTTPConnection.putrequest) # type: ignore
# Currently disabled. pytz doing I/O when getting timezone. # Currently disabled. pytz doing I/O when getting timezone.
# Prevent files being opened inside the event loop # Prevent files being opened inside the event loop

View file

@ -10,7 +10,7 @@ import weakref
import attr import attr
from homeassistant import data_entry_flow, loader from homeassistant import data_entry_flow, loader
from homeassistant.core import HomeAssistant, callback from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback
from homeassistant.exceptions import ConfigEntryNotReady, HomeAssistantError from homeassistant.exceptions import ConfigEntryNotReady, HomeAssistantError
from homeassistant.helpers import entity_registry from homeassistant.helpers import entity_registry
from homeassistant.helpers.event import Event from homeassistant.helpers.event import Event
@ -96,6 +96,9 @@ class OperationNotAllowed(ConfigError):
"""Raised when a config entry operation is not allowed.""" """Raised when a config entry operation is not allowed."""
UpdateListenerType = Callable[[HomeAssistant, "ConfigEntry"], Any]
class ConfigEntry: class ConfigEntry:
"""Hold a configuration entry.""" """Hold a configuration entry."""
@ -165,7 +168,7 @@ class ConfigEntry:
self.unique_id = unique_id self.unique_id = unique_id
# Listeners to call on update # Listeners to call on update
self.update_listeners: List = [] self.update_listeners: List[weakref.ReferenceType[UpdateListenerType]] = []
# Function to cancel a scheduled retry # Function to cancel a scheduled retry
self._async_cancel_retry_setup: Optional[Callable[[], Any]] = None self._async_cancel_retry_setup: Optional[Callable[[], Any]] = None
@ -398,11 +401,9 @@ class ConfigEntry:
) )
return False return False
def add_update_listener(self, listener: Callable) -> Callable: def add_update_listener(self, listener: UpdateListenerType) -> CALLBACK_TYPE:
"""Listen for when entry is updated. """Listen for when entry is updated.
Listener: Callback function(hass, entry)
Returns function to unlisten. Returns function to unlisten.
""" """
weak_listener = weakref.ref(listener) weak_listener = weakref.ref(listener)
@ -768,6 +769,7 @@ class ConfigEntries:
for listener_ref in entry.update_listeners: for listener_ref in entry.update_listeners:
listener = listener_ref() listener = listener_ref()
if listener is not None:
self.hass.async_create_task(listener(self.hass, entry)) self.hass.async_create_task(listener(self.hass, entry))
self._async_schedule_save() self._async_schedule_save()

View file

@ -2,7 +2,7 @@
from asyncio import Event from asyncio import Event
from collections import OrderedDict from collections import OrderedDict
import logging import logging
from typing import Iterable, MutableMapping, Optional, cast from typing import Dict, Iterable, List, MutableMapping, Optional, cast
import uuid import uuid
import attr import attr
@ -132,7 +132,7 @@ class AreaRegistry:
self._store.async_delay_save(self._data_to_save, SAVE_DELAY) self._store.async_delay_save(self._data_to_save, SAVE_DELAY)
@callback @callback
def _data_to_save(self) -> dict: def _data_to_save(self) -> Dict[str, List[Dict[str, Optional[str]]]]:
"""Return data of area registry to store in a file.""" """Return data of area registry to store in a file."""
data = {} data = {}

View file

@ -102,12 +102,12 @@ INCLUDE_EXCLUDE_FILTER_SCHEMA = vol.All(
) )
def _glob_to_re(glob: str) -> Pattern: def _glob_to_re(glob: str) -> Pattern[str]:
"""Translate and compile glob string into pattern.""" """Translate and compile glob string into pattern."""
return re.compile(fnmatch.translate(glob)) return re.compile(fnmatch.translate(glob))
def _test_against_patterns(patterns: List[Pattern], entity_id: str) -> bool: def _test_against_patterns(patterns: List[Pattern[str]], entity_id: str) -> bool:
"""Test entity against list of patterns, true if any match.""" """Test entity against list of patterns, true if any match."""
for pattern in patterns: for pattern in patterns:
if pattern.match(entity_id): if pattern.match(entity_id):

View file

@ -49,7 +49,7 @@ from homeassistant.helpers.service import (
CONF_SERVICE_DATA, CONF_SERVICE_DATA,
async_prepare_call_from_config, async_prepare_call_from_config,
) )
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType, TemplateVarsType
from homeassistant.util import slugify from homeassistant.util import slugify
from homeassistant.util.dt import utcnow from homeassistant.util.dt import utcnow
@ -134,7 +134,7 @@ class _ScriptRun:
self, self,
hass: HomeAssistant, hass: HomeAssistant,
script: "Script", script: "Script",
variables: Optional[Sequence], variables: TemplateVarsType,
context: Optional[Context], context: Optional[Context],
log_exceptions: bool, log_exceptions: bool,
) -> None: ) -> None:
@ -724,14 +724,16 @@ class Script:
self._referenced_entities = referenced self._referenced_entities = referenced
return referenced return referenced
def run(self, variables=None, context=None): def run(
self, variables: TemplateVarsType = None, context: Optional[Context] = None
) -> None:
"""Run script.""" """Run script."""
asyncio.run_coroutine_threadsafe( asyncio.run_coroutine_threadsafe(
self.async_run(variables, context), self._hass.loop self.async_run(variables, context), self._hass.loop
).result() ).result()
async def async_run( async def async_run(
self, variables: Optional[Sequence] = None, context: Optional[Context] = None self, variables: TemplateVarsType = None, context: Optional[Context] = None
) -> None: ) -> None:
"""Run script.""" """Run script."""
if self.is_running: if self.is_running:

View file

@ -95,8 +95,7 @@ class Store:
the second call will wait and return the result of the first call. the second call will wait and return the result of the first call.
""" """
if self._load_task is None: if self._load_task is None:
self._load_task = self.hass.async_add_job(self._async_load()) self._load_task = self.hass.async_create_task(self._async_load())
assert self._load_task is not None
return await self._load_task return await self._load_task

View file

@ -1,7 +1,7 @@
"""Helper to gather system info.""" """Helper to gather system info."""
import os import os
import platform import platform
from typing import Dict from typing import Any, Dict
from homeassistant.const import __version__ as current_version from homeassistant.const import __version__ as current_version
from homeassistant.loader import bind_hass from homeassistant.loader import bind_hass
@ -11,7 +11,7 @@ from .typing import HomeAssistantType
@bind_hass @bind_hass
async def async_get_system_info(hass: HomeAssistantType) -> Dict: async def async_get_system_info(hass: HomeAssistantType) -> Dict[str, Any]:
"""Return info about the system.""" """Return info about the system."""
info_object = { info_object = {
"installation_type": "Unknown", "installation_type": "Unknown",

View file

@ -37,7 +37,7 @@ else:
PolicyBase = asyncio.DefaultEventLoopPolicy # pylint: disable=invalid-name PolicyBase = asyncio.DefaultEventLoopPolicy # pylint: disable=invalid-name
class HassEventLoopPolicy(PolicyBase): class HassEventLoopPolicy(PolicyBase): # type: ignore
"""Event loop policy for Home Assistant.""" """Event loop policy for Home Assistant."""
def __init__(self, debug: bool) -> None: def __init__(self, debug: bool) -> None:
@ -48,11 +48,11 @@ class HassEventLoopPolicy(PolicyBase):
@property @property
def loop_name(self) -> str: def loop_name(self) -> str:
"""Return name of the loop.""" """Return name of the loop."""
return self._loop_factory.__name__ return self._loop_factory.__name__ # type: ignore
def new_event_loop(self): def new_event_loop(self) -> asyncio.AbstractEventLoop:
"""Get the event loop.""" """Get the event loop."""
loop = super().new_event_loop() loop: asyncio.AbstractEventLoop = super().new_event_loop()
loop.set_exception_handler(_async_loop_exception_handler) loop.set_exception_handler(_async_loop_exception_handler)
if self.debug: if self.debug:
loop.set_debug(True) loop.set_debug(True)
@ -68,14 +68,14 @@ class HassEventLoopPolicy(PolicyBase):
return loop return loop
# Copied from Python 3.9 source # Copied from Python 3.9 source
def _do_shutdown(future): def _do_shutdown(future: asyncio.Future) -> None:
try: try:
executor.shutdown(wait=True) executor.shutdown(wait=True)
loop.call_soon_threadsafe(future.set_result, None) loop.call_soon_threadsafe(future.set_result, None)
except Exception as ex: # pylint: disable=broad-except except Exception as ex: # pylint: disable=broad-except
loop.call_soon_threadsafe(future.set_exception, ex) loop.call_soon_threadsafe(future.set_exception, ex)
async def shutdown_default_executor(): async def shutdown_default_executor() -> None:
"""Schedule the shutdown of the default executor.""" """Schedule the shutdown of the default executor."""
future = loop.create_future() future = loop.create_future()
thread = threading.Thread(target=_do_shutdown, args=(future,)) thread = threading.Thread(target=_do_shutdown, args=(future,))
@ -85,7 +85,7 @@ class HassEventLoopPolicy(PolicyBase):
finally: finally:
thread.join() thread.join()
loop.shutdown_default_executor = shutdown_default_executor setattr(loop, "shutdown_default_executor", shutdown_default_executor)
return loop return loop

View file

@ -64,7 +64,7 @@ warn_incomplete_stub = true
warn_redundant_casts = true warn_redundant_casts = true
warn_unused_configs = true warn_unused_configs = true
[mypy-homeassistant.bootstrap,homeassistant.components,homeassistant.config_entries,homeassistant.config,homeassistant.const,homeassistant.core,homeassistant.data_entry_flow,homeassistant.exceptions,homeassistant.loader,homeassistant.__main__,homeassistant.requirements,homeassistant.setup,homeassistant.util,homeassistant.auth.*,homeassistant.components.automation.*,homeassistant.components.binary_sensor.*,homeassistant.components.calendar.*,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.*,homeassistant.components.integration.*,homeassistant.components.light.*,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.*] [mypy-homeassistant.block_async_io,homeassistant.bootstrap,homeassistant.components,homeassistant.config_entries,homeassistant.config,homeassistant.const,homeassistant.core,homeassistant.data_entry_flow,homeassistant.exceptions,homeassistant.__init__,homeassistant.loader,homeassistant.__main__,homeassistant.requirements,homeassistant.runner,homeassistant.setup,homeassistant.util,homeassistant.auth.*,homeassistant.components.automation.*,homeassistant.components.binary_sensor.*,homeassistant.components.calendar.*,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.*,homeassistant.components.integration.*,homeassistant.components.light.*,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.*]
strict = true strict = true
ignore_errors = false ignore_errors = false
warn_unreachable = true warn_unreachable = true