def _async_process_requirements(hass: core.HomeAssistant, name: str, requirements) -> bool: """Install the requirements for a component. This method is a coroutine. """ if hass.config.skip_pip: return True pip_lock = hass.data.get(DATA_PIP_LOCK) if pip_lock is None: pip_lock = hass.data[DATA_PIP_LOCK] = asyncio.Lock(loop=hass.loop) def pip_install(mod): """Install packages.""" return pkg_util.install_package( mod, target=hass.config.path('deps'), constraints=os.path.join(os.path.dirname(__file__), CONSTRAINT_FILE)) with (yield from pip_lock): for req in requirements: ret = yield from hass.loop.run_in_executor(None, pip_install, req) if not ret: _LOGGER.error('Not initializing %s because could not install ' 'dependency %s', name, req) async_notify_setup_error(hass, name) return False return True
def log_error(msg, link=True): """Log helper.""" _LOGGER.error("Setup failed for %s: %s", domain, msg) async_notify_setup_error(hass, domain, link)
def _async_setup_component(hass: core.HomeAssistant, domain: str, config) -> bool: """Set up a component for Home Assistant. This method is a coroutine. """ def log_error(msg, link=True): """Log helper.""" _LOGGER.error("Setup failed for %s: %s", domain, msg) async_notify_setup_error(hass, domain, link) component = loader.get_component(domain) if not component: log_error("Component not found.", False) return False # Validate no circular dependencies components = loader.load_order_component(domain) # OrderedSet is empty if component or dependencies could not be resolved if not components: log_error("Unable to resolve component or dependencies.") return False processed_config = \ conf_util.async_process_component_config(hass, config, domain) if processed_config is None: log_error("Invalid config.") return False try: yield from async_process_deps_reqs(hass, config, domain, component) except HomeAssistantError as err: log_error(str(err)) return False start = timer() _LOGGER.info("Setting up %s", domain) if hasattr(component, 'PLATFORM_SCHEMA'): # Entity components have their own warning warn_task = None else: warn_task = hass.loop.call_later( SLOW_SETUP_WARNING, _LOGGER.warning, "Setup of %s is taking over %s seconds.", domain, SLOW_SETUP_WARNING) try: if hasattr(component, 'async_setup'): result = yield from component.async_setup(hass, processed_config) else: result = yield from hass.async_add_job( component.setup, hass, processed_config) except Exception: # pylint: disable=broad-except _LOGGER.exception("Error during setup of component %s", domain) async_notify_setup_error(hass, domain, True) return False finally: end = timer() if warn_task: warn_task.cancel() _LOGGER.info("Setup of domain %s took %.1f seconds.", domain, end - start) if result is False: log_error("Component failed to initialize.") return False elif result is not True: log_error("Component did not return boolean if setup was successful. " "Disabling component.") loader.set_component(domain, None) return False for entry in hass.config_entries.async_entries(domain): yield from entry.async_setup(hass, component=component) hass.config.components.add(component.DOMAIN) # Cleanup if domain in hass.data[DATA_SETUP]: hass.data[DATA_SETUP].pop(domain) hass.bus.async_fire( EVENT_COMPONENT_LOADED, {ATTR_COMPONENT: component.DOMAIN} ) return True
def log_error(msg): """Log helper.""" _LOGGER.error("Unable to prepare setup for platform %s: %s", platform_path, msg) async_notify_setup_error(hass, platform_path)
def log_error(msg, link=True): """Log helper.""" _LOGGER.error("Setup failed for %s: %s", domain, msg) async_notify_setup_error(hass, domain, link)
def _async_setup_component(hass: core.HomeAssistant, domain: str, config) -> bool: """Set up a component for Home Assistant. This method is a coroutine. """ def log_error(msg, link=True): """Log helper.""" _LOGGER.error("Setup failed for %s: %s", domain, msg) async_notify_setup_error(hass, domain, link) component = loader.get_component(domain) if not component: log_error("Component not found.", False) return False # Validate no circular dependencies components = loader.load_order_component(domain) # OrderedSet is empty if component or dependencies could not be resolved if not components: log_error("Unable to resolve component or dependencies.") return False processed_config = \ conf_util.async_process_component_config(hass, config, domain) if processed_config is None: log_error("Invalid config.") return False if not hass.config.skip_pip and hasattr(component, 'REQUIREMENTS'): req_success = yield from _async_process_requirements( hass, domain, component.REQUIREMENTS) if not req_success: log_error("Could not install all requirements.") return False if hasattr(component, 'DEPENDENCIES'): dep_success = yield from _async_process_dependencies( hass, config, domain, component.DEPENDENCIES) if not dep_success: log_error("Could not setup all dependencies.") return False async_comp = hasattr(component, 'async_setup') start = timer() _LOGGER.info("Setting up %s", domain) warn_task = hass.loop.call_later(SLOW_SETUP_WARNING, _LOGGER.warning, "Setup of %s is taking over %s seconds.", domain, SLOW_SETUP_WARNING) try: if async_comp: result = yield from component.async_setup(hass, processed_config) else: result = yield from hass.async_add_job(component.setup, hass, processed_config) except Exception: # pylint: disable=broad-except _LOGGER.exception("Error during setup of component %s", domain) async_notify_setup_error(hass, domain, True) return False finally: end = timer() warn_task.cancel() _LOGGER.info("Setup of domain %s took %.1f seconds.", domain, end - start) if result is False: log_error("Component failed to initialize.") return False elif result is not True: log_error("Component did not return boolean if setup was successful. " "Disabling component.") loader.set_component(domain, None) return False hass.config.components.add(component.DOMAIN) # Cleanup if domain in hass.data[DATA_SETUP]: hass.data[DATA_SETUP].pop(domain) hass.bus.async_fire(EVENT_COMPONENT_LOADED, {ATTR_COMPONENT: component.DOMAIN}) return True
def log_error(msg: str, link: bool = True) -> None: """Log helper.""" _LOGGER.error("Setup failed for %s: %s", domain, msg) async_notify_setup_error(hass, domain, link)
async def _async_setup_component(hass: core.HomeAssistant, domain: str, config: Dict) -> bool: """Set up a component for Home Assistant. This method is a coroutine. """ def log_error(msg: str, link: bool = True) -> None: """Log helper.""" _LOGGER.error("Setup failed for %s: %s", domain, msg) async_notify_setup_error(hass, domain, link) component = loader.get_component(hass, domain) if not component: log_error("Component not found.", False) return False # Validate no circular dependencies components = loader.load_order_component(hass, domain) # OrderedSet is empty if component or dependencies could not be resolved if not components: log_error("Unable to resolve component or dependencies.") return False processed_config = \ conf_util.async_process_component_config(hass, config, domain) if processed_config is None: log_error("Invalid config.") return False try: await async_process_deps_reqs(hass, config, domain, component) except HomeAssistantError as err: log_error(str(err)) return False start = timer() _LOGGER.info("Setting up %s", domain) if hasattr(component, 'PLATFORM_SCHEMA'): # Entity components have their own warning warn_task = None else: warn_task = hass.loop.call_later( SLOW_SETUP_WARNING, _LOGGER.warning, "Setup of %s is taking over %s seconds.", domain, SLOW_SETUP_WARNING) try: if hasattr(component, 'async_setup'): result = await component.async_setup( # type: ignore hass, processed_config) else: result = await hass.async_add_executor_job(component.setup, hass, processed_config ) # type: ignore except Exception: # pylint: disable=broad-except _LOGGER.exception("Error during setup of component %s", domain) async_notify_setup_error(hass, domain, True) return False finally: end = timer() if warn_task: warn_task.cancel() _LOGGER.info("Setup of domain %s took %.1f seconds.", domain, end - start) if result is False: log_error("Component failed to initialize.") return False if result is not True: log_error("Component {!r} did not return boolean if setup was " "successful. Disabling component.".format(domain)) loader.set_component(hass, domain, None) return False if hass.config_entries: for entry in hass.config_entries.async_entries(domain): await entry.async_setup(hass, component=component) hass.config.components.add(component.DOMAIN) # type: ignore # Cleanup if domain in hass.data[DATA_SETUP]: hass.data[DATA_SETUP].pop(domain) hass.bus.async_fire( EVENT_COMPONENT_LOADED, {ATTR_COMPONENT: component.DOMAIN} # type: ignore ) return True
def log_error(msg: str) -> None: """Log helper.""" _LOGGER.error("Unable to prepare setup for platform %s: %s", platform_path, msg) async_notify_setup_error(hass, platform_path)
async def _async_setup_component(hass: core.HomeAssistant, domain: str, config: Dict) -> bool: """Set up a component for Home Assistant. This method is a coroutine. """ def log_error(msg: str, link: bool = True) -> None: """Log helper.""" _LOGGER.error("Setup failed for %s: %s", domain, msg) async_notify_setup_error(hass, domain, link) try: integration = await loader.async_get_integration(hass, domain) except loader.IntegrationNotFound: log_error("Integration not found.", False) return False # Validate all dependencies exist and there are no circular dependencies try: await loader.async_component_dependencies(hass, domain) except loader.IntegrationNotFound as err: _LOGGER.error( "Not setting up %s because we are unable to resolve " "(sub)dependency %s", domain, err.domain) return False except loader.CircularDependency as err: _LOGGER.error( "Not setting up %s because it contains a circular dependency: " "%s -> %s", domain, err.from_domain, err.to_domain) return False # Process requirements as soon as possible, so we can import the component # without requiring imports to be in functions. try: await async_process_deps_reqs(hass, config, integration) except HomeAssistantError as err: log_error(str(err)) return False processed_config = await conf_util.async_process_component_config( hass, config, integration) if processed_config is None: log_error("Invalid config.") return False start = timer() _LOGGER.info("Setting up %s", domain) try: component = integration.get_component() except ImportError: log_error("Unable to import component", False) return False if hasattr(component, 'PLATFORM_SCHEMA'): # Entity components have their own warning warn_task = None else: warn_task = hass.loop.call_later( SLOW_SETUP_WARNING, _LOGGER.warning, "Setup of %s is taking over %s seconds.", domain, SLOW_SETUP_WARNING) try: if hasattr(component, 'async_setup'): result = await component.async_setup( # type: ignore hass, processed_config) elif hasattr(component, 'setup'): result = await hass.async_add_executor_job( component.setup, hass, processed_config) # type: ignore else: log_error("No setup function defined.") return False except Exception: # pylint: disable=broad-except _LOGGER.exception("Error during setup of component %s", domain) async_notify_setup_error(hass, domain, True) return False finally: end = timer() if warn_task: warn_task.cancel() _LOGGER.info("Setup of domain %s took %.1f seconds.", domain, end - start) if result is False: log_error("Integration failed to initialize.") return False if result is not True: log_error("Integration {!r} did not return boolean if setup was " "successful. Disabling component.".format(domain)) return False if hass.config_entries: for entry in hass.config_entries.async_entries(domain): await entry.async_setup(hass, integration=integration) hass.config.components.add(domain) # Cleanup if domain in hass.data[DATA_SETUP]: hass.data[DATA_SETUP].pop(domain) hass.bus.async_fire( EVENT_COMPONENT_LOADED, {ATTR_COMPONENT: domain} ) return True
async def _async_setup_component( hass: core.HomeAssistant, domain: str, config: ConfigType ) -> bool: """Set up a component for Home Assistant. This method is a coroutine. """ def log_error(msg: str, link: str | None = None) -> None: """Log helper.""" _LOGGER.error("Setup failed for %s: %s", domain, msg) async_notify_setup_error(hass, domain, link) try: integration = await loader.async_get_integration(hass, domain) except loader.IntegrationNotFound: log_error("Integration not found.") return False if integration.disabled: log_error(f"Dependency is disabled - {integration.disabled}") return False # Validate all dependencies exist and there are no circular dependencies if not await integration.resolve_dependencies(): return False # Process requirements as soon as possible, so we can import the component # without requiring imports to be in functions. try: await async_process_deps_reqs(hass, config, integration) except HomeAssistantError as err: log_error(str(err), integration.documentation) return False # Some integrations fail on import because they call functions incorrectly. # So we do it before validating config to catch these errors. try: component = integration.get_component() except ImportError as err: log_error(f"Unable to import component: {err}", integration.documentation) return False except Exception: # pylint: disable=broad-except _LOGGER.exception("Setup failed for %s: unknown error", domain) return False processed_config = await conf_util.async_process_component_config( hass, config, integration ) if processed_config is None: log_error("Invalid config.", integration.documentation) return False start = timer() _LOGGER.info("Setting up %s", domain) with async_start_setup(hass, [domain]): if hasattr(component, "PLATFORM_SCHEMA"): # Entity components have their own warning warn_task = None else: warn_task = hass.loop.call_later( SLOW_SETUP_WARNING, _LOGGER.warning, "Setup of %s is taking over %s seconds.", domain, SLOW_SETUP_WARNING, ) task = None result = True try: if hasattr(component, "async_setup"): task = component.async_setup(hass, processed_config) # type: ignore elif hasattr(component, "setup"): # This should not be replaced with hass.async_add_executor_job because # we don't want to track this task in case it blocks startup. task = hass.loop.run_in_executor( None, component.setup, hass, processed_config # type: ignore ) elif not hasattr(component, "async_setup_entry"): log_error("No setup or config entry setup function defined.") return False if task: async with hass.timeout.async_timeout(SLOW_SETUP_MAX_WAIT, domain): result = await task except asyncio.TimeoutError: _LOGGER.error( "Setup of %s is taking longer than %s seconds." " Startup will proceed without waiting any longer", domain, SLOW_SETUP_MAX_WAIT, ) return False except Exception: # pylint: disable=broad-except _LOGGER.exception("Error during setup of component %s", domain) async_notify_setup_error(hass, domain, integration.documentation) return False finally: end = timer() if warn_task: warn_task.cancel() _LOGGER.info("Setup of domain %s took %.1f seconds", domain, end - start) if result is False: log_error("Integration failed to initialize.") return False if result is not True: log_error( f"Integration {domain!r} did not return boolean if setup was " "successful. Disabling component." ) return False # Flush out async_setup calling create_task. Fragile but covered by test. await asyncio.sleep(0) await hass.config_entries.flow.async_wait_init_flow_finish(domain) await asyncio.gather( *( entry.async_setup(hass, integration=integration) for entry in hass.config_entries.async_entries(domain) ) ) hass.config.components.add(domain) # Cleanup if domain in hass.data[DATA_SETUP]: hass.data[DATA_SETUP].pop(domain) hass.bus.async_fire(EVENT_COMPONENT_LOADED, {ATTR_COMPONENT: domain}) return True
def log_error(msg): """Log helper.""" _LOGGER.error('Unable to prepare setup for platform %s: %s', platform_path, msg) async_notify_setup_error(hass, platform_path)
def _async_setup_component(hass: core.HomeAssistant, domain: str, config) -> bool: """Setup a component for Home Assistant. This method is a coroutine. hass: Home Assistant instance. domain: Domain of component to setup. config: The Home Assistant configuration. """ def log_error(msg, link=True): """Log helper.""" _LOGGER.error('Setup failed for %s: %s', domain, msg) async_notify_setup_error(hass, domain, link) component = loader.get_component(domain) if not component: log_error('Component not found.', False) return False # Validate no circular dependencies components = loader.load_order_component(domain) # OrderedSet is empty if component or dependencies could not be resolved if not components: log_error('Unable to resolve component or dependencies.') return False processed_config = \ conf_util.async_process_component_config(hass, config, domain) if processed_config is None: log_error('Invalid config.') return False if not hass.config.skip_pip and hasattr(component, 'REQUIREMENTS'): req_success = yield from _async_process_requirements( hass, domain, component.REQUIREMENTS) if not req_success: log_error('Could not install all requirements.') return False if hasattr(component, 'DEPENDENCIES'): dep_success = yield from _async_process_dependencies( hass, config, domain, component.DEPENDENCIES) if not dep_success: log_error('Could not setup all dependencies.') return False async_comp = hasattr(component, 'async_setup') _LOGGER.info("Setting up %s", domain) warn_task = hass.loop.call_later( SLOW_SETUP_WARNING, _LOGGER.warning, 'Setup of %s is taking over %s seconds.', domain, SLOW_SETUP_WARNING) try: if async_comp: result = yield from component.async_setup(hass, processed_config) else: result = yield from hass.loop.run_in_executor( None, component.setup, hass, processed_config) except Exception: # pylint: disable=broad-except _LOGGER.exception('Error during setup of component %s', domain) async_notify_setup_error(hass, domain, True) return False finally: warn_task.cancel() if result is False: log_error('Component failed to initialize.') return False elif result is not True: log_error('Component did not return boolean if setup was successful. ' 'Disabling component.') loader.set_component(domain, None) return False hass.config.components.add(component.DOMAIN) # cleanup if domain in hass.data[DATA_SETUP]: hass.data[DATA_SETUP].pop(domain) hass.bus.async_fire( EVENT_COMPONENT_LOADED, {ATTR_COMPONENT: component.DOMAIN} ) return True
def log_error(msg: str, link: bool = True) -> None: """Log helper.""" _LOGGER.error("Setup failed for %s: %s", domain, msg) async_notify_setup_error(hass, domain, link)
async def _async_setup_component(hass: core.HomeAssistant, domain: str, config: Dict) -> bool: """Set up a component for Home Assistant. This method is a coroutine. """ def log_error(msg: str, link: bool = True) -> None: """Log helper.""" _LOGGER.error("Setup failed for %s: %s", domain, msg) async_notify_setup_error(hass, domain, link) component = loader.get_component(hass, domain) if not component: log_error("Component not found.", False) return False # Validate all dependencies exist and there are no circular dependencies try: loader.component_dependencies(hass, domain) except loader.ComponentNotFound as err: _LOGGER.error( "Not setting up %s because we are unable to resolve " "(sub)dependency %s", domain, err.domain) return False except loader.CircularDependency as err: _LOGGER.error( "Not setting up %s because it contains a circular dependency: " "%s -> %s", domain, err.from_domain, err.to_domain) return False processed_config = \ conf_util.async_process_component_config(hass, config, domain) if processed_config is None: log_error("Invalid config.") return False try: await async_process_deps_reqs(hass, config, domain, component) except HomeAssistantError as err: log_error(str(err)) return False start = timer() _LOGGER.info("Setting up %s", domain) if hasattr(component, 'PLATFORM_SCHEMA'): # Entity components have their own warning warn_task = None else: warn_task = hass.loop.call_later( SLOW_SETUP_WARNING, _LOGGER.warning, "Setup of %s is taking over %s seconds.", domain, SLOW_SETUP_WARNING) try: if hasattr(component, 'async_setup'): result = await component.async_setup( # type: ignore hass, processed_config) else: result = await hass.async_add_executor_job( component.setup, hass, processed_config) # type: ignore except Exception: # pylint: disable=broad-except _LOGGER.exception("Error during setup of component %s", domain) async_notify_setup_error(hass, domain, True) return False finally: end = timer() if warn_task: warn_task.cancel() _LOGGER.info("Setup of domain %s took %.1f seconds.", domain, end - start) if result is False: log_error("Component failed to initialize.") return False if result is not True: log_error("Component {!r} did not return boolean if setup was " "successful. Disabling component.".format(domain)) loader.set_component(hass, domain, None) return False if hass.config_entries: for entry in hass.config_entries.async_entries(domain): await entry.async_setup(hass, component=component) hass.config.components.add(component.DOMAIN) # type: ignore # Cleanup if domain in hass.data[DATA_SETUP]: hass.data[DATA_SETUP].pop(domain) hass.bus.async_fire( EVENT_COMPONENT_LOADED, {ATTR_COMPONENT: component.DOMAIN} # type: ignore ) return True