From 9411fca955a4ba301b7b8b0741b018fcad27873a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Sun, 11 Nov 2018 18:39:50 +0200 Subject: [PATCH] Add more type hints to helpers (#18350) * Add type hints to helpers.entityfilter * Add type hints to helpers.deprecation --- homeassistant/helpers/deprecation.py | 13 +++++++------ homeassistant/helpers/entityfilter.py | 21 ++++++++++++--------- tox.ini | 2 +- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/homeassistant/helpers/deprecation.py b/homeassistant/helpers/deprecation.py index 8b621b2f01c..6ed7cbb9b51 100644 --- a/homeassistant/helpers/deprecation.py +++ b/homeassistant/helpers/deprecation.py @@ -1,9 +1,10 @@ """Deprecation helpers for Home Assistant.""" import inspect import logging +from typing import Any, Callable, Dict, Optional -def deprecated_substitute(substitute_name): +def deprecated_substitute(substitute_name: str) -> Callable[..., Callable]: """Help migrate properties to new names. When a property is added to replace an older property, this decorator can @@ -11,9 +12,9 @@ def deprecated_substitute(substitute_name): If the old property is defined, its value will be used instead, and a log warning will be issued alerting the user of the impending change. """ - def decorator(func): + def decorator(func: Callable) -> Callable: """Decorate function as deprecated.""" - def func_wrapper(self): + def func_wrapper(self: Callable) -> Any: """Wrap for the original function.""" if hasattr(self, substitute_name): # If this platform is still using the old property, issue @@ -28,8 +29,7 @@ def deprecated_substitute(substitute_name): substitute_name, substitute_name, func.__name__, inspect.getfile(self.__class__)) warnings[module_name] = True - # pylint: disable=protected-access - func._deprecated_substitute_warnings = warnings + setattr(func, '_deprecated_substitute_warnings', warnings) # Return the old property return getattr(self, substitute_name) @@ -38,7 +38,8 @@ def deprecated_substitute(substitute_name): return decorator -def get_deprecated(config, new_name, old_name, default=None): +def get_deprecated(config: Dict[str, Any], new_name: str, old_name: str, + default: Optional[Any] = None) -> Optional[Any]: """Allow an old config name to be deprecated with a replacement. If the new config isn't found, but the old one is, the old value is used diff --git a/homeassistant/helpers/entityfilter.py b/homeassistant/helpers/entityfilter.py index 141fc912275..7db577dfdc6 100644 --- a/homeassistant/helpers/entityfilter.py +++ b/homeassistant/helpers/entityfilter.py @@ -1,4 +1,5 @@ """Helper class to implement include/exclude of entities and domains.""" +from typing import Callable, Dict, Iterable import voluptuous as vol @@ -11,14 +12,14 @@ CONF_EXCLUDE_DOMAINS = 'exclude_domains' CONF_EXCLUDE_ENTITIES = 'exclude_entities' -def _convert_filter(config): +def _convert_filter(config: Dict[str, Iterable[str]]) -> Callable[[str], bool]: filt = generate_filter( config[CONF_INCLUDE_DOMAINS], config[CONF_INCLUDE_ENTITIES], config[CONF_EXCLUDE_DOMAINS], config[CONF_EXCLUDE_ENTITIES], ) - filt.config = config + setattr(filt, 'config', config) return filt @@ -33,8 +34,10 @@ FILTER_SCHEMA = vol.All( }), _convert_filter) -def generate_filter(include_domains, include_entities, - exclude_domains, exclude_entities): +def generate_filter(include_domains: Iterable[str], + include_entities: Iterable[str], + exclude_domains: Iterable[str], + exclude_entities: Iterable[str]) -> Callable[[str], bool]: """Return a function that will filter entities based on the args.""" include_d = set(include_domains) include_e = set(include_entities) @@ -50,7 +53,7 @@ def generate_filter(include_domains, include_entities, # Case 2 - includes, no excludes - only include specified entities if have_include and not have_exclude: - def entity_filter_2(entity_id): + def entity_filter_2(entity_id: str) -> bool: """Return filter function for case 2.""" domain = split_entity_id(entity_id)[0] return (entity_id in include_e or @@ -60,7 +63,7 @@ def generate_filter(include_domains, include_entities, # Case 3 - excludes, no includes - only exclude specified entities if not have_include and have_exclude: - def entity_filter_3(entity_id): + def entity_filter_3(entity_id: str) -> bool: """Return filter function for case 3.""" domain = split_entity_id(entity_id)[0] return (entity_id not in exclude_e and @@ -75,7 +78,7 @@ def generate_filter(include_domains, include_entities, # note: if both include and exclude domains specified, # the exclude domains are ignored if include_d: - def entity_filter_4a(entity_id): + def entity_filter_4a(entity_id: str) -> bool: """Return filter function for case 4a.""" domain = split_entity_id(entity_id)[0] if domain in include_d: @@ -88,7 +91,7 @@ def generate_filter(include_domains, include_entities, # - if domain is excluded, pass if entity is included # - if domain is not excluded, pass if entity not excluded if exclude_d: - def entity_filter_4b(entity_id): + def entity_filter_4b(entity_id: str) -> bool: """Return filter function for case 4b.""" domain = split_entity_id(entity_id)[0] if domain in exclude_d: @@ -99,7 +102,7 @@ def generate_filter(include_domains, include_entities, # Case 4c - neither include or exclude domain specified # - Only pass if entity is included. Ignore entity excludes. - def entity_filter_4c(entity_id): + def entity_filter_4c(entity_id: str) -> bool: """Return filter function for case 4c.""" return entity_id in include_e diff --git a/tox.ini b/tox.ini index f5dee78893f..1ab771ff24b 100644 --- a/tox.ini +++ b/tox.ini @@ -60,4 +60,4 @@ whitelist_externals=/bin/bash deps = -r{toxinidir}/requirements_test.txt commands = - /bin/bash -c 'mypy homeassistant/*.py homeassistant/{auth,util}/ homeassistant/helpers/{__init__,dispatcher,entity_values,icon,intent,json,location,signal,state,sun,temperature,translation,typing}.py' + /bin/bash -c 'mypy homeassistant/*.py homeassistant/{auth,util}/ homeassistant/helpers/{__init__,deprecation,dispatcher,entity_values,entityfilter,icon,intent,json,location,signal,state,sun,temperature,translation,typing}.py'