async def test_async_start_setup(hass): """Test setup started context manager keeps track of setup times.""" with setup.async_start_setup(hass, ["august"]): assert isinstance(hass.data[setup.DATA_SETUP_STARTED]["august"], datetime.datetime) with setup.async_start_setup(hass, ["august"]): assert isinstance(hass.data[setup.DATA_SETUP_STARTED]["august_2"], datetime.datetime) assert "august" not in hass.data[setup.DATA_SETUP_STARTED] assert isinstance(hass.data[setup.DATA_SETUP_TIME]["august"], datetime.timedelta) assert "august_2" not in hass.data[setup.DATA_SETUP_TIME]
async def start_server(*_: Any) -> None: """Start the server.""" with async_start_setup(hass, ["http"]): hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, stop_server) # We already checked it's not None. assert conf is not None await start_http_server_and_save_config(hass, dict(conf), server)
async def async_setup_platform( integration_name: str, p_config: ConfigType | None = None, discovery_info: DiscoveryInfoType | None = None, ) -> None: """Set up a notify platform.""" if p_config is None: p_config = {} platform = await async_prepare_setup_platform(hass, config, DOMAIN, integration_name) if platform is None: LOGGER.error("Unknown notification service specified") return full_name = f"{DOMAIN}.{integration_name}" LOGGER.info("Setting up %s", full_name) with async_start_setup(hass, [full_name]): notify_service = None try: if hasattr(platform, "async_get_service"): notify_service = await platform.async_get_service( hass, p_config, discovery_info) elif hasattr(platform, "get_service"): notify_service = await hass.async_add_executor_job( platform.get_service, hass, p_config, discovery_info) else: raise HomeAssistantError("Invalid notify platform.") if notify_service is None: # Platforms can decide not to create a service based # on discovery data. if discovery_info is None: LOGGER.error( "Failed to initialize notification service %s", integration_name, ) return except Exception: # pylint: disable=broad-except LOGGER.exception("Error setting up platform %s", integration_name) return if discovery_info is None: discovery_info = {} conf_name = p_config.get(CONF_NAME) or discovery_info.get( CONF_NAME) target_service_name_prefix = conf_name or integration_name service_name = slugify(conf_name or SERVICE_NOTIFY) await notify_service.async_setup(hass, service_name, target_service_name_prefix) await notify_service.async_register_services() hass.data[NOTIFY_SERVICES].setdefault(integration_name, []).append(notify_service) hass.config.components.add(f"{DOMAIN}.{integration_name}")
async def async_setup_legacy( self, hass: HomeAssistant, tracker: DeviceTracker, discovery_info: dict[str, Any] | None = None, ) -> None: """Set up a legacy platform.""" assert self.type == PLATFORM_TYPE_LEGACY full_name = f"{DOMAIN}.{self.name}" LOGGER.info("Setting up %s", full_name) with async_start_setup(hass, [full_name]): try: scanner = None setup = None if hasattr(self.platform, "async_get_scanner"): scanner = await self.platform.async_get_scanner( hass, {DOMAIN: self.config} ) elif hasattr(self.platform, "get_scanner"): scanner = await hass.async_add_executor_job( self.platform.get_scanner, hass, {DOMAIN: self.config}, ) elif hasattr(self.platform, "async_setup_scanner"): setup = await self.platform.async_setup_scanner( hass, self.config, tracker.async_see, discovery_info ) elif hasattr(self.platform, "setup_scanner"): setup = await hass.async_add_executor_job( self.platform.setup_scanner, hass, self.config, tracker.see, discovery_info, ) else: raise HomeAssistantError("Invalid legacy device_tracker platform.") if scanner is not None: async_setup_scanner_platform( hass, self.config, scanner, tracker.async_see, self.type ) if setup is None and scanner is None: LOGGER.error( "Error setting up platform %s %s", self.type, self.name ) return hass.config.components.add(full_name) except Exception: # pylint: disable=broad-except LOGGER.exception( "Error setting up platform %s %s", self.type, self.name )
async def _async_setup_platform(self, async_create_setup_task: Callable[ [], Coroutine], tries: int = 0) -> bool: """Set up a platform via config file or config entry. async_create_setup_task creates a coroutine that sets up platform. """ current_platform.set(self) logger = self.logger hass = self.hass full_name = f"{self.domain}.{self.platform_name}" logger.info("Setting up %s", full_name) warn_task = hass.loop.call_later( SLOW_SETUP_WARNING, logger.warning, "Setup of %s platform %s is taking over %s seconds.", self.domain, self.platform_name, SLOW_SETUP_WARNING, ) with async_start_setup(hass, [full_name]): try: task = async_create_setup_task() async with hass.timeout.async_timeout(SLOW_SETUP_MAX_WAIT, self.domain): await asyncio.shield(task) # Block till all entities are done while self._tasks: pending = [task for task in self._tasks if not task.done()] self._tasks.clear() if pending: await asyncio.gather(*pending) hass.config.components.add(full_name) self._setup_complete = True return True except PlatformNotReady as ex: tries += 1 wait_time = min(tries, 6) * PLATFORM_NOT_READY_BASE_WAIT_TIME message = str(ex) ready_message = f"ready yet: {message}" if message else "ready yet" if tries == 1: logger.warning( "Platform %s not %s; Retrying in background in %d seconds", self.platform_name, ready_message, wait_time, ) else: logger.debug( "Platform %s not %s; Retrying in %d seconds", self.platform_name, ready_message, wait_time, ) async def setup_again(*_args: Any) -> None: """Run setup again.""" self._async_cancel_retry_setup = None await self._async_setup_platform(async_create_setup_task, tries) if hass.state == CoreState.running: self._async_cancel_retry_setup = async_call_later( hass, wait_time, setup_again) else: self._async_cancel_retry_setup = hass.bus.async_listen_once( EVENT_HOMEASSISTANT_STARTED, setup_again) return False except asyncio.TimeoutError: logger.error( "Setup of platform %s is taking longer than %s seconds." " Startup will proceed without waiting any longer.", self.platform_name, SLOW_SETUP_MAX_WAIT, ) return False except Exception: # pylint: disable=broad-except logger.exception( "Error while setting up %s platform for %s", self.platform_name, self.domain, ) return False finally: warn_task.cancel()