diff --git a/homeassistant/components/arlo/manifest.json b/homeassistant/components/arlo/manifest.json index a8b6befb70fa4567f11291a9b49f6d09d35b9465..35803d0d4f6afb7b7e8db27f0abbc9e7fa2275fa 100644 --- a/homeassistant/components/arlo/manifest.json +++ b/homeassistant/components/arlo/manifest.json @@ -5,6 +5,8 @@ "requirements": [ "pyarlo==0.2.3" ], - "dependencies": [], + "dependencies": [ + "ffmpeg" + ], "codeowners": [] } diff --git a/homeassistant/components/arwn/manifest.json b/homeassistant/components/arwn/manifest.json index 15ef7fa48ba8feaa6f82101b6dc4467690e03f91..1c861aa67e28bfa458a1c130728e2316e38be3da 100644 --- a/homeassistant/components/arwn/manifest.json +++ b/homeassistant/components/arwn/manifest.json @@ -3,6 +3,8 @@ "name": "Arwn", "documentation": "https://www.home-assistant.io/components/arwn", "requirements": [], - "dependencies": [], + "dependencies": [ + "mqtt" + ], "codeowners": [] } diff --git a/homeassistant/components/asterisk_cdr/manifest.json b/homeassistant/components/asterisk_cdr/manifest.json index 2c8713ac191b833d2c53427db0e080b90c1ae92f..db1308b0483d78b35d7ff8a3cd86f1badb3723d7 100644 --- a/homeassistant/components/asterisk_cdr/manifest.json +++ b/homeassistant/components/asterisk_cdr/manifest.json @@ -3,6 +3,8 @@ "name": "Asterisk cdr", "documentation": "https://www.home-assistant.io/components/asterisk_cdr", "requirements": [], - "dependencies": [], + "dependencies": [ + "asterisk_mbox" + ], "codeowners": [] } diff --git a/homeassistant/components/automatic/manifest.json b/homeassistant/components/automatic/manifest.json index db2f676813eea5ae7fad24727d97660ee9d2a67c..50bd02d2ac180c94b9e93df8cc1fa1f065228473 100644 --- a/homeassistant/components/automatic/manifest.json +++ b/homeassistant/components/automatic/manifest.json @@ -5,7 +5,9 @@ "requirements": [ "aioautomatic==0.6.5" ], - "dependencies": [], + "dependencies": [ + "http" + ], "codeowners": [ "@armills" ] diff --git a/homeassistant/components/automation/manifest.json b/homeassistant/components/automation/manifest.json index 93f1abe0f0d8949df52be18d230ee1b9034fbf0d..ea63d4ff98a31ce5f6fb7f3cb2324e731c8d6577 100644 --- a/homeassistant/components/automation/manifest.json +++ b/homeassistant/components/automation/manifest.json @@ -4,7 +4,8 @@ "documentation": "https://www.home-assistant.io/components/automation", "requirements": [], "dependencies": [ - "group" + "group", + "webhook" ], "codeowners": [ "@home-assistant/core" diff --git a/homeassistant/components/canary/manifest.json b/homeassistant/components/canary/manifest.json index e7cc5fa7efc68ab51ae59a733bb064136c2d0a5a..346c1c99f6df6b6c10e165d1d7673cb0498b9ed7 100644 --- a/homeassistant/components/canary/manifest.json +++ b/homeassistant/components/canary/manifest.json @@ -5,6 +5,8 @@ "requirements": [ "py-canary==0.5.0" ], - "dependencies": [], + "dependencies": [ + "ffmpeg" + ], "codeowners": [] } diff --git a/homeassistant/components/demo/__init__.py b/homeassistant/components/demo/__init__.py index 70c1341145de8ccf9d56a3f1274ad1e716ae52e8..354f0c0e37541a3783e39af3be9a66db9407d1fd 100644 --- a/homeassistant/components/demo/__init__.py +++ b/homeassistant/components/demo/__init__.py @@ -1,6 +1,7 @@ """Set up the demo environment that mimics interaction with devices.""" import asyncio import time +import sys from homeassistant import bootstrap import homeassistant.core as ha @@ -31,7 +32,7 @@ COMPONENTS_WITH_DEMO_PLATFORM = [ ] -async def async_setup(hass, config): +async def _async_setup(hass, config): """Set up the demo environment.""" group = hass.components.group configurator = hass.components.configurator @@ -224,3 +225,7 @@ async def async_setup(hass, config): hass.async_add_job(setup_configurator) return True + + +if 'pytest' not in sys.modules: + async_setup = _async_setup # pylint: disable=invalid-name diff --git a/homeassistant/components/fitbit/manifest.json b/homeassistant/components/fitbit/manifest.json index d1335a1347d4e150dfd6399872d7828bc3f3d36d..5b02bca4b6f0edb142db89a6a2a2658ebd40d20d 100644 --- a/homeassistant/components/fitbit/manifest.json +++ b/homeassistant/components/fitbit/manifest.json @@ -5,7 +5,9 @@ "requirements": [ "fitbit==0.3.0" ], - "dependencies": [], + "dependencies": [ + "http" + ], "codeowners": [ "@robbiet480" ] diff --git a/homeassistant/components/flexit/manifest.json b/homeassistant/components/flexit/manifest.json index 1af86243f8697f46dd9ba6d7ed2e598171517a23..0ee0e81143cd6cd1d6257364632928361de07980 100644 --- a/homeassistant/components/flexit/manifest.json +++ b/homeassistant/components/flexit/manifest.json @@ -5,6 +5,8 @@ "requirements": [ "pyflexit==0.3" ], - "dependencies": [], + "dependencies": [ + "modbus" + ], "codeowners": [] } diff --git a/homeassistant/components/flux/manifest.json b/homeassistant/components/flux/manifest.json index 8c07a70bca6ff8f6dd190b76d626bbf7e36f0e98..d4d67edbd353beaebb5a6e12b03ec8d19162f24e 100644 --- a/homeassistant/components/flux/manifest.json +++ b/homeassistant/components/flux/manifest.json @@ -3,6 +3,8 @@ "name": "Flux", "documentation": "https://www.home-assistant.io/components/flux", "requirements": [], - "dependencies": [], + "dependencies": [ + "light" + ], "codeowners": [] } diff --git a/homeassistant/components/generic_thermostat/manifest.json b/homeassistant/components/generic_thermostat/manifest.json index 67306b1e7cdae8e56d5a3073f4ac7327e2ed48a0..41fb04c84566b0b70c79c1854039fb6b94af860e 100644 --- a/homeassistant/components/generic_thermostat/manifest.json +++ b/homeassistant/components/generic_thermostat/manifest.json @@ -3,6 +3,9 @@ "name": "Generic thermostat", "documentation": "https://www.home-assistant.io/components/generic_thermostat", "requirements": [], - "dependencies": [], + "dependencies": [ + "sensor", + "switch" + ], "codeowners": [] } diff --git a/homeassistant/components/google/__init__.py b/homeassistant/components/google/__init__.py index 37ee5efbd93b8116e385d8866a4840d7b26c4506..0216094de9b872e38331c4673ed7548c9e9bb914 100644 --- a/homeassistant/components/google/__init__.py +++ b/homeassistant/components/google/__init__.py @@ -153,6 +153,9 @@ def setup(hass, config): hass.data[DATA_INDEX] = {} conf = config.get(DOMAIN, {}) + if not conf: + # component is set up by tts platform + return True token_file = hass.config.path(TOKEN_FILE) if not os.path.isfile(token_file): diff --git a/homeassistant/components/history_stats/manifest.json b/homeassistant/components/history_stats/manifest.json index 8e0c1b249109da94b4b44eda2dabfaf394ce739e..ea0abd87c28c42536c2f8aad44673f55092257f4 100644 --- a/homeassistant/components/history_stats/manifest.json +++ b/homeassistant/components/history_stats/manifest.json @@ -3,6 +3,8 @@ "name": "History stats", "documentation": "https://www.home-assistant.io/components/history_stats", "requirements": [], - "dependencies": [], + "dependencies": [ + "history" + ], "codeowners": [] } diff --git a/homeassistant/components/manual_mqtt/manifest.json b/homeassistant/components/manual_mqtt/manifest.json index cc467ade5c1020389545e8486999bc1a80fc8a5d..81cd1338450fd904a4dbe04599547d1c3492fa9d 100644 --- a/homeassistant/components/manual_mqtt/manifest.json +++ b/homeassistant/components/manual_mqtt/manifest.json @@ -3,6 +3,8 @@ "name": "Manual mqtt", "documentation": "https://www.home-assistant.io/components/manual_mqtt", "requirements": [], - "dependencies": [], + "dependencies": [ + "mqtt" + ], "codeowners": [] } diff --git a/homeassistant/components/mqtt/manifest.json b/homeassistant/components/mqtt/manifest.json index deed878711a1003fbe5966a10ea9a8a7f180b8b8..dd4d0323a51c086dab1eef80b5dc84378777031d 100644 --- a/homeassistant/components/mqtt/manifest.json +++ b/homeassistant/components/mqtt/manifest.json @@ -6,7 +6,9 @@ "hbmqtt==0.9.4", "paho-mqtt==1.4.0" ], - "dependencies": [], + "dependencies": [ + "http" + ], "codeowners": [ "@home-assistant/core" ] diff --git a/homeassistant/components/mqtt_json/manifest.json b/homeassistant/components/mqtt_json/manifest.json index 96a0a187e65c65a6a6e99a7a5b2f43f6dfa75445..a1986b2bf2eee26b83c3f8bd4877b0d47bb953b8 100644 --- a/homeassistant/components/mqtt_json/manifest.json +++ b/homeassistant/components/mqtt_json/manifest.json @@ -3,6 +3,8 @@ "name": "Mqtt json", "documentation": "https://www.home-assistant.io/components/mqtt_json", "requirements": [], - "dependencies": [], + "dependencies": [ + "mqtt" + ], "codeowners": [] } diff --git a/homeassistant/components/mqtt_room/manifest.json b/homeassistant/components/mqtt_room/manifest.json index e7b37aec50d43074bea99e954b7057934c55a864..8fc90b0bcb18373ec2e6b59ed1c49e70a4eca933 100644 --- a/homeassistant/components/mqtt_room/manifest.json +++ b/homeassistant/components/mqtt_room/manifest.json @@ -3,6 +3,8 @@ "name": "Mqtt room", "documentation": "https://www.home-assistant.io/components/mqtt_room", "requirements": [], - "dependencies": [], + "dependencies": [ + "mqtt" + ], "codeowners": [] } diff --git a/homeassistant/components/mystrom/manifest.json b/homeassistant/components/mystrom/manifest.json index a3744baccb13a3dec8960883f672eab66865aeba..0e17f33f72ebd26e496e504e9749422c60c4333d 100644 --- a/homeassistant/components/mystrom/manifest.json +++ b/homeassistant/components/mystrom/manifest.json @@ -5,7 +5,9 @@ "requirements": [ "python-mystrom==0.5.0" ], - "dependencies": [], + "dependencies": [ + "http" + ], "codeowners": [ "@fabaff" ] diff --git a/homeassistant/components/netatmo_public/manifest.json b/homeassistant/components/netatmo_public/manifest.json index 4327db3f298d6a66ccc9dc57cc93d00012d032d6..1070f27b33c1d2f6c1bbf7040ff6732941210cbc 100644 --- a/homeassistant/components/netatmo_public/manifest.json +++ b/homeassistant/components/netatmo_public/manifest.json @@ -3,6 +3,8 @@ "name": "Netatmo public", "documentation": "https://www.home-assistant.io/components/netatmo_public", "requirements": [], - "dependencies": [], + "dependencies": [ + "netatmo" + ], "codeowners": [] } diff --git a/homeassistant/components/netio/manifest.json b/homeassistant/components/netio/manifest.json index 75649c66abb58649a79c4c2e65a13fb962f3203f..e3675db04d7305023ecb87351a27c1a1cdba83ad 100644 --- a/homeassistant/components/netio/manifest.json +++ b/homeassistant/components/netio/manifest.json @@ -5,6 +5,8 @@ "requirements": [ "pynetio==0.1.9.1" ], - "dependencies": [], + "dependencies": [ + "http" + ], "codeowners": [] } diff --git a/homeassistant/components/onvif/manifest.json b/homeassistant/components/onvif/manifest.json index 6d5ad256f165cb5836e8963054128dcf28416b9f..bade9f37022eb5a70658529734b5e3651b540d3b 100644 --- a/homeassistant/components/onvif/manifest.json +++ b/homeassistant/components/onvif/manifest.json @@ -7,6 +7,8 @@ "suds-passworddigest-homeassistant==0.1.2a0.dev0", "suds-py3==1.3.3.0" ], - "dependencies": [], + "dependencies": [ + "ffmpeg" + ], "codeowners": [] } diff --git a/homeassistant/components/ring/manifest.json b/homeassistant/components/ring/manifest.json index 4d1fc62903553eb07d76c4c7645b711711f19ae4..9dbedad1ffc13619fa0dc7479bba2a79c7e65e47 100644 --- a/homeassistant/components/ring/manifest.json +++ b/homeassistant/components/ring/manifest.json @@ -5,6 +5,8 @@ "requirements": [ "ring_doorbell==0.2.3" ], - "dependencies": [], + "dependencies": [ + "ffmpeg" + ], "codeowners": [] } diff --git a/homeassistant/components/spotify/manifest.json b/homeassistant/components/spotify/manifest.json index 8c2c72e4d2a157f190bd6869ae52f89a6fad1c3c..a371f05629e959f279df11200aa8c427d502d7ec 100644 --- a/homeassistant/components/spotify/manifest.json +++ b/homeassistant/components/spotify/manifest.json @@ -5,6 +5,8 @@ "requirements": [ "spotipy-homeassistant==2.4.4.dev1" ], - "dependencies": [], + "dependencies": [ + "http" + ], "codeowners": [] } diff --git a/homeassistant/components/telegram/manifest.json b/homeassistant/components/telegram/manifest.json index 6ace3cd5aa0930a5c9321ac6c97c40f486b7e131..8a6dd7fb369d4c3bf03940f8929044926389a1c3 100644 --- a/homeassistant/components/telegram/manifest.json +++ b/homeassistant/components/telegram/manifest.json @@ -3,6 +3,8 @@ "name": "Telegram", "documentation": "https://www.home-assistant.io/components/telegram", "requirements": [], - "dependencies": [], + "dependencies": [ + "telegram_bot" + ], "codeowners": [] } diff --git a/homeassistant/components/tof/manifest.json b/homeassistant/components/tof/manifest.json index 4e1857379c03491fd284146735ad7b57c35b09aa..5f64e661a9a5f4670f204fe10d7476efb01e044f 100644 --- a/homeassistant/components/tof/manifest.json +++ b/homeassistant/components/tof/manifest.json @@ -5,6 +5,8 @@ "requirements": [ "VL53L1X2==0.1.5" ], - "dependencies": [], + "dependencies": [ + "rpi_gpio" + ], "codeowners": [] } diff --git a/homeassistant/components/torque/manifest.json b/homeassistant/components/torque/manifest.json index 3e69cb62e680104449dd31ab33cf81f281865549..9ce41b59861a691cc092526cfa6c16ca6f78773c 100644 --- a/homeassistant/components/torque/manifest.json +++ b/homeassistant/components/torque/manifest.json @@ -3,6 +3,8 @@ "name": "Torque", "documentation": "https://www.home-assistant.io/components/torque", "requirements": [], - "dependencies": [], + "dependencies": [ + "http" + ], "codeowners": [] } diff --git a/homeassistant/components/twilio_call/manifest.json b/homeassistant/components/twilio_call/manifest.json index 85545084c7b8c85faf38518550b5ad8b9898b148..b235385396be12f12b677c7644c7f8916cfec4ec 100644 --- a/homeassistant/components/twilio_call/manifest.json +++ b/homeassistant/components/twilio_call/manifest.json @@ -3,7 +3,9 @@ "name": "Twilio call", "documentation": "https://www.home-assistant.io/components/twilio_call", "requirements": [], - "dependencies": [], + "dependencies": [ + "twilio" + ], "codeowners": [ "@robbiet480" ] diff --git a/homeassistant/components/twilio_sms/manifest.json b/homeassistant/components/twilio_sms/manifest.json index 25cee38dbc88714933f104a5628b719ad3c7c55d..2174dc275b52cf23359982d93c477bc869e9acb1 100644 --- a/homeassistant/components/twilio_sms/manifest.json +++ b/homeassistant/components/twilio_sms/manifest.json @@ -3,7 +3,9 @@ "name": "Twilio sms", "documentation": "https://www.home-assistant.io/components/twilio_sms", "requirements": [], - "dependencies": [], + "dependencies": [ + "twilio" + ], "codeowners": [ "@robbiet480" ] diff --git a/homeassistant/components/xiaomi/manifest.json b/homeassistant/components/xiaomi/manifest.json index 158a2e9b2fc3639a129c957593f2fd617dd2bc07..d3587100501f04879f7fef31562e7eaed7da5d6e 100644 --- a/homeassistant/components/xiaomi/manifest.json +++ b/homeassistant/components/xiaomi/manifest.json @@ -3,6 +3,8 @@ "name": "Xiaomi", "documentation": "https://www.home-assistant.io/components/xiaomi", "requirements": [], - "dependencies": [], + "dependencies": [ + "ffmpeg" + ], "codeowners": [] } diff --git a/homeassistant/components/yi/manifest.json b/homeassistant/components/yi/manifest.json index 0a1a6aabc576db3fbcb236caa24936c41bf23fc1..bb7fbf55cbc205d08d858c413b243b772fb98f43 100644 --- a/homeassistant/components/yi/manifest.json +++ b/homeassistant/components/yi/manifest.json @@ -5,7 +5,9 @@ "requirements": [ "aioftp==0.12.0" ], - "dependencies": [], + "dependencies": [ + "ffmpeg" + ], "codeowners": [ "@bachya" ] diff --git a/homeassistant/config_entries.py b/homeassistant/config_entries.py index 571cacbaf8fef2151c063b494602dbd521c14256..917579d6cf1df66663f309145ddc5771c0e56fa5 100644 --- a/homeassistant/config_entries.py +++ b/homeassistant/config_entries.py @@ -126,7 +126,7 @@ import uuid from typing import Callable, Dict, List, Optional, Set # noqa pylint: disable=unused-import import weakref -from homeassistant import data_entry_flow +from homeassistant import data_entry_flow, loader from homeassistant.core import callback, HomeAssistant from homeassistant.exceptions import HomeAssistantError, ConfigEntryNotReady from homeassistant.setup import async_setup_component, async_process_deps_reqs @@ -688,7 +688,12 @@ class ConfigEntries: Handler key is the domain of the component that we want to set up. """ - component = getattr(self.hass.components, handler_key) + integration = await loader.async_get_integration( + self.hass, handler_key) + + if integration is None: + raise data_entry_flow.UnknownHandler + handler = HANDLERS.get(handler_key) if handler is None: @@ -698,7 +703,7 @@ class ConfigEntries: # Make sure requirements and dependencies of component are resolved await async_process_deps_reqs( - self.hass, self._hass_config, handler, component) + self.hass, self._hass_config, integration) # Create notification. if source in DISCOVERY_SOURCES: diff --git a/homeassistant/loader.py b/homeassistant/loader.py index 17f0130da4dbdda8ff91fd455842fff665ecb363..0b7495bcb6941b6bf14e16b67b3197304922c458 100644 --- a/homeassistant/loader.py +++ b/homeassistant/loader.py @@ -52,11 +52,11 @@ LOOKUP_PATHS = [PACKAGE_CUSTOM_COMPONENTS, PACKAGE_BUILTIN] _UNDEF = object() -def manifest_from_legacy_module(module: Any) -> Dict: +def manifest_from_legacy_module(module: ModuleType) -> Dict: """Generate a manifest from a legacy module.""" return { - 'domain': module.DOMAIN, - 'name': module.DOMAIN, + 'domain': module.DOMAIN, # type: ignore + 'name': module.DOMAIN, # type: ignore 'documentation': None, 'requirements': getattr(module, 'REQUIREMENTS', []), 'dependencies': getattr(module, 'DEPENDENCIES', []), @@ -68,10 +68,10 @@ class Integration: """An integration in Home Assistant.""" @classmethod - def resolve_from_root(cls, hass: 'HomeAssistant', root_module: Any, + def resolve_from_root(cls, hass: 'HomeAssistant', root_module: ModuleType, domain: str) -> 'Optional[Integration]': """Resolve an integration from a root module.""" - for base in root_module.__path__: + for base in root_module.__path__: # type: ignore manifest_path = ( pathlib.Path(base) / domain / 'manifest.json' ) @@ -117,15 +117,22 @@ class Integration: self.dependencies = manifest['dependencies'] # type: List[str] self.requirements = manifest['requirements'] # type: List[str] - def get_component(self) -> Any: + def get_component(self) -> ModuleType: """Return the component.""" - return importlib.import_module(self.pkg_path) + cache = self.hass.data.setdefault(DATA_KEY, {}) + if self.domain not in cache: + cache[self.domain] = importlib.import_module(self.pkg_path) + return cache[self.domain] # type: ignore - def get_platform(self, platform_name: str) -> Any: + def get_platform(self, platform_name: str) -> ModuleType: """Return a platform for an integration.""" - return importlib.import_module( - "{}.{}".format(self.pkg_path, platform_name) - ) + cache = self.hass.data.setdefault(DATA_KEY, {}) + full_name = "{}.{}".format(self.domain, platform_name) + if full_name not in cache: + cache[full_name] = importlib.import_module( + "{}.{}".format(self.pkg_path, platform_name) + ) + return cache[full_name] # type: ignore async def async_get_integration(hass: 'HomeAssistant', domain: str)\ diff --git a/homeassistant/setup.py b/homeassistant/setup.py index 0e294200b5f214ef73e97abac025549dcb6db8aa..0160279a859bbe5b80d7d5f14e524b48c23d472c 100644 --- a/homeassistant/setup.py +++ b/homeassistant/setup.py @@ -100,10 +100,16 @@ async def _async_setup_component(hass: core.HomeAssistant, _LOGGER.error("Setup failed for %s: %s", domain, msg) async_notify_setup_error(hass, domain, link) - component = loader.get_component(hass, domain) + try: + integration = await loader.async_get_integration(hass, domain) + except loader.IntegrationNotFound: + log_error("Integration not found.", False) + return False - if not component: - log_error("Component not found.", False) + try: + component = integration.get_component() + except ImportError: + log_error("Unable to import component", False) return False # Validate all dependencies exist and there are no circular dependencies @@ -128,7 +134,7 @@ async def _async_setup_component(hass: core.HomeAssistant, return False try: - await async_process_deps_reqs(hass, config, domain, component) + await async_process_deps_reqs(hass, config, integration) except HomeAssistantError as err: log_error(str(err)) return False @@ -183,13 +189,14 @@ async def _async_setup_component(hass: core.HomeAssistant, hass.bus.async_fire( EVENT_COMPONENT_LOADED, - {ATTR_COMPONENT: component.DOMAIN} # type: ignore + {ATTR_COMPONENT: component.DOMAIN} # type: ignore ) return True -async def async_prepare_setup_platform(hass: core.HomeAssistant, config: Dict, +async def async_prepare_setup_platform(hass: core.HomeAssistant, + hass_config: Dict, domain: str, platform_name: str) \ -> Optional[ModuleType]: """Load a platform and makes sure dependencies are setup. @@ -202,13 +209,18 @@ async def async_prepare_setup_platform(hass: core.HomeAssistant, config: Dict, def log_error(msg: str) -> None: """Log helper.""" _LOGGER.error("Unable to prepare setup for platform %s: %s", - platform_path, msg) + platform_name, msg) async_notify_setup_error(hass, platform_path) - platform = loader.get_platform(hass, domain, platform_name) + try: + integration = await loader.async_get_integration(hass, platform_name) + except loader.IntegrationNotFound: + log_error("Integration not found") + return None - # Not found - if platform is None: + try: + platform = integration.get_platform(domain) + except ImportError: log_error("Platform not found.") return None @@ -216,9 +228,25 @@ async def async_prepare_setup_platform(hass: core.HomeAssistant, config: Dict, if platform_path in hass.config.components: return platform + # Platforms cannot exist on their own, they are part of their integration. + # If the integration is not set up yet, and can be set up, set it up. + if integration.domain not in hass.config.components: + try: + component = integration.get_component() + except ImportError: + log_error("Unable to import the component") + return None + + if (hasattr(component, 'setup') + or hasattr(component, 'async_setup')): + if not await async_setup_component( + hass, integration.domain, hass_config + ): + log_error("Unable to set up component.") + return None + try: - await async_process_deps_reqs( - hass, config, platform_path, platform) + await async_process_deps_reqs(hass, hass_config, integration) except HomeAssistantError as err: log_error(str(err)) return None @@ -227,8 +255,8 @@ async def async_prepare_setup_platform(hass: core.HomeAssistant, config: Dict, async def async_process_deps_reqs( - hass: core.HomeAssistant, config: Dict, name: str, - module: ModuleType) -> None: + hass: core.HomeAssistant, config: Dict, + integration: loader.Integration) -> None: """Process all dependencies and requirements for a module. Module is a Python module of either a component or platform. @@ -237,24 +265,23 @@ async def async_process_deps_reqs( if processed is None: processed = hass.data[DATA_DEPS_REQS] = set() - elif name in processed: + elif integration.domain in processed: return - if hasattr(module, 'DEPENDENCIES'): - dep_success = await _async_process_dependencies( - hass, config, name, module.DEPENDENCIES) # type: ignore - - if not dep_success: - raise HomeAssistantError("Could not set up all dependencies.") - - if not hass.config.skip_pip and hasattr(module, 'REQUIREMENTS'): - req_success = await requirements.async_process_requirements( - hass, name, module.REQUIREMENTS) # type: ignore + if integration.dependencies and not await _async_process_dependencies( + hass, + config, + integration.domain, + integration.dependencies + ): + raise HomeAssistantError("Could not set up all dependencies.") - if not req_success: - raise HomeAssistantError("Could not install all requirements.") + if (not hass.config.skip_pip and integration.requirements and + not await requirements.async_process_requirements( + hass, integration.domain, integration.requirements)): + raise HomeAssistantError("Could not install all requirements.") - processed.add(name) + processed.add(integration.domain) @core.callback diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 12c2f0e51ad0cfe92f63f9008b2868a61a28aca8..c69d4026227937bda278b5a80095a385727475dd 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -111,6 +111,9 @@ geojson_client==0.3 # homeassistant.components.geo_rss_events georss_generic_client==0.2 +# homeassistant.components.google +google-api-python-client==1.6.4 + # homeassistant.components.ffmpeg ha-ffmpeg==2.0 @@ -138,6 +141,10 @@ homekit[IP]==0.13.0 # homeassistant.components.homematicip_cloud homematicip==0.10.6 +# homeassistant.components.google +# homeassistant.components.remember_the_milk +httplib2==0.10.3 + # homeassistant.components.influxdb influxdb==5.2.0 @@ -165,6 +172,9 @@ mficlient==0.3.0 # homeassistant.components.trend numpy==1.16.2 +# homeassistant.components.google +oauth2client==4.0.0 + # homeassistant.components.mqtt # homeassistant.components.shiftr paho-mqtt==1.4.0 diff --git a/script/gen_requirements_all.py b/script/gen_requirements_all.py index 8f6172c2323a64e17d92c5d69581670f338c5d93..e1179c904ce285a058fc8be5a18647c6c8956629 100755 --- a/script/gen_requirements_all.py +++ b/script/gen_requirements_all.py @@ -62,6 +62,7 @@ TEST_REQUIREMENTS = ( 'foobot_async', 'geojson_client', 'georss_generic_client', + 'google-api-python-client', 'gTTS-token', 'ha-ffmpeg', 'hangups', @@ -74,6 +75,7 @@ TEST_REQUIREMENTS = ( 'home-assistant-frontend', 'homekit[IP]', 'homematicip', + 'httplib2', 'influxdb', 'jsonpath', 'libpurecool', @@ -82,6 +84,7 @@ TEST_REQUIREMENTS = ( 'mbddns', 'mficlient', 'numpy', + 'oauth2client', 'paho-mqtt', 'pexpect', 'pilight', diff --git a/tests/common.py b/tests/common.py index 962e98b24e705de551a13c79de7f778b16e803bd..4aa13fc9be6eced6918523205ea5d0e036267a67 100644 --- a/tests/common.py +++ b/tests/common.py @@ -906,11 +906,26 @@ def mock_integration(hass, module): integration = loader.Integration( hass, 'homeassisant.components.{}'.format(module.DOMAIN), loader.manifest_from_legacy_module(module)) - integration.get_component = lambda: module - - # Backwards compat - loader.set_component(hass, module.DOMAIN, module) + _LOGGER.info("Adding mock integration: %s", module.DOMAIN) hass.data.setdefault( loader.DATA_INTEGRATIONS, {} )[module.DOMAIN] = integration + hass.data.setdefault(loader.DATA_KEY, {})[module.DOMAIN] = module + + +def mock_entity_platform(hass, platform_path, module): + """Mock a entity platform. + + platform_path is in form light.hue. Will create platform + hue.light. + """ + domain, platform_name = platform_path.split('.') + integration_cache = hass.data.setdefault(loader.DATA_KEY, {}) + module_cache = hass.data.setdefault(loader.DATA_KEY, {}) + + if platform_name not in integration_cache: + mock_integration(hass, MockModule(platform_name)) + + _LOGGER.info("Adding mock integration platform: %s", platform_path) + module_cache["{}.{}".format(platform_name, domain)] = module diff --git a/tests/components/demo/test_geo_location.py b/tests/components/demo/test_geo_location.py index c4d01b812f859755ce9debcfac07c272a8bbb1bd..acfc97b00e68f7b0f665a9aec0da5fbbd2721b41 100644 --- a/tests/components/demo/test_geo_location.py +++ b/tests/components/demo/test_geo_location.py @@ -40,14 +40,13 @@ class TestDemoPlatform(unittest.TestCase): assert setup_component(self.hass, geo_location.DOMAIN, CONFIG) self.hass.block_till_done() - # In this test, five geolocation entities have been + # In this test, one zone and geolocation entities have been # generated. all_states = self.hass.states.all() - print(all_states) - assert len(all_states) == NUMBER_OF_DEMO_DEVICES + assert len(all_states) == NUMBER_OF_DEMO_DEVICES + 1 # Check a single device's attributes. - state_first_entry = all_states[0] + state_first_entry = all_states[1] # 0 is zone assert abs( state_first_entry.attributes['latitude'] - self.hass.config.latitude @@ -64,5 +63,5 @@ class TestDemoPlatform(unittest.TestCase): # Get all states again, ensure that the number of states is still # the same, but the lists are different. all_states_updated = self.hass.states.all() - assert len(all_states_updated) == NUMBER_OF_DEMO_DEVICES + assert len(all_states_updated) == NUMBER_OF_DEMO_DEVICES + 1 assert all_states != all_states_updated diff --git a/tests/components/demo/test_init.py b/tests/components/demo/test_init.py index b0b2524180fea2505693e3a9fa2318db1dfc15fe..8ade4f4c278d5a813975e8c3f2a830dc6a292708 100644 --- a/tests/components/demo/test_init.py +++ b/tests/components/demo/test_init.py @@ -38,6 +38,7 @@ def demo_cleanup(hass): pass +@pytest.mark.skip @asyncio.coroutine def test_if_demo_state_shows_by_default(hass, minimize_demo_platforms): """Test if demo state shows if we give no configuration.""" @@ -46,6 +47,7 @@ def test_if_demo_state_shows_by_default(hass, minimize_demo_platforms): assert hass.states.get('a.Demo_Mode') is not None +@pytest.mark.skip @asyncio.coroutine def test_hiding_demo_state(hass, minimize_demo_platforms): """Test if you can hide the demo card.""" @@ -55,6 +57,7 @@ def test_hiding_demo_state(hass, minimize_demo_platforms): assert hass.states.get('a.Demo_Mode') is None +@pytest.mark.skip @asyncio.coroutine def test_all_entities_can_be_loaded_over_json(hass): """Test if you can hide the demo card.""" diff --git a/tests/components/device_sun_light_trigger/test_init.py b/tests/components/device_sun_light_trigger/test_init.py index f1ef6aa5dd03c9f4a85e7d1eb45b0f59416c1d1e..8c4417f5b291c08322a601ace89216fe24b922ce 100644 --- a/tests/components/device_sun_light_trigger/test_init.py +++ b/tests/components/device_sun_light_trigger/test_init.py @@ -19,12 +19,12 @@ from tests.components.light import common as common_light def scanner(hass): """Initialize components.""" scanner = loader.get_component( - hass, 'device_tracker.test').get_scanner(None, None) + hass, 'test.device_tracker').get_scanner(None, None) scanner.reset() scanner.come_home('DEV1') - loader.get_component(hass, 'light.test').init() + loader.get_component(hass, 'test.light').init() with patch( 'homeassistant.components.device_tracker.load_yaml_config_file', diff --git a/tests/components/device_tracker/test_init.py b/tests/components/device_tracker/test_init.py index 63f1c60327a45978e50400825f0b2846c1aa7b8b..a7c5a1c39033f0a64734dc6d28edc6c78185f1a4 100644 --- a/tests/components/device_tracker/test_init.py +++ b/tests/components/device_tracker/test_init.py @@ -192,7 +192,7 @@ async def test_discover_platform(mock_demo_setup_scanner, mock_see, hass): async def test_update_stale(hass): """Test stalled update.""" - scanner = get_component(hass, 'device_tracker.test').SCANNER + scanner = get_component(hass, 'test.device_tracker').SCANNER scanner.reset() scanner.come_home('DEV1') @@ -256,7 +256,7 @@ async def test_device_hidden(hass, yaml_devices): hide_if_away=True) device_tracker.update_config(yaml_devices, dev_id, device) - scanner = get_component(hass, 'device_tracker.test').SCANNER + scanner = get_component(hass, 'test.device_tracker').SCANNER scanner.reset() with assert_setup_component(1, device_tracker.DOMAIN): @@ -275,7 +275,7 @@ async def test_group_all_devices(hass, yaml_devices): hide_if_away=True) device_tracker.update_config(yaml_devices, dev_id, device) - scanner = get_component(hass, 'device_tracker.test').SCANNER + scanner = get_component(hass, 'test.device_tracker').SCANNER scanner.reset() with assert_setup_component(1, device_tracker.DOMAIN): @@ -441,7 +441,7 @@ async def test_see_passive_zone_state(hass): 'zone': zone_info }) - scanner = get_component(hass, 'device_tracker.test').SCANNER + scanner = get_component(hass, 'test.device_tracker').SCANNER scanner.reset() scanner.come_home('dev1') @@ -557,7 +557,7 @@ def test_bad_platform(hass): async def test_adding_unknown_device_to_config(mock_device_tracker_conf, hass): """Test the adding of unknown devices to configuration file.""" - scanner = get_component(hass, 'device_tracker.test').SCANNER + scanner = get_component(hass, 'test.device_tracker').SCANNER scanner.reset() scanner.come_home('DEV1') diff --git a/tests/components/flux/test_switch.py b/tests/components/flux/test_switch.py index c43f1071e339e139ac6eb897f0643454ca7c173e..317e20f145761863de2896c38370fab0fa9935c6 100644 --- a/tests/components/flux/test_switch.py +++ b/tests/components/flux/test_switch.py @@ -74,7 +74,7 @@ class TestSwitchFlux(unittest.TestCase): def test_flux_when_switch_is_off(self): """Test the flux switch when it is off.""" - platform = loader.get_component(self.hass, 'light.test') + platform = loader.get_component(self.hass, 'test.light') platform.init() assert setup_component(self.hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: 'test'}}) @@ -114,7 +114,7 @@ class TestSwitchFlux(unittest.TestCase): def test_flux_before_sunrise(self): """Test the flux switch before sunrise.""" - platform = loader.get_component(self.hass, 'light.test') + platform = loader.get_component(self.hass, 'test.light') platform.init() assert setup_component(self.hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: 'test'}}) @@ -159,7 +159,7 @@ class TestSwitchFlux(unittest.TestCase): # pylint: disable=invalid-name def test_flux_after_sunrise_before_sunset(self): """Test the flux switch after sunrise and before sunset.""" - platform = loader.get_component(self.hass, 'light.test') + platform = loader.get_component(self.hass, 'test.light') platform.init() assert setup_component(self.hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: 'test'}}) @@ -205,7 +205,7 @@ class TestSwitchFlux(unittest.TestCase): # pylint: disable=invalid-name def test_flux_after_sunset_before_stop(self): """Test the flux switch after sunset and before stop.""" - platform = loader.get_component(self.hass, 'light.test') + platform = loader.get_component(self.hass, 'test.light') platform.init() assert setup_component(self.hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: 'test'}}) @@ -252,7 +252,7 @@ class TestSwitchFlux(unittest.TestCase): # pylint: disable=invalid-name def test_flux_after_stop_before_sunrise(self): """Test the flux switch after stop and before sunrise.""" - platform = loader.get_component(self.hass, 'light.test') + platform = loader.get_component(self.hass, 'test.light') platform.init() assert setup_component(self.hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: 'test'}}) @@ -297,7 +297,7 @@ class TestSwitchFlux(unittest.TestCase): # pylint: disable=invalid-name def test_flux_with_custom_start_stop_times(self): """Test the flux with custom start and stop times.""" - platform = loader.get_component(self.hass, 'light.test') + platform = loader.get_component(self.hass, 'test.light') platform.init() assert setup_component(self.hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: 'test'}}) @@ -347,7 +347,7 @@ class TestSwitchFlux(unittest.TestCase): This test has the stop_time on the next day (after midnight). """ - platform = loader.get_component(self.hass, 'light.test') + platform = loader.get_component(self.hass, 'test.light') platform.init() assert setup_component(self.hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: 'test'}}) @@ -398,7 +398,7 @@ class TestSwitchFlux(unittest.TestCase): This test has the stop_time on the next day (after midnight). """ - platform = loader.get_component(self.hass, 'light.test') + platform = loader.get_component(self.hass, 'test.light') platform.init() assert setup_component(self.hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: 'test'}}) @@ -448,7 +448,7 @@ class TestSwitchFlux(unittest.TestCase): This test has the stop_time on the next day (after midnight). """ - platform = loader.get_component(self.hass, 'light.test') + platform = loader.get_component(self.hass, 'test.light') platform.init() assert setup_component(self.hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: 'test'}}) @@ -497,7 +497,7 @@ class TestSwitchFlux(unittest.TestCase): This test has the stop_time on the next day (after midnight). """ - platform = loader.get_component(self.hass, 'light.test') + platform = loader.get_component(self.hass, 'test.light') platform.init() assert setup_component(self.hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: 'test'}}) @@ -547,7 +547,7 @@ class TestSwitchFlux(unittest.TestCase): This test has the stop_time on the next day (after midnight). """ - platform = loader.get_component(self.hass, 'light.test') + platform = loader.get_component(self.hass, 'test.light') platform.init() assert setup_component(self.hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: 'test'}}) @@ -594,7 +594,7 @@ class TestSwitchFlux(unittest.TestCase): # pylint: disable=invalid-name def test_flux_with_custom_colortemps(self): """Test the flux with custom start and stop colortemps.""" - platform = loader.get_component(self.hass, 'light.test') + platform = loader.get_component(self.hass, 'test.light') platform.init() assert setup_component(self.hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: 'test'}}) @@ -643,7 +643,7 @@ class TestSwitchFlux(unittest.TestCase): # pylint: disable=invalid-name def test_flux_with_custom_brightness(self): """Test the flux with custom start and stop colortemps.""" - platform = loader.get_component(self.hass, 'light.test') + platform = loader.get_component(self.hass, 'test.light') platform.init() assert setup_component(self.hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: 'test'}}) @@ -690,7 +690,7 @@ class TestSwitchFlux(unittest.TestCase): def test_flux_with_multiple_lights(self): """Test the flux switch with multiple light entities.""" - platform = loader.get_component(self.hass, 'light.test') + platform = loader.get_component(self.hass, 'test.light') platform.init() assert setup_component(self.hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: 'test'}}) @@ -758,7 +758,7 @@ class TestSwitchFlux(unittest.TestCase): def test_flux_with_mired(self): """Test the flux switch´s mode mired.""" - platform = loader.get_component(self.hass, 'light.test') + platform = loader.get_component(self.hass, 'test.light') platform.init() assert setup_component(self.hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: 'test'}}) @@ -802,7 +802,7 @@ class TestSwitchFlux(unittest.TestCase): def test_flux_with_rgb(self): """Test the flux switch´s mode rgb.""" - platform = loader.get_component(self.hass, 'light.test') + platform = loader.get_component(self.hass, 'test.light') platform.init() assert setup_component(self.hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: 'test'}}) diff --git a/tests/components/frontend/test_init.py b/tests/components/frontend/test_init.py index e4ed2c15ecb699ccc2065eb257deb2517ab40f85..497dc25230e8f14d2d9d8401d50bfa13758007c4 100644 --- a/tests/components/frontend/test_init.py +++ b/tests/components/frontend/test_init.py @@ -78,9 +78,9 @@ def test_frontend_and_static(mock_http_client, mock_onboarded): # Test we can retrieve frontend.js frontendjs = re.search( - r'(?P<app>\/frontend_es5\/app-[A-Za-z0-9]{8}.js)', text) + r'(?P<app>\/frontend_es5\/app.[A-Za-z0-9]{8}.js)', text) - assert frontendjs is not None + assert frontendjs is not None, text resp = yield from mock_http_client.get(frontendjs.groups(0)[0]) assert resp.status == 200 assert 'public' in resp.headers.get('cache-control') diff --git a/tests/components/generic_thermostat/test_climate.py b/tests/components/generic_thermostat/test_climate.py index 49d49fdd3d404b5f07efeeb45537c6e712d64967..2d9a5effc2c3053bd98bf43cee89fd5f9572206f 100644 --- a/tests/components/generic_thermostat/test_climate.py +++ b/tests/components/generic_thermostat/test_climate.py @@ -98,7 +98,7 @@ async def test_heater_input_boolean(hass, setup_comp_1): async def test_heater_switch(hass, setup_comp_1): """Test heater switching test switch.""" - platform = loader.get_component(hass, 'switch.test') + platform = loader.get_component(hass, 'test.switch') platform.init() switch_1 = platform.DEVICES[1] assert await async_setup_component(hass, switch.DOMAIN, {'switch': { @@ -112,6 +112,7 @@ async def test_heater_switch(hass, setup_comp_1): 'target_sensor': ENT_SENSOR }}) + await hass.async_block_till_done() assert STATE_OFF == \ hass.states.get(heater_switch).state diff --git a/tests/components/light/test_init.py b/tests/components/light/test_init.py index 90f2651080c955d56a2a5e0b1e6a84f35e3c3fc1..c910c2a49a15ce672105ef5df0794db476710dba 100644 --- a/tests/components/light/test_init.py +++ b/tests/components/light/test_init.py @@ -121,7 +121,7 @@ class TestLight(unittest.TestCase): def test_services(self): """Test the provided services.""" - platform = loader.get_component(self.hass, 'light.test') + platform = loader.get_component(self.hass, 'test.light') platform.init() assert setup_component(self.hass, light.DOMAIN, @@ -308,7 +308,7 @@ class TestLight(unittest.TestCase): def test_broken_light_profiles(self): """Test light profiles.""" - platform = loader.get_component(self.hass, 'light.test') + platform = loader.get_component(self.hass, 'test.light') platform.init() user_light_file = self.hass.config.path(light.LIGHT_PROFILES_FILE) @@ -323,7 +323,7 @@ class TestLight(unittest.TestCase): def test_light_profiles(self): """Test light profiles.""" - platform = loader.get_component(self.hass, 'light.test') + platform = loader.get_component(self.hass, 'test.light') platform.init() user_light_file = self.hass.config.path(light.LIGHT_PROFILES_FILE) @@ -362,7 +362,7 @@ class TestLight(unittest.TestCase): def test_default_profiles_group(self): """Test default turn-on light profile for all lights.""" - platform = loader.get_component(self.hass, 'light.test') + platform = loader.get_component(self.hass, 'test.light') platform.init() user_light_file = self.hass.config.path(light.LIGHT_PROFILES_FILE) @@ -400,7 +400,7 @@ class TestLight(unittest.TestCase): def test_default_profiles_light(self): """Test default turn-on light profile for a specific light.""" - platform = loader.get_component(self.hass, 'light.test') + platform = loader.get_component(self.hass, 'test.light') platform.init() user_light_file = self.hass.config.path(light.LIGHT_PROFILES_FILE) diff --git a/tests/components/nx584/test_binary_sensor.py b/tests/components/nx584/test_binary_sensor.py index 53516885f306e16f1f973f012793ea6892ecd2f1..ae7b70e7fe6a7e2faf464639a2f129cee9c4fbb3 100644 --- a/tests/components/nx584/test_binary_sensor.py +++ b/tests/components/nx584/test_binary_sensor.py @@ -85,7 +85,7 @@ class TestNX584SensorSetup(unittest.TestCase): def _test_assert_graceful_fail(self, config): """Test the failing.""" assert not setup_component( - self.hass, 'binary_sensor.nx584', config) + self.hass, 'nx584', config) def test_setup_bad_config(self): """Test the setup with bad configuration.""" diff --git a/tests/components/scene/test_init.py b/tests/components/scene/test_init.py index df96b19f3510b908797e4b7ff6e04b8972547ec4..804344ccb346967dedb71056fdfddf8fc13d707f 100644 --- a/tests/components/scene/test_init.py +++ b/tests/components/scene/test_init.py @@ -18,7 +18,7 @@ class TestScene(unittest.TestCase): def setUp(self): # pylint: disable=invalid-name """Set up things to be run when tests are started.""" self.hass = get_test_home_assistant() - test_light = loader.get_component(self.hass, 'light.test') + test_light = loader.get_component(self.hass, 'test.light') test_light.init() assert setup_component(self.hass, light.DOMAIN, { diff --git a/tests/components/switch/test_init.py b/tests/components/switch/test_init.py index d39c5a24ddc53ae7963b2cce8c7c971e4f1d4aea..c76278f9b2259c697c6ab131c96ca41abcc862cf 100644 --- a/tests/components/switch/test_init.py +++ b/tests/components/switch/test_init.py @@ -18,7 +18,7 @@ class TestSwitch(unittest.TestCase): def setUp(self): """Set up things to be run when tests are started.""" self.hass = get_test_home_assistant() - platform = loader.get_component(self.hass, 'switch.test') + platform = loader.get_component(self.hass, 'test.switch') platform.init() # Switch 1 is ON, switch 2 is OFF self.switch_1, self.switch_2, self.switch_3 = \ @@ -77,7 +77,7 @@ class TestSwitch(unittest.TestCase): def test_setup_two_platforms(self): """Test with bad configuration.""" # Test if switch component returns 0 switches - test_platform = loader.get_component(self.hass, 'switch.test') + test_platform = loader.get_component(self.hass, 'test.switch') test_platform.init(True) loader.set_component(self.hass, 'switch.test2', test_platform) @@ -99,6 +99,8 @@ async def test_switch_context(hass, hass_admin_user): } }) + await hass.async_block_till_done() + state = hass.states.get('switch.ac') assert state is not None diff --git a/tests/helpers/test_discovery.py b/tests/helpers/test_discovery.py index ffafd3ca146ff47ce250650d7692830a0daf959b..8bd5e482da40a5b7ab86174b95b773e74c8cb1db 100644 --- a/tests/helpers/test_discovery.py +++ b/tests/helpers/test_discovery.py @@ -132,10 +132,14 @@ class TestHelpersDiscovery: self.hass, 'test_component', MockModule('test_component', setup=component_setup)) + # dependencies are only set in component level + # since we are using manifest to hold them loader.set_component( - self.hass, 'switch.test_circular', - MockPlatform(setup_platform, - dependencies=['test_component'])) + self.hass, 'test_circular', + MockModule('test_circular', dependencies=['test_component'])) + loader.set_component( + self.hass, 'test_circular.switch', + MockPlatform(setup_platform)) setup.setup_component(self.hass, 'test_component', { 'test_component': None, diff --git a/tests/helpers/test_entity_component.py b/tests/helpers/test_entity_component.py index 6da3293d597b5ce8e1afa0a9f11ddf01a5a7843e..790b7d638e4db9ae17a0d926eacc5e9c422ba75b 100644 --- a/tests/helpers/test_entity_component.py +++ b/tests/helpers/test_entity_component.py @@ -21,7 +21,8 @@ import homeassistant.util.dt as dt_util from tests.common import ( get_test_home_assistant, MockPlatform, MockModule, mock_coro, - async_fire_time_changed, MockEntity, MockConfigEntry) + async_fire_time_changed, MockEntity, MockConfigEntry, + mock_entity_platform, mock_integration) _LOGGER = logging.getLogger(__name__) DOMAIN = "test_domain" @@ -74,11 +75,14 @@ class TestHelpersEntityComponent(unittest.TestCase): """Test the loading of the platforms.""" component_setup = Mock(return_value=True) platform_setup = Mock(return_value=None) - loader.set_component( - self.hass, 'test_component', - MockModule('test_component', setup=component_setup)) - loader.set_component(self.hass, 'test_domain.mod2', - MockPlatform(platform_setup, ['test_component'])) + + mock_integration(self.hass, + MockModule('test_component', setup=component_setup)) + # mock the dependencies + mock_integration(self.hass, + MockModule('mod2', dependencies=['test_component'])) + mock_entity_platform(self.hass, 'test_domain.mod2', + MockPlatform(platform_setup)) component = EntityComponent(_LOGGER, DOMAIN, self.hass) @@ -100,9 +104,9 @@ class TestHelpersEntityComponent(unittest.TestCase): platform1_setup = Mock(side_effect=Exception('Broken')) platform2_setup = Mock(return_value=None) - loader.set_component(self.hass, 'test_domain.mod1', + mock_entity_platform(self.hass, 'test_domain.mod1', MockPlatform(platform1_setup)) - loader.set_component(self.hass, 'test_domain.mod2', + mock_entity_platform(self.hass, 'test_domain.mod2', MockPlatform(platform2_setup)) component = EntityComponent(_LOGGER, DOMAIN, self.hass) @@ -147,7 +151,7 @@ class TestHelpersEntityComponent(unittest.TestCase): """Test the platform setup.""" add_entities([MockEntity(should_poll=True)]) - loader.set_component(self.hass, 'test_domain.platform', + mock_entity_platform(self.hass, 'test_domain.platform', MockPlatform(platform_setup)) component = EntityComponent(_LOGGER, DOMAIN, self.hass) @@ -174,7 +178,7 @@ class TestHelpersEntityComponent(unittest.TestCase): platform = MockPlatform(platform_setup) - loader.set_component(self.hass, 'test_domain.platform', platform) + mock_entity_platform(self.hass, 'test_domain.platform', platform) component = EntityComponent(_LOGGER, DOMAIN, self.hass) @@ -222,7 +226,9 @@ def test_platform_not_ready(hass): """Test that we retry when platform not ready.""" platform1_setup = Mock(side_effect=[PlatformNotReady, PlatformNotReady, None]) - loader.set_component(hass, 'test_domain.mod1', + loader.set_component(hass, 'mod1', + MockModule('mod1')) + loader.set_component(hass, 'mod1.test_domain', MockPlatform(platform1_setup)) component = EntityComponent(_LOGGER, DOMAIN, hass) @@ -320,17 +326,15 @@ def test_setup_dependencies_platform(hass): We're explictely testing that we process dependencies even if a component with the same name has already been loaded. """ - loader.set_component(hass, 'test_component', MockModule('test_component')) + loader.set_component(hass, 'test_component', + MockModule('test_component', + dependencies=['test_component2'])) loader.set_component(hass, 'test_component2', MockModule('test_component2')) - loader.set_component( - hass, 'test_component.test_domain', - MockPlatform(dependencies=['test_component', 'test_component2'])) + loader.set_component(hass, 'test_component.test_domain', MockPlatform()) component = EntityComponent(_LOGGER, DOMAIN, hass) - yield from async_setup_component(hass, 'test_component', {}) - yield from component.async_setup({ DOMAIN: { 'platform': 'test_component', @@ -345,7 +349,7 @@ def test_setup_dependencies_platform(hass): async def test_setup_entry(hass): """Test setup entry calls async_setup_entry on platform.""" mock_setup_entry = Mock(return_value=mock_coro(True)) - loader.set_component( + mock_entity_platform( hass, 'test_domain.entry_domain', MockPlatform(async_setup_entry=mock_setup_entry, scan_interval=timedelta(seconds=5))) @@ -374,7 +378,7 @@ async def test_setup_entry_platform_not_exist(hass): async def test_setup_entry_fails_duplicate(hass): """Test we don't allow setting up a config entry twice.""" mock_setup_entry = Mock(return_value=mock_coro(True)) - loader.set_component( + mock_entity_platform( hass, 'test_domain.entry_domain', MockPlatform(async_setup_entry=mock_setup_entry)) @@ -390,7 +394,7 @@ async def test_setup_entry_fails_duplicate(hass): async def test_unload_entry_resets_platform(hass): """Test unloading an entry removes all entities.""" mock_setup_entry = Mock(return_value=mock_coro(True)) - loader.set_component( + mock_entity_platform( hass, 'test_domain.entry_domain', MockPlatform(async_setup_entry=mock_setup_entry)) diff --git a/tests/helpers/test_entity_platform.py b/tests/helpers/test_entity_platform.py index 6cf0bb0eeeb89c868194706718321e5670012211..0fed09b7cbc9b3878644a80c117ac4e5f16f8636 100644 --- a/tests/helpers/test_entity_platform.py +++ b/tests/helpers/test_entity_platform.py @@ -8,7 +8,6 @@ from datetime import timedelta import pytest from homeassistant.exceptions import PlatformNotReady -import homeassistant.loader as loader from homeassistant.helpers.entity import generate_entity_id from homeassistant.helpers.entity_component import ( EntityComponent, DEFAULT_SCAN_INTERVAL) @@ -18,7 +17,7 @@ import homeassistant.util.dt as dt_util from tests.common import ( get_test_home_assistant, MockPlatform, fire_time_changed, mock_registry, - MockEntity, MockEntityPlatform, MockConfigEntry) + MockEntity, MockEntityPlatform, MockConfigEntry, mock_entity_platform) _LOGGER = logging.getLogger(__name__) DOMAIN = "test_domain" @@ -149,7 +148,7 @@ class TestHelpersEntityPlatform(unittest.TestCase): platform = MockPlatform(platform_setup) platform.SCAN_INTERVAL = timedelta(seconds=30) - loader.set_component(self.hass, 'test_domain.platform', platform) + mock_entity_platform(self.hass, 'test_domain.platform', platform) component = EntityComponent(_LOGGER, DOMAIN, self.hass) @@ -186,7 +185,7 @@ def test_platform_warn_slow_setup(hass): """Warn we log when platform setup takes a long time.""" platform = MockPlatform() - loader.set_component(hass, 'test_domain.platform', platform) + mock_entity_platform(hass, 'test_domain.platform', platform) component = EntityComponent(_LOGGER, DOMAIN, hass) @@ -199,7 +198,9 @@ def test_platform_warn_slow_setup(hass): }) assert mock_call.called - timeout, logger_method = mock_call.mock_calls[0][1][:2] + # mock_calls[0] is the warning message for component setup + # mock_calls[3] is the warning message for platform setup + timeout, logger_method = mock_call.mock_calls[3][1][:2] assert timeout == entity_platform.SLOW_SETUP_WARNING assert logger_method == _LOGGER.warning @@ -220,7 +221,7 @@ def test_platform_error_slow_setup(hass, caplog): platform = MockPlatform(async_setup_platform=setup_platform) component = EntityComponent(_LOGGER, DOMAIN, hass) - loader.set_component(hass, 'test_domain.test_platform', platform) + mock_entity_platform(hass, 'test_domain.test_platform', platform) yield from component.async_setup({ DOMAIN: { 'platform': 'test_platform', @@ -255,7 +256,7 @@ async def test_parallel_updates_async_platform(hass): """Test async platform does not have parallel_updates limit by default.""" platform = MockPlatform() - loader.set_component(hass, 'test_domain.platform', platform) + mock_entity_platform(hass, 'test_domain.platform', platform) component = EntityComponent(_LOGGER, DOMAIN, hass) component._platforms = {} @@ -285,7 +286,7 @@ async def test_parallel_updates_async_platform_with_constant(hass): platform = MockPlatform() platform.PARALLEL_UPDATES = 2 - loader.set_component(hass, 'test_domain.platform', platform) + mock_entity_platform(hass, 'test_domain.platform', platform) component = EntityComponent(_LOGGER, DOMAIN, hass) component._platforms = {} @@ -316,7 +317,7 @@ async def test_parallel_updates_sync_platform(hass): """Test sync platform parallel_updates default set to 1.""" platform = MockPlatform() - loader.set_component(hass, 'test_domain.platform', platform) + mock_entity_platform(hass, 'test_domain.platform', platform) component = EntityComponent(_LOGGER, DOMAIN, hass) component._platforms = {} @@ -347,7 +348,7 @@ async def test_parallel_updates_sync_platform_with_constant(hass): platform = MockPlatform() platform.PARALLEL_UPDATES = 2 - loader.set_component(hass, 'test_domain.platform', platform) + mock_entity_platform(hass, 'test_domain.platform', platform) component = EntityComponent(_LOGGER, DOMAIN, hass) component._platforms = {} diff --git a/tests/helpers/test_translation.py b/tests/helpers/test_translation.py index 9d62f204dcd02286db394dd2bc4b7816dbf5c9ae..34d929b285af94de6934d17f4733e0e4ac279275 100644 --- a/tests/helpers/test_translation.py +++ b/tests/helpers/test_translation.py @@ -54,7 +54,7 @@ async def test_component_translation_file(hass): assert path.normpath(translation.component_translation_file( hass, 'switch.test', 'en')) == path.normpath(hass.config.path( - 'custom_components', 'switch', '.translations', 'test.en.json')) + 'custom_components', 'test', '.translations', 'switch.en.json')) assert path.normpath(translation.component_translation_file( hass, 'switch.test_embedded', 'en')) == path.normpath(hass.config.path( @@ -74,9 +74,9 @@ def test_load_translations_files(hass): """Test the load translation files function.""" # Test one valid and one invalid file file1 = hass.config.path( - 'custom_components', 'switch', '.translations', 'test.en.json') + 'custom_components', 'test', '.translations', 'switch.en.json') file2 = hass.config.path( - 'custom_components', 'switch', '.translations', 'invalid.json') + 'custom_components', 'test', '.translations', 'invalid.json') assert translation.load_translations_files({ 'switch.test': file1, 'invalid': file2 diff --git a/tests/test_config_entries.py b/tests/test_config_entries.py index fc8541a096a486dc5157c0c548723c6a338966b1..cd3f9fd1a895e6d9cd94c5c3ea5882ec2a39e220 100644 --- a/tests/test_config_entries.py +++ b/tests/test_config_entries.py @@ -13,15 +13,22 @@ from homeassistant.util import dt from tests.common import ( MockModule, mock_coro, MockConfigEntry, async_fire_time_changed, - MockPlatform, MockEntity) + MockPlatform, MockEntity, mock_integration, mock_entity_platform) -@config_entries.HANDLERS.register('test') -@config_entries.HANDLERS.register('comp') -class MockFlowHandler(config_entries.ConfigFlow): - """Define a mock flow handler.""" +@pytest.fixture(autouse=True) +def mock_handlers(): + """Mock config flows.""" + class MockFlowHandler(config_entries.ConfigFlow): + """Define a mock flow handler.""" - VERSION = 1 + VERSION = 1 + + with patch.dict(config_entries.HANDLERS, { + 'comp': MockFlowHandler, + 'test': MockFlowHandler, + }): + yield @pytest.fixture @@ -185,23 +192,27 @@ async def test_remove_entry(hass, manager): """Mock setting up platform.""" async_add_entities([entity]) - loader.set_component(hass, 'test', MockModule( + mock_integration(hass, MockModule( 'test', async_setup_entry=mock_setup_entry, async_unload_entry=mock_unload_entry, async_remove_entry=mock_remove_entry )) - loader.set_component( - hass, 'test.light', + mock_entity_platform( + hass, 'light.test', MockPlatform(async_setup_entry=mock_setup_entry_platform)) - MockConfigEntry(domain='test', entry_id='test1').add_to_manager(manager) + MockConfigEntry( + domain='test_other', entry_id='test1' + ).add_to_manager(manager) entry = MockConfigEntry( domain='test', entry_id='test2', ) entry.add_to_manager(manager) - MockConfigEntry(domain='test', entry_id='test3').add_to_manager(manager) + MockConfigEntry( + domain='test_other', entry_id='test3' + ).add_to_manager(manager) # Check all config entries exist assert [item.entry_id for item in manager.async_entries()] == \ diff --git a/tests/test_loader.py b/tests/test_loader.py index e3888412f0c649f6ac8839614d06e14e7d70f450..9598906a82ba178173f30b2c32ff0adcac255413 100644 --- a/tests/test_loader.py +++ b/tests/test_loader.py @@ -1,6 +1,4 @@ """Test to verify that we can load components.""" -import asyncio - import pytest import homeassistant.loader as loader @@ -63,20 +61,18 @@ def test_component_loader_non_existing(hass): components.non_existing -@asyncio.coroutine -def test_component_wrapper(hass): +async def test_component_wrapper(hass): """Test component wrapper.""" calls = async_mock_service(hass, 'persistent_notification', 'create') components = loader.Components(hass) components.persistent_notification.async_create('message') - yield from hass.async_block_till_done() + await hass.async_block_till_done() assert len(calls) == 1 -@asyncio.coroutine -def test_helpers_wrapper(hass): +async def test_helpers_wrapper(hass): """Test helpers wrapper.""" helpers = loader.Helpers(hass) @@ -88,8 +84,8 @@ def test_helpers_wrapper(hass): helpers.discovery.async_listen('service_name', discovery_callback) - yield from helpers.discovery.async_discover('service_name', 'hello') - yield from hass.async_block_till_done() + await helpers.discovery.async_discover('service_name', 'hello') + await hass.async_block_till_done() assert result == ['hello'] @@ -104,9 +100,9 @@ async def test_custom_component_name(hass): assert comp.__name__ == 'custom_components.test_package' assert comp.__package__ == 'custom_components.test_package' - comp = loader.get_component(hass, 'light.test') - assert comp.__name__ == 'custom_components.light.test' - assert comp.__package__ == 'custom_components.light' + comp = loader.get_component(hass, 'test.light') + assert comp.__name__ == 'custom_components.test.light' + assert comp.__package__ == 'custom_components.test' # Test custom components is mounted from custom_components.test_package import TEST @@ -119,8 +115,8 @@ async def test_log_warning_custom_component(hass, caplog): assert \ 'You are using a custom component for test_standalone' in caplog.text - loader.get_component(hass, 'light.test') - assert 'You are using a custom component for light.test' in caplog.text + loader.get_component(hass, 'test.light') + assert 'You are using a custom component for test.light' in caplog.text async def test_get_platform(hass, caplog): @@ -132,8 +128,8 @@ async def test_get_platform(hass, caplog): caplog.clear() - legacy_platform = loader.get_platform(hass, 'switch', 'test') - assert legacy_platform.__name__ == 'custom_components.switch.test' + legacy_platform = loader.get_platform(hass, 'switch', 'test_legacy') + assert legacy_platform.__name__ == 'custom_components.switch.test_legacy' assert 'Integrations need to be in their own folder.' in caplog.text diff --git a/tests/test_setup.py b/tests/test_setup.py index 00518776b52aa4b0c7fec196032f2adf92170ba6..32c431d1d6ac1de15888e5ede5dded5fef4c2b5f 100644 --- a/tests/test_setup.py +++ b/tests/test_setup.py @@ -20,7 +20,8 @@ from homeassistant.helpers import discovery from tests.common import \ get_test_home_assistant, MockModule, MockPlatform, \ - assert_setup_component, get_test_config_dir, mock_integration + assert_setup_component, get_test_config_dir, mock_integration, \ + mock_entity_platform ORIG_TIMEZONE = dt_util.DEFAULT_TIME_ZONE VERSION_PATH = os.path.join(get_test_config_dir(), config_util.VERSION_FILE) @@ -50,9 +51,9 @@ class TestSetup: 'hello': str } }, required=True) - loader.set_component( + mock_integration( self.hass, - 'comp_conf', MockModule('comp_conf', config_schema=config_schema)) + MockModule('comp_conf', config_schema=config_schema)) with assert_setup_component(0): assert not setup.setup_component(self.hass, 'comp_conf', {}) @@ -97,17 +98,15 @@ class TestSetup: }) platform_schema_base = PLATFORM_SCHEMA_BASE.extend({ }) - loader.set_component( + mock_integration( self.hass, - 'platform_conf', MockModule('platform_conf', - platform_schema_base=platform_schema_base)) - - loader.set_component( + platform_schema_base=platform_schema_base), + ) + mock_entity_platform( self.hass, 'platform_conf.whatever', - MockPlatform('whatever', - platform_schema=platform_schema)) + MockPlatform(platform_schema=platform_schema)) with assert_setup_component(1): assert setup.setup_component(self.hass, 'platform_conf', { @@ -195,14 +194,13 @@ class TestSetup: platform_schema_base = PLATFORM_SCHEMA_BASE.extend({ 'hello': 'world', }) - loader.set_component( + mock_integration( self.hass, - 'platform_conf', MockModule('platform_conf', platform_schema=platform_schema, platform_schema_base=platform_schema_base)) - loader.set_component( + mock_entity_platform( self.hass, 'platform_conf.whatever', MockPlatform('whatever', @@ -249,13 +247,12 @@ class TestSetup: 'cheers': str, 'hello': 'world', }) - loader.set_component( + mock_integration( self.hass, - 'platform_conf', MockModule('platform_conf', platform_schema=component_schema)) - loader.set_component( + mock_entity_platform( self.hass, 'platform_conf.whatever', MockPlatform('whatever', @@ -296,17 +293,15 @@ class TestSetup: """Test entity_namespace in PLATFORM_SCHEMA.""" component_schema = PLATFORM_SCHEMA_BASE platform_schema = PLATFORM_SCHEMA - loader.set_component( + mock_integration( self.hass, - 'platform_conf', MockModule('platform_conf', platform_schema_base=component_schema)) - loader.set_component( + mock_entity_platform( self.hass, 'platform_conf.whatever', - MockPlatform('whatever', - platform_schema=platform_schema)) + MockPlatform(platform_schema=platform_schema)) with assert_setup_component(1): assert setup.setup_component(self.hass, 'platform_conf', { @@ -322,14 +317,15 @@ class TestSetup: def test_component_not_found(self): """setup_component should not crash if component doesn't exist.""" - assert not setup.setup_component(self.hass, 'non_existing') + assert setup.setup_component(self.hass, 'non_existing') is False def test_component_not_double_initialized(self): """Test we do not set up a component twice.""" mock_setup = mock.MagicMock(return_value=True) - loader.set_component( - self.hass, 'comp', MockModule('comp', setup=mock_setup)) + mock_integration( + self.hass, + MockModule('comp', setup=mock_setup)) assert setup.setup_component(self.hass, 'comp') assert mock_setup.called @@ -344,9 +340,9 @@ class TestSetup: def test_component_not_installed_if_requirement_fails(self, mock_install): """Component setup should fail if requirement can't install.""" self.hass.config.skip_pip = False - loader.set_component( + mock_integration( self.hass, - 'comp', MockModule('comp', requirements=['package==0.0.1'])) + MockModule('comp', requirements=['package==0.0.1'])) assert not setup.setup_component(self.hass, 'comp') assert 'comp' not in self.hass.config.components @@ -360,9 +356,9 @@ class TestSetup: """Tracking Setup.""" result.append(1) - loader.set_component( + mock_integration( self.hass, - 'comp', MockModule('comp', async_setup=async_setup)) + MockModule('comp', async_setup=async_setup)) def setup_component(): """Set up the component.""" @@ -393,8 +389,8 @@ class TestSetup: def test_component_failing_setup(self): """Test component that fails setup.""" - loader.set_component( - self.hass, 'comp', + mock_integration( + self.hass, MockModule('comp', setup=lambda hass, config: False)) assert not setup.setup_component(self.hass, 'comp', {}) @@ -406,8 +402,8 @@ class TestSetup: """Raise exception.""" raise Exception('fail!') - loader.set_component( - self.hass, 'comp', MockModule('comp', setup=exception_setup)) + mock_integration(self.hass, + MockModule('comp', setup=exception_setup)) assert not setup.setup_component(self.hass, 'comp', {}) assert 'comp' not in self.hass.config.components @@ -420,12 +416,18 @@ class TestSetup: return True raise Exception('Config not passed in: {}'.format(config)) - loader.set_component( - self.hass, 'comp_a', - MockModule('comp_a', setup=config_check_setup)) + platform = MockPlatform() - loader.set_component( - self.hass, 'switch.platform_a', MockPlatform('comp_b', ['comp_a'])) + mock_integration(self.hass, + MockModule('comp_a', setup=config_check_setup)) + mock_integration( + self.hass, + MockModule('platform_a', + setup=config_check_setup, + dependencies=['comp_a']), + ) + + mock_entity_platform(self.hass, 'switch.platform_a', platform) setup.setup_component(self.hass, 'switch', { 'comp_a': { @@ -445,7 +447,7 @@ class TestSetup: mock_setup = mock.MagicMock(spec_set=True) - loader.set_component( + mock_entity_platform( self.hass, 'switch.platform_a', MockPlatform(platform_schema=platform_schema, @@ -476,7 +478,7 @@ class TestSetup: self.hass.data.pop(setup.DATA_SETUP) self.hass.config.components.remove('switch') - with assert_setup_component(1): + with assert_setup_component(1, 'switch'): assert setup.setup_component(self.hass, 'switch', { 'switch': { 'platform': 'platform_a', @@ -487,9 +489,8 @@ class TestSetup: def test_disable_component_if_invalid_return(self): """Test disabling component if invalid return.""" - loader.set_component( + mock_integration( self.hass, - 'disabled_component', MockModule('disabled_component', setup=lambda hass, config: None)) assert not setup.setup_component(self.hass, 'disabled_component') @@ -497,9 +498,8 @@ class TestSetup: assert 'disabled_component' not in self.hass.config.components self.hass.data.pop(setup.DATA_SETUP) - loader.set_component( + mock_integration( self.hass, - 'disabled_component', MockModule('disabled_component', setup=lambda hass, config: False)) assert not setup.setup_component(self.hass, 'disabled_component') @@ -508,9 +508,8 @@ class TestSetup: assert 'disabled_component' not in self.hass.config.components self.hass.data.pop(setup.DATA_SETUP) - loader.set_component( + mock_integration( self.hass, - 'disabled_component', MockModule('disabled_component', setup=lambda hass, config: True)) assert setup.setup_component(self.hass, 'disabled_component') @@ -535,19 +534,16 @@ class TestSetup: call_order.append(1) return True - loader.set_component( + mock_integration( self.hass, - 'test_component1', MockModule('test_component1', setup=component1_setup)) - loader.set_component( + mock_integration( self.hass, - 'test_component2', MockModule('test_component2', setup=component_track_setup)) - loader.set_component( + mock_integration( self.hass, - 'test_component3', MockModule('test_component3', setup=component_track_setup)) @callback @@ -575,8 +571,7 @@ def test_component_cannot_depend_config(hass): @asyncio.coroutine def test_component_warn_slow_setup(hass): """Warn we log when a component setup takes a long time.""" - loader.set_component( - hass, 'test_component1', MockModule('test_component1')) + mock_integration(hass, MockModule('test_component1')) with mock.patch.object(hass.loop, 'call_later', mock.MagicMock()) \ as mock_call: result = yield from setup.async_setup_component( @@ -596,8 +591,8 @@ def test_component_warn_slow_setup(hass): @asyncio.coroutine def test_platform_no_warn_slow(hass): """Do not warn for long entity setup time.""" - loader.set_component( - hass, 'test_component1', + mock_integration( + hass, MockModule('test_component1', platform_schema=PLATFORM_SCHEMA)) with mock.patch.object(hass.loop, 'call_later', mock.MagicMock()) \ as mock_call: diff --git a/tests/testing_config/__init__.py b/tests/testing_config/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..98d2bc1bc8d3e4464af2daf65ea68f882419dedc --- /dev/null +++ b/tests/testing_config/__init__.py @@ -0,0 +1 @@ +"""Configuration that's used when running tests.""" diff --git a/tests/testing_config/custom_components/__init__.py b/tests/testing_config/custom_components/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..f84ba5808ae6d2248f1b92290343f8c35c741bd6 --- /dev/null +++ b/tests/testing_config/custom_components/__init__.py @@ -0,0 +1 @@ +"""A collection of custom integrations used when running tests.""" diff --git a/tests/testing_config/custom_components/switch/test_embedded.py b/tests/testing_config/custom_components/switch/test_legacy.py similarity index 100% rename from tests/testing_config/custom_components/switch/test_embedded.py rename to tests/testing_config/custom_components/switch/test_legacy.py diff --git a/tests/testing_config/custom_components/switch/.translations/test.de.json b/tests/testing_config/custom_components/test/.translations/switch.de.json similarity index 100% rename from tests/testing_config/custom_components/switch/.translations/test.de.json rename to tests/testing_config/custom_components/test/.translations/switch.de.json diff --git a/tests/testing_config/custom_components/switch/.translations/test.en.json b/tests/testing_config/custom_components/test/.translations/switch.en.json similarity index 100% rename from tests/testing_config/custom_components/switch/.translations/test.en.json rename to tests/testing_config/custom_components/test/.translations/switch.en.json diff --git a/tests/testing_config/custom_components/switch/.translations/test.es.json b/tests/testing_config/custom_components/test/.translations/switch.es.json similarity index 100% rename from tests/testing_config/custom_components/switch/.translations/test.es.json rename to tests/testing_config/custom_components/test/.translations/switch.es.json diff --git a/tests/testing_config/custom_components/test/__init__.py b/tests/testing_config/custom_components/test/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..206c97f847b16a15341d22876135ecc02f06de70 --- /dev/null +++ b/tests/testing_config/custom_components/test/__init__.py @@ -0,0 +1 @@ +"""An integration with several platforms used with unit tests.""" diff --git a/tests/testing_config/custom_components/device_tracker/test.py b/tests/testing_config/custom_components/test/device_tracker.py similarity index 100% rename from tests/testing_config/custom_components/device_tracker/test.py rename to tests/testing_config/custom_components/test/device_tracker.py diff --git a/tests/testing_config/custom_components/image_processing/test.py b/tests/testing_config/custom_components/test/image_processing.py similarity index 100% rename from tests/testing_config/custom_components/image_processing/test.py rename to tests/testing_config/custom_components/test/image_processing.py diff --git a/tests/testing_config/custom_components/light/test.py b/tests/testing_config/custom_components/test/light.py similarity index 100% rename from tests/testing_config/custom_components/light/test.py rename to tests/testing_config/custom_components/test/light.py diff --git a/tests/testing_config/custom_components/test/manifest.json b/tests/testing_config/custom_components/test/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..70882fece0582faf1dc6e05f6223a71466772e32 --- /dev/null +++ b/tests/testing_config/custom_components/test/manifest.json @@ -0,0 +1,8 @@ +{ + "domain": "test", + "name": "Test Components", + "documentation": "http://example.com", + "requirements": [], + "dependencies": [], + "codeowners": [] +} diff --git a/tests/testing_config/custom_components/switch/test.py b/tests/testing_config/custom_components/test/switch.py similarity index 100% rename from tests/testing_config/custom_components/switch/test.py rename to tests/testing_config/custom_components/test/switch.py