From 24d2261060aa5b43600a13f0f6401e54ecbffc69 Mon Sep 17 00:00:00 2001 From: Andrey Date: Wed, 18 Jul 2018 01:28:44 +0300 Subject: [PATCH] Add check_untyped_defs (#15510) * Add check_untyped_defs * Change to regular if-else --- homeassistant/__main__.py | 4 ++-- homeassistant/bootstrap.py | 2 +- homeassistant/config.py | 8 ++++--- homeassistant/config_entries.py | 3 ++- homeassistant/core.py | 35 ++++++++++++++++++------------- homeassistant/data_entry_flow.py | 4 ++-- homeassistant/monkey_patch.py | 4 ++-- homeassistant/setup.py | 5 +++-- homeassistant/util/__init__.py | 9 ++++---- homeassistant/util/async_.py | 14 +++++++++---- homeassistant/util/location.py | 10 +++++++-- homeassistant/util/logging.py | 2 +- homeassistant/util/unit_system.py | 3 ++- homeassistant/util/yaml.py | 2 +- mypy.ini | 9 ++++---- 15 files changed, 70 insertions(+), 44 deletions(-) diff --git a/homeassistant/__main__.py b/homeassistant/__main__.py index 496308598dc..32e26ad7f7b 100644 --- a/homeassistant/__main__.py +++ b/homeassistant/__main__.py @@ -282,9 +282,9 @@ def setup_and_run_hass(config_dir: str, def open_browser(event): """Open the webinterface in a browser.""" - if hass.config.api is not None: + if hass.config.api is not None: # type: ignore import webbrowser - webbrowser.open(hass.config.api.base_url) + webbrowser.open(hass.config.api.base_url) # type: ignore run_callback_threadsafe( hass.loop, diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index a190aea9fa8..d832dda4754 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -293,7 +293,7 @@ def async_enable_logging(hass: core.HomeAssistant, async def async_stop_async_handler(event): """Cleanup async handler.""" - logging.getLogger('').removeHandler(async_handler) + logging.getLogger('').removeHandler(async_handler) # type: ignore await async_handler.async_close(blocking=True) hass.bus.async_listen_once( diff --git a/homeassistant/config.py b/homeassistant/config.py index d9206d62250..230a10498f3 100644 --- a/homeassistant/config.py +++ b/homeassistant/config.py @@ -653,7 +653,7 @@ def async_process_component_config(hass, config, domain): if hasattr(component, 'CONFIG_SCHEMA'): try: - config = component.CONFIG_SCHEMA(config) + config = component.CONFIG_SCHEMA(config) # type: ignore except vol.Invalid as ex: async_log_exception(ex, domain, config, hass) return None @@ -663,7 +663,8 @@ def async_process_component_config(hass, config, domain): for p_name, p_config in config_per_platform(config, domain): # Validate component specific platform schema try: - p_validated = component.PLATFORM_SCHEMA(p_config) + p_validated = component.PLATFORM_SCHEMA( # type: ignore + p_config) except vol.Invalid as ex: async_log_exception(ex, domain, config, hass) continue @@ -684,7 +685,8 @@ def async_process_component_config(hass, config, domain): if hasattr(platform, 'PLATFORM_SCHEMA'): # pylint: disable=no-member try: - p_validated = platform.PLATFORM_SCHEMA(p_validated) + p_validated = platform.PLATFORM_SCHEMA( # type: ignore + p_validated) except vol.Invalid as ex: async_log_exception(ex, '{}.{}'.format(domain, p_name), p_validated, hass) diff --git a/homeassistant/config_entries.py b/homeassistant/config_entries.py index 2e5613057f1..0fc66174c66 100644 --- a/homeassistant/config_entries.py +++ b/homeassistant/config_entries.py @@ -113,6 +113,7 @@ the flow from the config panel. import logging import uuid +from typing import Set # noqa pylint: disable=unused-import from homeassistant import data_entry_flow from homeassistant.core import callback @@ -279,7 +280,7 @@ class ConfigEntries: @callback def async_domains(self): """Return domains for which we have entries.""" - seen = set() + seen = set() # type: Set[ConfigEntry] result = [] for entry in self._entries: diff --git a/homeassistant/core.py b/homeassistant/core.py index 8b534bf1731..bfc3aed194f 100644 --- a/homeassistant/core.py +++ b/homeassistant/core.py @@ -18,7 +18,8 @@ from time import monotonic from types import MappingProxyType from typing import ( # NOQA - Optional, Any, Callable, List, TypeVar, Dict, Coroutine) + Optional, Any, Callable, List, TypeVar, Dict, Coroutine, Set, + TYPE_CHECKING) from async_timeout import timeout import voluptuous as vol @@ -42,6 +43,11 @@ import homeassistant.util.dt as dt_util import homeassistant.util.location as location from homeassistant.util.unit_system import UnitSystem, METRIC_SYSTEM # NOQA +# Typing imports that create a circular dependency +# pylint: disable=using-constant-test,unused-import +if TYPE_CHECKING: + from homeassistant.config_entries import ConfigEntries # noqa + T = TypeVar('T') DOMAIN = 'homeassistant' @@ -93,7 +99,8 @@ def async_loop_exception_handler(loop, context): kwargs['exc_info'] = (type(exception), exception, exception.__traceback__) - _LOGGER.error("Error doing job: %s", context['message'], **kwargs) + _LOGGER.error( # type: ignore + "Error doing job: %s", context['message'], **kwargs) class CoreState(enum.Enum): @@ -126,7 +133,7 @@ class HomeAssistant(object): self.executor = ThreadPoolExecutor(**executor_opts) self.loop.set_default_executor(self.executor) self.loop.set_exception_handler(async_loop_exception_handler) - self._pending_tasks = [] + self._pending_tasks = [] # type: list self._track_task = True self.bus = EventBus(self) self.services = ServiceRegistry(self) @@ -135,10 +142,10 @@ class HomeAssistant(object): self.components = loader.Components(self) self.helpers = loader.Helpers(self) # This is a dictionary that any component can store any data on. - self.data = {} + self.data = {} # type: dict self.state = CoreState.not_running self.exit_code = 0 # type: int - self.config_entries = None + self.config_entries = None # type: Optional[ConfigEntries] @property def is_running(self) -> bool: @@ -217,7 +224,7 @@ class HomeAssistant(object): task = None if asyncio.iscoroutine(target): - task = self.loop.create_task(target) + task = self.loop.create_task(target) # type: ignore elif is_callback(target): self.loop.call_soon(target, *args) elif asyncio.iscoroutinefunction(target): @@ -252,7 +259,7 @@ class HomeAssistant(object): target: Callable[..., Any], *args: Any) -> asyncio.Future: """Add an executor job from within the event loop.""" - task = self.loop.run_in_executor( + task = self.loop.run_in_executor( # type: ignore None, target, *args) # type: asyncio.Future # If a task is scheduled @@ -652,7 +659,7 @@ class StateMachine(object): def __init__(self, bus, loop): """Initialize state machine.""" - self._states = {} + self._states = {} # type: Dict[str, State] self._bus = bus self._loop = loop @@ -819,7 +826,7 @@ class ServiceRegistry(object): def __init__(self, hass): """Initialize a service registry.""" - self._services = {} + self._services = {} # type: Dict[str, Dict[str, Service]] self._hass = hass self._async_unsub_call_event = None @@ -971,7 +978,7 @@ class ServiceRegistry(object): } if blocking: - fut = asyncio.Future(loop=self._hass.loop) + fut = asyncio.Future(loop=self._hass.loop) # type: asyncio.Future @callback def service_executed(event): @@ -1064,18 +1071,18 @@ class Config(object): self.skip_pip = False # type: bool # List of loaded components - self.components = set() + self.components = set() # type: set # Remote.API object pointing at local API self.api = None # Directory that holds the configuration - self.config_dir = None + self.config_dir = None # type: Optional[str] # List of allowed external dirs to access - self.whitelist_external_dirs = set() + self.whitelist_external_dirs = set() # type: Set[str] - def distance(self, lat: float, lon: float) -> float: + def distance(self, lat: float, lon: float) -> Optional[float]: """Calculate distance from Home Assistant. Async friendly. diff --git a/homeassistant/data_entry_flow.py b/homeassistant/data_entry_flow.py index e51ba4d9718..24dcb46bb68 100644 --- a/homeassistant/data_entry_flow.py +++ b/homeassistant/data_entry_flow.py @@ -1,7 +1,7 @@ """Classes to help gather user submissions.""" import logging import uuid - +from typing import Dict, Any # noqa pylint: disable=unused-import from .core import callback from .exceptions import HomeAssistantError @@ -38,7 +38,7 @@ class FlowManager: def __init__(self, hass, async_create_flow, async_finish_flow): """Initialize the flow manager.""" self.hass = hass - self._progress = {} + self._progress = {} # type: Dict[str, Any] self._async_create_flow = async_create_flow self._async_finish_flow = async_finish_flow diff --git a/homeassistant/monkey_patch.py b/homeassistant/monkey_patch.py index d5c629c9d34..17329fbddff 100644 --- a/homeassistant/monkey_patch.py +++ b/homeassistant/monkey_patch.py @@ -34,7 +34,7 @@ def patch_weakref_tasks(): """No-op add.""" return - asyncio.tasks.Task._all_tasks = IgnoreCalls() + asyncio.tasks.Task._all_tasks = IgnoreCalls() # type: ignore try: del asyncio.tasks.Task.__del__ except: # noqa: E722 @@ -63,7 +63,7 @@ def disable_c_asyncio(): if fullname == self.PATH_TRIGGER: # We lint in Py35, exception is introduced in Py36 # pylint: disable=undefined-variable - raise ModuleNotFoundError() # noqa + raise ModuleNotFoundError() # type: ignore # noqa return None sys.path_hooks.append(AsyncioImportFinder) diff --git a/homeassistant/setup.py b/homeassistant/setup.py index 478320dca27..45482d5d14e 100644 --- a/homeassistant/setup.py +++ b/homeassistant/setup.py @@ -163,8 +163,9 @@ async def _async_setup_component(hass: core.HomeAssistant, loader.set_component(hass, domain, None) return False - for entry in hass.config_entries.async_entries(domain): - await entry.async_setup(hass, component=component) + if hass.config_entries: + for entry in hass.config_entries.async_entries(domain): + await entry.async_setup(hass, component=component) hass.config.components.add(component.DOMAIN) # type: ignore diff --git a/homeassistant/util/__init__.py b/homeassistant/util/__init__.py index bbf0f7e11e2..c52bfa584da 100644 --- a/homeassistant/util/__init__.py +++ b/homeassistant/util/__init__.py @@ -13,7 +13,8 @@ from functools import wraps from types import MappingProxyType from unicodedata import normalize -from typing import Any, Optional, TypeVar, Callable, KeysView, Union, Iterable +from typing import (Any, Optional, TypeVar, Callable, KeysView, Union, # noqa + Iterable, List, Mapping) from .dt import as_local, utcnow @@ -150,9 +151,9 @@ class OrderedSet(MutableSet): def __init__(self, iterable=None): """Initialize the set.""" - self.end = end = [] - end += [None, end, end] # sentinel node for doubly linked list - self.map = {} # key --> [key, prev, next] + self.end = end = [] # type: List[Any] + end += [None, end, end] # sentinel node for doubly linked list + self.map = {} # type: Mapping[List, Any] # key --> [key, prev, next] if iterable is not None: self |= iterable diff --git a/homeassistant/util/async_.py b/homeassistant/util/async_.py index b3aa370da2e..334b4f45483 100644 --- a/homeassistant/util/async_.py +++ b/homeassistant/util/async_.py @@ -65,8 +65,14 @@ def _chain_future(source, destination): if not isinstance(destination, (Future, concurrent.futures.Future)): raise TypeError('A future is required for destination argument') # pylint: disable=protected-access - source_loop = source._loop if isinstance(source, Future) else None - dest_loop = destination._loop if isinstance(destination, Future) else None + if isinstance(source, Future): + source_loop = source._loop # type: ignore + else: + source_loop = None + if isinstance(destination, Future): + dest_loop = destination._loop # type: ignore + else: + dest_loop = None def _set_state(future, other): if isinstance(future, Future): @@ -102,7 +108,7 @@ def run_coroutine_threadsafe(coro, loop): if not coroutines.iscoroutine(coro): raise TypeError('A coroutine object is required') - future = concurrent.futures.Future() + future = concurrent.futures.Future() # type: concurrent.futures.Future def callback(): """Handle the call to the coroutine.""" @@ -150,7 +156,7 @@ def run_callback_threadsafe(loop, callback, *args): if ident is not None and ident == threading.get_ident(): raise RuntimeError('Cannot be called from within the event loop') - future = concurrent.futures.Future() + future = concurrent.futures.Future() # type: concurrent.futures.Future def run_callback(): """Run callback and store result.""" diff --git a/homeassistant/util/location.py b/homeassistant/util/location.py index e390b537d34..9fc87b24a9b 100644 --- a/homeassistant/util/location.py +++ b/homeassistant/util/location.py @@ -49,12 +49,18 @@ def detect_location_info(): return LocationInfo(**data) -def distance(lat1, lon1, lat2, lon2): +def distance(lat1: Optional[float], lon1: Optional[float], + lat2: float, lon2: float) -> Optional[float]: """Calculate the distance in meters between two points. Async friendly. """ - return vincenty((lat1, lon1), (lat2, lon2)) * 1000 + if lat1 is None or lon1 is None: + return None + result = vincenty((lat1, lon1), (lat2, lon2)) + if result is None: + return None + return result * 1000 def elevation(latitude, longitude): diff --git a/homeassistant/util/logging.py b/homeassistant/util/logging.py index 10b43445184..65999a3a5c7 100644 --- a/homeassistant/util/logging.py +++ b/homeassistant/util/logging.py @@ -29,7 +29,7 @@ class AsyncHandler(object): """Initialize async logging handler wrapper.""" self.handler = handler self.loop = loop - self._queue = asyncio.Queue(loop=loop) + self._queue = asyncio.Queue(loop=loop) # type: asyncio.Queue self._thread = threading.Thread(target=self._process) # Delegate from handler diff --git a/homeassistant/util/unit_system.py b/homeassistant/util/unit_system.py index 4cc0fff96b9..ec17c1b796b 100644 --- a/homeassistant/util/unit_system.py +++ b/homeassistant/util/unit_system.py @@ -1,6 +1,7 @@ """Unit system helper class and methods.""" import logging +from typing import Optional from numbers import Number from homeassistant.const import ( @@ -99,7 +100,7 @@ class UnitSystem(object): return temperature_util.convert(temperature, from_unit, self.temperature_unit) - def length(self, length: float, from_unit: str) -> float: + def length(self, length: Optional[float], from_unit: str) -> float: """Convert the given length to this unit system.""" if not isinstance(length, Number): raise TypeError('{} is not a numeric value.'.format(str(length))) diff --git a/homeassistant/util/yaml.py b/homeassistant/util/yaml.py index 298d52722a5..ddf7eb44601 100644 --- a/homeassistant/util/yaml.py +++ b/homeassistant/util/yaml.py @@ -311,7 +311,7 @@ yaml.SafeLoader.add_constructor('!include_dir_merge_named', # pylint: disable=redefined-outer-name def represent_odict(dump, tag, mapping, flow_style=None): """Like BaseRepresenter.represent_mapping but does not issue the sort().""" - value = [] + value = [] # type: list node = yaml.MappingNode(tag, value, flow_style=flow_style) if dump.alias_key is not None: dump.represented_objects[dump.alias_key] = node diff --git a/mypy.ini b/mypy.ini index 3970ea72d47..5a597994d6b 100644 --- a/mypy.ini +++ b/mypy.ini @@ -1,10 +1,11 @@ [mypy] -warn_redundant_casts = true -warn_unused_configs = true -ignore_missing_imports = true +check_untyped_defs = true follow_imports = silent -warn_unused_ignores = true +ignore_missing_imports = true +warn_redundant_casts = true warn_return_any = true +warn_unused_configs = true +warn_unused_ignores = true [mypy-homeassistant.util.yaml] warn_return_any = false