Update typing 16 (#48087)

This commit is contained in:
Marc Mueller 2021-03-18 22:58:19 +01:00 committed by GitHub
parent 0f5efca76b
commit 4cb7718192
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
59 changed files with 180 additions and 166 deletions

View file

@ -43,7 +43,7 @@ class User:
groups: list[Group] = attr.ib(factory=list, eq=False, order=False) groups: list[Group] = attr.ib(factory=list, eq=False, order=False)
# List of credentials of a user. # List of credentials of a user.
credentials: list["Credentials"] = attr.ib(factory=list, eq=False, order=False) credentials: list[Credentials] = attr.ib(factory=list, eq=False, order=False)
# Tokens associated with a user. # Tokens associated with a user.
refresh_tokens: dict[str, "RefreshToken"] = attr.ib( refresh_tokens: dict[str, "RefreshToken"] = attr.ib(

View file

@ -76,7 +76,7 @@ STAGE_1_INTEGRATIONS = {
async def async_setup_hass( async def async_setup_hass(
runtime_config: "RuntimeConfig", runtime_config: RuntimeConfig,
) -> core.HomeAssistant | None: ) -> core.HomeAssistant | None:
"""Set up Home Assistant.""" """Set up Home Assistant."""
hass = core.HomeAssistant() hass = core.HomeAssistant()

View file

@ -253,7 +253,7 @@ class AlexaEntity:
The API handlers should manipulate entities only through this interface. The API handlers should manipulate entities only through this interface.
""" """
def __init__(self, hass: HomeAssistant, config: "AbstractConfig", entity: State): def __init__(self, hass: HomeAssistant, config: AbstractConfig, entity: State):
"""Initialize Alexa Entity.""" """Initialize Alexa Entity."""
self.hass = hass self.hass = hass
self.config = config self.config = config

View file

@ -15,13 +15,13 @@ class ChromecastInfo:
This also has the same attributes as the mDNS fields by zeroconf. This also has the same attributes as the mDNS fields by zeroconf.
""" """
services: Optional[set] = attr.ib() services: set | None = attr.ib()
uuid: Optional[str] = attr.ib( uuid: str | None = attr.ib(
converter=attr.converters.optional(str), default=None converter=attr.converters.optional(str), default=None
) # always convert UUID to string if not None ) # always convert UUID to string if not None
_manufacturer = attr.ib(type=Optional[str], default=None) _manufacturer = attr.ib(type=Optional[str], default=None)
model_name: str = attr.ib(default="") model_name: str = attr.ib(default="")
friendly_name: Optional[str] = attr.ib(default=None) friendly_name: str | None = attr.ib(default=None)
is_audio_group = attr.ib(type=Optional[bool], default=False) is_audio_group = attr.ib(type=Optional[bool], default=False)
is_dynamic_group = attr.ib(type=Optional[bool], default=None) is_dynamic_group = attr.ib(type=Optional[bool], default=None)

View file

@ -52,7 +52,7 @@ class RuntimeEntryData:
"""Store runtime data for esphome config entries.""" """Store runtime data for esphome config entries."""
entry_id: str = attr.ib() entry_id: str = attr.ib()
client: "APIClient" = attr.ib() client: APIClient = attr.ib()
store: Store = attr.ib() store: Store = attr.ib()
reconnect_task: asyncio.Task | None = attr.ib(default=None) reconnect_task: asyncio.Task | None = attr.ib(default=None)
state: dict[str, dict[str, Any]] = attr.ib(factory=dict) state: dict[str, dict[str, Any]] = attr.ib(factory=dict)

View file

@ -225,7 +225,7 @@ class HERETravelTimeSensor(Entity):
destination: str, destination: str,
origin_entity_id: str, origin_entity_id: str,
destination_entity_id: str, destination_entity_id: str,
here_data: "HERETravelTimeData", here_data: HERETravelTimeData,
) -> None: ) -> None:
"""Initialize the sensor.""" """Initialize the sensor."""
self._name = name self._name = name

View file

@ -78,7 +78,7 @@ async def async_setup_entry(
@callback @callback
def init_controller(ctrl: Controller): def init_controller(ctrl: Controller):
"""Register the controller device and the containing zones.""" """Register the controller device and the containing zones."""
conf = hass.data.get(DATA_CONFIG) # type: ConfigType conf: ConfigType = hass.data.get(DATA_CONFIG)
# Filter out any entities excluded in the config file # Filter out any entities excluded in the config file
if conf and ctrl.device_uid in conf[CONF_EXCLUDE]: if conf and ctrl.device_uid in conf[CONF_EXCLUDE]:

View file

@ -1,4 +1,6 @@
"""Lovelace dashboard support.""" """Lovelace dashboard support."""
from __future__ import annotations
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
import logging import logging
import os import os
@ -231,7 +233,7 @@ class DashboardsCollection(collection.StorageCollection):
_LOGGER, _LOGGER,
) )
async def _async_load_data(self) -> Optional[dict]: async def _async_load_data(self) -> dict | None:
"""Load the data.""" """Load the data."""
data = await self.store.async_load() data = await self.store.async_load()

View file

@ -43,7 +43,7 @@ def supports_push(hass, webhook_id: str) -> bool:
@callback @callback
def get_notify_service(hass, webhook_id: str) -> str | None: def get_notify_service(hass, webhook_id: str) -> str | None:
"""Return the notify service for this webhook ID.""" """Return the notify service for this webhook ID."""
notify_service: "MobileAppNotificationService" = hass.data[DOMAIN][DATA_NOTIFY] notify_service: MobileAppNotificationService = hass.data[DOMAIN][DATA_NOTIFY]
for target_service, target_webhook_id in notify_service.registered_targets.items(): for target_service, target_webhook_id in notify_service.registered_targets.items():
if target_webhook_id == webhook_id: if target_webhook_id == webhook_id:

View file

@ -87,7 +87,7 @@ class TriggerInstance:
action: AutomationActionType = attr.ib() action: AutomationActionType = attr.ib()
automation_info: dict = attr.ib() automation_info: dict = attr.ib()
trigger: "Trigger" = attr.ib() trigger: Trigger = attr.ib()
remove: CALLBACK_TYPE | None = attr.ib(default=None) remove: CALLBACK_TYPE | None = attr.ib(default=None)
async def async_attach_trigger(self): async def async_attach_trigger(self):

View file

@ -69,7 +69,7 @@ ATTR_RSSI = "rssi"
async def async_setup_entry(hass, config_entry, async_add_entities): async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up the Shark IQ vacuum cleaner.""" """Set up the Shark IQ vacuum cleaner."""
coordinator: SharkIqUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id] coordinator: SharkIqUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]
devices: Iterable["SharkIqVacuum"] = coordinator.shark_vacs.values() devices: Iterable[SharkIqVacuum] = coordinator.shark_vacs.values()
device_names = [d.name for d in devices] device_names = [d.name for d in devices]
_LOGGER.debug( _LOGGER.debug(
"Found %d Shark IQ device(s): %s", "Found %d Shark IQ device(s): %s",

View file

@ -60,7 +60,7 @@ async def _register_system_health_platform(hass, integration_domain, platform):
async def get_integration_info( async def get_integration_info(
hass: HomeAssistant, registration: "SystemHealthRegistration" hass: HomeAssistant, registration: SystemHealthRegistration
): ):
"""Get integration system health.""" """Get integration system health."""
try: try:

View file

@ -48,7 +48,7 @@ class TriggerInstance:
action: AutomationActionType = attr.ib() action: AutomationActionType = attr.ib()
automation_info: dict = attr.ib() automation_info: dict = attr.ib()
trigger: "Trigger" = attr.ib() trigger: Trigger = attr.ib()
remove: CALLBACK_TYPE | None = attr.ib(default=None) remove: CALLBACK_TYPE | None = attr.ib(default=None)
async def async_attach_trigger(self): async def async_attach_trigger(self):

View file

@ -3,7 +3,6 @@ from __future__ import annotations
from datetime import timedelta from datetime import timedelta
import logging import logging
from typing import List
import transmissionrpc import transmissionrpc
from transmissionrpc.error import TransmissionError from transmissionrpc.error import TransmissionError
@ -173,8 +172,8 @@ class TransmissionClient:
"""Initialize the Transmission RPC API.""" """Initialize the Transmission RPC API."""
self.hass = hass self.hass = hass
self.config_entry = config_entry self.config_entry = config_entry
self.tm_api = None # type: transmissionrpc.Client self.tm_api: transmissionrpc.Client = None
self._tm_data = None # type: TransmissionData self._tm_data: TransmissionData = None
self.unsub_timer = None self.unsub_timer = None
@property @property
@ -345,14 +344,14 @@ class TransmissionData:
"""Initialize the Transmission RPC API.""" """Initialize the Transmission RPC API."""
self.hass = hass self.hass = hass
self.config = config self.config = config
self.data = None # type: transmissionrpc.Session self.data: transmissionrpc.Session = None
self.available = True # type: bool self.available: bool = True
self._all_torrents = [] # type: List[transmissionrpc.Torrent] self._all_torrents: list[transmissionrpc.Torrent] = []
self._api = api # type: transmissionrpc.Client self._api: transmissionrpc.Client = api
self._completed_torrents = [] # type: List[transmissionrpc.Torrent] self._completed_torrents: list[transmissionrpc.Torrent] = []
self._session = None # type: transmissionrpc.Session self._session: transmissionrpc.Session = None
self._started_torrents = [] # type: List[transmissionrpc.Torrent] self._started_torrents: list[transmissionrpc.Torrent] = []
self._torrents = [] # type: List[transmissionrpc.Torrent] self._torrents: list[transmissionrpc.Torrent] = []
@property @property
def host(self): def host(self):
@ -365,7 +364,7 @@ class TransmissionData:
return f"{DATA_UPDATED}-{self.host}" return f"{DATA_UPDATED}-{self.host}"
@property @property
def torrents(self) -> List[transmissionrpc.Torrent]: def torrents(self) -> list[transmissionrpc.Torrent]:
"""Get the list of torrents.""" """Get the list of torrents."""
return self._torrents return self._torrents

View file

@ -43,7 +43,7 @@ class TransmissionSensor(Entity):
def __init__(self, tm_client, client_name, sensor_name, sub_type=None): def __init__(self, tm_client, client_name, sensor_name, sub_type=None):
"""Initialize the sensor.""" """Initialize the sensor."""
self._tm_client = tm_client # type: TransmissionClient self._tm_client: TransmissionClient = tm_client
self._client_name = client_name self._client_name = client_name
self._name = sensor_name self._name = sensor_name
self._sub_type = sub_type self._sub_type = sub_type

View file

@ -74,7 +74,7 @@ async def async_update_options(hass: HomeAssistant, config_entry: ConfigEntry):
async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry): async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry):
"""Unload a config entry.""" """Unload a config entry."""
api: "WiffiIntegrationApi" = hass.data[DOMAIN][config_entry.entry_id] api: WiffiIntegrationApi = hass.data[DOMAIN][config_entry.entry_id]
await api.server.close_server() await api.server.close_server()
unload_ok = all( unload_ok = all(

View file

@ -1,4 +1,6 @@
"""Support for exposing Home Assistant via Zeroconf.""" """Support for exposing Home Assistant via Zeroconf."""
from __future__ import annotations
import fnmatch import fnmatch
from functools import partial from functools import partial
import ipaddress import ipaddress
@ -107,7 +109,7 @@ async def _async_get_instance(hass, **zcargs):
class HaServiceBrowser(ServiceBrowser): class HaServiceBrowser(ServiceBrowser):
"""ServiceBrowser that only consumes DNSPointer records.""" """ServiceBrowser that only consumes DNSPointer records."""
def update_record(self, zc: "Zeroconf", now: float, record: DNSRecord) -> None: def update_record(self, zc: Zeroconf, now: float, record: DNSRecord) -> None:
"""Pre-Filter update_record to DNSPointers for the configured type.""" """Pre-Filter update_record to DNSPointers for the configured type."""
# #

View file

@ -463,7 +463,7 @@ class ConfigEntriesFlowManager(data_entry_flow.FlowManager):
"""Manage all the config entry flows that are in progress.""" """Manage all the config entry flows that are in progress."""
def __init__( def __init__(
self, hass: HomeAssistant, config_entries: "ConfigEntries", hass_config: dict self, hass: HomeAssistant, config_entries: ConfigEntries, hass_config: dict
): ):
"""Initialize the config entry flow manager.""" """Initialize the config entry flow manager."""
super().__init__(hass) super().__init__(hass)

View file

@ -214,9 +214,9 @@ class CoreState(enum.Enum):
class HomeAssistant: class HomeAssistant:
"""Root object of the Home Assistant home automation.""" """Root object of the Home Assistant home automation."""
auth: "AuthManager" auth: AuthManager
http: "HomeAssistantHTTP" = None # type: ignore http: HomeAssistantHTTP = None # type: ignore
config_entries: "ConfigEntries" = None # type: ignore config_entries: ConfigEntries = None # type: ignore
def __init__(self) -> None: def __init__(self) -> None:
"""Initialize new Home Assistant object.""" """Initialize new Home Assistant object."""

View file

@ -86,13 +86,11 @@ class FlowManager(abc.ABC):
@abc.abstractmethod @abc.abstractmethod
async def async_finish_flow( async def async_finish_flow(
self, flow: "FlowHandler", result: dict[str, Any] self, flow: FlowHandler, result: dict[str, Any]
) -> dict[str, Any]: ) -> dict[str, Any]:
"""Finish a config flow and add an entry.""" """Finish a config flow and add an entry."""
async def async_post_init( async def async_post_init(self, flow: FlowHandler, result: dict[str, Any]) -> None:
self, flow: "FlowHandler", result: dict[str, Any]
) -> None:
"""Entry has finished executing its first step asynchronously.""" """Entry has finished executing its first step asynchronously."""
@callback @callback

View file

@ -10,7 +10,7 @@ if TYPE_CHECKING:
from .typing import ConfigType from .typing import ConfigType
def config_per_platform(config: "ConfigType", domain: str) -> Iterable[tuple[Any, Any]]: def config_per_platform(config: ConfigType, domain: str) -> Iterable[tuple[Any, Any]]:
"""Break a component config into different platforms. """Break a component config into different platforms.
For example, will find 'switch', 'switch 2', 'switch 3', .. etc For example, will find 'switch', 'switch 2', 'switch 3', .. etc
@ -34,7 +34,7 @@ def config_per_platform(config: "ConfigType", domain: str) -> Iterable[tuple[Any
yield platform, item yield platform, item
def extract_domain_configs(config: "ConfigType", domain: str) -> Sequence[str]: def extract_domain_configs(config: ConfigType, domain: str) -> Sequence[str]:
"""Extract keys from config for given domain name. """Extract keys from config for given domain name.
Async friendly. Async friendly.

View file

@ -658,7 +658,7 @@ def async_entries_for_config_entry(
@callback @callback
def async_config_entry_disabled_by_changed( def async_config_entry_disabled_by_changed(
registry: DeviceRegistry, config_entry: "ConfigEntry" registry: DeviceRegistry, config_entry: ConfigEntry
) -> None: ) -> None:
"""Handle a config entry being disabled or enabled. """Handle a config entry being disabled or enabled.

View file

@ -628,7 +628,7 @@ def async_entries_for_config_entry(
@callback @callback
def async_config_entry_disabled_by_changed( def async_config_entry_disabled_by_changed(
registry: EntityRegistry, config_entry: "ConfigEntry" registry: EntityRegistry, config_entry: ConfigEntry
) -> None: ) -> None:
"""Handle a config entry being disabled or enabled. """Handle a config entry being disabled or enabled.

View file

@ -291,7 +291,7 @@ class _ScriptRun:
def __init__( def __init__(
self, self,
hass: HomeAssistant, hass: HomeAssistant,
script: "Script", script: Script,
variables: dict[str, Any], variables: dict[str, Any],
context: Context | None, context: Context | None,
log_exceptions: bool, log_exceptions: bool,

View file

@ -1,4 +1,6 @@
"""Selectors for Home Assistant.""" """Selectors for Home Assistant."""
from __future__ import annotations
from typing import Any, Callable, Dict, cast from typing import Any, Callable, Dict, cast
import voluptuous as vol import voluptuous as vol
@ -9,7 +11,7 @@ from homeassistant.util import decorator
SELECTORS = decorator.Registry() SELECTORS = decorator.Registry()
def validate_selector(config: Any) -> Dict: def validate_selector(config: Any) -> dict:
"""Validate a selector.""" """Validate a selector."""
if not isinstance(config, dict): if not isinstance(config, dict):
raise vol.Invalid("Expected a dictionary") raise vol.Invalid("Expected a dictionary")

View file

@ -5,16 +5,7 @@ import asyncio
import dataclasses import dataclasses
from functools import partial, wraps from functools import partial, wraps
import logging import logging
from typing import ( from typing import TYPE_CHECKING, Any, Awaitable, Callable, Iterable, TypedDict
TYPE_CHECKING,
Any,
Awaitable,
Callable,
Iterable,
Optional,
TypedDict,
Union,
)
import voluptuous as vol import voluptuous as vol
@ -83,9 +74,9 @@ class ServiceTargetSelector:
def __init__(self, service_call: ha.ServiceCall): def __init__(self, service_call: ha.ServiceCall):
"""Extract ids from service call data.""" """Extract ids from service call data."""
entity_ids: Optional[Union[str, list]] = service_call.data.get(ATTR_ENTITY_ID) entity_ids: str | list | None = service_call.data.get(ATTR_ENTITY_ID)
device_ids: Optional[Union[str, list]] = service_call.data.get(ATTR_DEVICE_ID) device_ids: str | list | None = service_call.data.get(ATTR_DEVICE_ID)
area_ids: Optional[Union[str, list]] = service_call.data.get(ATTR_AREA_ID) area_ids: str | list | None = service_call.data.get(ATTR_AREA_ID)
self.entity_ids = ( self.entity_ids = (
set(cv.ensure_list(entity_ids)) if _has_match(entity_ids) else set() set(cv.ensure_list(entity_ids)) if _has_match(entity_ids) else set()
@ -319,7 +310,7 @@ async def async_extract_entity_ids(
return referenced.referenced | referenced.indirectly_referenced return referenced.referenced | referenced.indirectly_referenced
def _has_match(ids: Optional[Union[str, list]]) -> bool: def _has_match(ids: str | list | None) -> bool:
"""Check if ids can match anything.""" """Check if ids can match anything."""
return ids not in (None, ENTITY_MATCH_NONE) return ids not in (None, ENTITY_MATCH_NONE)
@ -514,7 +505,7 @@ def async_set_service_schema(
@bind_hass @bind_hass
async def entity_service_call( async def entity_service_call(
hass: HomeAssistantType, hass: HomeAssistantType,
platforms: Iterable["EntityPlatform"], platforms: Iterable[EntityPlatform],
func: str | Callable[..., Any], func: str | Callable[..., Any],
call: ha.ServiceCall, call: ha.ServiceCall,
required_features: Iterable[int] | None = None, required_features: Iterable[int] | None = None,
@ -557,7 +548,7 @@ async def entity_service_call(
# Check the permissions # Check the permissions
# A list with entities to call the service on. # A list with entities to call the service on.
entity_candidates: list["Entity"] = [] entity_candidates: list[Entity] = []
if entity_perms is None: if entity_perms is None:
for platform in platforms: for platform in platforms:

View file

@ -103,7 +103,7 @@ def manifest_from_legacy_module(domain: str, module: ModuleType) -> Manifest:
async def _async_get_custom_components( async def _async_get_custom_components(
hass: "HomeAssistant", hass: HomeAssistant,
) -> dict[str, Integration]: ) -> dict[str, Integration]:
"""Return list of custom integrations.""" """Return list of custom integrations."""
if hass.config.safe_mode: if hass.config.safe_mode:
@ -144,7 +144,7 @@ async def _async_get_custom_components(
async def async_get_custom_components( async def async_get_custom_components(
hass: "HomeAssistant", hass: HomeAssistant,
) -> dict[str, Integration]: ) -> dict[str, Integration]:
"""Return cached list of custom integrations.""" """Return cached list of custom integrations."""
reg_or_evt = hass.data.get(DATA_CUSTOM_COMPONENTS) reg_or_evt = hass.data.get(DATA_CUSTOM_COMPONENTS)
@ -276,7 +276,7 @@ class Integration:
@classmethod @classmethod
def resolve_from_root( def resolve_from_root(
cls, hass: "HomeAssistant", root_module: ModuleType, domain: str cls, hass: HomeAssistant, root_module: ModuleType, domain: str
) -> Integration | None: ) -> Integration | None:
"""Resolve an integration from a root module.""" """Resolve an integration from a root module."""
for base in root_module.__path__: # type: ignore for base in root_module.__path__: # type: ignore
@ -300,7 +300,7 @@ class Integration:
return None return None
@classmethod @classmethod
def resolve_legacy(cls, hass: "HomeAssistant", domain: str) -> Integration | None: def resolve_legacy(cls, hass: HomeAssistant, domain: str) -> Integration | None:
"""Resolve legacy component. """Resolve legacy component.
Will create a stub manifest. Will create a stub manifest.
@ -319,7 +319,7 @@ class Integration:
def __init__( def __init__(
self, self,
hass: "HomeAssistant", hass: HomeAssistant,
pkg_path: str, pkg_path: str,
file_path: pathlib.Path, file_path: pathlib.Path,
manifest: Manifest, manifest: Manifest,
@ -494,7 +494,7 @@ class Integration:
return f"<Integration {self.domain}: {self.pkg_path}>" return f"<Integration {self.domain}: {self.pkg_path}>"
async def async_get_integration(hass: "HomeAssistant", domain: str) -> Integration: async def async_get_integration(hass: HomeAssistant, domain: str) -> Integration:
"""Get an integration.""" """Get an integration."""
cache = hass.data.get(DATA_INTEGRATIONS) cache = hass.data.get(DATA_INTEGRATIONS)
if cache is None: if cache is None:
@ -579,7 +579,7 @@ class CircularDependency(LoaderError):
def _load_file( def _load_file(
hass: "HomeAssistant", comp_or_platform: str, base_paths: list[str] hass: HomeAssistant, comp_or_platform: str, base_paths: list[str]
) -> ModuleType | None: ) -> ModuleType | None:
"""Try to load specified file. """Try to load specified file.
@ -640,7 +640,7 @@ def _load_file(
class ModuleWrapper: class ModuleWrapper:
"""Class to wrap a Python module and auto fill in hass argument.""" """Class to wrap a Python module and auto fill in hass argument."""
def __init__(self, hass: "HomeAssistant", module: ModuleType) -> None: def __init__(self, hass: HomeAssistant, module: ModuleType) -> None:
"""Initialize the module wrapper.""" """Initialize the module wrapper."""
self._hass = hass self._hass = hass
self._module = module self._module = module
@ -704,7 +704,7 @@ def bind_hass(func: CALLABLE_T) -> CALLABLE_T:
async def _async_component_dependencies( async def _async_component_dependencies(
hass: "HomeAssistant", hass: HomeAssistant,
start_domain: str, start_domain: str,
integration: Integration, integration: Integration,
loaded: set[str], loaded: set[str],

View file

@ -1,5 +1,5 @@
"""Generate CODEOWNERS.""" """Generate CODEOWNERS."""
from typing import Dict from __future__ import annotations
from .model import Config, Integration from .model import Config, Integration
@ -33,7 +33,7 @@ homeassistant/components/demo/weather @fabaff
""" """
def generate_and_validate(integrations: Dict[str, Integration]): def generate_and_validate(integrations: dict[str, Integration]):
"""Generate CODEOWNERS.""" """Generate CODEOWNERS."""
parts = [BASE] parts = [BASE]
@ -61,7 +61,7 @@ def generate_and_validate(integrations: Dict[str, Integration]):
return "\n".join(parts) return "\n".join(parts)
def validate(integrations: Dict[str, Integration], config: Config): def validate(integrations: dict[str, Integration], config: Config):
"""Validate CODEOWNERS.""" """Validate CODEOWNERS."""
codeowners_path = config.root / "CODEOWNERS" codeowners_path = config.root / "CODEOWNERS"
config.cache["codeowners"] = content = generate_and_validate(integrations) config.cache["codeowners"] = content = generate_and_validate(integrations)
@ -79,7 +79,7 @@ def validate(integrations: Dict[str, Integration], config: Config):
return return
def generate(integrations: Dict[str, Integration], config: Config): def generate(integrations: dict[str, Integration], config: Config):
"""Generate CODEOWNERS.""" """Generate CODEOWNERS."""
codeowners_path = config.root / "CODEOWNERS" codeowners_path = config.root / "CODEOWNERS"
with open(str(codeowners_path), "w") as fp: with open(str(codeowners_path), "w") as fp:

View file

@ -1,6 +1,7 @@
"""Generate config flow file.""" """Generate config flow file."""
from __future__ import annotations
import json import json
from typing import Dict
from .model import Config, Integration from .model import Config, Integration
@ -90,7 +91,7 @@ def validate_integration(config: Config, integration: Integration):
) )
def generate_and_validate(integrations: Dict[str, Integration], config: Config): def generate_and_validate(integrations: dict[str, Integration], config: Config):
"""Validate and generate config flow data.""" """Validate and generate config flow data."""
domains = [] domains = []
@ -117,7 +118,7 @@ def generate_and_validate(integrations: Dict[str, Integration], config: Config):
return BASE.format(json.dumps(domains, indent=4)) return BASE.format(json.dumps(domains, indent=4))
def validate(integrations: Dict[str, Integration], config: Config): def validate(integrations: dict[str, Integration], config: Config):
"""Validate config flow file.""" """Validate config flow file."""
config_flow_path = config.root / "homeassistant/generated/config_flows.py" config_flow_path = config.root / "homeassistant/generated/config_flows.py"
config.cache["config_flow"] = content = generate_and_validate(integrations, config) config.cache["config_flow"] = content = generate_and_validate(integrations, config)
@ -136,7 +137,7 @@ def validate(integrations: Dict[str, Integration], config: Config):
return return
def generate(integrations: Dict[str, Integration], config: Config): def generate(integrations: dict[str, Integration], config: Config):
"""Generate config flow file.""" """Generate config flow file."""
config_flow_path = config.root / "homeassistant/generated/config_flows.py" config_flow_path = config.root / "homeassistant/generated/config_flows.py"
with open(str(config_flow_path), "w") as fp: with open(str(config_flow_path), "w") as fp:

View file

@ -1,6 +1,7 @@
"""Validate coverage files.""" """Validate coverage files."""
from __future__ import annotations
from pathlib import Path from pathlib import Path
from typing import Dict
from .model import Config, Integration from .model import Config, Integration
@ -69,7 +70,7 @@ ALLOWED_IGNORE_VIOLATIONS = {
} }
def validate(integrations: Dict[str, Integration], config: Config): def validate(integrations: dict[str, Integration], config: Config):
"""Validate coverage.""" """Validate coverage."""
coverage_path = config.root / ".coveragerc" coverage_path = config.root / ".coveragerc"

View file

@ -1,7 +1,8 @@
"""Validate dependencies.""" """Validate dependencies."""
from __future__ import annotations
import ast import ast
from pathlib import Path from pathlib import Path
from typing import Dict, Set
from homeassistant.requirements import DISCOVERY_INTEGRATIONS from homeassistant.requirements import DISCOVERY_INTEGRATIONS
@ -14,7 +15,7 @@ class ImportCollector(ast.NodeVisitor):
def __init__(self, integration: Integration): def __init__(self, integration: Integration):
"""Initialize the import collector.""" """Initialize the import collector."""
self.integration = integration self.integration = integration
self.referenced: Dict[Path, Set[str]] = {} self.referenced: dict[Path, set[str]] = {}
# Current file or dir we're inspecting # Current file or dir we're inspecting
self._cur_fil_dir = None self._cur_fil_dir = None
@ -156,7 +157,7 @@ IGNORE_VIOLATIONS = {
} }
def calc_allowed_references(integration: Integration) -> Set[str]: def calc_allowed_references(integration: Integration) -> set[str]:
"""Return a set of allowed references.""" """Return a set of allowed references."""
allowed_references = ( allowed_references = (
ALLOWED_USED_COMPONENTS ALLOWED_USED_COMPONENTS
@ -173,9 +174,9 @@ def calc_allowed_references(integration: Integration) -> Set[str]:
def find_non_referenced_integrations( def find_non_referenced_integrations(
integrations: Dict[str, Integration], integrations: dict[str, Integration],
integration: Integration, integration: Integration,
references: Dict[Path, Set[str]], references: dict[Path, set[str]],
): ):
"""Find intergrations that are not allowed to be referenced.""" """Find intergrations that are not allowed to be referenced."""
allowed_references = calc_allowed_references(integration) allowed_references = calc_allowed_references(integration)
@ -221,7 +222,7 @@ def find_non_referenced_integrations(
def validate_dependencies( def validate_dependencies(
integrations: Dict[str, Integration], integration: Integration integrations: dict[str, Integration], integration: Integration
): ):
"""Validate all dependencies.""" """Validate all dependencies."""
# Some integrations are allowed to have violations. # Some integrations are allowed to have violations.
@ -244,7 +245,7 @@ def validate_dependencies(
) )
def validate(integrations: Dict[str, Integration], config): def validate(integrations: dict[str, Integration], config):
"""Handle dependencies for integrations.""" """Handle dependencies for integrations."""
# check for non-existing dependencies # check for non-existing dependencies
for integration in integrations.values(): for integration in integrations.values():

View file

@ -1,6 +1,7 @@
"""Generate dhcp file.""" """Generate dhcp file."""
from __future__ import annotations
import json import json
from typing import Dict, List
from .model import Config, Integration from .model import Config, Integration
@ -16,7 +17,7 @@ DHCP = {}
""".strip() """.strip()
def generate_and_validate(integrations: List[Dict[str, str]]): def generate_and_validate(integrations: list[dict[str, str]]):
"""Validate and generate dhcp data.""" """Validate and generate dhcp data."""
match_list = [] match_list = []
@ -37,7 +38,7 @@ def generate_and_validate(integrations: List[Dict[str, str]]):
return BASE.format(json.dumps(match_list, indent=4)) return BASE.format(json.dumps(match_list, indent=4))
def validate(integrations: Dict[str, Integration], config: Config): def validate(integrations: dict[str, Integration], config: Config):
"""Validate dhcp file.""" """Validate dhcp file."""
dhcp_path = config.root / "homeassistant/generated/dhcp.py" dhcp_path = config.root / "homeassistant/generated/dhcp.py"
config.cache["dhcp"] = content = generate_and_validate(integrations) config.cache["dhcp"] = content = generate_and_validate(integrations)
@ -56,7 +57,7 @@ def validate(integrations: Dict[str, Integration], config: Config):
return return
def generate(integrations: Dict[str, Integration], config: Config): def generate(integrations: dict[str, Integration], config: Config):
"""Generate dhcp file.""" """Generate dhcp file."""
dhcp_path = config.root / "homeassistant/generated/dhcp.py" dhcp_path = config.root / "homeassistant/generated/dhcp.py"
with open(str(dhcp_path), "w") as fp: with open(str(dhcp_path), "w") as fp:

View file

@ -1,6 +1,7 @@
"""Validate integration JSON files.""" """Validate integration JSON files."""
from __future__ import annotations
import json import json
from typing import Dict
from .model import Integration from .model import Integration
@ -20,7 +21,7 @@ def validate_json_files(integration: Integration):
return return
def validate(integrations: Dict[str, Integration], config): def validate(integrations: dict[str, Integration], config):
"""Handle JSON files inside integrations.""" """Handle JSON files inside integrations."""
if not config.specific_integrations: if not config.specific_integrations:
return return

View file

@ -1,5 +1,6 @@
"""Manifest validation.""" """Manifest validation."""
from typing import Dict from __future__ import annotations
from urllib.parse import urlparse from urllib.parse import urlparse
import voluptuous as vol import voluptuous as vol
@ -145,7 +146,7 @@ def validate_manifest(integration: Integration):
validate_version(integration) validate_version(integration)
def validate(integrations: Dict[str, Integration], config): def validate(integrations: dict[str, Integration], config):
"""Handle all integrations manifests.""" """Handle all integrations manifests."""
for integration in integrations.values(): for integration in integrations.values():
if integration.manifest: if integration.manifest:

View file

@ -1,8 +1,10 @@
"""Models for manifest validator.""" """Models for manifest validator."""
from __future__ import annotations
import importlib import importlib
import json import json
import pathlib import pathlib
from typing import Any, Dict, List, Optional from typing import Any
import attr import attr
@ -24,12 +26,12 @@ class Error:
class Config: class Config:
"""Config for the run.""" """Config for the run."""
specific_integrations: Optional[pathlib.Path] = attr.ib() specific_integrations: pathlib.Path | None = attr.ib()
root: pathlib.Path = attr.ib() root: pathlib.Path = attr.ib()
action: str = attr.ib() action: str = attr.ib()
requirements: bool = attr.ib() requirements: bool = attr.ib()
errors: List[Error] = attr.ib(factory=list) errors: list[Error] = attr.ib(factory=list)
cache: Dict[str, Any] = attr.ib(factory=dict) cache: dict[str, Any] = attr.ib(factory=dict)
def add_error(self, *args, **kwargs): def add_error(self, *args, **kwargs):
"""Add an error.""" """Add an error."""
@ -65,9 +67,9 @@ class Integration:
return integrations return integrations
path: pathlib.Path = attr.ib() path: pathlib.Path = attr.ib()
manifest: Optional[dict] = attr.ib(default=None) manifest: dict | None = attr.ib(default=None)
errors: List[Error] = attr.ib(factory=list) errors: list[Error] = attr.ib(factory=list)
warnings: List[Error] = attr.ib(factory=list) warnings: list[Error] = attr.ib(factory=list)
@property @property
def domain(self) -> str: def domain(self) -> str:
@ -80,17 +82,17 @@ class Integration:
return self.path.as_posix().startswith("homeassistant/components") return self.path.as_posix().startswith("homeassistant/components")
@property @property
def disabled(self) -> Optional[str]: def disabled(self) -> str | None:
"""List of disabled.""" """List of disabled."""
return self.manifest.get("disabled") return self.manifest.get("disabled")
@property @property
def requirements(self) -> List[str]: def requirements(self) -> list[str]:
"""List of requirements.""" """List of requirements."""
return self.manifest.get("requirements", []) return self.manifest.get("requirements", [])
@property @property
def dependencies(self) -> List[str]: def dependencies(self) -> list[str]:
"""List of dependencies.""" """List of dependencies."""
return self.manifest.get("dependencies", []) return self.manifest.get("dependencies", [])

View file

@ -1,7 +1,8 @@
"""Generate MQTT file.""" """Generate MQTT file."""
from __future__ import annotations
from collections import defaultdict from collections import defaultdict
import json import json
from typing import Dict
from .model import Config, Integration from .model import Config, Integration
@ -17,7 +18,7 @@ MQTT = {}
""".strip() """.strip()
def generate_and_validate(integrations: Dict[str, Integration]): def generate_and_validate(integrations: dict[str, Integration]):
"""Validate and generate MQTT data.""" """Validate and generate MQTT data."""
data = defaultdict(list) data = defaultdict(list)
@ -39,7 +40,7 @@ def generate_and_validate(integrations: Dict[str, Integration]):
return BASE.format(json.dumps(data, indent=4)) return BASE.format(json.dumps(data, indent=4))
def validate(integrations: Dict[str, Integration], config: Config): def validate(integrations: dict[str, Integration], config: Config):
"""Validate MQTT file.""" """Validate MQTT file."""
mqtt_path = config.root / "homeassistant/generated/mqtt.py" mqtt_path = config.root / "homeassistant/generated/mqtt.py"
config.cache["mqtt"] = content = generate_and_validate(integrations) config.cache["mqtt"] = content = generate_and_validate(integrations)
@ -57,7 +58,7 @@ def validate(integrations: Dict[str, Integration], config: Config):
return return
def generate(integrations: Dict[str, Integration], config: Config): def generate(integrations: dict[str, Integration], config: Config):
"""Generate MQTT file.""" """Generate MQTT file."""
mqtt_path = config.root / "homeassistant/generated/mqtt.py" mqtt_path = config.root / "homeassistant/generated/mqtt.py"
with open(str(mqtt_path), "w") as fp: with open(str(mqtt_path), "w") as fp:

View file

@ -1,4 +1,6 @@
"""Validate requirements.""" """Validate requirements."""
from __future__ import annotations
from collections import deque from collections import deque
import json import json
import operator import operator
@ -6,7 +8,6 @@ import os
import re import re
import subprocess import subprocess
import sys import sys
from typing import Dict, Set
from stdlib_list import stdlib_list from stdlib_list import stdlib_list
from tqdm import tqdm from tqdm import tqdm
@ -58,7 +59,7 @@ def normalize_package_name(requirement: str) -> str:
return package return package
def validate(integrations: Dict[str, Integration], config: Config): def validate(integrations: dict[str, Integration], config: Config):
"""Handle requirements for integrations.""" """Handle requirements for integrations."""
ensure_cache() ensure_cache()
@ -153,7 +154,7 @@ def ensure_cache():
PIPDEPTREE_CACHE = cache PIPDEPTREE_CACHE = cache
def get_requirements(integration: Integration, packages: Set[str]) -> Set[str]: def get_requirements(integration: Integration, packages: set[str]) -> set[str]:
"""Return all (recursively) requirements for an integration.""" """Return all (recursively) requirements for an integration."""
ensure_cache() ensure_cache()
@ -184,7 +185,7 @@ def get_requirements(integration: Integration, packages: Set[str]) -> Set[str]:
return all_requirements return all_requirements
def install_requirements(integration: Integration, requirements: Set[str]) -> bool: def install_requirements(integration: Integration, requirements: set[str]) -> bool:
"""Install integration requirements. """Install integration requirements.
Return True if successful. Return True if successful.

View file

@ -1,7 +1,8 @@
"""Validate dependencies.""" """Validate dependencies."""
from __future__ import annotations
import pathlib import pathlib
import re import re
from typing import Dict
import voluptuous as vol import voluptuous as vol
from voluptuous.humanize import humanize_error from voluptuous.humanize import humanize_error
@ -93,7 +94,7 @@ def validate_services(integration: Integration):
) )
def validate(integrations: Dict[str, Integration], config): def validate(integrations: dict[str, Integration], config):
"""Handle dependencies for integrations.""" """Handle dependencies for integrations."""
# check services.yaml is cool # check services.yaml is cool
for integration in integrations.values(): for integration in integrations.values():

View file

@ -1,7 +1,8 @@
"""Generate ssdp file.""" """Generate ssdp file."""
from __future__ import annotations
from collections import OrderedDict, defaultdict from collections import OrderedDict, defaultdict
import json import json
from typing import Dict
from .model import Config, Integration from .model import Config, Integration
@ -22,7 +23,7 @@ def sort_dict(value):
return OrderedDict((key, value[key]) for key in sorted(value)) return OrderedDict((key, value[key]) for key in sorted(value))
def generate_and_validate(integrations: Dict[str, Integration]): def generate_and_validate(integrations: dict[str, Integration]):
"""Validate and generate ssdp data.""" """Validate and generate ssdp data."""
data = defaultdict(list) data = defaultdict(list)
@ -44,7 +45,7 @@ def generate_and_validate(integrations: Dict[str, Integration]):
return BASE.format(json.dumps(data, indent=4)) return BASE.format(json.dumps(data, indent=4))
def validate(integrations: Dict[str, Integration], config: Config): def validate(integrations: dict[str, Integration], config: Config):
"""Validate ssdp file.""" """Validate ssdp file."""
ssdp_path = config.root / "homeassistant/generated/ssdp.py" ssdp_path = config.root / "homeassistant/generated/ssdp.py"
config.cache["ssdp"] = content = generate_and_validate(integrations) config.cache["ssdp"] = content = generate_and_validate(integrations)
@ -62,7 +63,7 @@ def validate(integrations: Dict[str, Integration], config: Config):
return return
def generate(integrations: Dict[str, Integration], config: Config): def generate(integrations: dict[str, Integration], config: Config):
"""Generate ssdp file.""" """Generate ssdp file."""
ssdp_path = config.root / "homeassistant/generated/ssdp.py" ssdp_path = config.root / "homeassistant/generated/ssdp.py"
with open(str(ssdp_path), "w") as fp: with open(str(ssdp_path), "w") as fp:

View file

@ -1,9 +1,10 @@
"""Validate integration translation files.""" """Validate integration translation files."""
from __future__ import annotations
from functools import partial from functools import partial
from itertools import chain from itertools import chain
import json import json
import re import re
from typing import Dict
import voluptuous as vol import voluptuous as vol
from voluptuous.humanize import humanize_error from voluptuous.humanize import humanize_error
@ -295,7 +296,7 @@ def validate_translation_file(config: Config, integration: Integration, all_stri
) )
def validate(integrations: Dict[str, Integration], config: Config): def validate(integrations: dict[str, Integration], config: Config):
"""Handle JSON files inside integrations.""" """Handle JSON files inside integrations."""
if config.specific_integrations: if config.specific_integrations:
all_strings = None all_strings = None

View file

@ -1,7 +1,8 @@
"""Generate zeroconf file.""" """Generate zeroconf file."""
from __future__ import annotations
from collections import OrderedDict, defaultdict from collections import OrderedDict, defaultdict
import json import json
from typing import Dict
from .model import Config, Integration from .model import Config, Integration
@ -19,7 +20,7 @@ HOMEKIT = {}
""".strip() """.strip()
def generate_and_validate(integrations: Dict[str, Integration]): def generate_and_validate(integrations: dict[str, Integration]):
"""Validate and generate zeroconf data.""" """Validate and generate zeroconf data."""
service_type_dict = defaultdict(list) service_type_dict = defaultdict(list)
homekit_dict = {} homekit_dict = {}
@ -89,7 +90,7 @@ def generate_and_validate(integrations: Dict[str, Integration]):
return BASE.format(json.dumps(zeroconf, indent=4), json.dumps(homekit, indent=4)) return BASE.format(json.dumps(zeroconf, indent=4), json.dumps(homekit, indent=4))
def validate(integrations: Dict[str, Integration], config: Config): def validate(integrations: dict[str, Integration], config: Config):
"""Validate zeroconf file.""" """Validate zeroconf file."""
zeroconf_path = config.root / "homeassistant/generated/zeroconf.py" zeroconf_path = config.root / "homeassistant/generated/zeroconf.py"
config.cache["zeroconf"] = content = generate_and_validate(integrations) config.cache["zeroconf"] = content = generate_and_validate(integrations)
@ -108,7 +109,7 @@ def validate(integrations: Dict[str, Integration], config: Config):
return return
def generate(integrations: Dict[str, Integration], config: Config): def generate(integrations: dict[str, Integration], config: Config):
"""Generate zeroconf file.""" """Generate zeroconf file."""
zeroconf_path = config.root / "homeassistant/generated/zeroconf.py" zeroconf_path = config.root / "homeassistant/generated/zeroconf.py"
with open(str(zeroconf_path), "w") as fp: with open(str(zeroconf_path), "w") as fp:

View file

@ -1,7 +1,8 @@
"""Models for scaffolding.""" """Models for scaffolding."""
from __future__ import annotations
import json import json
from pathlib import Path from pathlib import Path
from typing import Set
import attr import attr
@ -21,9 +22,9 @@ class Info:
discoverable: str = attr.ib(default=None) discoverable: str = attr.ib(default=None)
oauth2: str = attr.ib(default=None) oauth2: str = attr.ib(default=None)
files_added: Set[Path] = attr.ib(factory=set) files_added: set[Path] = attr.ib(factory=set)
tests_added: Set[Path] = attr.ib(factory=set) tests_added: set[Path] = attr.ib(factory=set)
examples_added: Set[Path] = attr.ib(factory=set) examples_added: set[Path] = attr.ib(factory=set)
@property @property
def integration_dir(self) -> Path: def integration_dir(self) -> Path:

View file

@ -1,5 +1,5 @@
"""Provides device actions for NEW_NAME.""" """Provides device actions for NEW_NAME."""
from typing import List, Optional from __future__ import annotations
import voluptuous as vol import voluptuous as vol
@ -29,7 +29,7 @@ ACTION_SCHEMA = cv.DEVICE_ACTION_BASE_SCHEMA.extend(
) )
async def async_get_actions(hass: HomeAssistant, device_id: str) -> List[dict]: async def async_get_actions(hass: HomeAssistant, device_id: str) -> list[dict]:
"""List device actions for NEW_NAME devices.""" """List device actions for NEW_NAME devices."""
registry = await entity_registry.async_get_registry(hass) registry = await entity_registry.async_get_registry(hass)
actions = [] actions = []
@ -69,7 +69,7 @@ async def async_get_actions(hass: HomeAssistant, device_id: str) -> List[dict]:
async def async_call_action_from_config( async def async_call_action_from_config(
hass: HomeAssistant, config: dict, variables: dict, context: Optional[Context] hass: HomeAssistant, config: dict, variables: dict, context: Context | None
) -> None: ) -> None:
"""Execute a device action.""" """Execute a device action."""
service_data = {ATTR_ENTITY_ID: config[CONF_ENTITY_ID]} service_data = {ATTR_ENTITY_ID: config[CONF_ENTITY_ID]}

View file

@ -1,5 +1,5 @@
"""Provide the device conditions for NEW_NAME.""" """Provide the device conditions for NEW_NAME."""
from typing import Dict, List from __future__ import annotations
import voluptuous as vol import voluptuous as vol
@ -33,7 +33,7 @@ CONDITION_SCHEMA = DEVICE_CONDITION_BASE_SCHEMA.extend(
async def async_get_conditions( async def async_get_conditions(
hass: HomeAssistant, device_id: str hass: HomeAssistant, device_id: str
) -> List[Dict[str, str]]: ) -> list[dict[str, str]]:
"""List device conditions for NEW_NAME devices.""" """List device conditions for NEW_NAME devices."""
registry = await entity_registry.async_get_registry(hass) registry = await entity_registry.async_get_registry(hass)
conditions = [] conditions = []

View file

@ -1,5 +1,5 @@
"""Provides device triggers for NEW_NAME.""" """Provides device triggers for NEW_NAME."""
from typing import List from __future__ import annotations
import voluptuous as vol import voluptuous as vol
@ -32,7 +32,7 @@ TRIGGER_SCHEMA = TRIGGER_BASE_SCHEMA.extend(
) )
async def async_get_triggers(hass: HomeAssistant, device_id: str) -> List[dict]: async def async_get_triggers(hass: HomeAssistant, device_id: str) -> list[dict]:
"""List device triggers for NEW_NAME devices.""" """List device triggers for NEW_NAME devices."""
registry = await entity_registry.async_get_registry(hass) registry = await entity_registry.async_get_registry(hass)
triggers = [] triggers = []

View file

@ -1,7 +1,9 @@
"""Reproduce an NEW_NAME state.""" """Reproduce an NEW_NAME state."""
from __future__ import annotations
import asyncio import asyncio
import logging import logging
from typing import Any, Dict, Iterable, Optional from typing import Any, Iterable
from homeassistant.const import ( from homeassistant.const import (
ATTR_ENTITY_ID, ATTR_ENTITY_ID,
@ -25,8 +27,8 @@ async def _async_reproduce_state(
hass: HomeAssistantType, hass: HomeAssistantType,
state: State, state: State,
*, *,
context: Optional[Context] = None, context: Context | None = None,
reproduce_options: Optional[Dict[str, Any]] = None, reproduce_options: dict[str, Any] | None = None,
) -> None: ) -> None:
"""Reproduce a single state.""" """Reproduce a single state."""
cur_state = hass.states.get(state.entity_id) cur_state = hass.states.get(state.entity_id)
@ -70,8 +72,8 @@ async def async_reproduce_states(
hass: HomeAssistantType, hass: HomeAssistantType,
states: Iterable[State], states: Iterable[State],
*, *,
context: Optional[Context] = None, context: Context | None = None,
reproduce_options: Optional[Dict[str, Any]] = None, reproduce_options: dict[str, Any] | None = None,
) -> None: ) -> None:
"""Reproduce NEW_NAME states.""" """Reproduce NEW_NAME states."""
# TODO pick one and remove other one # TODO pick one and remove other one

View file

@ -1,5 +1,7 @@
"""Helper to test significant NEW_NAME state changes.""" """Helper to test significant NEW_NAME state changes."""
from typing import Any, Optional from __future__ import annotations
from typing import Any
from homeassistant.const import ATTR_DEVICE_CLASS from homeassistant.const import ATTR_DEVICE_CLASS
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
@ -13,7 +15,7 @@ def async_check_significant_change(
new_state: str, new_state: str,
new_attrs: dict, new_attrs: dict,
**kwargs: Any, **kwargs: Any,
) -> Optional[bool]: ) -> bool | None:
"""Test if state significantly changed.""" """Test if state significantly changed."""
device_class = new_attrs.get(ATTR_DEVICE_CLASS) device_class = new_attrs.get(ATTR_DEVICE_CLASS)

View file

@ -1,11 +1,12 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
"""Merge all translation sources into a single JSON file.""" """Merge all translation sources into a single JSON file."""
from __future__ import annotations
import json import json
import os import os
import pathlib import pathlib
import re import re
import subprocess import subprocess
from typing import Dict, List, Union
from .const import CLI_2_DOCKER_IMAGE, CORE_PROJECT_ID, INTEGRATIONS_DIR from .const import CLI_2_DOCKER_IMAGE, CORE_PROJECT_ID, INTEGRATIONS_DIR
from .error import ExitApp from .error import ExitApp
@ -51,7 +52,7 @@ def run_download_docker():
raise ExitApp("Failed to download translations") raise ExitApp("Failed to download translations")
def save_json(filename: str, data: Union[List, Dict]): def save_json(filename: str, data: list | dict):
"""Save JSON data to a file. """Save JSON data to a file.
Returns True on success. Returns True on success.

View file

@ -202,9 +202,9 @@ async def async_test_home_assistant(loop, load_registries=True):
start_time: float | None = None start_time: float | None = None
while len(self._pending_tasks) > max_remaining_tasks: while len(self._pending_tasks) > max_remaining_tasks:
pending = [ pending: Collection[Awaitable[Any]] = [
task for task in self._pending_tasks if not task.done() task for task in self._pending_tasks if not task.done()
] # type: Collection[Awaitable[Any]] ]
self._pending_tasks.clear() self._pending_tasks.clear()
if len(pending) > max_remaining_tasks: if len(pending) > max_remaining_tasks:
remaining_pending = await self._await_count_and_log_pending( remaining_pending = await self._await_count_and_log_pending(

View file

@ -118,7 +118,7 @@ class ComponentFactory:
if controller_config.legacy_entity_unique_id: if controller_config.legacy_entity_unique_id:
component_config[CONF_LEGACY_UNIQUE_ID] = True component_config[CONF_LEGACY_UNIQUE_ID] = True
controller = MagicMock(spec=pv.VeraController) # type: pv.VeraController controller: pv.VeraController = MagicMock(spec=pv.VeraController)
controller.base_url = component_config.get(CONF_CONTROLLER) controller.base_url = component_config.get(CONF_CONTROLLER)
controller.register = MagicMock() controller.register = MagicMock()
controller.start = MagicMock() controller.start = MagicMock()

View file

@ -12,7 +12,7 @@ async def test_binary_sensor(
hass: HomeAssistant, vera_component_factory: ComponentFactory hass: HomeAssistant, vera_component_factory: ComponentFactory
) -> None: ) -> None:
"""Test function.""" """Test function."""
vera_device = MagicMock(spec=pv.VeraBinarySensor) # type: pv.VeraBinarySensor vera_device: pv.VeraBinarySensor = MagicMock(spec=pv.VeraBinarySensor)
vera_device.device_id = 1 vera_device.device_id = 1
vera_device.comm_failure = False vera_device.comm_failure = False
vera_device.vera_device_id = vera_device.device_id vera_device.vera_device_id = vera_device.device_id

View file

@ -20,7 +20,7 @@ async def test_climate(
hass: HomeAssistant, vera_component_factory: ComponentFactory hass: HomeAssistant, vera_component_factory: ComponentFactory
) -> None: ) -> None:
"""Test function.""" """Test function."""
vera_device = MagicMock(spec=pv.VeraThermostat) # type: pv.VeraThermostat vera_device: pv.VeraThermostat = MagicMock(spec=pv.VeraThermostat)
vera_device.device_id = 1 vera_device.device_id = 1
vera_device.vera_device_id = vera_device.device_id vera_device.vera_device_id = vera_device.device_id
vera_device.comm_failure = False vera_device.comm_failure = False
@ -131,7 +131,7 @@ async def test_climate_f(
hass: HomeAssistant, vera_component_factory: ComponentFactory hass: HomeAssistant, vera_component_factory: ComponentFactory
) -> None: ) -> None:
"""Test function.""" """Test function."""
vera_device = MagicMock(spec=pv.VeraThermostat) # type: pv.VeraThermostat vera_device: pv.VeraThermostat = MagicMock(spec=pv.VeraThermostat)
vera_device.device_id = 1 vera_device.device_id = 1
vera_device.vera_device_id = vera_device.device_id vera_device.vera_device_id = vera_device.device_id
vera_device.comm_failure = False vera_device.comm_failure = False

View file

@ -12,7 +12,7 @@ async def test_cover(
hass: HomeAssistant, vera_component_factory: ComponentFactory hass: HomeAssistant, vera_component_factory: ComponentFactory
) -> None: ) -> None:
"""Test function.""" """Test function."""
vera_device = MagicMock(spec=pv.VeraCurtain) # type: pv.VeraCurtain vera_device: pv.VeraCurtain = MagicMock(spec=pv.VeraCurtain)
vera_device.device_id = 1 vera_device.device_id = 1
vera_device.vera_device_id = vera_device.device_id vera_device.vera_device_id = vera_device.device_id
vera_device.comm_failure = False vera_device.comm_failure = False

View file

@ -24,7 +24,7 @@ async def test_init(
hass: HomeAssistant, vera_component_factory: ComponentFactory hass: HomeAssistant, vera_component_factory: ComponentFactory
) -> None: ) -> None:
"""Test function.""" """Test function."""
vera_device1 = MagicMock(spec=pv.VeraBinarySensor) # type: pv.VeraBinarySensor vera_device1: pv.VeraBinarySensor = MagicMock(spec=pv.VeraBinarySensor)
vera_device1.device_id = 1 vera_device1.device_id = 1
vera_device1.vera_device_id = vera_device1.device_id vera_device1.vera_device_id = vera_device1.device_id
vera_device1.name = "first_dev" vera_device1.name = "first_dev"
@ -51,7 +51,7 @@ async def test_init_from_file(
hass: HomeAssistant, vera_component_factory: ComponentFactory hass: HomeAssistant, vera_component_factory: ComponentFactory
) -> None: ) -> None:
"""Test function.""" """Test function."""
vera_device1 = MagicMock(spec=pv.VeraBinarySensor) # type: pv.VeraBinarySensor vera_device1: pv.VeraBinarySensor = MagicMock(spec=pv.VeraBinarySensor)
vera_device1.device_id = 1 vera_device1.device_id = 1
vera_device1.vera_device_id = vera_device1.device_id vera_device1.vera_device_id = vera_device1.device_id
vera_device1.name = "first_dev" vera_device1.name = "first_dev"
@ -78,14 +78,14 @@ async def test_multiple_controllers_with_legacy_one(
hass: HomeAssistant, vera_component_factory: ComponentFactory hass: HomeAssistant, vera_component_factory: ComponentFactory
) -> None: ) -> None:
"""Test multiple controllers with one legacy controller.""" """Test multiple controllers with one legacy controller."""
vera_device1 = MagicMock(spec=pv.VeraBinarySensor) # type: pv.VeraBinarySensor vera_device1: pv.VeraBinarySensor = MagicMock(spec=pv.VeraBinarySensor)
vera_device1.device_id = 1 vera_device1.device_id = 1
vera_device1.vera_device_id = vera_device1.device_id vera_device1.vera_device_id = vera_device1.device_id
vera_device1.name = "first_dev" vera_device1.name = "first_dev"
vera_device1.is_tripped = False vera_device1.is_tripped = False
entity1_id = "binary_sensor.first_dev_1" entity1_id = "binary_sensor.first_dev_1"
vera_device2 = MagicMock(spec=pv.VeraBinarySensor) # type: pv.VeraBinarySensor vera_device2: pv.VeraBinarySensor = MagicMock(spec=pv.VeraBinarySensor)
vera_device2.device_id = 2 vera_device2.device_id = 2
vera_device2.vera_device_id = vera_device2.device_id vera_device2.vera_device_id = vera_device2.device_id
vera_device2.name = "second_dev" vera_device2.name = "second_dev"
@ -133,7 +133,7 @@ async def test_unload(
hass: HomeAssistant, vera_component_factory: ComponentFactory hass: HomeAssistant, vera_component_factory: ComponentFactory
) -> None: ) -> None:
"""Test function.""" """Test function."""
vera_device1 = MagicMock(spec=pv.VeraBinarySensor) # type: pv.VeraBinarySensor vera_device1: pv.VeraBinarySensor = MagicMock(spec=pv.VeraBinarySensor)
vera_device1.device_id = 1 vera_device1.device_id = 1
vera_device1.vera_device_id = vera_device1.device_id vera_device1.vera_device_id = vera_device1.device_id
vera_device1.name = "first_dev" vera_device1.name = "first_dev"
@ -187,21 +187,21 @@ async def test_exclude_and_light_ids(
hass: HomeAssistant, vera_component_factory: ComponentFactory, options hass: HomeAssistant, vera_component_factory: ComponentFactory, options
) -> None: ) -> None:
"""Test device exclusion, marking switches as lights and fixing the data type.""" """Test device exclusion, marking switches as lights and fixing the data type."""
vera_device1 = MagicMock(spec=pv.VeraBinarySensor) # type: pv.VeraBinarySensor vera_device1: pv.VeraBinarySensor = MagicMock(spec=pv.VeraBinarySensor)
vera_device1.device_id = 1 vera_device1.device_id = 1
vera_device1.vera_device_id = 1 vera_device1.vera_device_id = 1
vera_device1.name = "dev1" vera_device1.name = "dev1"
vera_device1.is_tripped = False vera_device1.is_tripped = False
entity_id1 = "binary_sensor.dev1_1" entity_id1 = "binary_sensor.dev1_1"
vera_device2 = MagicMock(spec=pv.VeraBinarySensor) # type: pv.VeraBinarySensor vera_device2: pv.VeraBinarySensor = MagicMock(spec=pv.VeraBinarySensor)
vera_device2.device_id = 2 vera_device2.device_id = 2
vera_device2.vera_device_id = 2 vera_device2.vera_device_id = 2
vera_device2.name = "dev2" vera_device2.name = "dev2"
vera_device2.is_tripped = False vera_device2.is_tripped = False
entity_id2 = "binary_sensor.dev2_2" entity_id2 = "binary_sensor.dev2_2"
vera_device3 = MagicMock(spec=pv.VeraSwitch) # type: pv.VeraSwitch vera_device3: pv.VeraSwitch = MagicMock(spec=pv.VeraSwitch)
vera_device3.device_id = 3 vera_device3.device_id = 3
vera_device3.vera_device_id = 3 vera_device3.vera_device_id = 3
vera_device3.name = "dev3" vera_device3.name = "dev3"
@ -210,7 +210,7 @@ async def test_exclude_and_light_ids(
entity_id3 = "switch.dev3_3" entity_id3 = "switch.dev3_3"
vera_device4 = MagicMock(spec=pv.VeraSwitch) # type: pv.VeraSwitch vera_device4: pv.VeraSwitch = MagicMock(spec=pv.VeraSwitch)
vera_device4.device_id = 4 vera_device4.device_id = 4
vera_device4.vera_device_id = 4 vera_device4.vera_device_id = 4
vera_device4.name = "dev4" vera_device4.name = "dev4"

View file

@ -13,7 +13,7 @@ async def test_light(
hass: HomeAssistant, vera_component_factory: ComponentFactory hass: HomeAssistant, vera_component_factory: ComponentFactory
) -> None: ) -> None:
"""Test function.""" """Test function."""
vera_device = MagicMock(spec=pv.VeraDimmer) # type: pv.VeraDimmer vera_device: pv.VeraDimmer = MagicMock(spec=pv.VeraDimmer)
vera_device.device_id = 1 vera_device.device_id = 1
vera_device.vera_device_id = vera_device.device_id vera_device.vera_device_id = vera_device.device_id
vera_device.comm_failure = False vera_device.comm_failure = False

View file

@ -13,7 +13,7 @@ async def test_lock(
hass: HomeAssistant, vera_component_factory: ComponentFactory hass: HomeAssistant, vera_component_factory: ComponentFactory
) -> None: ) -> None:
"""Test function.""" """Test function."""
vera_device = MagicMock(spec=pv.VeraLock) # type: pv.VeraLock vera_device: pv.VeraLock = MagicMock(spec=pv.VeraLock)
vera_device.device_id = 1 vera_device.device_id = 1
vera_device.vera_device_id = vera_device.device_id vera_device.vera_device_id = vera_device.device_id
vera_device.comm_failure = False vera_device.comm_failure = False

View file

@ -12,7 +12,7 @@ async def test_scene(
hass: HomeAssistant, vera_component_factory: ComponentFactory hass: HomeAssistant, vera_component_factory: ComponentFactory
) -> None: ) -> None:
"""Test function.""" """Test function."""
vera_scene = MagicMock(spec=pv.VeraScene) # type: pv.VeraScene vera_scene: pv.VeraScene = MagicMock(spec=pv.VeraScene)
vera_scene.scene_id = 1 vera_scene.scene_id = 1
vera_scene.vera_scene_id = vera_scene.scene_id vera_scene.vera_scene_id = vera_scene.scene_id
vera_scene.name = "dev1" vera_scene.name = "dev1"

View file

@ -22,7 +22,7 @@ async def run_sensor_test(
setup_callback: Callable[[pv.VeraController], None] = None, setup_callback: Callable[[pv.VeraController], None] = None,
) -> None: ) -> None:
"""Test generic sensor.""" """Test generic sensor."""
vera_device = MagicMock(spec=pv.VeraSensor) # type: pv.VeraSensor vera_device: pv.VeraSensor = MagicMock(spec=pv.VeraSensor)
vera_device.device_id = 1 vera_device.device_id = 1
vera_device.vera_device_id = vera_device.device_id vera_device.vera_device_id = vera_device.device_id
vera_device.comm_failure = False vera_device.comm_failure = False
@ -178,7 +178,7 @@ async def test_scene_controller_sensor(
hass: HomeAssistant, vera_component_factory: ComponentFactory hass: HomeAssistant, vera_component_factory: ComponentFactory
) -> None: ) -> None:
"""Test function.""" """Test function."""
vera_device = MagicMock(spec=pv.VeraSensor) # type: pv.VeraSensor vera_device: pv.VeraSensor = MagicMock(spec=pv.VeraSensor)
vera_device.device_id = 1 vera_device.device_id = 1
vera_device.vera_device_id = vera_device.device_id vera_device.vera_device_id = vera_device.device_id
vera_device.comm_failure = False vera_device.comm_failure = False

View file

@ -12,7 +12,7 @@ async def test_switch(
hass: HomeAssistant, vera_component_factory: ComponentFactory hass: HomeAssistant, vera_component_factory: ComponentFactory
) -> None: ) -> None:
"""Test function.""" """Test function."""
vera_device = MagicMock(spec=pv.VeraSwitch) # type: pv.VeraSwitch vera_device: pv.VeraSwitch = MagicMock(spec=pv.VeraSwitch)
vera_device.device_id = 1 vera_device.device_id = 1
vera_device.vera_device_id = vera_device.device_id vera_device.vera_device_id = vera_device.device_id
vera_device.comm_failure = False vera_device.comm_failure = False