diff --git a/homeassistant/components/ambiclimate/manifest.json b/homeassistant/components/ambiclimate/manifest.json index 3d175165abd..151b761dff8 100644 --- a/homeassistant/components/ambiclimate/manifest.json +++ b/homeassistant/components/ambiclimate/manifest.json @@ -3,11 +3,7 @@ "name": "Ambiclimate", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/ambiclimate", - "requirements": [ - "ambiclimate==0.2.1" - ], - "dependencies": [], - "codeowners": [ - "@danielhiversen" - ] + "requirements": ["ambiclimate==0.2.1"], + "dependencies": ["http"], + "codeowners": ["@danielhiversen"] } diff --git a/homeassistant/components/apns/manifest.json b/homeassistant/components/apns/manifest.json index 4845c45a963..3c38238f7eb 100644 --- a/homeassistant/components/apns/manifest.json +++ b/homeassistant/components/apns/manifest.json @@ -2,9 +2,8 @@ "domain": "apns", "name": "Apns", "documentation": "https://www.home-assistant.io/integrations/apns", - "requirements": [ - "apns2==0.3.0" - ], + "requirements": ["apns2==0.3.0"], "dependencies": [], + "after_dependencies": ["device_tracker"], "codeowners": [] } diff --git a/homeassistant/components/camera/manifest.json b/homeassistant/components/camera/manifest.json index 1bd4bb7caeb..32cd7c3fe47 100644 --- a/homeassistant/components/camera/manifest.json +++ b/homeassistant/components/camera/manifest.json @@ -4,5 +4,6 @@ "documentation": "https://www.home-assistant.io/integrations/camera", "requirements": [], "dependencies": ["http"], + "after_dependencies": ["stream", "media_player"], "codeowners": [] } diff --git a/homeassistant/components/cloud/manifest.json b/homeassistant/components/cloud/manifest.json index ec9a556af0a..accc4a0c0f9 100644 --- a/homeassistant/components/cloud/manifest.json +++ b/homeassistant/components/cloud/manifest.json @@ -4,5 +4,6 @@ "documentation": "https://www.home-assistant.io/integrations/cloud", "requirements": ["hass-nabucasa==0.30"], "dependencies": ["http", "webhook"], + "after_dependencies": ["alexa", "google_assistant"], "codeowners": ["@home-assistant/cloud"] } diff --git a/homeassistant/components/doorbird/manifest.json b/homeassistant/components/doorbird/manifest.json index c9cdb32e18a..61225b86a44 100644 --- a/homeassistant/components/doorbird/manifest.json +++ b/homeassistant/components/doorbird/manifest.json @@ -2,11 +2,7 @@ "domain": "doorbird", "name": "Doorbird", "documentation": "https://www.home-assistant.io/integrations/doorbird", - "requirements": [ - "doorbirdpy==2.0.8" - ], - "dependencies": [], - "codeowners": [ - "@oblogic7" - ] + "requirements": ["doorbirdpy==2.0.8"], + "dependencies": ["http"], + "codeowners": ["@oblogic7"] } diff --git a/homeassistant/components/hikvisioncam/switch.py b/homeassistant/components/hikvisioncam/switch.py index 020b894c0f7..f86853a5468 100644 --- a/homeassistant/components/hikvisioncam/switch.py +++ b/homeassistant/components/hikvisioncam/switch.py @@ -5,7 +5,7 @@ import hikvision.api from hikvision.error import HikvisionError, MissingParamError import voluptuous as vol -from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.components.switch import PLATFORM_SCHEMA, SwitchDevice from homeassistant.const import ( CONF_HOST, CONF_NAME, @@ -16,7 +16,6 @@ from homeassistant.const import ( STATE_ON, ) import homeassistant.helpers.config_validation as cv -from homeassistant.helpers.entity import ToggleEntity # This is the last working version, please test before updating @@ -60,7 +59,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None): add_entities([HikvisionMotionSwitch(name, hikvision_cam)]) -class HikvisionMotionSwitch(ToggleEntity): +class HikvisionMotionSwitch(SwitchDevice): """Representation of a switch to toggle on/off motion detection.""" def __init__(self, name, hikvision_cam): diff --git a/homeassistant/components/html5/manifest.json b/homeassistant/components/html5/manifest.json index 667a5789182..dd794ae0386 100644 --- a/homeassistant/components/html5/manifest.json +++ b/homeassistant/components/html5/manifest.json @@ -2,11 +2,7 @@ "domain": "html5", "name": "HTML5 Notifications", "documentation": "https://www.home-assistant.io/integrations/html5", - "requirements": [ - "pywebpush==1.9.2" - ], - "dependencies": ["frontend"], - "codeowners": [ - "@robbiet480" - ] + "requirements": ["pywebpush==1.9.2"], + "dependencies": ["http"], + "codeowners": ["@robbiet480"] } diff --git a/homeassistant/components/logbook/manifest.json b/homeassistant/components/logbook/manifest.json index e8e3ad8ac2e..08083ea4024 100644 --- a/homeassistant/components/logbook/manifest.json +++ b/homeassistant/components/logbook/manifest.json @@ -3,9 +3,6 @@ "name": "Logbook", "documentation": "https://www.home-assistant.io/integrations/logbook", "requirements": [], - "dependencies": [ - "frontend", - "recorder" - ], + "dependencies": ["frontend", "http", "recorder"], "codeowners": [] } diff --git a/homeassistant/components/logi_circle/manifest.json b/homeassistant/components/logi_circle/manifest.json index 22502956e06..bd6dc8a8d27 100644 --- a/homeassistant/components/logi_circle/manifest.json +++ b/homeassistant/components/logi_circle/manifest.json @@ -4,6 +4,6 @@ "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/logi_circle", "requirements": ["logi_circle==0.2.2"], - "dependencies": ["ffmpeg"], + "dependencies": ["ffmpeg", "http"], "codeowners": ["@evanjd"] } diff --git a/homeassistant/components/melissa/climate.py b/homeassistant/components/melissa/climate.py index 38f4977c96a..c09203c3e33 100644 --- a/homeassistant/components/melissa/climate.py +++ b/homeassistant/components/melissa/climate.py @@ -11,8 +11,11 @@ from homeassistant.components.climate.const import ( HVAC_MODE_OFF, SUPPORT_FAN_MODE, SUPPORT_TARGET_TEMPERATURE, + FAN_AUTO, + FAN_HIGH, + FAN_MEDIUM, + FAN_LOW, ) -from homeassistant.components.fan import SPEED_HIGH, SPEED_LOW, SPEED_MEDIUM from homeassistant.const import ATTR_TEMPERATURE, PRECISION_WHOLE, TEMP_CELSIUS from . import DATA_MELISSA @@ -29,7 +32,7 @@ OP_MODES = [ HVAC_MODE_OFF, ] -FAN_MODES = [HVAC_MODE_AUTO, SPEED_HIGH, SPEED_MEDIUM, SPEED_LOW] +FAN_MODES = [FAN_AUTO, FAN_HIGH, FAN_MEDIUM, FAN_LOW] async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): @@ -200,11 +203,11 @@ class MelissaClimate(ClimateDevice): if fan == self._api.FAN_AUTO: return HVAC_MODE_AUTO if fan == self._api.FAN_LOW: - return SPEED_LOW + return FAN_LOW if fan == self._api.FAN_MEDIUM: - return SPEED_MEDIUM + return FAN_MEDIUM if fan == self._api.FAN_HIGH: - return SPEED_HIGH + return FAN_HIGH _LOGGER.warning("Fan mode %s could not be mapped to hass", fan) return None @@ -224,10 +227,10 @@ class MelissaClimate(ClimateDevice): """Translate hass fan modes to melissa modes.""" if fan == HVAC_MODE_AUTO: return self._api.FAN_AUTO - if fan == SPEED_LOW: + if fan == FAN_LOW: return self._api.FAN_LOW - if fan == SPEED_MEDIUM: + if fan == FAN_MEDIUM: return self._api.FAN_MEDIUM - if fan == SPEED_HIGH: + if fan == FAN_HIGH: return self._api.FAN_HIGH _LOGGER.warning("Melissa have no setting for %s fan mode", fan) diff --git a/homeassistant/components/nsw_fuel_station/sensor.py b/homeassistant/components/nsw_fuel_station/sensor.py index a84aa554be9..3c900b46be0 100644 --- a/homeassistant/components/nsw_fuel_station/sensor.py +++ b/homeassistant/components/nsw_fuel_station/sensor.py @@ -6,7 +6,7 @@ from typing import Optional import voluptuous as vol import homeassistant.helpers.config_validation as cv -from homeassistant.components.light import PLATFORM_SCHEMA +from homeassistant.components.sensor import PLATFORM_SCHEMA from homeassistant.const import ATTR_ATTRIBUTION from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle diff --git a/homeassistant/components/person/manifest.json b/homeassistant/components/person/manifest.json index cf50b8029c2..afcd428d6af 100644 --- a/homeassistant/components/person/manifest.json +++ b/homeassistant/components/person/manifest.json @@ -4,5 +4,6 @@ "documentation": "https://www.home-assistant.io/integrations/person", "requirements": [], "dependencies": [], + "after_dependencies": ["device_tracker"], "codeowners": [] } diff --git a/homeassistant/components/plant/manifest.json b/homeassistant/components/plant/manifest.json index 721a57e7822..c1e009ccec3 100644 --- a/homeassistant/components/plant/manifest.json +++ b/homeassistant/components/plant/manifest.json @@ -3,11 +3,7 @@ "name": "Plant", "documentation": "https://www.home-assistant.io/integrations/plant", "requirements": [], - "dependencies": [ - "group", - "zone" - ], - "codeowners": [ - "@ChristianKuehnel" - ] + "dependencies": ["group", "zone"], + "after_dependencies": ["recorder"], + "codeowners": ["@ChristianKuehnel"] } diff --git a/homeassistant/components/point/manifest.json b/homeassistant/components/point/manifest.json index 4c29f37e67c..1c74052ee7e 100644 --- a/homeassistant/components/point/manifest.json +++ b/homeassistant/components/point/manifest.json @@ -3,13 +3,7 @@ "name": "Point", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/point", - "requirements": [ - "pypoint==1.1.2" - ], - "dependencies": [ - "webhook" - ], - "codeowners": [ - "@fredrike" - ] + "requirements": ["pypoint==1.1.2"], + "dependencies": ["webhook", "http"], + "codeowners": ["@fredrike"] } diff --git a/homeassistant/components/rachio/manifest.json b/homeassistant/components/rachio/manifest.json index 79e3677d65e..fae640f9262 100644 --- a/homeassistant/components/rachio/manifest.json +++ b/homeassistant/components/rachio/manifest.json @@ -2,9 +2,7 @@ "domain": "rachio", "name": "Rachio", "documentation": "https://www.home-assistant.io/integrations/rachio", - "requirements": [ - "rachiopy==0.1.3" - ], - "dependencies": [], + "requirements": ["rachiopy==0.1.3"], + "dependencies": ["http"], "codeowners": [] } diff --git a/homeassistant/components/statistics/manifest.json b/homeassistant/components/statistics/manifest.json index 3dab05942b9..17ade1283ce 100644 --- a/homeassistant/components/statistics/manifest.json +++ b/homeassistant/components/statistics/manifest.json @@ -4,7 +4,6 @@ "documentation": "https://www.home-assistant.io/integrations/statistics", "requirements": [], "dependencies": [], - "codeowners": [ - "@fabaff" - ] + "after_dependencies": ["recorder"], + "codeowners": ["@fabaff"] } diff --git a/homeassistant/components/telegram_bot/__init__.py b/homeassistant/components/telegram_bot/__init__.py index d365060e204..12bde6c72d8 100644 --- a/homeassistant/components/telegram_bot/__init__.py +++ b/homeassistant/components/telegram_bot/__init__.py @@ -19,7 +19,6 @@ from telegram.parsemode import ParseMode from telegram.utils.request import Request import voluptuous as vol -from homeassistant.components.notify import ATTR_DATA, ATTR_MESSAGE, ATTR_TITLE from homeassistant.const import ( ATTR_COMMAND, ATTR_LATITUDE, @@ -35,6 +34,10 @@ from homeassistant.exceptions import TemplateError _LOGGER = logging.getLogger(__name__) +ATTR_DATA = "data" +ATTR_MESSAGE = "message" +ATTR_TITLE = "title" + ATTR_ARGS = "args" ATTR_AUTHENTICATION = "authentication" ATTR_CALLBACK_QUERY = "callback_query" diff --git a/homeassistant/components/tts/manifest.json b/homeassistant/components/tts/manifest.json index cb780523977..b57d5c36112 100644 --- a/homeassistant/components/tts/manifest.json +++ b/homeassistant/components/tts/manifest.json @@ -2,13 +2,8 @@ "domain": "tts", "name": "Tts", "documentation": "https://www.home-assistant.io/integrations/tts", - "requirements": [ - "mutagen==1.43.0" - ], - "dependencies": [ - "http" - ], - "codeowners": [ - "@robbiet480" - ] + "requirements": ["mutagen==1.43.0"], + "dependencies": ["http"], + "after_dependencies": ["media_player"], + "codeowners": ["@robbiet480"] } diff --git a/homeassistant/components/wink/manifest.json b/homeassistant/components/wink/manifest.json index acf9c38e632..a1bae648292 100644 --- a/homeassistant/components/wink/manifest.json +++ b/homeassistant/components/wink/manifest.json @@ -2,10 +2,7 @@ "domain": "wink", "name": "Wink", "documentation": "https://www.home-assistant.io/integrations/wink", - "requirements": [ - "pubnubsub-handler==1.0.8", - "python-wink==1.10.5" - ], - "dependencies": ["configurator"], + "requirements": ["pubnubsub-handler==1.0.8", "python-wink==1.10.5"], + "dependencies": ["configurator", "http"], "codeowners": [] } diff --git a/homeassistant/components/workday/binary_sensor.py b/homeassistant/components/workday/binary_sensor.py index f95447c1e72..efa8b6ad77b 100644 --- a/homeassistant/components/workday/binary_sensor.py +++ b/homeassistant/components/workday/binary_sensor.py @@ -5,9 +5,8 @@ from datetime import datetime, timedelta import holidays import voluptuous as vol -from homeassistant.components.sensor import PLATFORM_SCHEMA from homeassistant.const import CONF_NAME, WEEKDAYS -from homeassistant.components.binary_sensor import BinarySensorDevice +from homeassistant.components.binary_sensor import BinarySensorDevice, PLATFORM_SCHEMA import homeassistant.helpers.config_validation as cv _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/worxlandroid/sensor.py b/homeassistant/components/worxlandroid/sensor.py index 4e9bf0a6a4a..ad583d6d943 100644 --- a/homeassistant/components/worxlandroid/sensor.py +++ b/homeassistant/components/worxlandroid/sensor.py @@ -10,7 +10,7 @@ import voluptuous as vol import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import Entity -from homeassistant.components.switch import PLATFORM_SCHEMA +from homeassistant.components.sensor import PLATFORM_SCHEMA from homeassistant.const import CONF_HOST, CONF_PIN, CONF_TIMEOUT from homeassistant.helpers.aiohttp_client import async_get_clientsession diff --git a/script/hassfest/dependencies.py b/script/hassfest/dependencies.py index e47deb76ad5..42a31f20610 100644 --- a/script/hassfest/dependencies.py +++ b/script/hassfest/dependencies.py @@ -16,7 +16,19 @@ def grep_dir(path: pathlib.Path, glob_pattern: str, search_pattern: str) -> Set[ continue for match in pattern.finditer(fil.read_text()): - found.add(match.groups()[0]) + integration = match.groups()[1] + + if ( + # If it's importing something from itself + integration == path.name + # Platform file + or (path / f"{integration}.py").exists() + # Dir for platform + or (path / integration).exists() + ): + continue + + found.add(match.groups()[1]) return found @@ -30,19 +42,65 @@ ALLOWED_USED_COMPONENTS = { "hassio", "system_health", "websocket_api", + "automation", + "device_automation", + "zone", + "homeassistant", + "system_log", + "person", + # Discovery + "ssdp", + "discovery", + # Other + "mjpeg", # base class, has no reqs or component to load. } +IGNORE_VIOLATIONS = [ + # Has same requirement, gets defaults. + ("sql", "recorder"), + # Sharing a base class + ("openalpr_cloud", "openalpr_local"), + ("lutron_caseta", "lutron"), + ("ffmpeg_noise", "ffmpeg_motion"), + # Demo + ("demo", "manual"), + ("demo", "openalpr_local"), + # This should become a helper method that integrations can submit data to + ("websocket_api", "lovelace"), + # Expose HA to external systems + "homekit", + "alexa", + "google_assistant", + "emulated_hue", + "prometheus", + "conversation", + "logbook", + # These should be extracted to external package + "pvoutput", + "dwd_weather_warnings", + # Should be rewritten to use own data fetcher + "scrape", +] + def validate_dependencies(integration: Integration): """Validate all dependencies.""" # Find usage of hass.components - referenced = grep_dir(integration.path, "**/*.py", r"hass\.components\.(\w+)") + referenced = grep_dir( + integration.path, "**/*.py", r"(hass|homeassistant)\.components\.(\w+)" + ) referenced -= ALLOWED_USED_COMPONENTS referenced -= set(integration.manifest["dependencies"]) referenced -= set(integration.manifest.get("after_dependencies", [])) if referenced: for domain in sorted(referenced): + if ( + integration.domain in IGNORE_VIOLATIONS + or (integration.domain, domain) in IGNORE_VIOLATIONS + ): + continue + integration.add_error( "dependencies", "Using component {} but it's not in 'dependencies' or 'after_dependencies'".format(