Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make integration setup optional #48381

Merged
merged 3 commits into from
Mar 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions homeassistant/components/accuweather/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
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
Expand All @@ -26,12 +25,6 @@
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]
Expand All @@ -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,
}
Expand Down
6 changes: 0 additions & 6 deletions homeassistant/components/adguard/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
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__)

Expand All @@ -49,11 +48,6 @@
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])
Expand Down
5 changes: 0 additions & 5 deletions homeassistant/components/airnow/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,6 @@
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]
Expand Down
5 changes: 0 additions & 5 deletions homeassistant/components/deconz/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@
)


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.
Expand Down
6 changes: 0 additions & 6 deletions homeassistant/components/elgato/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,10 @@
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)
Expand Down
7 changes: 1 addition & 6 deletions homeassistant/components/esphome/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
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
Expand All @@ -56,11 +56,6 @@
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, {})
Expand Down
6 changes: 0 additions & 6 deletions homeassistant/components/tasmota/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
EVENT_DEVICE_REGISTRY_UPDATED,
async_entries_for_config_entry,
)
from homeassistant.helpers.typing import HomeAssistantType

from . import device_automation, discovery
from .const import (
Expand All @@ -38,11 +37,6 @@
_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)
Expand Down
6 changes: 0 additions & 6 deletions homeassistant/components/wled/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
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,
Expand All @@ -37,11 +36,6 @@
_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."""

Expand Down
13 changes: 8 additions & 5 deletions homeassistant/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ def log_error(msg: str, link: str | None = None) -> None:
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
Expand Down Expand Up @@ -219,6 +219,8 @@ def log_error(msg: str, link: str | None = None) -> None:
SLOW_SETUP_WARNING,
)

task = None
result = True
try:
if hasattr(component, "async_setup"):
task = component.async_setup(hass, processed_config) # type: ignore
Expand All @@ -228,13 +230,14 @@ def log_error(msg: str, link: str | None = None) -> None:
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."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -14,11 +13,6 @@
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -14,11 +13,6 @@
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
Expand Down
2 changes: 1 addition & 1 deletion tests/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ def __init__(
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)

Expand Down
5 changes: 1 addition & 4 deletions tests/components/airnow/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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


Expand Down
3 changes: 0 additions & 3 deletions tests/components/deconz/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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


Expand Down
28 changes: 27 additions & 1 deletion tests/test_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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", {})