Add type hints to hassfest models (#82074)
* Add type hints to hassfest models * Implement review
This commit is contained in:
parent
de313dcc3f
commit
55444b15a9
1 changed files with 25 additions and 10 deletions
|
@ -4,6 +4,7 @@ from __future__ import annotations
|
||||||
import importlib
|
import importlib
|
||||||
import json
|
import json
|
||||||
import pathlib
|
import pathlib
|
||||||
|
from types import ModuleType
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import attr
|
import attr
|
||||||
|
@ -44,10 +45,10 @@ class Brand:
|
||||||
"""Represent a brand in our validator."""
|
"""Represent a brand in our validator."""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load_dir(cls, path: pathlib.Path, config: Config):
|
def load_dir(cls, path: pathlib.Path, config: Config) -> dict[str, Brand]:
|
||||||
"""Load all brands in a directory."""
|
"""Load all brands in a directory."""
|
||||||
assert path.is_dir()
|
assert path.is_dir()
|
||||||
brands = {}
|
brands: dict[str, Brand] = {}
|
||||||
for fil in path.iterdir():
|
for fil in path.iterdir():
|
||||||
brand = cls(fil)
|
brand = cls(fil)
|
||||||
brand.load_brand(config)
|
brand.load_brand(config)
|
||||||
|
@ -66,16 +67,19 @@ class Brand:
|
||||||
@property
|
@property
|
||||||
def name(self) -> str | None:
|
def name(self) -> str | None:
|
||||||
"""Return name of the integration."""
|
"""Return name of the integration."""
|
||||||
|
assert self.brand is not None, "brand has not been loaded"
|
||||||
return self.brand.get("name")
|
return self.brand.get("name")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def integrations(self) -> list[str]:
|
def integrations(self) -> list[str]:
|
||||||
"""Return the sub integrations of this brand."""
|
"""Return the sub integrations of this brand."""
|
||||||
return self.brand.get("integrations")
|
assert self.brand is not None, "brand has not been loaded"
|
||||||
|
return self.brand.get("integrations", [])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def iot_standards(self) -> list[str]:
|
def iot_standards(self) -> list[str]:
|
||||||
"""Return list of supported IoT standards."""
|
"""Return list of supported IoT standards."""
|
||||||
|
assert self.brand is not None, "brand has not been loaded"
|
||||||
return self.brand.get("iot_standards", [])
|
return self.brand.get("iot_standards", [])
|
||||||
|
|
||||||
def load_brand(self, config: Config) -> None:
|
def load_brand(self, config: Config) -> None:
|
||||||
|
@ -85,7 +89,7 @@ class Brand:
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
brand = json.loads(self.path.read_text())
|
brand: dict[str, Any] = json.loads(self.path.read_text())
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
config.add_error(
|
config.add_error(
|
||||||
"model", f"Brand file {self.path.name} contains invalid JSON: {err}"
|
"model", f"Brand file {self.path.name} contains invalid JSON: {err}"
|
||||||
|
@ -100,10 +104,10 @@ class Integration:
|
||||||
"""Represent an integration in our validator."""
|
"""Represent an integration in our validator."""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load_dir(cls, path: pathlib.Path):
|
def load_dir(cls, path: pathlib.Path) -> dict[str, Integration]:
|
||||||
"""Load all integrations in a directory."""
|
"""Load all integrations in a directory."""
|
||||||
assert path.is_dir()
|
assert path.is_dir()
|
||||||
integrations = {}
|
integrations: dict[str, Integration] = {}
|
||||||
for fil in path.iterdir():
|
for fil in path.iterdir():
|
||||||
if fil.is_file() or fil.name == "__pycache__":
|
if fil.is_file() or fil.name == "__pycache__":
|
||||||
continue
|
continue
|
||||||
|
@ -143,51 +147,62 @@ class Integration:
|
||||||
@property
|
@property
|
||||||
def disabled(self) -> str | None:
|
def disabled(self) -> str | None:
|
||||||
"""Return if integration is disabled."""
|
"""Return if integration is disabled."""
|
||||||
|
assert self.manifest is not None, "manifest has not been loaded"
|
||||||
return self.manifest.get("disabled")
|
return self.manifest.get("disabled")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
"""Return name of the integration."""
|
"""Return name of the integration."""
|
||||||
return self.manifest["name"]
|
assert self.manifest is not None, "manifest has not been loaded"
|
||||||
|
name: str = self.manifest["name"]
|
||||||
|
return name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def quality_scale(self) -> str:
|
def quality_scale(self) -> str | None:
|
||||||
"""Return quality scale of the integration."""
|
"""Return quality scale of the integration."""
|
||||||
|
assert self.manifest is not None, "manifest has not been loaded"
|
||||||
return self.manifest.get("quality_scale")
|
return self.manifest.get("quality_scale")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def config_flow(self) -> bool:
|
def config_flow(self) -> bool:
|
||||||
"""Return if the integration has a config flow."""
|
"""Return if the integration has a config flow."""
|
||||||
|
assert self.manifest is not None, "manifest has not been loaded"
|
||||||
return self.manifest.get("config_flow", False)
|
return self.manifest.get("config_flow", False)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def requirements(self) -> list[str]:
|
def requirements(self) -> list[str]:
|
||||||
"""List of requirements."""
|
"""List of requirements."""
|
||||||
|
assert self.manifest is not None, "manifest has not been loaded"
|
||||||
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."""
|
||||||
|
assert self.manifest is not None, "manifest has not been loaded"
|
||||||
return self.manifest.get("dependencies", [])
|
return self.manifest.get("dependencies", [])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def supported_by(self) -> str:
|
def supported_by(self) -> str:
|
||||||
"""Return the integration supported by this virtual integration."""
|
"""Return the integration supported by this virtual integration."""
|
||||||
|
assert self.manifest is not None, "manifest has not been loaded"
|
||||||
return self.manifest.get("supported_by", {})
|
return self.manifest.get("supported_by", {})
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def integration_type(self) -> str:
|
def integration_type(self) -> str:
|
||||||
"""Get integration_type."""
|
"""Get integration_type."""
|
||||||
|
assert self.manifest is not None, "manifest has not been loaded"
|
||||||
return self.manifest.get("integration_type", "hub")
|
return self.manifest.get("integration_type", "hub")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def iot_class(self) -> str | None:
|
def iot_class(self) -> str | None:
|
||||||
"""Return the integration IoT Class."""
|
"""Return the integration IoT Class."""
|
||||||
|
assert self.manifest is not None, "manifest has not been loaded"
|
||||||
return self.manifest.get("iot_class")
|
return self.manifest.get("iot_class")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def iot_standards(self) -> list[str]:
|
def iot_standards(self) -> list[str]:
|
||||||
"""Return the IoT standard supported by this virtual integration."""
|
"""Return the IoT standard supported by this virtual integration."""
|
||||||
|
assert self.manifest is not None, "manifest has not been loaded"
|
||||||
return self.manifest.get("iot_standards", [])
|
return self.manifest.get("iot_standards", [])
|
||||||
|
|
||||||
def add_error(self, *args: Any, **kwargs: Any) -> None:
|
def add_error(self, *args: Any, **kwargs: Any) -> None:
|
||||||
|
@ -206,14 +221,14 @@ class Integration:
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
manifest = json.loads(manifest_path.read_text())
|
manifest: dict[str, Any] = json.loads(manifest_path.read_text())
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
self.add_error("model", f"Manifest contains invalid JSON: {err}")
|
self.add_error("model", f"Manifest contains invalid JSON: {err}")
|
||||||
return
|
return
|
||||||
|
|
||||||
self.manifest = manifest
|
self.manifest = manifest
|
||||||
|
|
||||||
def import_pkg(self, platform=None):
|
def import_pkg(self, platform: str | None = None) -> ModuleType:
|
||||||
"""Import the Python file."""
|
"""Import the Python file."""
|
||||||
pkg = f"homeassistant.components.{self.domain}"
|
pkg = f"homeassistant.components.{self.domain}"
|
||||||
if platform is not None:
|
if platform is not None:
|
||||||
|
|
Loading…
Add table
Reference in a new issue