Make hassfest stricter (#29494)

* Make hassfest stricter

* Update manifest.json
This commit is contained in:
Paulus Schoutsen 2019-12-05 01:15:28 -08:00 committed by Pascal Vizeli
parent f6d1eb97a3
commit a050d54847
22 changed files with 112 additions and 84 deletions

View File

@ -3,11 +3,7 @@
"name": "Ambiclimate", "name": "Ambiclimate",
"config_flow": true, "config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/ambiclimate", "documentation": "https://www.home-assistant.io/integrations/ambiclimate",
"requirements": [ "requirements": ["ambiclimate==0.2.1"],
"ambiclimate==0.2.1" "dependencies": ["http"],
], "codeowners": ["@danielhiversen"]
"dependencies": [],
"codeowners": [
"@danielhiversen"
]
} }

View File

@ -2,9 +2,8 @@
"domain": "apns", "domain": "apns",
"name": "Apns", "name": "Apns",
"documentation": "https://www.home-assistant.io/integrations/apns", "documentation": "https://www.home-assistant.io/integrations/apns",
"requirements": [ "requirements": ["apns2==0.3.0"],
"apns2==0.3.0"
],
"dependencies": [], "dependencies": [],
"after_dependencies": ["device_tracker"],
"codeowners": [] "codeowners": []
} }

View File

@ -4,5 +4,6 @@
"documentation": "https://www.home-assistant.io/integrations/camera", "documentation": "https://www.home-assistant.io/integrations/camera",
"requirements": [], "requirements": [],
"dependencies": ["http"], "dependencies": ["http"],
"after_dependencies": ["stream", "media_player"],
"codeowners": [] "codeowners": []
} }

View File

@ -4,5 +4,6 @@
"documentation": "https://www.home-assistant.io/integrations/cloud", "documentation": "https://www.home-assistant.io/integrations/cloud",
"requirements": ["hass-nabucasa==0.30"], "requirements": ["hass-nabucasa==0.30"],
"dependencies": ["http", "webhook"], "dependencies": ["http", "webhook"],
"after_dependencies": ["alexa", "google_assistant"],
"codeowners": ["@home-assistant/cloud"] "codeowners": ["@home-assistant/cloud"]
} }

View File

@ -2,11 +2,7 @@
"domain": "doorbird", "domain": "doorbird",
"name": "Doorbird", "name": "Doorbird",
"documentation": "https://www.home-assistant.io/integrations/doorbird", "documentation": "https://www.home-assistant.io/integrations/doorbird",
"requirements": [ "requirements": ["doorbirdpy==2.0.8"],
"doorbirdpy==2.0.8" "dependencies": ["http"],
], "codeowners": ["@oblogic7"]
"dependencies": [],
"codeowners": [
"@oblogic7"
]
} }

View File

@ -5,7 +5,7 @@ import hikvision.api
from hikvision.error import HikvisionError, MissingParamError from hikvision.error import HikvisionError, MissingParamError
import voluptuous as vol import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA from homeassistant.components.switch import PLATFORM_SCHEMA, SwitchDevice
from homeassistant.const import ( from homeassistant.const import (
CONF_HOST, CONF_HOST,
CONF_NAME, CONF_NAME,
@ -16,7 +16,6 @@ from homeassistant.const import (
STATE_ON, STATE_ON,
) )
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import ToggleEntity
# This is the last working version, please test before updating # 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)]) add_entities([HikvisionMotionSwitch(name, hikvision_cam)])
class HikvisionMotionSwitch(ToggleEntity): class HikvisionMotionSwitch(SwitchDevice):
"""Representation of a switch to toggle on/off motion detection.""" """Representation of a switch to toggle on/off motion detection."""
def __init__(self, name, hikvision_cam): def __init__(self, name, hikvision_cam):

View File

@ -2,11 +2,7 @@
"domain": "html5", "domain": "html5",
"name": "HTML5 Notifications", "name": "HTML5 Notifications",
"documentation": "https://www.home-assistant.io/integrations/html5", "documentation": "https://www.home-assistant.io/integrations/html5",
"requirements": [ "requirements": ["pywebpush==1.9.2"],
"pywebpush==1.9.2" "dependencies": ["http"],
], "codeowners": ["@robbiet480"]
"dependencies": ["frontend"],
"codeowners": [
"@robbiet480"
]
} }

View File

@ -3,9 +3,6 @@
"name": "Logbook", "name": "Logbook",
"documentation": "https://www.home-assistant.io/integrations/logbook", "documentation": "https://www.home-assistant.io/integrations/logbook",
"requirements": [], "requirements": [],
"dependencies": [ "dependencies": ["frontend", "http", "recorder"],
"frontend",
"recorder"
],
"codeowners": [] "codeowners": []
} }

View File

@ -4,6 +4,6 @@
"config_flow": true, "config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/logi_circle", "documentation": "https://www.home-assistant.io/integrations/logi_circle",
"requirements": ["logi_circle==0.2.2"], "requirements": ["logi_circle==0.2.2"],
"dependencies": ["ffmpeg"], "dependencies": ["ffmpeg", "http"],
"codeowners": ["@evanjd"] "codeowners": ["@evanjd"]
} }

View File

@ -11,8 +11,11 @@ from homeassistant.components.climate.const import (
HVAC_MODE_OFF, HVAC_MODE_OFF,
SUPPORT_FAN_MODE, SUPPORT_FAN_MODE,
SUPPORT_TARGET_TEMPERATURE, 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 homeassistant.const import ATTR_TEMPERATURE, PRECISION_WHOLE, TEMP_CELSIUS
from . import DATA_MELISSA from . import DATA_MELISSA
@ -29,7 +32,7 @@ OP_MODES = [
HVAC_MODE_OFF, 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): 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: if fan == self._api.FAN_AUTO:
return HVAC_MODE_AUTO return HVAC_MODE_AUTO
if fan == self._api.FAN_LOW: if fan == self._api.FAN_LOW:
return SPEED_LOW return FAN_LOW
if fan == self._api.FAN_MEDIUM: if fan == self._api.FAN_MEDIUM:
return SPEED_MEDIUM return FAN_MEDIUM
if fan == self._api.FAN_HIGH: if fan == self._api.FAN_HIGH:
return SPEED_HIGH return FAN_HIGH
_LOGGER.warning("Fan mode %s could not be mapped to hass", fan) _LOGGER.warning("Fan mode %s could not be mapped to hass", fan)
return None return None
@ -224,10 +227,10 @@ class MelissaClimate(ClimateDevice):
"""Translate hass fan modes to melissa modes.""" """Translate hass fan modes to melissa modes."""
if fan == HVAC_MODE_AUTO: if fan == HVAC_MODE_AUTO:
return self._api.FAN_AUTO return self._api.FAN_AUTO
if fan == SPEED_LOW: if fan == FAN_LOW:
return self._api.FAN_LOW return self._api.FAN_LOW
if fan == SPEED_MEDIUM: if fan == FAN_MEDIUM:
return self._api.FAN_MEDIUM return self._api.FAN_MEDIUM
if fan == SPEED_HIGH: if fan == FAN_HIGH:
return self._api.FAN_HIGH return self._api.FAN_HIGH
_LOGGER.warning("Melissa have no setting for %s fan mode", fan) _LOGGER.warning("Melissa have no setting for %s fan mode", fan)

View File

@ -6,7 +6,7 @@ from typing import Optional
import voluptuous as vol import voluptuous as vol
import homeassistant.helpers.config_validation as cv 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.const import ATTR_ATTRIBUTION
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
from homeassistant.util import Throttle from homeassistant.util import Throttle

View File

@ -4,5 +4,6 @@
"documentation": "https://www.home-assistant.io/integrations/person", "documentation": "https://www.home-assistant.io/integrations/person",
"requirements": [], "requirements": [],
"dependencies": [], "dependencies": [],
"after_dependencies": ["device_tracker"],
"codeowners": [] "codeowners": []
} }

View File

@ -3,11 +3,7 @@
"name": "Plant", "name": "Plant",
"documentation": "https://www.home-assistant.io/integrations/plant", "documentation": "https://www.home-assistant.io/integrations/plant",
"requirements": [], "requirements": [],
"dependencies": [ "dependencies": ["group", "zone"],
"group", "after_dependencies": ["recorder"],
"zone" "codeowners": ["@ChristianKuehnel"]
],
"codeowners": [
"@ChristianKuehnel"
]
} }

View File

@ -3,13 +3,7 @@
"name": "Point", "name": "Point",
"config_flow": true, "config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/point", "documentation": "https://www.home-assistant.io/integrations/point",
"requirements": [ "requirements": ["pypoint==1.1.2"],
"pypoint==1.1.2" "dependencies": ["webhook", "http"],
], "codeowners": ["@fredrike"]
"dependencies": [
"webhook"
],
"codeowners": [
"@fredrike"
]
} }

View File

@ -2,9 +2,7 @@
"domain": "rachio", "domain": "rachio",
"name": "Rachio", "name": "Rachio",
"documentation": "https://www.home-assistant.io/integrations/rachio", "documentation": "https://www.home-assistant.io/integrations/rachio",
"requirements": [ "requirements": ["rachiopy==0.1.3"],
"rachiopy==0.1.3" "dependencies": ["http"],
],
"dependencies": [],
"codeowners": [] "codeowners": []
} }

View File

@ -4,7 +4,6 @@
"documentation": "https://www.home-assistant.io/integrations/statistics", "documentation": "https://www.home-assistant.io/integrations/statistics",
"requirements": [], "requirements": [],
"dependencies": [], "dependencies": [],
"codeowners": [ "after_dependencies": ["recorder"],
"@fabaff" "codeowners": ["@fabaff"]
]
} }

View File

@ -19,7 +19,6 @@ from telegram.parsemode import ParseMode
from telegram.utils.request import Request from telegram.utils.request import Request
import voluptuous as vol import voluptuous as vol
from homeassistant.components.notify import ATTR_DATA, ATTR_MESSAGE, ATTR_TITLE
from homeassistant.const import ( from homeassistant.const import (
ATTR_COMMAND, ATTR_COMMAND,
ATTR_LATITUDE, ATTR_LATITUDE,
@ -35,6 +34,10 @@ from homeassistant.exceptions import TemplateError
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
ATTR_DATA = "data"
ATTR_MESSAGE = "message"
ATTR_TITLE = "title"
ATTR_ARGS = "args" ATTR_ARGS = "args"
ATTR_AUTHENTICATION = "authentication" ATTR_AUTHENTICATION = "authentication"
ATTR_CALLBACK_QUERY = "callback_query" ATTR_CALLBACK_QUERY = "callback_query"

View File

@ -2,13 +2,8 @@
"domain": "tts", "domain": "tts",
"name": "Tts", "name": "Tts",
"documentation": "https://www.home-assistant.io/integrations/tts", "documentation": "https://www.home-assistant.io/integrations/tts",
"requirements": [ "requirements": ["mutagen==1.43.0"],
"mutagen==1.43.0" "dependencies": ["http"],
], "after_dependencies": ["media_player"],
"dependencies": [ "codeowners": ["@robbiet480"]
"http"
],
"codeowners": [
"@robbiet480"
]
} }

View File

@ -2,10 +2,7 @@
"domain": "wink", "domain": "wink",
"name": "Wink", "name": "Wink",
"documentation": "https://www.home-assistant.io/integrations/wink", "documentation": "https://www.home-assistant.io/integrations/wink",
"requirements": [ "requirements": ["pubnubsub-handler==1.0.8", "python-wink==1.10.5"],
"pubnubsub-handler==1.0.8", "dependencies": ["configurator", "http"],
"python-wink==1.10.5"
],
"dependencies": ["configurator"],
"codeowners": [] "codeowners": []
} }

View File

@ -5,9 +5,8 @@ from datetime import datetime, timedelta
import holidays import holidays
import voluptuous as vol import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA
from homeassistant.const import CONF_NAME, WEEKDAYS 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 import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)

View File

@ -10,7 +10,7 @@ import voluptuous as vol
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity 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.const import CONF_HOST, CONF_PIN, CONF_TIMEOUT
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession

View File

@ -16,7 +16,19 @@ def grep_dir(path: pathlib.Path, glob_pattern: str, search_pattern: str) -> Set[
continue continue
for match in pattern.finditer(fil.read_text()): 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 return found
@ -30,19 +42,65 @@ ALLOWED_USED_COMPONENTS = {
"hassio", "hassio",
"system_health", "system_health",
"websocket_api", "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): def validate_dependencies(integration: Integration):
"""Validate all dependencies.""" """Validate all dependencies."""
# Find usage of hass.components # 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 -= ALLOWED_USED_COMPONENTS
referenced -= set(integration.manifest["dependencies"]) referenced -= set(integration.manifest["dependencies"])
referenced -= set(integration.manifest.get("after_dependencies", [])) referenced -= set(integration.manifest.get("after_dependencies", []))
if referenced: if referenced:
for domain in sorted(referenced): for domain in sorted(referenced):
if (
integration.domain in IGNORE_VIOLATIONS
or (integration.domain, domain) in IGNORE_VIOLATIONS
):
continue
integration.add_error( integration.add_error(
"dependencies", "dependencies",
"Using component {} but it's not in 'dependencies' or 'after_dependencies'".format( "Using component {} but it's not in 'dependencies' or 'after_dependencies'".format(