Beispiel #1
0
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)
Beispiel #3
0
    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}")
Beispiel #4
0
    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
                )
Beispiel #5
0
    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()