Integrations v2.1: Virtual integrations (#80613)
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from awesomeversion import (
|
||||
@@ -158,7 +159,7 @@ def verify_wildcard(value: str):
|
||||
return value
|
||||
|
||||
|
||||
MANIFEST_SCHEMA = vol.Schema(
|
||||
INTEGRATION_MANIFEST_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required("domain"): str,
|
||||
vol.Required("name"): str,
|
||||
@@ -254,14 +255,32 @@ MANIFEST_SCHEMA = vol.Schema(
|
||||
vol.Optional("loggers"): [str],
|
||||
vol.Optional("disabled"): str,
|
||||
vol.Optional("iot_class"): vol.In(SUPPORTED_IOT_CLASSES),
|
||||
vol.Optional("supported_brands"): vol.Schema({str: str}),
|
||||
}
|
||||
)
|
||||
|
||||
CUSTOM_INTEGRATION_MANIFEST_SCHEMA = MANIFEST_SCHEMA.extend(
|
||||
VIRTUAL_INTEGRATION_MANIFEST_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required("domain"): str,
|
||||
vol.Required("name"): str,
|
||||
vol.Required("integration_type"): "virtual",
|
||||
vol.Exclusive("iot_standard", "virtual_integration"): vol.Any(
|
||||
"homekit", "zigbee", "zwave"
|
||||
),
|
||||
vol.Exclusive("supported_by", "virtual_integration"): str,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def manifest_schema(value: dict[str, Any]) -> vol.Schema:
|
||||
"""Validate integration manifest."""
|
||||
if value.get("integration_type") == "virtual":
|
||||
return VIRTUAL_INTEGRATION_MANIFEST_SCHEMA(value)
|
||||
return INTEGRATION_MANIFEST_SCHEMA(value)
|
||||
|
||||
|
||||
CUSTOM_INTEGRATION_MANIFEST_SCHEMA = INTEGRATION_MANIFEST_SCHEMA.extend(
|
||||
{
|
||||
vol.Optional("version"): vol.All(str, verify_version),
|
||||
vol.Remove("supported_brands"): dict,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -284,7 +303,7 @@ def validate_manifest(integration: Integration, core_components_dir: Path) -> No
|
||||
|
||||
try:
|
||||
if integration.core:
|
||||
MANIFEST_SCHEMA(integration.manifest)
|
||||
manifest_schema(integration.manifest)
|
||||
else:
|
||||
CUSTOM_INTEGRATION_MANIFEST_SCHEMA(integration.manifest)
|
||||
except vol.Invalid as err:
|
||||
@@ -312,15 +331,19 @@ def validate_manifest(integration: Integration, core_components_dir: Path) -> No
|
||||
if (
|
||||
integration.manifest["domain"] not in NO_IOT_CLASS
|
||||
and "iot_class" not in integration.manifest
|
||||
and integration.manifest.get("integration_type") != "virtual"
|
||||
):
|
||||
integration.add_error("manifest", "Domain is missing an IoT Class")
|
||||
|
||||
for domain, _name in integration.manifest.get("supported_brands", {}).items():
|
||||
if (core_components_dir / domain).exists():
|
||||
integration.add_warning(
|
||||
"manifest",
|
||||
f"Supported brand domain {domain} collides with built-in core integration",
|
||||
)
|
||||
if (
|
||||
integration.manifest.get("integration_type") == "virtual"
|
||||
and (supported_by := integration.manifest.get("supported_by"))
|
||||
and not (core_components_dir / supported_by).exists()
|
||||
):
|
||||
integration.add_error(
|
||||
"manifest",
|
||||
"Virtual integration points to non-existing supported_by integration",
|
||||
)
|
||||
|
||||
if not integration.core:
|
||||
validate_version(integration)
|
||||
|
||||
Reference in New Issue
Block a user