mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 16:57:53 +00:00
Make integration setup optional (#48381)
This commit is contained in:
parent
dda9f957b6
commit
52475c108f
@ -8,7 +8,6 @@ from aiohttp.client_exceptions import ClientConnectorError
|
||||
from async_timeout import timeout
|
||||
|
||||
from homeassistant.const import CONF_API_KEY
|
||||
from homeassistant.core import Config, HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
@ -26,12 +25,6 @@ _LOGGER = logging.getLogger(__name__)
|
||||
PLATFORMS = ["sensor", "weather"]
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: Config) -> bool:
|
||||
"""Set up configured AccuWeather."""
|
||||
hass.data.setdefault(DOMAIN, {})
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup_entry(hass, config_entry) -> bool:
|
||||
"""Set up AccuWeather as config entry."""
|
||||
api_key = config_entry.data[CONF_API_KEY]
|
||||
@ -52,7 +45,7 @@ async def async_setup_entry(hass, config_entry) -> bool:
|
||||
|
||||
undo_listener = config_entry.add_update_listener(update_listener)
|
||||
|
||||
hass.data[DOMAIN][config_entry.entry_id] = {
|
||||
hass.data.setdefault(DOMAIN, {})[config_entry.entry_id] = {
|
||||
COORDINATOR: coordinator,
|
||||
UNDO_UPDATE_LISTENER: undo_listener,
|
||||
}
|
||||
|
@ -34,7 +34,6 @@ from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@ -49,11 +48,6 @@ SERVICE_REFRESH_SCHEMA = vol.Schema(
|
||||
PLATFORMS = ["sensor", "switch"]
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
"""Set up the AdGuard Home components."""
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Set up AdGuard Home from a config entry."""
|
||||
session = async_get_clientsession(hass, entry.data[CONF_VERIFY_SSL])
|
||||
|
@ -38,11 +38,6 @@ _LOGGER = logging.getLogger(__name__)
|
||||
PLATFORMS = ["sensor"]
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: dict):
|
||||
"""Set up the AirNow component."""
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
||||
"""Set up AirNow from a config entry."""
|
||||
api_key = entry.data[CONF_API_KEY]
|
||||
|
@ -20,11 +20,6 @@ CONFIG_SCHEMA = vol.Schema(
|
||||
)
|
||||
|
||||
|
||||
async def async_setup(hass, config):
|
||||
"""Old way of setting up deCONZ integrations."""
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup_entry(hass, config_entry):
|
||||
"""Set up a deCONZ bridge for a config entry.
|
||||
|
||||
|
@ -9,16 +9,10 @@ from homeassistant.const import CONF_HOST, CONF_PORT
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
|
||||
from .const import DATA_ELGATO_CLIENT, DOMAIN
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
"""Set up the Elgato Key Light components."""
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Set up Elgato Key Light from a config entry."""
|
||||
session = async_get_clientsession(hass)
|
||||
|
@ -42,7 +42,7 @@ from homeassistant.helpers.json import JSONEncoder
|
||||
from homeassistant.helpers.service import async_set_service_schema
|
||||
from homeassistant.helpers.storage import Store
|
||||
from homeassistant.helpers.template import Template
|
||||
from homeassistant.helpers.typing import ConfigType, HomeAssistantType
|
||||
from homeassistant.helpers.typing import HomeAssistantType
|
||||
|
||||
# Import config flow so that it's added to the registry
|
||||
from .entry_data import RuntimeEntryData
|
||||
@ -56,11 +56,6 @@ STORAGE_VERSION = 1
|
||||
CONFIG_SCHEMA = vol.Schema({}, extra=vol.ALLOW_EXTRA)
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool:
|
||||
"""Stub to allow setting up this component."""
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool:
|
||||
"""Set up the esphome component."""
|
||||
hass.data.setdefault(DOMAIN, {})
|
||||
|
@ -24,7 +24,6 @@ from homeassistant.helpers.device_registry import (
|
||||
EVENT_DEVICE_REGISTRY_UPDATED,
|
||||
async_entries_for_config_entry,
|
||||
)
|
||||
from homeassistant.helpers.typing import HomeAssistantType
|
||||
|
||||
from . import device_automation, discovery
|
||||
from .const import (
|
||||
@ -38,11 +37,6 @@ from .const import (
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistantType, config: dict):
|
||||
"""Set up the Tasmota component."""
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup_entry(hass, entry):
|
||||
"""Set up Tasmota from a config entry."""
|
||||
websocket_api.async_register_command(hass, websocket_remove_device)
|
||||
|
@ -16,7 +16,6 @@ from homeassistant.const import ATTR_NAME, CONF_HOST
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
from homeassistant.helpers.update_coordinator import (
|
||||
CoordinatorEntity,
|
||||
DataUpdateCoordinator,
|
||||
@ -37,11 +36,6 @@ PLATFORMS = (LIGHT_DOMAIN, SENSOR_DOMAIN, SWITCH_DOMAIN)
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
"""Set up the WLED components."""
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Set up WLED from a config entry."""
|
||||
|
||||
|
@ -169,7 +169,7 @@ async def _async_setup_component(
|
||||
return False
|
||||
|
||||
if integration.disabled:
|
||||
log_error(f"dependency is disabled - {integration.disabled}")
|
||||
log_error(f"Dependency is disabled - {integration.disabled}")
|
||||
return False
|
||||
|
||||
# Validate all dependencies exist and there are no circular dependencies
|
||||
@ -219,6 +219,8 @@ async def _async_setup_component(
|
||||
SLOW_SETUP_WARNING,
|
||||
)
|
||||
|
||||
task = None
|
||||
result = True
|
||||
try:
|
||||
if hasattr(component, "async_setup"):
|
||||
task = component.async_setup(hass, processed_config) # type: ignore
|
||||
@ -228,13 +230,14 @@ async def _async_setup_component(
|
||||
task = hass.loop.run_in_executor(
|
||||
None, component.setup, hass, processed_config # type: ignore
|
||||
)
|
||||
else:
|
||||
log_error("No setup function defined.")
|
||||
elif not hasattr(component, "async_setup_entry"):
|
||||
log_error("No setup or config entry setup function defined.")
|
||||
hass.data[DATA_SETUP_STARTED].pop(domain)
|
||||
return False
|
||||
|
||||
async with hass.timeout.async_timeout(SLOW_SETUP_MAX_WAIT, domain):
|
||||
result = await task
|
||||
if task:
|
||||
async with hass.timeout.async_timeout(SLOW_SETUP_MAX_WAIT, domain):
|
||||
result = await task
|
||||
except asyncio.TimeoutError:
|
||||
_LOGGER.error(
|
||||
"Setup of %s is taking longer than %s seconds."
|
||||
|
@ -2,7 +2,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from typing import Any
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
@ -14,11 +13,6 @@ from .const import DOMAIN
|
||||
PLATFORMS = ["light"]
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: dict[str, Any]) -> bool:
|
||||
"""Set up the NEW_NAME component."""
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Set up NEW_NAME from a config entry."""
|
||||
# TODO Store an API object for your platforms to access
|
||||
|
@ -20,8 +20,6 @@ async def test_form(hass: HomeAssistant) -> None:
|
||||
"homeassistant.components.NEW_DOMAIN.config_flow.PlaceholderHub.authenticate",
|
||||
return_value=True,
|
||||
), patch(
|
||||
"homeassistant.components.NEW_DOMAIN.async_setup", return_value=True
|
||||
) as mock_setup, patch(
|
||||
"homeassistant.components.NEW_DOMAIN.async_setup_entry",
|
||||
return_value=True,
|
||||
) as mock_setup_entry:
|
||||
@ -42,7 +40,6 @@ async def test_form(hass: HomeAssistant) -> None:
|
||||
"username": "test-username",
|
||||
"password": "test-password",
|
||||
}
|
||||
assert len(mock_setup.mock_calls) == 1
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from typing import Any
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
@ -14,11 +13,6 @@ from .const import DOMAIN
|
||||
PLATFORMS = ["light"]
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: dict[str, Any]) -> bool:
|
||||
"""Set up the NEW_NAME component."""
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Set up NEW_NAME from a config entry."""
|
||||
# TODO Store an API object for your platforms to access
|
||||
|
@ -566,7 +566,7 @@ class MockModule:
|
||||
if platform_schema_base is not None:
|
||||
self.PLATFORM_SCHEMA_BASE = platform_schema_base
|
||||
|
||||
if setup is not None:
|
||||
if setup:
|
||||
# We run this in executor, wrap it in function
|
||||
self.setup = lambda *args: setup(*args)
|
||||
|
||||
|
@ -75,9 +75,7 @@ async def test_form(hass):
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||
assert result["errors"] == {}
|
||||
|
||||
with patch("pyairnow.WebServiceAPI._get", return_value=MOCK_RESPONSE,), patch(
|
||||
"homeassistant.components.airnow.async_setup", return_value=True
|
||||
) as mock_setup, patch(
|
||||
with patch("pyairnow.WebServiceAPI._get", return_value=MOCK_RESPONSE), patch(
|
||||
"homeassistant.components.airnow.async_setup_entry",
|
||||
return_value=True,
|
||||
) as mock_setup_entry:
|
||||
@ -90,7 +88,6 @@ async def test_form(hass):
|
||||
|
||||
assert result2["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||
assert result2["data"] == CONFIG
|
||||
assert len(mock_setup.mock_calls) == 1
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
|
@ -539,8 +539,6 @@ async def test_flow_hassio_discovery(hass):
|
||||
assert result["description_placeholders"] == {"addon": "Mock Addon"}
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.deconz.async_setup", return_value=True
|
||||
) as mock_setup, patch(
|
||||
"homeassistant.components.deconz.async_setup_entry",
|
||||
return_value=True,
|
||||
) as mock_setup_entry:
|
||||
@ -555,7 +553,6 @@ async def test_flow_hassio_discovery(hass):
|
||||
CONF_PORT: 80,
|
||||
CONF_API_KEY: API_KEY,
|
||||
}
|
||||
assert len(mock_setup.mock_calls) == 1
|
||||
assert len(mock_setup_entry.mock_calls) == 1
|
||||
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
import asyncio
|
||||
import os
|
||||
import threading
|
||||
from unittest.mock import Mock, patch
|
||||
from unittest.mock import AsyncMock, Mock, patch
|
||||
|
||||
import pytest
|
||||
import voluptuous as vol
|
||||
@ -618,3 +618,29 @@ async def test_async_get_loaded_integrations(hass):
|
||||
"myintegration",
|
||||
"device_tracker",
|
||||
}
|
||||
|
||||
|
||||
async def test_integration_no_setup(hass, caplog):
|
||||
"""Test we fail integration setup without setup functions."""
|
||||
mock_integration(
|
||||
hass,
|
||||
MockModule("test_integration_without_setup", setup=False),
|
||||
)
|
||||
result = await setup.async_setup_component(
|
||||
hass, "test_integration_without_setup", {}
|
||||
)
|
||||
assert not result
|
||||
assert "No setup or config entry setup function defined" in caplog.text
|
||||
|
||||
|
||||
async def test_integration_only_setup_entry(hass):
|
||||
"""Test we have an integration with only a setup entry method."""
|
||||
mock_integration(
|
||||
hass,
|
||||
MockModule(
|
||||
"test_integration_only_entry",
|
||||
setup=False,
|
||||
async_setup_entry=AsyncMock(return_value=True),
|
||||
),
|
||||
)
|
||||
assert await setup.async_setup_component(hass, "test_integration_only_entry", {})
|
||||
|
Loading…
x
Reference in New Issue
Block a user