mirror of
https://github.com/home-assistant/core.git
synced 2026-04-02 00:20:30 +01:00
Create IntegrationType enum (#166598)
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from .model import Config, Integration
|
||||
from .model import Config, Integration, IntegrationType
|
||||
|
||||
BASE = """
|
||||
# This file is generated by script/hassfest/codeowners.py
|
||||
@@ -65,7 +65,7 @@ def generate_and_validate(integrations: dict[str, Integration], config: Config)
|
||||
for domain in sorted(integrations):
|
||||
integration = integrations[domain]
|
||||
|
||||
if integration.integration_type == "virtual":
|
||||
if integration.integration_type == IntegrationType.VIRTUAL:
|
||||
continue
|
||||
|
||||
codeowners = integration.manifest["codeowners"]
|
||||
|
||||
@@ -6,7 +6,7 @@ import json
|
||||
from typing import Any
|
||||
|
||||
from .brand import validate as validate_brands
|
||||
from .model import Brand, Config, Integration
|
||||
from .model import Brand, Config, Integration, IntegrationType
|
||||
from .serializer import format_python_namespace
|
||||
|
||||
UNIQUE_ID_IGNORE = {"huawei_lte", "mqtt", "adguard"}
|
||||
@@ -75,7 +75,7 @@ def _generate_and_validate(integrations: dict[str, Integration], config: Config)
|
||||
|
||||
_validate_integration(config, integration)
|
||||
|
||||
if integration.integration_type == "helper":
|
||||
if integration.integration_type == IntegrationType.HELPER:
|
||||
domains["helper"].append(domain)
|
||||
else:
|
||||
domains["integration"].append(domain)
|
||||
@@ -94,8 +94,8 @@ def _populate_brand_integrations(
|
||||
for domain in sub_integrations:
|
||||
integration = integrations.get(domain)
|
||||
if not integration or integration.integration_type in (
|
||||
"entity",
|
||||
"system",
|
||||
IntegrationType.ENTITY,
|
||||
IntegrationType.SYSTEM,
|
||||
):
|
||||
continue
|
||||
metadata: dict[str, Any] = {
|
||||
@@ -170,7 +170,10 @@ def _generate_integrations(
|
||||
result["integration"][domain] = metadata
|
||||
else: # integration
|
||||
integration = integrations[domain]
|
||||
if integration.integration_type in ("entity", "system"):
|
||||
if integration.integration_type in (
|
||||
IntegrationType.ENTITY,
|
||||
IntegrationType.SYSTEM,
|
||||
):
|
||||
continue
|
||||
|
||||
if integration.translated_name:
|
||||
@@ -180,7 +183,7 @@ def _generate_integrations(
|
||||
|
||||
metadata["integration_type"] = integration.integration_type
|
||||
|
||||
if integration.integration_type == "virtual":
|
||||
if integration.integration_type == IntegrationType.VIRTUAL:
|
||||
if integration.supported_by:
|
||||
metadata["supported_by"] = integration.supported_by
|
||||
if integration.iot_standards:
|
||||
@@ -195,7 +198,7 @@ def _generate_integrations(
|
||||
):
|
||||
metadata["single_config_entry"] = single_config_entry
|
||||
|
||||
if integration.integration_type == "helper":
|
||||
if integration.integration_type == IntegrationType.HELPER:
|
||||
result["helper"][domain] = metadata
|
||||
else:
|
||||
result["integration"][domain] = metadata
|
||||
|
||||
@@ -4,7 +4,7 @@ import re
|
||||
|
||||
from homeassistant.util.yaml import load_yaml_dict
|
||||
|
||||
from .model import Config, Integration
|
||||
from .model import Config, Integration, IntegrationType
|
||||
|
||||
# Non-entity-platform components that belong in base_platforms
|
||||
EXTRA_BASE_PLATFORMS = {"diagnostics"}
|
||||
@@ -29,7 +29,7 @@ def validate(integrations: dict[str, Integration], config: Config) -> None:
|
||||
entity_platforms = {
|
||||
integration.domain
|
||||
for integration in integrations.values()
|
||||
if integration.manifest.get("integration_type") == "entity"
|
||||
if integration.integration_type == IntegrationType.ENTITY
|
||||
and integration.domain != "tag"
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ from voluptuous.humanize import humanize_error
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.icon import convert_shorthand_service_icon
|
||||
|
||||
from .model import Config, Integration
|
||||
from .model import Config, Integration, IntegrationType
|
||||
from .translations import translation_key_validator
|
||||
|
||||
|
||||
@@ -141,7 +141,7 @@ TRIGGER_ICONS_SCHEMA = cv.schema_with_slug_keys(
|
||||
|
||||
|
||||
def icon_schema(
|
||||
core_integration: bool, integration_type: str, no_entity_platform: bool
|
||||
core_integration: bool, integration_type: IntegrationType, no_entity_platform: bool
|
||||
) -> vol.Schema:
|
||||
"""Create an icon schema."""
|
||||
|
||||
@@ -189,8 +189,12 @@ def icon_schema(
|
||||
}
|
||||
)
|
||||
|
||||
if integration_type in ("entity", "helper", "system"):
|
||||
if integration_type != "entity" or no_entity_platform:
|
||||
if integration_type in (
|
||||
IntegrationType.ENTITY,
|
||||
IntegrationType.HELPER,
|
||||
IntegrationType.SYSTEM,
|
||||
):
|
||||
if integration_type != IntegrationType.ENTITY or no_entity_platform:
|
||||
field = vol.Optional("entity_component")
|
||||
else:
|
||||
field = vol.Required("entity_component")
|
||||
@@ -207,7 +211,7 @@ def icon_schema(
|
||||
)
|
||||
}
|
||||
)
|
||||
if integration_type not in ("entity", "system"):
|
||||
if integration_type not in (IntegrationType.ENTITY, IntegrationType.SYSTEM):
|
||||
schema = schema.extend(
|
||||
{
|
||||
vol.Optional("entity"): vol.All(
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from .model import Config, Integration
|
||||
from .model import Config, Integration, IntegrationType
|
||||
from .serializer import format_python
|
||||
|
||||
|
||||
@@ -12,12 +12,12 @@ def validate(integrations: dict[str, Integration], config: Config) -> None:
|
||||
if config.specific_integrations:
|
||||
return
|
||||
|
||||
int_type = "entity"
|
||||
int_type = IntegrationType.ENTITY
|
||||
|
||||
domains = [
|
||||
integration.domain
|
||||
for integration in integrations.values()
|
||||
if integration.manifest.get("integration_type") == int_type
|
||||
if integration.integration_type == int_type
|
||||
# Tag is type "entity" but has no entity platform
|
||||
and integration.domain != "tag"
|
||||
]
|
||||
@@ -36,7 +36,7 @@ def validate(integrations: dict[str, Integration], config: Config) -> None:
|
||||
|
||||
def generate(integrations: dict[str, Integration], config: Config) -> None:
|
||||
"""Generate integration file."""
|
||||
int_type = "entity"
|
||||
int_type = IntegrationType.ENTITY
|
||||
filename = "entity_platforms"
|
||||
platform_path = config.root / f"homeassistant/generated/{filename}.py"
|
||||
platform_path.write_text(config.cache[f"integrations_{int_type}"])
|
||||
|
||||
@@ -21,7 +21,7 @@ from homeassistant.const import Platform
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
from script.util import sort_manifest as util_sort_manifest
|
||||
|
||||
from .model import Config, Integration, ScaledQualityScaleTiers
|
||||
from .model import Config, Integration, IntegrationType, ScaledQualityScaleTiers
|
||||
|
||||
DOCUMENTATION_URL_SCHEMA = "https"
|
||||
DOCUMENTATION_URL_HOST = "www.home-assistant.io"
|
||||
@@ -206,15 +206,7 @@ INTEGRATION_MANIFEST_SCHEMA = vol.Schema(
|
||||
vol.Required("domain"): str,
|
||||
vol.Required("name"): str,
|
||||
vol.Optional("integration_type", default="hub"): vol.In(
|
||||
[
|
||||
"device",
|
||||
"entity",
|
||||
"hardware",
|
||||
"helper",
|
||||
"hub",
|
||||
"service",
|
||||
"system",
|
||||
]
|
||||
[t.value for t in IntegrationType if t != IntegrationType.VIRTUAL]
|
||||
),
|
||||
vol.Optional("config_flow"): bool,
|
||||
vol.Optional("mqtt"): [str],
|
||||
@@ -311,7 +303,7 @@ VIRTUAL_INTEGRATION_MANIFEST_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required("domain"): str,
|
||||
vol.Required("name"): str,
|
||||
vol.Required("integration_type"): "virtual",
|
||||
vol.Required("integration_type"): IntegrationType.VIRTUAL.value,
|
||||
vol.Exclusive("iot_standards", "virtual_integration"): [
|
||||
vol.Any("homekit", "zigbee", "zwave")
|
||||
],
|
||||
@@ -322,7 +314,7 @@ VIRTUAL_INTEGRATION_MANIFEST_SCHEMA = vol.Schema(
|
||||
|
||||
def manifest_schema(value: dict[str, Any]) -> vol.Schema:
|
||||
"""Validate integration manifest."""
|
||||
if value.get("integration_type") == "virtual":
|
||||
if value.get("integration_type") == IntegrationType.VIRTUAL:
|
||||
return VIRTUAL_INTEGRATION_MANIFEST_SCHEMA(value)
|
||||
return INTEGRATION_MANIFEST_SCHEMA(value)
|
||||
|
||||
@@ -373,12 +365,12 @@ def validate_manifest(integration: Integration, core_components_dir: Path) -> No
|
||||
if (
|
||||
domain not in NO_IOT_CLASS
|
||||
and "iot_class" not in integration.manifest
|
||||
and integration.manifest.get("integration_type") != "virtual"
|
||||
and integration.integration_type != IntegrationType.VIRTUAL
|
||||
):
|
||||
integration.add_error("manifest", "Domain is missing an IoT Class")
|
||||
|
||||
if (
|
||||
integration.manifest.get("integration_type") == "virtual"
|
||||
integration.integration_type == IntegrationType.VIRTUAL
|
||||
and (supported_by := integration.manifest.get("supported_by"))
|
||||
and not (core_components_dir / supported_by).exists()
|
||||
):
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from enum import IntEnum
|
||||
from enum import IntEnum, StrEnum
|
||||
import json
|
||||
import pathlib
|
||||
from typing import Any, Literal
|
||||
@@ -200,9 +200,15 @@ class Integration:
|
||||
return self.manifest.get("supported_by", {})
|
||||
|
||||
@property
|
||||
def integration_type(self) -> str:
|
||||
def integration_type(self) -> IntegrationType:
|
||||
"""Get integration_type."""
|
||||
return self.manifest.get("integration_type", "hub")
|
||||
integration_type = self.manifest.get("integration_type", "hub")
|
||||
try:
|
||||
return IntegrationType(integration_type)
|
||||
except ValueError:
|
||||
# The manifest validation will catch this as an error, so we can default to
|
||||
# a valid value here to avoid ValueErrors in other plugins
|
||||
return IntegrationType.HUB
|
||||
|
||||
@property
|
||||
def iot_class(self) -> str | None:
|
||||
@@ -248,6 +254,19 @@ class Integration:
|
||||
self.manifest_path = manifest_path
|
||||
|
||||
|
||||
class IntegrationType(StrEnum):
|
||||
"""Supported integration types."""
|
||||
|
||||
DEVICE = "device"
|
||||
ENTITY = "entity"
|
||||
HARDWARE = "hardware"
|
||||
HELPER = "helper"
|
||||
HUB = "hub"
|
||||
SERVICE = "service"
|
||||
SYSTEM = "system"
|
||||
VIRTUAL = "virtual"
|
||||
|
||||
|
||||
class ScaledQualityScaleTiers(IntEnum):
|
||||
"""Supported manifest quality scales."""
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ from homeassistant.const import Platform
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.util.yaml import load_yaml_dict
|
||||
|
||||
from .model import Config, Integration, ScaledQualityScaleTiers
|
||||
from .model import Config, Integration, IntegrationType, ScaledQualityScaleTiers
|
||||
from .quality_scale_validation import (
|
||||
RuleValidationProtocol,
|
||||
action_setup,
|
||||
@@ -2200,7 +2200,7 @@ def validate_iqs_file(config: Config, integration: Integration) -> None:
|
||||
if (
|
||||
integration.domain not in INTEGRATIONS_WITHOUT_QUALITY_SCALE_FILE
|
||||
and integration.domain not in NO_QUALITY_SCALE
|
||||
and integration.integration_type != "virtual"
|
||||
and integration.integration_type != IntegrationType.VIRTUAL
|
||||
):
|
||||
integration.add_error(
|
||||
"quality_scale",
|
||||
@@ -2218,7 +2218,7 @@ def validate_iqs_file(config: Config, integration: Integration) -> None:
|
||||
)
|
||||
return
|
||||
return
|
||||
if integration.integration_type == "virtual":
|
||||
if integration.integration_type == IntegrationType.VIRTUAL:
|
||||
integration.add_error(
|
||||
"quality_scale",
|
||||
"Virtual integrations are not allowed to have a quality scale file.",
|
||||
|
||||
@@ -14,7 +14,7 @@ from voluptuous.humanize import humanize_error
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from script.translations import upload
|
||||
|
||||
from .model import Config, Integration
|
||||
from .model import Config, Integration, IntegrationType
|
||||
|
||||
UNDEFINED = 0
|
||||
REQUIRED = 1
|
||||
@@ -345,7 +345,9 @@ def gen_strings_schema(config: Config, integration: Integration) -> vol.Schema:
|
||||
flow_title=REMOVED,
|
||||
require_step_title=False,
|
||||
mandatory_description=(
|
||||
"user" if integration.integration_type == "helper" else None
|
||||
"user"
|
||||
if integration.integration_type == IntegrationType.HELPER
|
||||
else None
|
||||
),
|
||||
),
|
||||
vol.Optional("config_subentries"): cv.schema_with_slug_keys(
|
||||
|
||||
Reference in New Issue
Block a user