Generics and other type hint improvements (#45250)
parent
4928476abe
commit
94dbcc9d2b
|
@ -571,7 +571,7 @@ class Context:
|
|||
parent_id: Optional[str] = attr.ib(default=None)
|
||||
id: str = attr.ib(factory=uuid_util.random_uuid_hex)
|
||||
|
||||
def as_dict(self) -> dict:
|
||||
def as_dict(self) -> Dict[str, Optional[str]]:
|
||||
"""Return a dictionary representation of the context."""
|
||||
return {"id": self.id, "parent_id": self.parent_id, "user_id": self.user_id}
|
||||
|
||||
|
@ -612,7 +612,7 @@ class Event:
|
|||
# The only event type that shares context are the TIME_CHANGED
|
||||
return hash((self.event_type, self.context.id, self.time_fired))
|
||||
|
||||
def as_dict(self) -> Dict:
|
||||
def as_dict(self) -> Dict[str, Any]:
|
||||
"""Create a dict representation of this Event.
|
||||
|
||||
Async friendly.
|
||||
|
@ -682,7 +682,7 @@ class EventBus:
|
|||
def async_fire(
|
||||
self,
|
||||
event_type: str,
|
||||
event_data: Optional[Dict] = None,
|
||||
event_data: Optional[Dict[str, Any]] = None,
|
||||
origin: EventOrigin = EventOrigin.local,
|
||||
context: Optional[Context] = None,
|
||||
time_fired: Optional[datetime.datetime] = None,
|
||||
|
@ -844,7 +844,7 @@ class State:
|
|||
self,
|
||||
entity_id: str,
|
||||
state: str,
|
||||
attributes: Optional[Mapping] = None,
|
||||
attributes: Optional[Mapping[str, Any]] = None,
|
||||
last_changed: Optional[datetime.datetime] = None,
|
||||
last_updated: Optional[datetime.datetime] = None,
|
||||
context: Optional[Context] = None,
|
||||
|
@ -1091,7 +1091,7 @@ class StateMachine:
|
|||
self,
|
||||
entity_id: str,
|
||||
new_state: str,
|
||||
attributes: Optional[Dict] = None,
|
||||
attributes: Optional[Mapping[str, Any]] = None,
|
||||
force_update: bool = False,
|
||||
context: Optional[Context] = None,
|
||||
) -> None:
|
||||
|
@ -1140,7 +1140,7 @@ class StateMachine:
|
|||
self,
|
||||
entity_id: str,
|
||||
new_state: str,
|
||||
attributes: Optional[Dict] = None,
|
||||
attributes: Optional[Mapping[str, Any]] = None,
|
||||
force_update: bool = False,
|
||||
context: Optional[Context] = None,
|
||||
) -> None:
|
||||
|
|
|
@ -6,18 +6,20 @@ from typing import Any, Dict, Optional, Pattern
|
|||
|
||||
from homeassistant.core import split_entity_id
|
||||
|
||||
# mypy: disallow-any-generics
|
||||
|
||||
|
||||
class EntityValues:
|
||||
"""Class to store entity id based values."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
exact: Optional[Dict] = None,
|
||||
domain: Optional[Dict] = None,
|
||||
glob: Optional[Dict] = None,
|
||||
exact: Optional[Dict[str, Dict[str, str]]] = None,
|
||||
domain: Optional[Dict[str, Dict[str, str]]] = None,
|
||||
glob: Optional[Dict[str, Dict[str, str]]] = None,
|
||||
) -> None:
|
||||
"""Initialize an EntityConfigDict."""
|
||||
self._cache: Dict[str, Dict] = {}
|
||||
self._cache: Dict[str, Dict[str, str]] = {}
|
||||
self._exact = exact
|
||||
self._domain = domain
|
||||
|
||||
|
@ -30,7 +32,7 @@ class EntityValues:
|
|||
|
||||
self._glob = compiled
|
||||
|
||||
def get(self, entity_id: str) -> Dict:
|
||||
def get(self, entity_id: str) -> Dict[str, str]:
|
||||
"""Get config for an entity id."""
|
||||
if entity_id in self._cache:
|
||||
return self._cache[entity_id]
|
||||
|
|
|
@ -20,6 +20,7 @@ from typing import (
|
|||
List,
|
||||
Optional,
|
||||
Set,
|
||||
TypedDict,
|
||||
TypeVar,
|
||||
Union,
|
||||
cast,
|
||||
|
@ -34,7 +35,11 @@ from homeassistant.generated.zeroconf import HOMEKIT, ZEROCONF
|
|||
if TYPE_CHECKING:
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
CALLABLE_T = TypeVar("CALLABLE_T", bound=Callable) # pylint: disable=invalid-name
|
||||
# mypy: disallow-any-generics
|
||||
|
||||
CALLABLE_T = TypeVar( # pylint: disable=invalid-name
|
||||
"CALLABLE_T", bound=Callable[..., Any]
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -54,12 +59,38 @@ _UNDEF = object() # Internal; not helpers.typing.UNDEFINED due to circular depe
|
|||
MAX_LOAD_CONCURRENTLY = 4
|
||||
|
||||
|
||||
def manifest_from_legacy_module(domain: str, module: ModuleType) -> Dict:
|
||||
class Manifest(TypedDict, total=False):
|
||||
"""
|
||||
Integration manifest.
|
||||
|
||||
Note that none of the attributes are marked Optional here. However, some of them may be optional in manifest.json
|
||||
in the sense that they can be omitted altogether. But when present, they should not have null values in it.
|
||||
"""
|
||||
|
||||
name: str
|
||||
disabled: str
|
||||
domain: str
|
||||
dependencies: List[str]
|
||||
after_dependencies: List[str]
|
||||
requirements: List[str]
|
||||
config_flow: bool
|
||||
documentation: str
|
||||
issue_tracker: str
|
||||
quality_scale: str
|
||||
mqtt: List[str]
|
||||
ssdp: List[Dict[str, str]]
|
||||
zeroconf: List[Union[str, Dict[str, str]]]
|
||||
dhcp: List[Dict[str, str]]
|
||||
homekit: Dict[str, List[str]]
|
||||
is_built_in: bool
|
||||
codeowners: List[str]
|
||||
|
||||
|
||||
def manifest_from_legacy_module(domain: str, module: ModuleType) -> Manifest:
|
||||
"""Generate a manifest from a legacy module."""
|
||||
return {
|
||||
"domain": domain,
|
||||
"name": domain,
|
||||
"documentation": None,
|
||||
"requirements": getattr(module, "REQUIREMENTS", []),
|
||||
"dependencies": getattr(module, "DEPENDENCIES", []),
|
||||
"codeowners": [],
|
||||
|
@ -205,10 +236,10 @@ async def async_get_homekit(hass: "HomeAssistant") -> Dict[str, str]:
|
|||
return homekit
|
||||
|
||||
|
||||
async def async_get_ssdp(hass: "HomeAssistant") -> Dict[str, List]:
|
||||
async def async_get_ssdp(hass: "HomeAssistant") -> Dict[str, List[Dict[str, str]]]:
|
||||
"""Return cached list of ssdp mappings."""
|
||||
|
||||
ssdp: Dict[str, List] = SSDP.copy()
|
||||
ssdp: Dict[str, List[Dict[str, str]]] = SSDP.copy()
|
||||
|
||||
integrations = await async_get_custom_components(hass)
|
||||
for integration in integrations.values():
|
||||
|
@ -220,10 +251,10 @@ async def async_get_ssdp(hass: "HomeAssistant") -> Dict[str, List]:
|
|||
return ssdp
|
||||
|
||||
|
||||
async def async_get_mqtt(hass: "HomeAssistant") -> Dict[str, List]:
|
||||
async def async_get_mqtt(hass: "HomeAssistant") -> Dict[str, List[str]]:
|
||||
"""Return cached list of MQTT mappings."""
|
||||
|
||||
mqtt: Dict[str, List] = MQTT.copy()
|
||||
mqtt: Dict[str, List[str]] = MQTT.copy()
|
||||
|
||||
integrations = await async_get_custom_components(hass)
|
||||
for integration in integrations.values():
|
||||
|
@ -288,7 +319,7 @@ class Integration:
|
|||
hass: "HomeAssistant",
|
||||
pkg_path: str,
|
||||
file_path: pathlib.Path,
|
||||
manifest: Dict[str, Any],
|
||||
manifest: Manifest,
|
||||
):
|
||||
"""Initialize an integration."""
|
||||
self.hass = hass
|
||||
|
@ -309,77 +340,77 @@ class Integration:
|
|||
@property
|
||||
def name(self) -> str:
|
||||
"""Return name."""
|
||||
return cast(str, self.manifest["name"])
|
||||
return self.manifest["name"]
|
||||
|
||||
@property
|
||||
def disabled(self) -> Optional[str]:
|
||||
"""Return reason integration is disabled."""
|
||||
return cast(Optional[str], self.manifest.get("disabled"))
|
||||
return self.manifest.get("disabled")
|
||||
|
||||
@property
|
||||
def domain(self) -> str:
|
||||
"""Return domain."""
|
||||
return cast(str, self.manifest["domain"])
|
||||
return self.manifest["domain"]
|
||||
|
||||
@property
|
||||
def dependencies(self) -> List[str]:
|
||||
"""Return dependencies."""
|
||||
return cast(List[str], self.manifest.get("dependencies", []))
|
||||
return self.manifest.get("dependencies", [])
|
||||
|
||||
@property
|
||||
def after_dependencies(self) -> List[str]:
|
||||
"""Return after_dependencies."""
|
||||
return cast(List[str], self.manifest.get("after_dependencies", []))
|
||||
return self.manifest.get("after_dependencies", [])
|
||||
|
||||
@property
|
||||
def requirements(self) -> List[str]:
|
||||
"""Return requirements."""
|
||||
return cast(List[str], self.manifest.get("requirements", []))
|
||||
return self.manifest.get("requirements", [])
|
||||
|
||||
@property
|
||||
def config_flow(self) -> bool:
|
||||
"""Return config_flow."""
|
||||
return cast(bool, self.manifest.get("config_flow", False))
|
||||
return self.manifest.get("config_flow") or False
|
||||
|
||||
@property
|
||||
def documentation(self) -> Optional[str]:
|
||||
"""Return documentation."""
|
||||
return cast(str, self.manifest.get("documentation"))
|
||||
return self.manifest.get("documentation")
|
||||
|
||||
@property
|
||||
def issue_tracker(self) -> Optional[str]:
|
||||
"""Return issue tracker link."""
|
||||
return cast(str, self.manifest.get("issue_tracker"))
|
||||
return self.manifest.get("issue_tracker")
|
||||
|
||||
@property
|
||||
def quality_scale(self) -> Optional[str]:
|
||||
"""Return Integration Quality Scale."""
|
||||
return cast(str, self.manifest.get("quality_scale"))
|
||||
return self.manifest.get("quality_scale")
|
||||
|
||||
@property
|
||||
def mqtt(self) -> Optional[list]:
|
||||
def mqtt(self) -> Optional[List[str]]:
|
||||
"""Return Integration MQTT entries."""
|
||||
return cast(List[dict], self.manifest.get("mqtt"))
|
||||
return self.manifest.get("mqtt")
|
||||
|
||||
@property
|
||||
def ssdp(self) -> Optional[list]:
|
||||
def ssdp(self) -> Optional[List[Dict[str, str]]]:
|
||||
"""Return Integration SSDP entries."""
|
||||
return cast(List[dict], self.manifest.get("ssdp"))
|
||||
return self.manifest.get("ssdp")
|
||||
|
||||
@property
|
||||
def zeroconf(self) -> Optional[list]:
|
||||
def zeroconf(self) -> Optional[List[Union[str, Dict[str, str]]]]:
|
||||
"""Return Integration zeroconf entries."""
|
||||
return cast(List[str], self.manifest.get("zeroconf"))
|
||||
return self.manifest.get("zeroconf")
|
||||
|
||||
@property
|
||||
def dhcp(self) -> Optional[list]:
|
||||
def dhcp(self) -> Optional[List[Dict[str, str]]]:
|
||||
"""Return Integration dhcp entries."""
|
||||
return cast(List[str], self.manifest.get("dhcp"))
|
||||
return self.manifest.get("dhcp")
|
||||
|
||||
@property
|
||||
def homekit(self) -> Optional[dict]:
|
||||
def homekit(self) -> Optional[Dict[str, List[str]]]:
|
||||
"""Return Integration homekit entries."""
|
||||
return cast(Dict[str, List], self.manifest.get("homekit"))
|
||||
return self.manifest.get("homekit")
|
||||
|
||||
@property
|
||||
def is_built_in(self) -> bool:
|
||||
|
|
|
@ -9,6 +9,8 @@ from homeassistant.helpers.typing import UNDEFINED, UndefinedType
|
|||
from homeassistant.loader import Integration, IntegrationNotFound, async_get_integration
|
||||
import homeassistant.util.package as pkg_util
|
||||
|
||||
# mypy: disallow-any-generics
|
||||
|
||||
DATA_PIP_LOCK = "pip_lock"
|
||||
DATA_PKG_CACHE = "pkg_cache"
|
||||
DATA_INTEGRATIONS_WITH_REQS = "integrations_with_reqs"
|
||||
|
@ -24,7 +26,7 @@ DISCOVERY_INTEGRATIONS: Dict[str, Iterable[str]] = {
|
|||
class RequirementsNotFound(HomeAssistantError):
|
||||
"""Raised when a component is not found."""
|
||||
|
||||
def __init__(self, domain: str, requirements: List) -> None:
|
||||
def __init__(self, domain: str, requirements: List[str]) -> None:
|
||||
"""Initialize a component not found error."""
|
||||
super().__init__(f"Requirements for {domain} not found: {requirements}.")
|
||||
self.domain = domain
|
||||
|
@ -124,7 +126,7 @@ async def async_process_requirements(
|
|||
if pkg_util.is_installed(req):
|
||||
continue
|
||||
|
||||
def _install(req: str, kwargs: Dict) -> bool:
|
||||
def _install(req: str, kwargs: Dict[str, Any]) -> bool:
|
||||
"""Install requirement."""
|
||||
return pkg_util.install_package(req, **kwargs)
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ from homeassistant import bootstrap
|
|||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.frame import warn_use
|
||||
|
||||
# mypy: disallow-any-generics
|
||||
|
||||
#
|
||||
# Python 3.8 has significantly less workers by default
|
||||
# than Python 3.7. In order to be consistent between
|
||||
|
@ -81,7 +83,7 @@ class HassEventLoopPolicy(asyncio.DefaultEventLoopPolicy): # type: ignore[valid
|
|||
|
||||
|
||||
@callback
|
||||
def _async_loop_exception_handler(_: Any, context: Dict) -> None:
|
||||
def _async_loop_exception_handler(_: Any, context: Dict[str, Any]) -> None:
|
||||
"""Handle all exception inside the core loop."""
|
||||
kwargs = {}
|
||||
exception = context.get("exception")
|
||||
|
|
|
@ -1,9 +1,17 @@
|
|||
"""Util to handle processes."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import subprocess
|
||||
from typing import Any
|
||||
|
||||
# mypy: disallow-any-generics
|
||||
|
||||
|
||||
def kill_subprocess(process: subprocess.Popen) -> None:
|
||||
def kill_subprocess(
|
||||
# pylint: disable=unsubscriptable-object # https://github.com/PyCQA/pylint/issues/4034
|
||||
process: subprocess.Popen[Any],
|
||||
) -> None:
|
||||
"""Force kill a subprocess and wait for it to exit."""
|
||||
process.kill()
|
||||
process.communicate()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"""Unit system helper class and methods."""
|
||||
from numbers import Number
|
||||
from typing import Optional
|
||||
from typing import Dict, Optional
|
||||
|
||||
from homeassistant.const import (
|
||||
CONF_UNIT_SYSTEM_IMPERIAL,
|
||||
|
@ -31,6 +31,8 @@ from homeassistant.util import (
|
|||
volume as volume_util,
|
||||
)
|
||||
|
||||
# mypy: disallow-any-generics
|
||||
|
||||
LENGTH_UNITS = distance_util.VALID_UNITS
|
||||
|
||||
MASS_UNITS = [MASS_POUNDS, MASS_OUNCES, MASS_KILOGRAMS, MASS_GRAMS]
|
||||
|
@ -135,7 +137,7 @@ class UnitSystem:
|
|||
# type ignore: https://github.com/python/mypy/issues/7207
|
||||
return volume_util.convert(volume, from_unit, self.volume_unit) # type: ignore
|
||||
|
||||
def as_dict(self) -> dict:
|
||||
def as_dict(self) -> Dict[str, str]:
|
||||
"""Convert the unit system to a dictionary."""
|
||||
return {
|
||||
LENGTH: self.length_unit,
|
||||
|
|
Loading…
Reference in New Issue