Migrate legacy typehints in core to PEP-526 (#26403)
* Migrate legacy typehints in core to PEP-526 * Fix one type
This commit is contained in:
parent
2dc90be94f
commit
2f0eb07624
45 changed files with 221 additions and 263 deletions
|
@ -7,7 +7,7 @@ import platform
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import threading
|
import threading
|
||||||
from typing import List, Dict, Any, TYPE_CHECKING # noqa pylint: disable=unused-import
|
from typing import List, Dict, Any, TYPE_CHECKING
|
||||||
|
|
||||||
from homeassistant import monkey_patch
|
from homeassistant import monkey_patch
|
||||||
from homeassistant.const import __version__, REQUIRED_PYTHON_VER, RESTART_EXIT_CODE
|
from homeassistant.const import __version__, REQUIRED_PYTHON_VER, RESTART_EXIT_CODE
|
||||||
|
@ -280,7 +280,7 @@ async def setup_and_run_hass(config_dir: str, args: argparse.Namespace) -> int:
|
||||||
hass = core.HomeAssistant()
|
hass = core.HomeAssistant()
|
||||||
|
|
||||||
if args.demo_mode:
|
if args.demo_mode:
|
||||||
config = {"frontend": {}, "demo": {}} # type: Dict[str, Any]
|
config: Dict[str, Any] = {"frontend": {}, "demo": {}}
|
||||||
bootstrap.async_from_config_dict(
|
bootstrap.async_from_config_dict(
|
||||||
config,
|
config,
|
||||||
hass,
|
hass,
|
||||||
|
|
|
@ -47,7 +47,7 @@ async def auth_manager_from_config(
|
||||||
else:
|
else:
|
||||||
providers = ()
|
providers = ()
|
||||||
# So returned auth providers are in same order as config
|
# So returned auth providers are in same order as config
|
||||||
provider_hash = OrderedDict() # type: _ProviderDict
|
provider_hash: _ProviderDict = OrderedDict()
|
||||||
for provider in providers:
|
for provider in providers:
|
||||||
key = (provider.type, provider.id)
|
key = (provider.type, provider.id)
|
||||||
provider_hash[key] = provider
|
provider_hash[key] = provider
|
||||||
|
@ -59,7 +59,7 @@ async def auth_manager_from_config(
|
||||||
else:
|
else:
|
||||||
modules = ()
|
modules = ()
|
||||||
# So returned auth modules are in same order as config
|
# So returned auth modules are in same order as config
|
||||||
module_hash = OrderedDict() # type: _MfaModuleDict
|
module_hash: _MfaModuleDict = OrderedDict()
|
||||||
for module in modules:
|
for module in modules:
|
||||||
module_hash[module.id] = module
|
module_hash[module.id] = module
|
||||||
|
|
||||||
|
@ -168,11 +168,11 @@ class AuthManager:
|
||||||
|
|
||||||
async def async_create_user(self, name: str) -> models.User:
|
async def async_create_user(self, name: str) -> models.User:
|
||||||
"""Create a user."""
|
"""Create a user."""
|
||||||
kwargs = {
|
kwargs: Dict[str, Any] = {
|
||||||
"name": name,
|
"name": name,
|
||||||
"is_active": True,
|
"is_active": True,
|
||||||
"group_ids": [GROUP_ID_ADMIN],
|
"group_ids": [GROUP_ID_ADMIN],
|
||||||
} # type: Dict[str, Any]
|
}
|
||||||
|
|
||||||
if await self._user_should_be_owner():
|
if await self._user_should_be_owner():
|
||||||
kwargs["is_owner"] = True
|
kwargs["is_owner"] = True
|
||||||
|
@ -238,7 +238,7 @@ class AuthManager:
|
||||||
group_ids: Optional[List[str]] = None,
|
group_ids: Optional[List[str]] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Update a user."""
|
"""Update a user."""
|
||||||
kwargs = {} # type: Dict[str,Any]
|
kwargs: Dict[str, Any] = {}
|
||||||
if name is not None:
|
if name is not None:
|
||||||
kwargs["name"] = name
|
kwargs["name"] = name
|
||||||
if group_ids is not None:
|
if group_ids is not None:
|
||||||
|
@ -299,7 +299,7 @@ class AuthManager:
|
||||||
|
|
||||||
async def async_get_enabled_mfa(self, user: models.User) -> Dict[str, str]:
|
async def async_get_enabled_mfa(self, user: models.User) -> Dict[str, str]:
|
||||||
"""List enabled mfa modules for user."""
|
"""List enabled mfa modules for user."""
|
||||||
modules = OrderedDict() # type: Dict[str, str]
|
modules: Dict[str, str] = OrderedDict()
|
||||||
for module_id, module in self._mfa_modules.items():
|
for module_id, module in self._mfa_modules.items():
|
||||||
if await module.async_is_user_setup(user.id):
|
if await module.async_is_user_setup(user.id):
|
||||||
modules[module_id] = module.name
|
modules[module_id] = module.name
|
||||||
|
|
|
@ -4,7 +4,7 @@ from collections import OrderedDict
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import hmac
|
import hmac
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from typing import Any, Dict, List, Optional # noqa: F401
|
from typing import Any, Dict, List, Optional
|
||||||
|
|
||||||
from homeassistant.auth.const import ACCESS_TOKEN_EXPIRATION
|
from homeassistant.auth.const import ACCESS_TOKEN_EXPIRATION
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
|
@ -13,7 +13,7 @@ from homeassistant.util import dt as dt_util
|
||||||
from . import models
|
from . import models
|
||||||
from .const import GROUP_ID_ADMIN, GROUP_ID_USER, GROUP_ID_READ_ONLY
|
from .const import GROUP_ID_ADMIN, GROUP_ID_USER, GROUP_ID_READ_ONLY
|
||||||
from .permissions import PermissionLookup, system_policies
|
from .permissions import PermissionLookup, system_policies
|
||||||
from .permissions.types import PolicyType # noqa: F401
|
from .permissions.types import PolicyType
|
||||||
|
|
||||||
STORAGE_VERSION = 1
|
STORAGE_VERSION = 1
|
||||||
STORAGE_KEY = "auth"
|
STORAGE_KEY = "auth"
|
||||||
|
@ -34,9 +34,9 @@ class AuthStore:
|
||||||
def __init__(self, hass: HomeAssistant) -> None:
|
def __init__(self, hass: HomeAssistant) -> None:
|
||||||
"""Initialize the auth store."""
|
"""Initialize the auth store."""
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
self._users = None # type: Optional[Dict[str, models.User]]
|
self._users: Optional[Dict[str, models.User]] = None
|
||||||
self._groups = None # type: Optional[Dict[str, models.Group]]
|
self._groups: Optional[Dict[str, models.Group]] = None
|
||||||
self._perm_lookup = None # type: Optional[PermissionLookup]
|
self._perm_lookup: Optional[PermissionLookup] = None
|
||||||
self._store = hass.helpers.storage.Store(
|
self._store = hass.helpers.storage.Store(
|
||||||
STORAGE_VERSION, STORAGE_KEY, private=True
|
STORAGE_VERSION, STORAGE_KEY, private=True
|
||||||
)
|
)
|
||||||
|
@ -97,13 +97,13 @@ class AuthStore:
|
||||||
raise ValueError(f"Invalid group specified {group_id}")
|
raise ValueError(f"Invalid group specified {group_id}")
|
||||||
groups.append(group)
|
groups.append(group)
|
||||||
|
|
||||||
kwargs = {
|
kwargs: Dict[str, Any] = {
|
||||||
"name": name,
|
"name": name,
|
||||||
# Until we get group management, we just put everyone in the
|
# Until we get group management, we just put everyone in the
|
||||||
# same group.
|
# same group.
|
||||||
"groups": groups,
|
"groups": groups,
|
||||||
"perm_lookup": self._perm_lookup,
|
"perm_lookup": self._perm_lookup,
|
||||||
} # type: Dict[str, Any]
|
}
|
||||||
|
|
||||||
if is_owner is not None:
|
if is_owner is not None:
|
||||||
kwargs["is_owner"] = is_owner
|
kwargs["is_owner"] = is_owner
|
||||||
|
@ -210,12 +210,12 @@ class AuthStore:
|
||||||
access_token_expiration: timedelta = ACCESS_TOKEN_EXPIRATION,
|
access_token_expiration: timedelta = ACCESS_TOKEN_EXPIRATION,
|
||||||
) -> models.RefreshToken:
|
) -> models.RefreshToken:
|
||||||
"""Create a new token for a user."""
|
"""Create a new token for a user."""
|
||||||
kwargs = {
|
kwargs: Dict[str, Any] = {
|
||||||
"user": user,
|
"user": user,
|
||||||
"client_id": client_id,
|
"client_id": client_id,
|
||||||
"token_type": token_type,
|
"token_type": token_type,
|
||||||
"access_token_expiration": access_token_expiration,
|
"access_token_expiration": access_token_expiration,
|
||||||
} # type: Dict[str, Any]
|
}
|
||||||
if client_name:
|
if client_name:
|
||||||
kwargs["client_name"] = client_name
|
kwargs["client_name"] = client_name
|
||||||
if client_icon:
|
if client_icon:
|
||||||
|
@ -307,8 +307,8 @@ class AuthStore:
|
||||||
self._set_defaults()
|
self._set_defaults()
|
||||||
return
|
return
|
||||||
|
|
||||||
users = OrderedDict() # type: Dict[str, models.User]
|
users: Dict[str, models.User] = OrderedDict()
|
||||||
groups = OrderedDict() # type: Dict[str, models.Group]
|
groups: Dict[str, models.Group] = OrderedDict()
|
||||||
|
|
||||||
# Soft-migrating data as we load. We are going to make sure we have a
|
# Soft-migrating data as we load. We are going to make sure we have a
|
||||||
# read only group and an admin group. There are two states that we can
|
# read only group and an admin group. There are two states that we can
|
||||||
|
@ -325,7 +325,7 @@ class AuthStore:
|
||||||
# was added.
|
# was added.
|
||||||
|
|
||||||
for group_dict in data.get("groups", []):
|
for group_dict in data.get("groups", []):
|
||||||
policy = None # type: Optional[PolicyType]
|
policy: Optional[PolicyType] = None
|
||||||
|
|
||||||
if group_dict["id"] == GROUP_ID_ADMIN:
|
if group_dict["id"] == GROUP_ID_ADMIN:
|
||||||
has_admin_group = True
|
has_admin_group = True
|
||||||
|
@ -503,11 +503,11 @@ class AuthStore:
|
||||||
|
|
||||||
groups = []
|
groups = []
|
||||||
for group in self._groups.values():
|
for group in self._groups.values():
|
||||||
g_dict = {
|
g_dict: Dict[str, Any] = {
|
||||||
"id": group.id,
|
"id": group.id,
|
||||||
# Name not read for sys groups. Kept here for backwards compat
|
# Name not read for sys groups. Kept here for backwards compat
|
||||||
"name": group.name,
|
"name": group.name,
|
||||||
} # type: Dict[str, Any]
|
}
|
||||||
|
|
||||||
if not group.system_generated:
|
if not group.system_generated:
|
||||||
g_dict["policy"] = group.policy
|
g_dict["policy"] = group.policy
|
||||||
|
@ -558,7 +558,7 @@ class AuthStore:
|
||||||
"""Set default values for auth store."""
|
"""Set default values for auth store."""
|
||||||
self._users = OrderedDict()
|
self._users = OrderedDict()
|
||||||
|
|
||||||
groups = OrderedDict() # type: Dict[str, models.Group]
|
groups: Dict[str, models.Group] = OrderedDict()
|
||||||
admin_group = _system_admin_group()
|
admin_group = _system_admin_group()
|
||||||
groups[admin_group.id] = admin_group
|
groups[admin_group.id] = admin_group
|
||||||
user_group = _system_user_group()
|
user_group = _system_user_group()
|
||||||
|
|
|
@ -109,7 +109,7 @@ class SetupFlow(data_entry_flow.FlowHandler):
|
||||||
Return self.async_show_form(step_id='init') if user_input is None.
|
Return self.async_show_form(step_id='init') if user_input is None.
|
||||||
Return self.async_create_entry(data={'result': result}) if finish.
|
Return self.async_create_entry(data={'result': result}) if finish.
|
||||||
"""
|
"""
|
||||||
errors = {} # type: Dict[str, str]
|
errors: Dict[str, str] = {}
|
||||||
|
|
||||||
if user_input:
|
if user_input:
|
||||||
result = await self._auth_module.async_setup_user(self._user_id, user_input)
|
result = await self._auth_module.async_setup_user(self._user_id, user_input)
|
||||||
|
|
|
@ -95,7 +95,7 @@ class NotifyAuthModule(MultiFactorAuthModule):
|
||||||
def __init__(self, hass: HomeAssistant, config: Dict[str, Any]) -> None:
|
def __init__(self, hass: HomeAssistant, config: Dict[str, Any]) -> None:
|
||||||
"""Initialize the user data store."""
|
"""Initialize the user data store."""
|
||||||
super().__init__(hass, config)
|
super().__init__(hass, config)
|
||||||
self._user_settings = None # type: Optional[_UsersDict]
|
self._user_settings: Optional[_UsersDict] = None
|
||||||
self._user_store = hass.helpers.storage.Store(
|
self._user_store = hass.helpers.storage.Store(
|
||||||
STORAGE_VERSION, STORAGE_KEY, private=True
|
STORAGE_VERSION, STORAGE_KEY, private=True
|
||||||
)
|
)
|
||||||
|
@ -279,18 +279,18 @@ class NotifySetupFlow(SetupFlow):
|
||||||
"""Initialize the setup flow."""
|
"""Initialize the setup flow."""
|
||||||
super().__init__(auth_module, setup_schema, user_id)
|
super().__init__(auth_module, setup_schema, user_id)
|
||||||
# to fix typing complaint
|
# to fix typing complaint
|
||||||
self._auth_module = auth_module # type: NotifyAuthModule
|
self._auth_module: NotifyAuthModule = auth_module
|
||||||
self._available_notify_services = available_notify_services
|
self._available_notify_services = available_notify_services
|
||||||
self._secret = None # type: Optional[str]
|
self._secret: Optional[str] = None
|
||||||
self._count = None # type: Optional[int]
|
self._count: Optional[int] = None
|
||||||
self._notify_service = None # type: Optional[str]
|
self._notify_service: Optional[str] = None
|
||||||
self._target = None # type: Optional[str]
|
self._target: Optional[str] = None
|
||||||
|
|
||||||
async def async_step_init(
|
async def async_step_init(
|
||||||
self, user_input: Optional[Dict[str, str]] = None
|
self, user_input: Optional[Dict[str, str]] = None
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
"""Let user select available notify services."""
|
"""Let user select available notify services."""
|
||||||
errors = {} # type: Dict[str, str]
|
errors: Dict[str, str] = {}
|
||||||
|
|
||||||
hass = self._auth_module.hass
|
hass = self._auth_module.hass
|
||||||
if user_input:
|
if user_input:
|
||||||
|
@ -304,7 +304,7 @@ class NotifySetupFlow(SetupFlow):
|
||||||
if not self._available_notify_services:
|
if not self._available_notify_services:
|
||||||
return self.async_abort(reason="no_available_service")
|
return self.async_abort(reason="no_available_service")
|
||||||
|
|
||||||
schema = OrderedDict() # type: Dict[str, Any]
|
schema: Dict[str, Any] = OrderedDict()
|
||||||
schema["notify_service"] = vol.In(self._available_notify_services)
|
schema["notify_service"] = vol.In(self._available_notify_services)
|
||||||
schema["target"] = vol.Optional(str)
|
schema["target"] = vol.Optional(str)
|
||||||
|
|
||||||
|
@ -316,7 +316,7 @@ class NotifySetupFlow(SetupFlow):
|
||||||
self, user_input: Optional[Dict[str, str]] = None
|
self, user_input: Optional[Dict[str, str]] = None
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
"""Verify user can recevie one-time password."""
|
"""Verify user can recevie one-time password."""
|
||||||
errors = {} # type: Dict[str, str]
|
errors: Dict[str, str] = {}
|
||||||
|
|
||||||
hass = self._auth_module.hass
|
hass = self._auth_module.hass
|
||||||
if user_input:
|
if user_input:
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from typing import Any, Dict, Optional, Tuple # noqa: F401
|
from typing import Any, Dict, Optional, Tuple
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ class TotpAuthModule(MultiFactorAuthModule):
|
||||||
def __init__(self, hass: HomeAssistant, config: Dict[str, Any]) -> None:
|
def __init__(self, hass: HomeAssistant, config: Dict[str, Any]) -> None:
|
||||||
"""Initialize the user data store."""
|
"""Initialize the user data store."""
|
||||||
super().__init__(hass, config)
|
super().__init__(hass, config)
|
||||||
self._users = None # type: Optional[Dict[str, str]]
|
self._users: Optional[Dict[str, str]] = None
|
||||||
self._user_store = hass.helpers.storage.Store(
|
self._user_store = hass.helpers.storage.Store(
|
||||||
STORAGE_VERSION, STORAGE_KEY, private=True
|
STORAGE_VERSION, STORAGE_KEY, private=True
|
||||||
)
|
)
|
||||||
|
@ -107,7 +107,7 @@ class TotpAuthModule(MultiFactorAuthModule):
|
||||||
"""Create a ota_secret for user."""
|
"""Create a ota_secret for user."""
|
||||||
import pyotp
|
import pyotp
|
||||||
|
|
||||||
ota_secret = secret or pyotp.random_base32() # type: str
|
ota_secret: str = secret or pyotp.random_base32()
|
||||||
|
|
||||||
self._users[user_id] = ota_secret # type: ignore
|
self._users[user_id] = ota_secret # type: ignore
|
||||||
return ota_secret
|
return ota_secret
|
||||||
|
@ -181,9 +181,9 @@ class TotpSetupFlow(SetupFlow):
|
||||||
"""Initialize the setup flow."""
|
"""Initialize the setup flow."""
|
||||||
super().__init__(auth_module, setup_schema, user.id)
|
super().__init__(auth_module, setup_schema, user.id)
|
||||||
# to fix typing complaint
|
# to fix typing complaint
|
||||||
self._auth_module = auth_module # type: TotpAuthModule
|
self._auth_module: TotpAuthModule = auth_module
|
||||||
self._user = user
|
self._user = user
|
||||||
self._ota_secret = None # type: Optional[str]
|
self._ota_secret: Optional[str] = None
|
||||||
self._url = None # type Optional[str]
|
self._url = None # type Optional[str]
|
||||||
self._image = None # type Optional[str]
|
self._image = None # type Optional[str]
|
||||||
|
|
||||||
|
@ -197,7 +197,7 @@ class TotpSetupFlow(SetupFlow):
|
||||||
"""
|
"""
|
||||||
import pyotp
|
import pyotp
|
||||||
|
|
||||||
errors = {} # type: Dict[str, str]
|
errors: Dict[str, str] = {}
|
||||||
|
|
||||||
if user_input:
|
if user_input:
|
||||||
verified = await self.hass.async_add_executor_job( # type: ignore
|
verified = await self.hass.async_add_executor_job( # type: ignore
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
"""Auth models."""
|
"""Auth models."""
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from typing import Dict, List, NamedTuple, Optional # noqa: F401
|
from typing import Dict, List, NamedTuple, Optional
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
import attr
|
import attr
|
||||||
|
@ -31,9 +31,7 @@ class User:
|
||||||
"""A user."""
|
"""A user."""
|
||||||
|
|
||||||
name = attr.ib(type=str) # type: Optional[str]
|
name = attr.ib(type=str) # type: Optional[str]
|
||||||
perm_lookup = attr.ib(
|
perm_lookup = attr.ib(type=perm_mdl.PermissionLookup, cmp=False)
|
||||||
type=perm_mdl.PermissionLookup, cmp=False
|
|
||||||
) # type: perm_mdl.PermissionLookup
|
|
||||||
id = attr.ib(type=str, factory=lambda: uuid.uuid4().hex)
|
id = attr.ib(type=str, factory=lambda: uuid.uuid4().hex)
|
||||||
is_owner = attr.ib(type=bool, default=False)
|
is_owner = attr.ib(type=bool, default=False)
|
||||||
is_active = attr.ib(type=bool, default=False)
|
is_active = attr.ib(type=bool, default=False)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
"""Entity permissions."""
|
"""Entity permissions."""
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from typing import Callable, Optional # noqa: F401
|
from typing import Callable, Optional
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
|
@ -8,8 +8,7 @@ from .const import SUBCAT_ALL, POLICY_READ, POLICY_CONTROL, POLICY_EDIT
|
||||||
from .models import PermissionLookup
|
from .models import PermissionLookup
|
||||||
from .types import CategoryType, SubCategoryDict, ValueType
|
from .types import CategoryType, SubCategoryDict, ValueType
|
||||||
|
|
||||||
# pylint: disable=unused-import
|
from .util import SubCatLookupType, lookup_all, compile_policy
|
||||||
from .util import SubCatLookupType, lookup_all, compile_policy # noqa
|
|
||||||
|
|
||||||
SINGLE_ENTITY_SCHEMA = vol.Any(
|
SINGLE_ENTITY_SCHEMA = vol.Any(
|
||||||
True,
|
True,
|
||||||
|
@ -90,7 +89,7 @@ def compile_entities(
|
||||||
policy: CategoryType, perm_lookup: PermissionLookup
|
policy: CategoryType, perm_lookup: PermissionLookup
|
||||||
) -> Callable[[str, str], bool]:
|
) -> Callable[[str, str], bool]:
|
||||||
"""Compile policy into a function that tests policy."""
|
"""Compile policy into a function that tests policy."""
|
||||||
subcategories = OrderedDict() # type: SubCatLookupType
|
subcategories: SubCatLookupType = OrderedDict()
|
||||||
subcategories[ENTITY_ENTITY_IDS] = _lookup_entity_id
|
subcategories[ENTITY_ENTITY_IDS] = _lookup_entity_id
|
||||||
subcategories[ENTITY_DEVICE_IDS] = _lookup_device
|
subcategories[ENTITY_DEVICE_IDS] = _lookup_device
|
||||||
subcategories[ENTITY_AREAS] = _lookup_area
|
subcategories[ENTITY_AREAS] = _lookup_area
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
"""Merging of policies."""
|
"""Merging of policies."""
|
||||||
from typing import cast, Dict, List, Set # noqa: F401
|
from typing import cast, Dict, List, Set
|
||||||
|
|
||||||
from .types import PolicyType, CategoryType
|
from .types import PolicyType, CategoryType
|
||||||
|
|
||||||
|
|
||||||
def merge_policies(policies: List[PolicyType]) -> PolicyType:
|
def merge_policies(policies: List[PolicyType]) -> PolicyType:
|
||||||
"""Merge policies."""
|
"""Merge policies."""
|
||||||
new_policy = {} # type: Dict[str, CategoryType]
|
new_policy: Dict[str, CategoryType] = {}
|
||||||
seen = set() # type: Set[str]
|
seen: Set[str] = set()
|
||||||
for policy in policies:
|
for policy in policies:
|
||||||
for category in policy:
|
for category in policy:
|
||||||
if category in seen:
|
if category in seen:
|
||||||
|
@ -33,8 +33,8 @@ def _merge_policies(sources: List[CategoryType]) -> CategoryType:
|
||||||
# If there are multiple sources with a dict as policy, we recursively
|
# If there are multiple sources with a dict as policy, we recursively
|
||||||
# merge each key in the source.
|
# merge each key in the source.
|
||||||
|
|
||||||
policy = None # type: CategoryType
|
policy: CategoryType = None
|
||||||
seen = set() # type: Set[str]
|
seen: Set[str] = set()
|
||||||
for source in sources:
|
for source in sources:
|
||||||
if source is None:
|
if source is None:
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
"""Helpers to deal with permissions."""
|
"""Helpers to deal with permissions."""
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
from typing import Callable, Dict, List, Optional, cast # noqa: F401
|
from typing import Callable, Dict, List, Optional, cast
|
||||||
|
|
||||||
from .const import SUBCAT_ALL
|
from .const import SUBCAT_ALL
|
||||||
from .models import PermissionLookup
|
from .models import PermissionLookup
|
||||||
|
@ -45,7 +45,7 @@ def compile_policy(
|
||||||
|
|
||||||
assert isinstance(policy, dict)
|
assert isinstance(policy, dict)
|
||||||
|
|
||||||
funcs = [] # type: List[Callable[[str, str], Optional[bool]]]
|
funcs: List[Callable[[str, str], Optional[bool]]] = []
|
||||||
|
|
||||||
for key, lookup_func in subcategories.items():
|
for key, lookup_func in subcategories.items():
|
||||||
lookup_value = policy.get(key)
|
lookup_value = policy.get(key)
|
||||||
|
@ -85,7 +85,7 @@ def _gen_dict_test_func(
|
||||||
|
|
||||||
def test_value(object_id: str, key: str) -> Optional[bool]:
|
def test_value(object_id: str, key: str) -> Optional[bool]:
|
||||||
"""Test if permission is allowed based on the keys."""
|
"""Test if permission is allowed based on the keys."""
|
||||||
schema = lookup_func(perm_lookup, lookup_dict, object_id) # type: ValueType
|
schema: ValueType = lookup_func(perm_lookup, lookup_dict, object_id)
|
||||||
|
|
||||||
if schema is None or isinstance(schema, bool):
|
if schema is None or isinstance(schema, bool):
|
||||||
return schema
|
return schema
|
||||||
|
|
|
@ -16,7 +16,7 @@ from homeassistant.util.decorator import Registry
|
||||||
|
|
||||||
from ..auth_store import AuthStore
|
from ..auth_store import AuthStore
|
||||||
from ..const import MFA_SESSION_EXPIRATION
|
from ..const import MFA_SESSION_EXPIRATION
|
||||||
from ..models import Credentials, User, UserMeta # noqa: F401
|
from ..models import Credentials, User, UserMeta
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
DATA_REQS = "auth_prov_reqs_processed"
|
DATA_REQS = "auth_prov_reqs_processed"
|
||||||
|
@ -175,12 +175,12 @@ class LoginFlow(data_entry_flow.FlowHandler):
|
||||||
def __init__(self, auth_provider: AuthProvider) -> None:
|
def __init__(self, auth_provider: AuthProvider) -> None:
|
||||||
"""Initialize the login flow."""
|
"""Initialize the login flow."""
|
||||||
self._auth_provider = auth_provider
|
self._auth_provider = auth_provider
|
||||||
self._auth_module_id = None # type: Optional[str]
|
self._auth_module_id: Optional[str] = None
|
||||||
self._auth_manager = auth_provider.hass.auth # type: ignore
|
self._auth_manager = auth_provider.hass.auth # type: ignore
|
||||||
self.available_mfa_modules = {} # type: Dict[str, str]
|
self.available_mfa_modules: Dict[str, str] = {}
|
||||||
self.created_at = dt_util.utcnow()
|
self.created_at = dt_util.utcnow()
|
||||||
self.invalid_mfa_times = 0
|
self.invalid_mfa_times = 0
|
||||||
self.user = None # type: Optional[User]
|
self.user: Optional[User] = None
|
||||||
|
|
||||||
async def async_step_init(
|
async def async_step_init(
|
||||||
self, user_input: Optional[Dict[str, str]] = None
|
self, user_input: Optional[Dict[str, str]] = None
|
||||||
|
@ -255,10 +255,10 @@ class LoginFlow(data_entry_flow.FlowHandler):
|
||||||
if not errors:
|
if not errors:
|
||||||
return await self.async_finish(self.user)
|
return await self.async_finish(self.user)
|
||||||
|
|
||||||
description_placeholders = {
|
description_placeholders: Dict[str, Optional[str]] = {
|
||||||
"mfa_module_name": auth_module.name,
|
"mfa_module_name": auth_module.name,
|
||||||
"mfa_module_id": auth_module.id,
|
"mfa_module_id": auth_module.id,
|
||||||
} # type: Dict[str, Optional[str]]
|
}
|
||||||
|
|
||||||
return self.async_show_form(
|
return self.async_show_form(
|
||||||
step_id="mfa",
|
step_id="mfa",
|
||||||
|
|
|
@ -53,7 +53,7 @@ class CommandLineAuthProvider(AuthProvider):
|
||||||
attributes provided by external programs.
|
attributes provided by external programs.
|
||||||
"""
|
"""
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self._user_meta = {} # type: Dict[str, Dict[str, Any]]
|
self._user_meta: Dict[str, Dict[str, Any]] = {}
|
||||||
|
|
||||||
async def async_login_flow(self, context: Optional[dict]) -> LoginFlow:
|
async def async_login_flow(self, context: Optional[dict]) -> LoginFlow:
|
||||||
"""Return a flow to login."""
|
"""Return a flow to login."""
|
||||||
|
@ -85,7 +85,7 @@ class CommandLineAuthProvider(AuthProvider):
|
||||||
raise InvalidAuthError
|
raise InvalidAuthError
|
||||||
|
|
||||||
if self.config[CONF_META]:
|
if self.config[CONF_META]:
|
||||||
meta = {} # type: Dict[str, str]
|
meta: Dict[str, str] = {}
|
||||||
for _line in stdout.splitlines():
|
for _line in stdout.splitlines():
|
||||||
try:
|
try:
|
||||||
line = _line.decode().lstrip()
|
line = _line.decode().lstrip()
|
||||||
|
@ -146,7 +146,7 @@ class CommandLineLoginFlow(LoginFlow):
|
||||||
user_input.pop("password")
|
user_input.pop("password")
|
||||||
return await self.async_finish(user_input)
|
return await self.async_finish(user_input)
|
||||||
|
|
||||||
schema = collections.OrderedDict() # type: Dict[str, type]
|
schema: Dict[str, type] = collections.OrderedDict()
|
||||||
schema["username"] = str
|
schema["username"] = str
|
||||||
schema["password"] = str
|
schema["password"] = str
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import base64
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from typing import Any, Dict, List, Optional, Set, cast # noqa: F401
|
from typing import Any, Dict, List, Optional, Set, cast
|
||||||
|
|
||||||
import bcrypt
|
import bcrypt
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
@ -53,7 +53,7 @@ class Data:
|
||||||
self._store = hass.helpers.storage.Store(
|
self._store = hass.helpers.storage.Store(
|
||||||
STORAGE_VERSION, STORAGE_KEY, private=True
|
STORAGE_VERSION, STORAGE_KEY, private=True
|
||||||
)
|
)
|
||||||
self._data = None # type: Optional[Dict[str, Any]]
|
self._data: Optional[Dict[str, Any]] = None
|
||||||
# Legacy mode will allow usernames to start/end with whitespace
|
# Legacy mode will allow usernames to start/end with whitespace
|
||||||
# and will compare usernames case-insensitive.
|
# and will compare usernames case-insensitive.
|
||||||
# Remove in 2020 or when we launch 1.0.
|
# Remove in 2020 or when we launch 1.0.
|
||||||
|
@ -74,7 +74,7 @@ class Data:
|
||||||
if data is None:
|
if data is None:
|
||||||
data = {"users": []}
|
data = {"users": []}
|
||||||
|
|
||||||
seen = set() # type: Set[str]
|
seen: Set[str] = set()
|
||||||
|
|
||||||
for user in data["users"]:
|
for user in data["users"]:
|
||||||
username = user["username"]
|
username = user["username"]
|
||||||
|
@ -210,7 +210,7 @@ class HassAuthProvider(AuthProvider):
|
||||||
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
||||||
"""Initialize an Home Assistant auth provider."""
|
"""Initialize an Home Assistant auth provider."""
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.data = None # type: Optional[Data]
|
self.data: Optional[Data] = None
|
||||||
self._init_lock = asyncio.Lock()
|
self._init_lock = asyncio.Lock()
|
||||||
|
|
||||||
async def async_initialize(self) -> None:
|
async def async_initialize(self) -> None:
|
||||||
|
@ -296,7 +296,7 @@ class HassLoginFlow(LoginFlow):
|
||||||
user_input.pop("password")
|
user_input.pop("password")
|
||||||
return await self.async_finish(user_input)
|
return await self.async_finish(user_input)
|
||||||
|
|
||||||
schema = OrderedDict() # type: Dict[str, type]
|
schema: Dict[str, type] = OrderedDict()
|
||||||
schema["username"] = str
|
schema["username"] = str
|
||||||
schema["password"] = str
|
schema["password"] = str
|
||||||
|
|
||||||
|
|
|
@ -112,7 +112,7 @@ class ExampleLoginFlow(LoginFlow):
|
||||||
user_input.pop("password")
|
user_input.pop("password")
|
||||||
return await self.async_finish(user_input)
|
return await self.async_finish(user_input)
|
||||||
|
|
||||||
schema = OrderedDict() # type: Dict[str, type]
|
schema: Dict[str, type] = OrderedDict()
|
||||||
schema["username"] = str
|
schema["username"] = str
|
||||||
schema["password"] = str
|
schema["password"] = str
|
||||||
|
|
||||||
|
|
|
@ -206,9 +206,9 @@ def async_enable_logging(
|
||||||
):
|
):
|
||||||
|
|
||||||
if log_rotate_days:
|
if log_rotate_days:
|
||||||
err_handler = logging.handlers.TimedRotatingFileHandler(
|
err_handler: logging.FileHandler = logging.handlers.TimedRotatingFileHandler(
|
||||||
err_log_path, when="midnight", backupCount=log_rotate_days
|
err_log_path, when="midnight", backupCount=log_rotate_days
|
||||||
) # type: logging.FileHandler
|
)
|
||||||
else:
|
else:
|
||||||
err_handler = logging.FileHandler(err_log_path, mode="w", delay=True)
|
err_handler = logging.FileHandler(err_log_path, mode="w", delay=True)
|
||||||
|
|
||||||
|
@ -335,7 +335,7 @@ async def _async_set_up_integrations(
|
||||||
)
|
)
|
||||||
|
|
||||||
# Load all integrations
|
# Load all integrations
|
||||||
after_dependencies = {} # type: Dict[str, Set[str]]
|
after_dependencies: Dict[str, Set[str]] = {}
|
||||||
|
|
||||||
for int_or_exc in await asyncio.gather(
|
for int_or_exc in await asyncio.gather(
|
||||||
*(loader.async_get_integration(hass, domain) for domain in stage_2_domains),
|
*(loader.async_get_integration(hass, domain) for domain in stage_2_domains),
|
||||||
|
|
|
@ -532,7 +532,7 @@ class Device(RestoreEntity):
|
||||||
class DeviceScanner:
|
class DeviceScanner:
|
||||||
"""Device scanner object."""
|
"""Device scanner object."""
|
||||||
|
|
||||||
hass = None # type: HomeAssistantType
|
hass: HomeAssistantType = None
|
||||||
|
|
||||||
def scan_devices(self) -> List[str]:
|
def scan_devices(self) -> List[str]:
|
||||||
"""Scan for devices."""
|
"""Scan for devices."""
|
||||||
|
|
|
@ -7,17 +7,7 @@ import logging
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
from typing import ( # noqa: F401 pylint: disable=unused-import
|
from typing import Any, Tuple, Optional, Dict, Union, Callable, Sequence, Set
|
||||||
Any,
|
|
||||||
Tuple,
|
|
||||||
Optional,
|
|
||||||
Dict,
|
|
||||||
List,
|
|
||||||
Union,
|
|
||||||
Callable,
|
|
||||||
Sequence,
|
|
||||||
Set,
|
|
||||||
)
|
|
||||||
from types import ModuleType
|
from types import ModuleType
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
from voluptuous.humanize import humanize_error
|
from voluptuous.humanize import humanize_error
|
||||||
|
@ -118,7 +108,7 @@ def _no_duplicate_auth_provider(
|
||||||
Each type of auth provider can only have one config without optional id.
|
Each type of auth provider can only have one config without optional id.
|
||||||
Unique id is required if same type of auth provider used multiple times.
|
Unique id is required if same type of auth provider used multiple times.
|
||||||
"""
|
"""
|
||||||
config_keys = set() # type: Set[Tuple[str, Optional[str]]]
|
config_keys: Set[Tuple[str, Optional[str]]] = set()
|
||||||
for config in configs:
|
for config in configs:
|
||||||
key = (config[CONF_TYPE], config.get(CONF_ID))
|
key = (config[CONF_TYPE], config.get(CONF_ID))
|
||||||
if key in config_keys:
|
if key in config_keys:
|
||||||
|
@ -142,7 +132,7 @@ def _no_duplicate_auth_mfa_module(
|
||||||
times.
|
times.
|
||||||
Note: this is different than auth provider
|
Note: this is different than auth provider
|
||||||
"""
|
"""
|
||||||
config_keys = set() # type: Set[str]
|
config_keys: Set[str] = set()
|
||||||
for config in configs:
|
for config in configs:
|
||||||
key = config.get(CONF_ID, config[CONF_TYPE])
|
key = config.get(CONF_ID, config[CONF_TYPE])
|
||||||
if key in config_keys:
|
if key in config_keys:
|
||||||
|
@ -623,7 +613,7 @@ def _identify_config_schema(module: ModuleType) -> Tuple[Optional[str], Optional
|
||||||
|
|
||||||
def _recursive_merge(conf: Dict[str, Any], package: Dict[str, Any]) -> Union[bool, str]:
|
def _recursive_merge(conf: Dict[str, Any], package: Dict[str, Any]) -> Union[bool, str]:
|
||||||
"""Merge package into conf, recursively."""
|
"""Merge package into conf, recursively."""
|
||||||
error = False # type: Union[bool, str]
|
error: Union[bool, str] = False
|
||||||
for key, pack_conf in package.items():
|
for key, pack_conf in package.items():
|
||||||
if isinstance(pack_conf, dict):
|
if isinstance(pack_conf, dict):
|
||||||
if not pack_conf:
|
if not pack_conf:
|
||||||
|
|
|
@ -138,10 +138,10 @@ class ConfigEntry:
|
||||||
self.state = state
|
self.state = state
|
||||||
|
|
||||||
# Listeners to call on update
|
# Listeners to call on update
|
||||||
self.update_listeners = [] # type: list
|
self.update_listeners: List = []
|
||||||
|
|
||||||
# Function to cancel a scheduled retry
|
# Function to cancel a scheduled retry
|
||||||
self._async_cancel_retry_setup = None # type: Optional[Callable[[], Any]]
|
self._async_cancel_retry_setup: Optional[Callable[[], Any]] = None
|
||||||
|
|
||||||
async def async_setup(
|
async def async_setup(
|
||||||
self,
|
self,
|
||||||
|
@ -386,14 +386,14 @@ class ConfigEntries:
|
||||||
)
|
)
|
||||||
self.options = OptionsFlowManager(hass)
|
self.options = OptionsFlowManager(hass)
|
||||||
self._hass_config = hass_config
|
self._hass_config = hass_config
|
||||||
self._entries = [] # type: List[ConfigEntry]
|
self._entries: List[ConfigEntry] = []
|
||||||
self._store = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY)
|
self._store = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY)
|
||||||
EntityRegistryDisabledHandler(hass).async_setup()
|
EntityRegistryDisabledHandler(hass).async_setup()
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_domains(self) -> List[str]:
|
def async_domains(self) -> List[str]:
|
||||||
"""Return domains for which we have entries."""
|
"""Return domains for which we have entries."""
|
||||||
seen = set() # type: Set[str]
|
seen: Set[str] = set()
|
||||||
result = []
|
result = []
|
||||||
|
|
||||||
for entry in self._entries:
|
for entry in self._entries:
|
||||||
|
|
|
@ -260,8 +260,8 @@ ATTR_ICON = "icon"
|
||||||
# The unit of measurement if applicable
|
# The unit of measurement if applicable
|
||||||
ATTR_UNIT_OF_MEASUREMENT = "unit_of_measurement"
|
ATTR_UNIT_OF_MEASUREMENT = "unit_of_measurement"
|
||||||
|
|
||||||
CONF_UNIT_SYSTEM_METRIC = "metric" # type: str
|
CONF_UNIT_SYSTEM_METRIC: str = "metric"
|
||||||
CONF_UNIT_SYSTEM_IMPERIAL = "imperial" # type: str
|
CONF_UNIT_SYSTEM_IMPERIAL: str = "imperial"
|
||||||
|
|
||||||
# Electrical attributes
|
# Electrical attributes
|
||||||
ATTR_VOLTAGE = "voltage"
|
ATTR_VOLTAGE = "voltage"
|
||||||
|
@ -334,39 +334,39 @@ TEMP_CELSIUS = "°C"
|
||||||
TEMP_FAHRENHEIT = "°F"
|
TEMP_FAHRENHEIT = "°F"
|
||||||
|
|
||||||
# Length units
|
# Length units
|
||||||
LENGTH_CENTIMETERS = "cm" # type: str
|
LENGTH_CENTIMETERS: str = "cm"
|
||||||
LENGTH_METERS = "m" # type: str
|
LENGTH_METERS: str = "m"
|
||||||
LENGTH_KILOMETERS = "km" # type: str
|
LENGTH_KILOMETERS: str = "km"
|
||||||
|
|
||||||
LENGTH_INCHES = "in" # type: str
|
LENGTH_INCHES: str = "in"
|
||||||
LENGTH_FEET = "ft" # type: str
|
LENGTH_FEET: str = "ft"
|
||||||
LENGTH_YARD = "yd" # type: str
|
LENGTH_YARD: str = "yd"
|
||||||
LENGTH_MILES = "mi" # type: str
|
LENGTH_MILES: str = "mi"
|
||||||
|
|
||||||
# Pressure units
|
# Pressure units
|
||||||
PRESSURE_PA = "Pa" # type: str
|
PRESSURE_PA: str = "Pa"
|
||||||
PRESSURE_HPA = "hPa" # type: str
|
PRESSURE_HPA: str = "hPa"
|
||||||
PRESSURE_BAR = "bar" # type: str
|
PRESSURE_BAR: str = "bar"
|
||||||
PRESSURE_MBAR = "mbar" # type: str
|
PRESSURE_MBAR: str = "mbar"
|
||||||
PRESSURE_INHG = "inHg" # type: str
|
PRESSURE_INHG: str = "inHg"
|
||||||
PRESSURE_PSI = "psi" # type: str
|
PRESSURE_PSI: str = "psi"
|
||||||
|
|
||||||
# Volume units
|
# Volume units
|
||||||
VOLUME_LITERS = "L" # type: str
|
VOLUME_LITERS: str = "L"
|
||||||
VOLUME_MILLILITERS = "mL" # type: str
|
VOLUME_MILLILITERS: str = "mL"
|
||||||
|
|
||||||
VOLUME_GALLONS = "gal" # type: str
|
VOLUME_GALLONS: str = "gal"
|
||||||
VOLUME_FLUID_OUNCE = "fl. oz." # type: str
|
VOLUME_FLUID_OUNCE: str = "fl. oz."
|
||||||
|
|
||||||
# Mass units
|
# Mass units
|
||||||
MASS_GRAMS = "g" # type: str
|
MASS_GRAMS: str = "g"
|
||||||
MASS_KILOGRAMS = "kg" # type: str
|
MASS_KILOGRAMS: str = "kg"
|
||||||
|
|
||||||
MASS_OUNCES = "oz" # type: str
|
MASS_OUNCES: str = "oz"
|
||||||
MASS_POUNDS = "lb" # type: str
|
MASS_POUNDS: str = "lb"
|
||||||
|
|
||||||
# UV Index units
|
# UV Index units
|
||||||
UNIT_UV_INDEX = "UV index" # type: str
|
UNIT_UV_INDEX: str = "UV index"
|
||||||
|
|
||||||
# #### SERVICES ####
|
# #### SERVICES ####
|
||||||
SERVICE_HOMEASSISTANT_STOP = "stop"
|
SERVICE_HOMEASSISTANT_STOP = "stop"
|
||||||
|
@ -460,15 +460,15 @@ CONTENT_TYPE_TEXT_PLAIN = "text/plain"
|
||||||
# The exit code to send to request a restart
|
# The exit code to send to request a restart
|
||||||
RESTART_EXIT_CODE = 100
|
RESTART_EXIT_CODE = 100
|
||||||
|
|
||||||
UNIT_NOT_RECOGNIZED_TEMPLATE = "{} is not a recognized {} unit." # type: str
|
UNIT_NOT_RECOGNIZED_TEMPLATE: str = "{} is not a recognized {} unit."
|
||||||
|
|
||||||
LENGTH = "length" # type: str
|
LENGTH: str = "length"
|
||||||
MASS = "mass" # type: str
|
MASS: str = "mass"
|
||||||
PRESSURE = "pressure" # type: str
|
PRESSURE: str = "pressure"
|
||||||
VOLUME = "volume" # type: str
|
VOLUME: str = "volume"
|
||||||
TEMPERATURE = "temperature" # type: str
|
TEMPERATURE: str = "temperature"
|
||||||
SPEED_MS = "speed_ms" # type: str
|
SPEED_MS: str = "speed_ms"
|
||||||
ILLUMINANCE = "illuminance" # type: str
|
ILLUMINANCE: str = "illuminance"
|
||||||
|
|
||||||
WEEKDAYS = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"]
|
WEEKDAYS = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"]
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ from time import monotonic
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from types import MappingProxyType
|
from types import MappingProxyType
|
||||||
from typing import ( # noqa: F401 pylint: disable=unused-import
|
from typing import (
|
||||||
Optional,
|
Optional,
|
||||||
Any,
|
Any,
|
||||||
Callable,
|
Callable,
|
||||||
|
@ -28,7 +28,6 @@ from typing import ( # noqa: F401 pylint: disable=unused-import
|
||||||
Set,
|
Set,
|
||||||
TYPE_CHECKING,
|
TYPE_CHECKING,
|
||||||
Awaitable,
|
Awaitable,
|
||||||
Iterator,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
from async_timeout import timeout
|
from async_timeout import timeout
|
||||||
|
@ -170,10 +169,10 @@ class HomeAssistant:
|
||||||
"""Initialize new Home Assistant object."""
|
"""Initialize new Home Assistant object."""
|
||||||
self.loop: asyncio.events.AbstractEventLoop = (loop or asyncio.get_event_loop())
|
self.loop: asyncio.events.AbstractEventLoop = (loop or asyncio.get_event_loop())
|
||||||
|
|
||||||
executor_opts = {
|
executor_opts: Dict[str, Any] = {
|
||||||
"max_workers": None,
|
"max_workers": None,
|
||||||
"thread_name_prefix": "SyncWorker",
|
"thread_name_prefix": "SyncWorker",
|
||||||
} # type: Dict[str, Any]
|
}
|
||||||
|
|
||||||
self.executor = ThreadPoolExecutor(**executor_opts)
|
self.executor = ThreadPoolExecutor(**executor_opts)
|
||||||
self.loop.set_default_executor(self.executor)
|
self.loop.set_default_executor(self.executor)
|
||||||
|
@ -733,7 +732,7 @@ class State:
|
||||||
)
|
)
|
||||||
|
|
||||||
self.entity_id = entity_id.lower()
|
self.entity_id = entity_id.lower()
|
||||||
self.state = state # type: str
|
self.state: str = state
|
||||||
self.attributes = MappingProxyType(attributes or {})
|
self.attributes = MappingProxyType(attributes or {})
|
||||||
self.last_updated = last_updated or dt_util.utcnow()
|
self.last_updated = last_updated or dt_util.utcnow()
|
||||||
self.last_changed = last_changed or self.last_updated
|
self.last_changed = last_changed or self.last_updated
|
||||||
|
@ -836,7 +835,7 @@ class StateMachine:
|
||||||
|
|
||||||
def __init__(self, bus: EventBus, loop: asyncio.events.AbstractEventLoop) -> None:
|
def __init__(self, bus: EventBus, loop: asyncio.events.AbstractEventLoop) -> None:
|
||||||
"""Initialize state machine."""
|
"""Initialize state machine."""
|
||||||
self._states = {} # type: Dict[str, State]
|
self._states: Dict[str, State] = {}
|
||||||
self._bus = bus
|
self._bus = bus
|
||||||
self._loop = loop
|
self._loop = loop
|
||||||
|
|
||||||
|
@ -1050,7 +1049,7 @@ class ServiceRegistry:
|
||||||
|
|
||||||
def __init__(self, hass: HomeAssistant) -> None:
|
def __init__(self, hass: HomeAssistant) -> None:
|
||||||
"""Initialize a service registry."""
|
"""Initialize a service registry."""
|
||||||
self._services = {} # type: Dict[str, Dict[str, Service]]
|
self._services: Dict[str, Dict[str, Service]] = {}
|
||||||
self._hass = hass
|
self._hass = hass
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -1269,29 +1268,29 @@ class Config:
|
||||||
"""Initialize a new config object."""
|
"""Initialize a new config object."""
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
|
|
||||||
self.latitude = 0 # type: float
|
self.latitude: float = 0
|
||||||
self.longitude = 0 # type: float
|
self.longitude: float = 0
|
||||||
self.elevation = 0 # type: int
|
self.elevation: int = 0
|
||||||
self.location_name = "Home" # type: str
|
self.location_name: str = "Home"
|
||||||
self.time_zone = dt_util.UTC # type: datetime.tzinfo
|
self.time_zone: datetime.tzinfo = dt_util.UTC
|
||||||
self.units = METRIC_SYSTEM # type: UnitSystem
|
self.units: UnitSystem = METRIC_SYSTEM
|
||||||
|
|
||||||
self.config_source = "default" # type: str
|
self.config_source: str = "default"
|
||||||
|
|
||||||
# If True, pip install is skipped for requirements on startup
|
# If True, pip install is skipped for requirements on startup
|
||||||
self.skip_pip = False # type: bool
|
self.skip_pip: bool = False
|
||||||
|
|
||||||
# List of loaded components
|
# List of loaded components
|
||||||
self.components = set() # type: set
|
self.components: set = set()
|
||||||
|
|
||||||
# API (HTTP) server configuration, see components.http.ApiConfig
|
# API (HTTP) server configuration, see components.http.ApiConfig
|
||||||
self.api = None # type: Optional[Any]
|
self.api: Optional[Any] = None
|
||||||
|
|
||||||
# Directory that holds the configuration
|
# Directory that holds the configuration
|
||||||
self.config_dir = None # type: Optional[str]
|
self.config_dir: Optional[str] = None
|
||||||
|
|
||||||
# List of allowed external dirs to access
|
# List of allowed external dirs to access
|
||||||
self.whitelist_external_dirs = set() # type: Set[str]
|
self.whitelist_external_dirs: Set[str] = set()
|
||||||
|
|
||||||
def distance(self, lat: float, lon: float) -> Optional[float]:
|
def distance(self, lat: float, lon: float) -> Optional[float]:
|
||||||
"""Calculate distance from Home Assistant.
|
"""Calculate distance from Home Assistant.
|
||||||
|
|
|
@ -1,13 +1,6 @@
|
||||||
"""Classes to help gather user submissions."""
|
"""Classes to help gather user submissions."""
|
||||||
import logging
|
import logging
|
||||||
from typing import (
|
from typing import Dict, Any, Callable, Hashable, List, Optional
|
||||||
Dict,
|
|
||||||
Any,
|
|
||||||
Callable,
|
|
||||||
Hashable,
|
|
||||||
List,
|
|
||||||
Optional,
|
|
||||||
) # noqa pylint: disable=unused-import
|
|
||||||
import uuid
|
import uuid
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
from .core import callback, HomeAssistant
|
from .core import callback, HomeAssistant
|
||||||
|
@ -52,7 +45,7 @@ class FlowManager:
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the flow manager."""
|
"""Initialize the flow manager."""
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
self._progress = {} # type: Dict[str, Any]
|
self._progress: Dict[str, Any] = {}
|
||||||
self._async_create_flow = async_create_flow
|
self._async_create_flow = async_create_flow
|
||||||
self._async_finish_flow = async_finish_flow
|
self._async_finish_flow = async_finish_flow
|
||||||
|
|
||||||
|
@ -136,7 +129,7 @@ class FlowManager:
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
result = await getattr(flow, method)(user_input) # type: Dict
|
result: Dict = await getattr(flow, method)(user_input)
|
||||||
|
|
||||||
if result["type"] not in (
|
if result["type"] not in (
|
||||||
RESULT_TYPE_FORM,
|
RESULT_TYPE_FORM,
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
"""Helper for aiohttp webclient stuff."""
|
"""Helper for aiohttp webclient stuff."""
|
||||||
import asyncio
|
import asyncio
|
||||||
import sys
|
import sys
|
||||||
from ssl import SSLContext # noqa: F401
|
from ssl import SSLContext
|
||||||
from typing import Any, Awaitable, Optional, cast
|
from typing import Any, Awaitable, Optional, cast
|
||||||
from typing import Union # noqa: F401
|
from typing import Union
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
from aiohttp.hdrs import USER_AGENT, CONTENT_TYPE
|
from aiohttp.hdrs import USER_AGENT, CONTENT_TYPE
|
||||||
|
@ -171,7 +171,7 @@ def _async_get_connector(
|
||||||
return cast(aiohttp.BaseConnector, hass.data[key])
|
return cast(aiohttp.BaseConnector, hass.data[key])
|
||||||
|
|
||||||
if verify_ssl:
|
if verify_ssl:
|
||||||
ssl_context = ssl_util.client_context() # type: Union[bool, SSLContext]
|
ssl_context: Union[bool, SSLContext] = ssl_util.client_context()
|
||||||
else:
|
else:
|
||||||
ssl_context = False
|
ssl_context = False
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import logging
|
||||||
import uuid
|
import uuid
|
||||||
from asyncio import Event
|
from asyncio import Event
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from typing import MutableMapping # noqa: F401
|
from typing import MutableMapping
|
||||||
from typing import Iterable, Optional, cast
|
from typing import Iterable, Optional, cast
|
||||||
|
|
||||||
import attr
|
import attr
|
||||||
|
@ -36,7 +36,7 @@ class AreaRegistry:
|
||||||
def __init__(self, hass: HomeAssistantType) -> None:
|
def __init__(self, hass: HomeAssistantType) -> None:
|
||||||
"""Initialize the area registry."""
|
"""Initialize the area registry."""
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
self.areas = {} # type: MutableMapping[str, AreaEntry]
|
self.areas: MutableMapping[str, AreaEntry] = {}
|
||||||
self._store = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY)
|
self._store = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
|
@ -119,7 +119,7 @@ class AreaRegistry:
|
||||||
"""Load the area registry."""
|
"""Load the area registry."""
|
||||||
data = await self._store.async_load()
|
data = await self._store.async_load()
|
||||||
|
|
||||||
areas = OrderedDict() # type: OrderedDict[str, AreaEntry]
|
areas: MutableMapping[str, AreaEntry] = OrderedDict()
|
||||||
|
|
||||||
if data is not None:
|
if data is not None:
|
||||||
for area in data["areas"]:
|
for area in data["areas"]:
|
||||||
|
|
|
@ -36,7 +36,7 @@ CheckConfigError = namedtuple("CheckConfigError", "message domain config")
|
||||||
class HomeAssistantConfig(OrderedDict):
|
class HomeAssistantConfig(OrderedDict):
|
||||||
"""Configuration result with errors attribute."""
|
"""Configuration result with errors attribute."""
|
||||||
|
|
||||||
errors = attr.ib(default=attr.Factory(list)) # type: List[CheckConfigError]
|
errors: List[CheckConfigError] = attr.ib(default=attr.Factory(list))
|
||||||
|
|
||||||
def add_error(self, message, domain=None, config=None):
|
def add_error(self, message, domain=None, config=None):
|
||||||
"""Add a single error."""
|
"""Add a single error."""
|
||||||
|
|
|
@ -823,7 +823,7 @@ OR_CONDITION_SCHEMA = vol.Schema(
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
CONDITION_SCHEMA = vol.Any(
|
CONDITION_SCHEMA: vol.Schema = vol.Any(
|
||||||
NUMERIC_STATE_CONDITION_SCHEMA,
|
NUMERIC_STATE_CONDITION_SCHEMA,
|
||||||
STATE_CONDITION_SCHEMA,
|
STATE_CONDITION_SCHEMA,
|
||||||
SUN_CONDITION_SCHEMA,
|
SUN_CONDITION_SCHEMA,
|
||||||
|
@ -832,7 +832,7 @@ CONDITION_SCHEMA = vol.Any(
|
||||||
ZONE_CONDITION_SCHEMA,
|
ZONE_CONDITION_SCHEMA,
|
||||||
AND_CONDITION_SCHEMA,
|
AND_CONDITION_SCHEMA,
|
||||||
OR_CONDITION_SCHEMA,
|
OR_CONDITION_SCHEMA,
|
||||||
) # type: vol.Schema
|
)
|
||||||
|
|
||||||
_SCRIPT_DELAY_SCHEMA = vol.Schema(
|
_SCRIPT_DELAY_SCHEMA = vol.Schema(
|
||||||
{
|
{
|
||||||
|
|
|
@ -91,7 +91,7 @@ class Entity:
|
||||||
entity_id = None # type: str
|
entity_id = None # type: str
|
||||||
|
|
||||||
# Owning hass instance. Will be set by EntityPlatform
|
# Owning hass instance. Will be set by EntityPlatform
|
||||||
hass = None # type: Optional[HomeAssistant]
|
hass: Optional[HomeAssistant] = None
|
||||||
|
|
||||||
# Owning platform instance. Will be set by EntityPlatform
|
# Owning platform instance. Will be set by EntityPlatform
|
||||||
platform = None
|
platform = None
|
||||||
|
@ -109,10 +109,10 @@ class Entity:
|
||||||
parallel_updates = None
|
parallel_updates = None
|
||||||
|
|
||||||
# Entry in the entity registry
|
# Entry in the entity registry
|
||||||
registry_entry = None # type: Optional[RegistryEntry]
|
registry_entry: Optional[RegistryEntry] = None
|
||||||
|
|
||||||
# Hold list for functions to call on remove.
|
# Hold list for functions to call on remove.
|
||||||
_on_remove = None # type: Optional[List[CALLBACK_TYPE]]
|
_on_remove: Optional[List[CALLBACK_TYPE]] = None
|
||||||
|
|
||||||
# Context
|
# Context
|
||||||
_context = None
|
_context = None
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
import fnmatch
|
import fnmatch
|
||||||
import re
|
import re
|
||||||
from typing import Any, Dict, Optional, Pattern # noqa: F401
|
from typing import Any, Dict, Optional, Pattern
|
||||||
|
|
||||||
from homeassistant.core import split_entity_id
|
from homeassistant.core import split_entity_id
|
||||||
|
|
||||||
|
@ -17,12 +17,12 @@ class EntityValues:
|
||||||
glob: Optional[Dict] = None,
|
glob: Optional[Dict] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize an EntityConfigDict."""
|
"""Initialize an EntityConfigDict."""
|
||||||
self._cache = {} # type: Dict[str, Dict]
|
self._cache: Dict[str, Dict] = {}
|
||||||
self._exact = exact
|
self._exact = exact
|
||||||
self._domain = domain
|
self._domain = domain
|
||||||
|
|
||||||
if glob is None:
|
if glob is None:
|
||||||
compiled = None # type: Optional[Dict[Pattern[str], Any]]
|
compiled: Optional[Dict[Pattern[str], Any]] = None
|
||||||
else:
|
else:
|
||||||
compiled = OrderedDict()
|
compiled = OrderedDict()
|
||||||
for key, value in glob.items():
|
for key, value in glob.items():
|
||||||
|
|
|
@ -55,7 +55,7 @@ async def async_handle(
|
||||||
text_input: Optional[str] = None,
|
text_input: Optional[str] = None,
|
||||||
) -> "IntentResponse":
|
) -> "IntentResponse":
|
||||||
"""Handle an intent."""
|
"""Handle an intent."""
|
||||||
handler = hass.data.get(DATA_KEY, {}).get(intent_type) # type: IntentHandler
|
handler: IntentHandler = hass.data.get(DATA_KEY, {}).get(intent_type)
|
||||||
|
|
||||||
if handler is None:
|
if handler is None:
|
||||||
raise UnknownIntent(f"Unknown intent {intent_type}")
|
raise UnknownIntent(f"Unknown intent {intent_type}")
|
||||||
|
@ -122,10 +122,10 @@ def async_test_feature(state: State, feature: int, feature_name: str) -> None:
|
||||||
class IntentHandler:
|
class IntentHandler:
|
||||||
"""Intent handler registration."""
|
"""Intent handler registration."""
|
||||||
|
|
||||||
intent_type = None # type: Optional[str]
|
intent_type: Optional[str] = None
|
||||||
slot_schema = None # type: Optional[vol.Schema]
|
slot_schema: Optional[vol.Schema] = None
|
||||||
_slot_schema = None
|
_slot_schema = None
|
||||||
platforms = [] # type: Optional[Iterable[str]]
|
platforms: Optional[Iterable[str]] = []
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_can_handle(self, intent_obj: "Intent") -> bool:
|
def async_can_handle(self, intent_obj: "Intent") -> bool:
|
||||||
|
@ -236,8 +236,8 @@ class IntentResponse:
|
||||||
def __init__(self, intent: Optional[Intent] = None) -> None:
|
def __init__(self, intent: Optional[Intent] = None) -> None:
|
||||||
"""Initialize an IntentResponse."""
|
"""Initialize an IntentResponse."""
|
||||||
self.intent = intent
|
self.intent = intent
|
||||||
self.speech = {} # type: Dict[str, Dict[str, Any]]
|
self.speech: Dict[str, Dict[str, Any]] = {}
|
||||||
self.card = {} # type: Dict[str, Dict[str, str]]
|
self.card: Dict[str, Dict[str, str]] = {}
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_set_speech(
|
def async_set_speech(
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
from datetime import timedelta, datetime
|
from datetime import timedelta, datetime
|
||||||
from typing import Any, Dict, List, Set, Optional # noqa pylint_disable=unused-import
|
from typing import Any, Dict, List, Set, Optional
|
||||||
|
|
||||||
from homeassistant.core import (
|
from homeassistant.core import (
|
||||||
HomeAssistant,
|
HomeAssistant,
|
||||||
|
@ -17,7 +17,7 @@ from homeassistant.helpers.entity import Entity
|
||||||
from homeassistant.helpers.event import async_track_time_interval
|
from homeassistant.helpers.event import async_track_time_interval
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers.json import JSONEncoder
|
from homeassistant.helpers.json import JSONEncoder
|
||||||
from homeassistant.helpers.storage import Store # noqa pylint_disable=unused-import
|
from homeassistant.helpers.storage import Store
|
||||||
|
|
||||||
|
|
||||||
# mypy: allow-untyped-calls, allow-untyped-defs, no-check-untyped-defs
|
# mypy: allow-untyped-calls, allow-untyped-defs, no-check-untyped-defs
|
||||||
|
@ -108,12 +108,12 @@ class RestoreStateData:
|
||||||
|
|
||||||
def __init__(self, hass: HomeAssistant) -> None:
|
def __init__(self, hass: HomeAssistant) -> None:
|
||||||
"""Initialize the restore state data class."""
|
"""Initialize the restore state data class."""
|
||||||
self.hass = hass # type: HomeAssistant
|
self.hass: HomeAssistant = hass
|
||||||
self.store = Store(
|
self.store: Store = Store(
|
||||||
hass, STORAGE_VERSION, STORAGE_KEY, encoder=JSONEncoder
|
hass, STORAGE_VERSION, STORAGE_KEY, encoder=JSONEncoder
|
||||||
) # type: Store
|
)
|
||||||
self.last_states = {} # type: Dict[str, StoredState]
|
self.last_states: Dict[str, StoredState] = {}
|
||||||
self.entity_ids = set() # type: Set[str]
|
self.entity_ids: Set[str] = set()
|
||||||
|
|
||||||
def async_get_stored_states(self) -> List[StoredState]:
|
def async_get_stored_states(self) -> List[StoredState]:
|
||||||
"""Get the set of states which should be stored.
|
"""Get the set of states which should be stored.
|
||||||
|
|
|
@ -102,15 +102,15 @@ class Script:
|
||||||
self.name = name
|
self.name = name
|
||||||
self._change_listener = change_listener
|
self._change_listener = change_listener
|
||||||
self._cur = -1
|
self._cur = -1
|
||||||
self._exception_step = None # type: Optional[int]
|
self._exception_step: Optional[int] = None
|
||||||
self.last_action = None
|
self.last_action = None
|
||||||
self.last_triggered = None # type: Optional[datetime]
|
self.last_triggered: Optional[datetime] = None
|
||||||
self.can_cancel = any(
|
self.can_cancel = any(
|
||||||
CONF_DELAY in action or CONF_WAIT_TEMPLATE in action
|
CONF_DELAY in action or CONF_WAIT_TEMPLATE in action
|
||||||
for action in self.sequence
|
for action in self.sequence
|
||||||
)
|
)
|
||||||
self._async_listener = [] # type: List[CALLBACK_TYPE]
|
self._async_listener: List[CALLBACK_TYPE] = []
|
||||||
self._config_cache = {} # type: Dict[Set[Tuple], Callable[..., bool]]
|
self._config_cache: Dict[Set[Tuple], Callable[..., bool]] = {}
|
||||||
self._actions = {
|
self._actions = {
|
||||||
ACTION_DELAY: self._async_delay,
|
ACTION_DELAY: self._async_delay,
|
||||||
ACTION_WAIT_TEMPLATE: self._async_wait_template,
|
ACTION_WAIT_TEMPLATE: self._async_wait_template,
|
||||||
|
|
|
@ -5,16 +5,7 @@ import json
|
||||||
import logging
|
import logging
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from types import ModuleType, TracebackType
|
from types import ModuleType, TracebackType
|
||||||
from typing import ( # noqa: F401 pylint: disable=unused-import
|
from typing import Awaitable, Dict, Iterable, List, Optional, Tuple, Type, Union
|
||||||
Awaitable,
|
|
||||||
Dict,
|
|
||||||
Iterable,
|
|
||||||
List,
|
|
||||||
Optional,
|
|
||||||
Tuple,
|
|
||||||
Type,
|
|
||||||
Union,
|
|
||||||
)
|
|
||||||
|
|
||||||
from homeassistant.loader import bind_hass, async_get_integration, IntegrationNotFound
|
from homeassistant.loader import bind_hass, async_get_integration, IntegrationNotFound
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
|
@ -99,7 +90,7 @@ class AsyncTrackStates:
|
||||||
def __init__(self, hass: HomeAssistantType) -> None:
|
def __init__(self, hass: HomeAssistantType) -> None:
|
||||||
"""Initialize a TrackStates block."""
|
"""Initialize a TrackStates block."""
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
self.states = [] # type: List[State]
|
self.states: List[State] = []
|
||||||
|
|
||||||
# pylint: disable=attribute-defined-outside-init
|
# pylint: disable=attribute-defined-outside-init
|
||||||
def __enter__(self) -> List[State]:
|
def __enter__(self) -> List[State]:
|
||||||
|
@ -147,7 +138,7 @@ async def async_reproduce_state(
|
||||||
if isinstance(states, State):
|
if isinstance(states, State):
|
||||||
states = [states]
|
states = [states]
|
||||||
|
|
||||||
to_call = defaultdict(list) # type: Dict[str, List[State]]
|
to_call: Dict[str, List[State]] = defaultdict(list)
|
||||||
|
|
||||||
for state in states:
|
for state in states:
|
||||||
to_call[state.domain].append(state)
|
to_call[state.domain].append(state)
|
||||||
|
@ -191,7 +182,7 @@ async def async_reproduce_state_legacy(
|
||||||
context: Optional[Context] = None,
|
context: Optional[Context] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Reproduce given state."""
|
"""Reproduce given state."""
|
||||||
to_call = defaultdict(list) # type: Dict[Tuple[str, str], List[str]]
|
to_call: Dict[Tuple[str, str], List[str]] = defaultdict(list)
|
||||||
|
|
||||||
if domain == GROUP_DOMAIN:
|
if domain == GROUP_DOMAIN:
|
||||||
service_domain = HASS_DOMAIN
|
service_domain = HASS_DOMAIN
|
||||||
|
@ -238,7 +229,7 @@ async def async_reproduce_state_legacy(
|
||||||
key = (service, json.dumps(dict(state.attributes), sort_keys=True))
|
key = (service, json.dumps(dict(state.attributes), sort_keys=True))
|
||||||
to_call[key].append(state.entity_id)
|
to_call[key].append(state.entity_id)
|
||||||
|
|
||||||
domain_tasks = [] # type: List[Awaitable[Optional[bool]]]
|
domain_tasks: List[Awaitable[Optional[bool]]] = []
|
||||||
for (service, service_data), entity_ids in to_call.items():
|
for (service, service_data), entity_ids in to_call.items():
|
||||||
data = json.loads(service_data)
|
data = json.loads(service_data)
|
||||||
data[ATTR_ENTITY_ID] = entity_ids
|
data[ATTR_ENTITY_ID] = entity_ids
|
||||||
|
|
|
@ -70,11 +70,11 @@ class Store:
|
||||||
self.key = key
|
self.key = key
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
self._private = private
|
self._private = private
|
||||||
self._data = None # type: Optional[Dict[str, Any]]
|
self._data: Optional[Dict[str, Any]] = None
|
||||||
self._unsub_delay_listener = None
|
self._unsub_delay_listener = None
|
||||||
self._unsub_stop_listener = None
|
self._unsub_stop_listener = None
|
||||||
self._write_lock = asyncio.Lock()
|
self._write_lock = asyncio.Lock()
|
||||||
self._load_task = None # type: Optional[asyncio.Future]
|
self._load_task: Optional[asyncio.Future] = None
|
||||||
self._encoder = encoder
|
self._encoder = encoder
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -68,14 +68,14 @@ def get_location_astral_event_next(
|
||||||
mod = -1
|
mod = -1
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
next_dt = (
|
next_dt: datetime.datetime = (
|
||||||
getattr(location, event)(
|
getattr(location, event)(
|
||||||
dt_util.as_local(utc_point_in_time).date()
|
dt_util.as_local(utc_point_in_time).date()
|
||||||
+ datetime.timedelta(days=mod),
|
+ datetime.timedelta(days=mod),
|
||||||
local=False,
|
local=False,
|
||||||
)
|
)
|
||||||
+ offset
|
+ offset
|
||||||
) # type: datetime.datetime
|
)
|
||||||
if next_dt > utc_point_in_time:
|
if next_dt > utc_point_in_time:
|
||||||
return next_dt
|
return next_dt
|
||||||
except AstralError:
|
except AstralError:
|
||||||
|
|
|
@ -82,7 +82,7 @@ def build_resources(
|
||||||
) -> Dict[str, Dict[str, Any]]:
|
) -> Dict[str, Dict[str, Any]]:
|
||||||
"""Build the resources response for the given components."""
|
"""Build the resources response for the given components."""
|
||||||
# Build response
|
# Build response
|
||||||
resources = {} # type: Dict[str, Dict[str, Any]]
|
resources: Dict[str, Dict[str, Any]] = {}
|
||||||
for component in components:
|
for component in components:
|
||||||
if "." not in component:
|
if "." not in component:
|
||||||
domain = component
|
domain = component
|
||||||
|
|
|
@ -127,7 +127,7 @@ async def async_get_config_flows(hass: "HomeAssistant") -> Set[str]:
|
||||||
"""Return cached list of config flows."""
|
"""Return cached list of config flows."""
|
||||||
from homeassistant.generated.config_flows import FLOWS
|
from homeassistant.generated.config_flows import FLOWS
|
||||||
|
|
||||||
flows = set() # type: Set[str]
|
flows: Set[str] = set()
|
||||||
flows.update(FLOWS)
|
flows.update(FLOWS)
|
||||||
|
|
||||||
integrations = await async_get_custom_components(hass)
|
integrations = await async_get_custom_components(hass)
|
||||||
|
@ -201,14 +201,14 @@ class Integration:
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
self.pkg_path = pkg_path
|
self.pkg_path = pkg_path
|
||||||
self.file_path = file_path
|
self.file_path = file_path
|
||||||
self.name = manifest["name"] # type: str
|
self.name: str = manifest["name"]
|
||||||
self.domain = manifest["domain"] # type: str
|
self.domain: str = manifest["domain"]
|
||||||
self.dependencies = manifest["dependencies"] # type: List[str]
|
self.dependencies: List[str] = manifest["dependencies"]
|
||||||
self.after_dependencies = manifest.get(
|
self.after_dependencies: Optional[List[str]] = manifest.get(
|
||||||
"after_dependencies"
|
"after_dependencies"
|
||||||
) # type: Optional[List[str]]
|
)
|
||||||
self.requirements = manifest["requirements"] # type: List[str]
|
self.requirements: List[str] = manifest["requirements"]
|
||||||
self.config_flow = manifest.get("config_flow", False) # type: bool
|
self.config_flow: bool = manifest.get("config_flow", False)
|
||||||
_LOGGER.info("Loaded %s from %s", self.domain, pkg_path)
|
_LOGGER.info("Loaded %s from %s", self.domain, pkg_path)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -246,9 +246,7 @@ async def async_get_integration(hass: "HomeAssistant", domain: str) -> Integrati
|
||||||
raise IntegrationNotFound(domain)
|
raise IntegrationNotFound(domain)
|
||||||
cache = hass.data[DATA_INTEGRATIONS] = {}
|
cache = hass.data[DATA_INTEGRATIONS] = {}
|
||||||
|
|
||||||
int_or_evt = cache.get(
|
int_or_evt: Union[Integration, asyncio.Event, None] = cache.get(domain, _UNDEF)
|
||||||
domain, _UNDEF
|
|
||||||
) # type: Union[Integration, asyncio.Event, None]
|
|
||||||
|
|
||||||
if isinstance(int_or_evt, asyncio.Event):
|
if isinstance(int_or_evt, asyncio.Event):
|
||||||
await int_or_evt.wait()
|
await int_or_evt.wait()
|
||||||
|
@ -428,7 +426,7 @@ class Components:
|
||||||
integration = self._hass.data.get(DATA_INTEGRATIONS, {}).get(comp_name)
|
integration = self._hass.data.get(DATA_INTEGRATIONS, {}).get(comp_name)
|
||||||
|
|
||||||
if isinstance(integration, Integration):
|
if isinstance(integration, Integration):
|
||||||
component = integration.get_component() # type: Optional[ModuleType]
|
component: Optional[ModuleType] = integration.get_component()
|
||||||
else:
|
else:
|
||||||
# Fallback to importing old-school
|
# Fallback to importing old-school
|
||||||
component = _load_file(self._hass, comp_name, LOOKUP_PATHS)
|
component = _load_file(self._hass, comp_name, LOOKUP_PATHS)
|
||||||
|
|
|
@ -15,7 +15,7 @@ from homeassistant.util import dt as dt_util
|
||||||
# mypy: allow-untyped-calls, allow-untyped-defs, no-check-untyped-defs
|
# mypy: allow-untyped-calls, allow-untyped-defs, no-check-untyped-defs
|
||||||
# mypy: no-warn-return-any
|
# mypy: no-warn-return-any
|
||||||
|
|
||||||
BENCHMARKS = {} # type: Dict[str, Callable]
|
BENCHMARKS: Dict[str, Callable] = {}
|
||||||
|
|
||||||
|
|
||||||
def run(args):
|
def run(args):
|
||||||
|
|
|
@ -21,11 +21,11 @@ REQUIREMENTS = ("colorlog==4.0.2",)
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
MOCKS = {
|
MOCKS: Dict[str, Tuple[str, Callable]] = {
|
||||||
"load": ("homeassistant.util.yaml.loader.load_yaml", yaml_loader.load_yaml),
|
"load": ("homeassistant.util.yaml.loader.load_yaml", yaml_loader.load_yaml),
|
||||||
"load*": ("homeassistant.config.load_yaml", yaml_loader.load_yaml),
|
"load*": ("homeassistant.config.load_yaml", yaml_loader.load_yaml),
|
||||||
"secrets": ("homeassistant.util.yaml.loader.secret_yaml", yaml_loader.secret_yaml),
|
"secrets": ("homeassistant.util.yaml.loader.secret_yaml", yaml_loader.secret_yaml),
|
||||||
} # type: Dict[str, Tuple[str, Callable]]
|
}
|
||||||
SILENCE = ("homeassistant.scripts.check_config.yaml_loader.clear_secret_cache",)
|
SILENCE = ("homeassistant.scripts.check_config.yaml_loader.clear_secret_cache",)
|
||||||
|
|
||||||
PATCHES: Dict[str, Any] = {}
|
PATCHES: Dict[str, Any] = {}
|
||||||
|
@ -82,7 +82,7 @@ def run(script_args: List) -> int:
|
||||||
|
|
||||||
res = check(config_dir, args.secrets)
|
res = check(config_dir, args.secrets)
|
||||||
|
|
||||||
domain_info = [] # type: List[str]
|
domain_info: List[str] = []
|
||||||
if args.info:
|
if args.info:
|
||||||
domain_info = args.info.split(",")
|
domain_info = args.info.split(",")
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ def run(script_args: List) -> int:
|
||||||
dump_dict(res["components"].get(domain, None))
|
dump_dict(res["components"].get(domain, None))
|
||||||
|
|
||||||
if args.secrets:
|
if args.secrets:
|
||||||
flatsecret = {} # type: Dict[str, str]
|
flatsecret: Dict[str, str] = {}
|
||||||
|
|
||||||
for sfn, sdict in res["secret_cache"].items():
|
for sfn, sdict in res["secret_cache"].items():
|
||||||
sss = []
|
sss = []
|
||||||
|
@ -153,13 +153,13 @@ def run(script_args: List) -> int:
|
||||||
def check(config_dir, secrets=False):
|
def check(config_dir, secrets=False):
|
||||||
"""Perform a check by mocking hass load functions."""
|
"""Perform a check by mocking hass load functions."""
|
||||||
logging.getLogger("homeassistant.loader").setLevel(logging.CRITICAL)
|
logging.getLogger("homeassistant.loader").setLevel(logging.CRITICAL)
|
||||||
res = {
|
res: Dict[str, Any] = {
|
||||||
"yaml_files": OrderedDict(), # yaml_files loaded
|
"yaml_files": OrderedDict(), # yaml_files loaded
|
||||||
"secrets": OrderedDict(), # secret cache and secrets loaded
|
"secrets": OrderedDict(), # secret cache and secrets loaded
|
||||||
"except": OrderedDict(), # exceptions raised (with config)
|
"except": OrderedDict(), # exceptions raised (with config)
|
||||||
#'components' is a HomeAssistantConfig # noqa: E265
|
#'components' is a HomeAssistantConfig # noqa: E265
|
||||||
"secret_cache": None,
|
"secret_cache": None,
|
||||||
} # type: Dict[str, Any]
|
}
|
||||||
|
|
||||||
# pylint: disable=possibly-unused-variable
|
# pylint: disable=possibly-unused-variable
|
||||||
def mock_load(filename):
|
def mock_load(filename):
|
||||||
|
|
|
@ -22,7 +22,7 @@ class MockRequest:
|
||||||
self.method = method
|
self.method = method
|
||||||
self.url = url
|
self.url = url
|
||||||
self.status = status
|
self.status = status
|
||||||
self.headers = CIMultiDict(headers or {}) # type: CIMultiDict[str]
|
self.headers: CIMultiDict[str] = CIMultiDict(headers or {})
|
||||||
self.query_string = query_string or ""
|
self.query_string = query_string or ""
|
||||||
self._content = content
|
self._content = content
|
||||||
|
|
||||||
|
|
|
@ -103,11 +103,11 @@ def _chain_future(
|
||||||
raise TypeError("A future is required for destination argument")
|
raise TypeError("A future is required for destination argument")
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
if isinstance(source, Future):
|
if isinstance(source, Future):
|
||||||
source_loop = source._loop # type: Optional[AbstractEventLoop]
|
source_loop: Optional[AbstractEventLoop] = source._loop
|
||||||
else:
|
else:
|
||||||
source_loop = None
|
source_loop = None
|
||||||
if isinstance(destination, Future):
|
if isinstance(destination, Future):
|
||||||
dest_loop = destination._loop # type: Optional[AbstractEventLoop]
|
dest_loop: Optional[AbstractEventLoop] = destination._loop
|
||||||
else:
|
else:
|
||||||
dest_loop = None
|
dest_loop = None
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ def run_coroutine_threadsafe(
|
||||||
|
|
||||||
if not coroutines.iscoroutine(coro):
|
if not coroutines.iscoroutine(coro):
|
||||||
raise TypeError("A coroutine object is required")
|
raise TypeError("A coroutine object is required")
|
||||||
future = concurrent.futures.Future() # type: concurrent.futures.Future
|
future: concurrent.futures.Future = concurrent.futures.Future()
|
||||||
|
|
||||||
def callback() -> None:
|
def callback() -> None:
|
||||||
"""Handle the call to the coroutine."""
|
"""Handle the call to the coroutine."""
|
||||||
|
@ -200,7 +200,7 @@ def run_callback_threadsafe(
|
||||||
if ident is not None and ident == threading.get_ident():
|
if ident is not None and ident == threading.get_ident():
|
||||||
raise RuntimeError("Cannot be called from within the event loop")
|
raise RuntimeError("Cannot be called from within the event loop")
|
||||||
|
|
||||||
future = concurrent.futures.Future() # type: concurrent.futures.Future
|
future: concurrent.futures.Future = concurrent.futures.Future()
|
||||||
|
|
||||||
def run_callback() -> None:
|
def run_callback() -> None:
|
||||||
"""Run callback and store result."""
|
"""Run callback and store result."""
|
||||||
|
|
|
@ -1,25 +1,17 @@
|
||||||
"""Helper methods to handle the time in Home Assistant."""
|
"""Helper methods to handle the time in Home Assistant."""
|
||||||
import datetime as dt
|
import datetime as dt
|
||||||
import re
|
import re
|
||||||
from typing import (
|
from typing import Any, Union, Optional, Tuple, List, cast, Dict
|
||||||
Any,
|
|
||||||
Union,
|
|
||||||
Optional, # noqa pylint: disable=unused-import
|
|
||||||
Tuple,
|
|
||||||
List,
|
|
||||||
cast,
|
|
||||||
Dict,
|
|
||||||
)
|
|
||||||
|
|
||||||
import pytz
|
import pytz
|
||||||
import pytz.exceptions as pytzexceptions
|
import pytz.exceptions as pytzexceptions
|
||||||
import pytz.tzinfo as pytzinfo # noqa pylint: disable=unused-import
|
import pytz.tzinfo as pytzinfo
|
||||||
|
|
||||||
from homeassistant.const import MATCH_ALL
|
from homeassistant.const import MATCH_ALL
|
||||||
|
|
||||||
DATE_STR_FORMAT = "%Y-%m-%d"
|
DATE_STR_FORMAT = "%Y-%m-%d"
|
||||||
UTC = pytz.utc
|
UTC = pytz.utc
|
||||||
DEFAULT_TIME_ZONE = pytz.utc # type: dt.tzinfo
|
DEFAULT_TIME_ZONE: dt.tzinfo = pytz.utc
|
||||||
|
|
||||||
|
|
||||||
# Copyright (c) Django Software Foundation and individual contributors.
|
# Copyright (c) Django Software Foundation and individual contributors.
|
||||||
|
@ -83,7 +75,7 @@ def as_utc(dattim: dt.datetime) -> dt.datetime:
|
||||||
def as_timestamp(dt_value: dt.datetime) -> float:
|
def as_timestamp(dt_value: dt.datetime) -> float:
|
||||||
"""Convert a date/time into a unix time (seconds since 1970)."""
|
"""Convert a date/time into a unix time (seconds since 1970)."""
|
||||||
if hasattr(dt_value, "timestamp"):
|
if hasattr(dt_value, "timestamp"):
|
||||||
parsed_dt = dt_value # type: Optional[dt.datetime]
|
parsed_dt: Optional[dt.datetime] = dt_value
|
||||||
else:
|
else:
|
||||||
parsed_dt = parse_datetime(str(dt_value))
|
parsed_dt = parse_datetime(str(dt_value))
|
||||||
if parsed_dt is None:
|
if parsed_dt is None:
|
||||||
|
@ -111,7 +103,7 @@ def start_of_local_day(
|
||||||
) -> dt.datetime:
|
) -> dt.datetime:
|
||||||
"""Return local datetime object of start of day from date or datetime."""
|
"""Return local datetime object of start of day from date or datetime."""
|
||||||
if dt_or_d is None:
|
if dt_or_d is None:
|
||||||
date = now().date() # type: dt.date
|
date: dt.date = now().date()
|
||||||
elif isinstance(dt_or_d, dt.datetime):
|
elif isinstance(dt_or_d, dt.datetime):
|
||||||
date = dt_or_d.date()
|
date = dt_or_d.date()
|
||||||
return DEFAULT_TIME_ZONE.localize( # type: ignore
|
return DEFAULT_TIME_ZONE.localize( # type: ignore
|
||||||
|
@ -133,12 +125,12 @@ def parse_datetime(dt_str: str) -> Optional[dt.datetime]:
|
||||||
match = DATETIME_RE.match(dt_str)
|
match = DATETIME_RE.match(dt_str)
|
||||||
if not match:
|
if not match:
|
||||||
return None
|
return None
|
||||||
kws = match.groupdict() # type: Dict[str, Any]
|
kws: Dict[str, Any] = match.groupdict()
|
||||||
if kws["microsecond"]:
|
if kws["microsecond"]:
|
||||||
kws["microsecond"] = kws["microsecond"].ljust(6, "0")
|
kws["microsecond"] = kws["microsecond"].ljust(6, "0")
|
||||||
tzinfo_str = kws.pop("tzinfo")
|
tzinfo_str = kws.pop("tzinfo")
|
||||||
|
|
||||||
tzinfo = None # type: Optional[dt.tzinfo]
|
tzinfo: Optional[dt.tzinfo] = None
|
||||||
if tzinfo_str == "Z":
|
if tzinfo_str == "Z":
|
||||||
tzinfo = UTC
|
tzinfo = UTC
|
||||||
elif tzinfo_str is not None:
|
elif tzinfo_str is not None:
|
||||||
|
@ -324,7 +316,7 @@ def find_next_time_expression_time(
|
||||||
# Now we need to handle timezones. We will make this datetime object
|
# Now we need to handle timezones. We will make this datetime object
|
||||||
# "naive" first and then re-convert it to the target timezone.
|
# "naive" first and then re-convert it to the target timezone.
|
||||||
# This is so that we can call pytz's localize and handle DST changes.
|
# This is so that we can call pytz's localize and handle DST changes.
|
||||||
tzinfo = result.tzinfo # type: pytzinfo.DstTzInfo
|
tzinfo: pytzinfo.DstTzInfo = result.tzinfo
|
||||||
result = result.replace(tzinfo=None)
|
result = result.replace(tzinfo=None)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -34,7 +34,7 @@ class AsyncHandler:
|
||||||
"""Initialize async logging handler wrapper."""
|
"""Initialize async logging handler wrapper."""
|
||||||
self.handler = handler
|
self.handler = handler
|
||||||
self.loop = loop
|
self.loop = loop
|
||||||
self._queue = asyncio.Queue(loop=loop) # type: asyncio.Queue
|
self._queue: asyncio.Queue = asyncio.Queue(loop=loop)
|
||||||
self._thread = threading.Thread(target=self._process)
|
self._thread = threading.Thread(target=self._process)
|
||||||
|
|
||||||
# Delegate from handler
|
# Delegate from handler
|
||||||
|
|
|
@ -22,7 +22,7 @@ JSON_TYPE = Union[List, Dict, str] # pylint: disable=invalid-name
|
||||||
class ExtSafeConstructor(SafeConstructor):
|
class ExtSafeConstructor(SafeConstructor):
|
||||||
"""Extended SafeConstructor."""
|
"""Extended SafeConstructor."""
|
||||||
|
|
||||||
name = None # type: Optional[str]
|
name: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
class UnsupportedYamlError(HomeAssistantError):
|
class UnsupportedYamlError(HomeAssistantError):
|
||||||
|
@ -67,7 +67,7 @@ def object_to_yaml(data: JSON_TYPE) -> str:
|
||||||
stream = StringIO()
|
stream = StringIO()
|
||||||
try:
|
try:
|
||||||
yaml.dump(data, stream)
|
yaml.dump(data, stream)
|
||||||
result = stream.getvalue() # type: str
|
result: str = stream.getvalue()
|
||||||
return result
|
return result
|
||||||
except YAMLError as exc:
|
except YAMLError as exc:
|
||||||
_LOGGER.error("YAML error: %s", exc)
|
_LOGGER.error("YAML error: %s", exc)
|
||||||
|
@ -78,7 +78,7 @@ def yaml_to_object(data: str) -> JSON_TYPE:
|
||||||
"""Create object from yaml string."""
|
"""Create object from yaml string."""
|
||||||
yaml = YAML(typ="rt")
|
yaml = YAML(typ="rt")
|
||||||
try:
|
try:
|
||||||
result = yaml.load(data) # type: Union[List, Dict, str]
|
result: Union[List, Dict, str] = yaml.load(data)
|
||||||
return result
|
return result
|
||||||
except YAMLError as exc:
|
except YAMLError as exc:
|
||||||
_LOGGER.error("YAML error: %s", exc)
|
_LOGGER.error("YAML error: %s", exc)
|
||||||
|
|
|
@ -75,7 +75,7 @@ class UnitSystem:
|
||||||
pressure: str,
|
pressure: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the unit system object."""
|
"""Initialize the unit system object."""
|
||||||
errors = ", ".join(
|
errors: str = ", ".join(
|
||||||
UNIT_NOT_RECOGNIZED_TEMPLATE.format(unit, unit_type)
|
UNIT_NOT_RECOGNIZED_TEMPLATE.format(unit, unit_type)
|
||||||
for unit, unit_type in [
|
for unit, unit_type in [
|
||||||
(temperature, TEMPERATURE),
|
(temperature, TEMPERATURE),
|
||||||
|
@ -85,7 +85,7 @@ class UnitSystem:
|
||||||
(pressure, PRESSURE),
|
(pressure, PRESSURE),
|
||||||
]
|
]
|
||||||
if not is_valid_unit(unit, unit_type)
|
if not is_valid_unit(unit, unit_type)
|
||||||
) # type: str
|
)
|
||||||
|
|
||||||
if errors:
|
if errors:
|
||||||
raise ValueError(errors)
|
raise ValueError(errors)
|
||||||
|
|
|
@ -29,7 +29,7 @@ def represent_odict( # type: ignore
|
||||||
dump, tag, mapping, flow_style=None
|
dump, tag, mapping, flow_style=None
|
||||||
) -> yaml.MappingNode:
|
) -> yaml.MappingNode:
|
||||||
"""Like BaseRepresenter.represent_mapping but does not issue the sort()."""
|
"""Like BaseRepresenter.represent_mapping but does not issue the sort()."""
|
||||||
value = [] # type: list
|
value: list = []
|
||||||
node = yaml.MappingNode(tag, value, flow_style=flow_style)
|
node = yaml.MappingNode(tag, value, flow_style=flow_style)
|
||||||
if dump.alias_key is not None:
|
if dump.alias_key is not None:
|
||||||
dump.represented_objects[dump.alias_key] = node
|
dump.represented_objects[dump.alias_key] = node
|
||||||
|
|
|
@ -26,12 +26,12 @@ from .objects import NodeListClass, NodeStrClass
|
||||||
|
|
||||||
# mypy: allow-untyped-calls, no-warn-return-any
|
# mypy: allow-untyped-calls, no-warn-return-any
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
|
||||||
__SECRET_CACHE = {} # type: Dict[str, JSON_TYPE]
|
|
||||||
|
|
||||||
JSON_TYPE = Union[List, Dict, str] # pylint: disable=invalid-name
|
JSON_TYPE = Union[List, Dict, str] # pylint: disable=invalid-name
|
||||||
DICT_T = TypeVar("DICT_T", bound=Dict) # pylint: disable=invalid-name
|
DICT_T = TypeVar("DICT_T", bound=Dict) # pylint: disable=invalid-name
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
__SECRET_CACHE: Dict[str, JSON_TYPE] = {}
|
||||||
|
|
||||||
|
|
||||||
def clear_secret_cache() -> None:
|
def clear_secret_cache() -> None:
|
||||||
"""Clear the secret cache.
|
"""Clear the secret cache.
|
||||||
|
@ -47,10 +47,8 @@ class SafeLineLoader(yaml.SafeLoader):
|
||||||
|
|
||||||
def compose_node(self, parent: yaml.nodes.Node, index: int) -> yaml.nodes.Node:
|
def compose_node(self, parent: yaml.nodes.Node, index: int) -> yaml.nodes.Node:
|
||||||
"""Annotate a node with the first line it was seen."""
|
"""Annotate a node with the first line it was seen."""
|
||||||
last_line = self.line # type: int
|
last_line: int = self.line
|
||||||
node = super(SafeLineLoader, self).compose_node(
|
node: yaml.nodes.Node = super(SafeLineLoader, self).compose_node(parent, index)
|
||||||
parent, index
|
|
||||||
) # type: yaml.nodes.Node
|
|
||||||
node.__line__ = last_line + 1 # type: ignore
|
node.__line__ = last_line + 1 # type: ignore
|
||||||
return node
|
return node
|
||||||
|
|
||||||
|
@ -141,7 +139,7 @@ def _include_dir_named_yaml(
|
||||||
loader: SafeLineLoader, node: yaml.nodes.Node
|
loader: SafeLineLoader, node: yaml.nodes.Node
|
||||||
) -> OrderedDict:
|
) -> OrderedDict:
|
||||||
"""Load multiple files from directory as a dictionary."""
|
"""Load multiple files from directory as a dictionary."""
|
||||||
mapping = OrderedDict() # type: OrderedDict
|
mapping: OrderedDict = OrderedDict()
|
||||||
loc = os.path.join(os.path.dirname(loader.name), node.value)
|
loc = os.path.join(os.path.dirname(loader.name), node.value)
|
||||||
for fname in _find_files(loc, "*.yaml"):
|
for fname in _find_files(loc, "*.yaml"):
|
||||||
filename = os.path.splitext(os.path.basename(fname))[0]
|
filename = os.path.splitext(os.path.basename(fname))[0]
|
||||||
|
@ -155,7 +153,7 @@ def _include_dir_merge_named_yaml(
|
||||||
loader: SafeLineLoader, node: yaml.nodes.Node
|
loader: SafeLineLoader, node: yaml.nodes.Node
|
||||||
) -> OrderedDict:
|
) -> OrderedDict:
|
||||||
"""Load multiple files from directory as a merged dictionary."""
|
"""Load multiple files from directory as a merged dictionary."""
|
||||||
mapping = OrderedDict() # type: OrderedDict
|
mapping: OrderedDict = OrderedDict()
|
||||||
loc = os.path.join(os.path.dirname(loader.name), node.value)
|
loc = os.path.join(os.path.dirname(loader.name), node.value)
|
||||||
for fname in _find_files(loc, "*.yaml"):
|
for fname in _find_files(loc, "*.yaml"):
|
||||||
if os.path.basename(fname) == SECRET_YAML:
|
if os.path.basename(fname) == SECRET_YAML:
|
||||||
|
@ -182,8 +180,8 @@ def _include_dir_merge_list_yaml(
|
||||||
loader: SafeLineLoader, node: yaml.nodes.Node
|
loader: SafeLineLoader, node: yaml.nodes.Node
|
||||||
) -> JSON_TYPE:
|
) -> JSON_TYPE:
|
||||||
"""Load multiple files from directory as a merged list."""
|
"""Load multiple files from directory as a merged list."""
|
||||||
loc = os.path.join(os.path.dirname(loader.name), node.value) # type: str
|
loc: str = os.path.join(os.path.dirname(loader.name), node.value)
|
||||||
merged_list = [] # type: List[JSON_TYPE]
|
merged_list: List[JSON_TYPE] = []
|
||||||
for fname in _find_files(loc, "*.yaml"):
|
for fname in _find_files(loc, "*.yaml"):
|
||||||
if os.path.basename(fname) == SECRET_YAML:
|
if os.path.basename(fname) == SECRET_YAML:
|
||||||
continue
|
continue
|
||||||
|
@ -198,7 +196,7 @@ def _ordered_dict(loader: SafeLineLoader, node: yaml.nodes.MappingNode) -> Order
|
||||||
loader.flatten_mapping(node)
|
loader.flatten_mapping(node)
|
||||||
nodes = loader.construct_pairs(node)
|
nodes = loader.construct_pairs(node)
|
||||||
|
|
||||||
seen = {} # type: Dict
|
seen: Dict = {}
|
||||||
for (key, _), (child_node, _) in zip(nodes, node.value):
|
for (key, _), (child_node, _) in zip(nodes, node.value):
|
||||||
line = child_node.start_mark.line
|
line = child_node.start_mark.line
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue