Пример #1
0
    async def _async_handle_step(
        self,
        flow: Any,
        step_id: str,
        user_input: dict | None,
        step_done: asyncio.Future | None = None,
    ) -> FlowResult:
        """Handle a step of a flow."""
        method = f"async_step_{step_id}"

        if not hasattr(flow, method):
            self._async_remove_flow_progress(flow.flow_id)
            if step_done:
                step_done.set_result(None)
            raise UnknownStep(
                f"Handler {flow.__class__.__name__} doesn't support step {step_id}"
            )

        try:
            result: FlowResult = await getattr(flow, method)(user_input)
        except AbortFlow as err:
            result = _create_abort_data(flow.flow_id, flow.handler, err.reason,
                                        err.description_placeholders)

        # Mark the step as done.
        # We do this before calling async_finish_flow because config entries will hit a
        # circular dependency where async_finish_flow sets up new entry, which needs the
        # integration to be set up, which is waiting for init to be done.
        if step_done:
            step_done.set_result(None)

        if result["type"] not in (
                RESULT_TYPE_FORM,
                RESULT_TYPE_EXTERNAL_STEP,
                RESULT_TYPE_CREATE_ENTRY,
                RESULT_TYPE_ABORT,
                RESULT_TYPE_EXTERNAL_STEP_DONE,
                RESULT_TYPE_SHOW_PROGRESS,
                RESULT_TYPE_SHOW_PROGRESS_DONE,
        ):
            raise ValueError(
                f"Handler returned incorrect type: {result['type']}")

        if result["type"] in (
                RESULT_TYPE_FORM,
                RESULT_TYPE_EXTERNAL_STEP,
                RESULT_TYPE_EXTERNAL_STEP_DONE,
                RESULT_TYPE_SHOW_PROGRESS,
                RESULT_TYPE_SHOW_PROGRESS_DONE,
        ):
            flow.cur_step = result
            return result

        # We pass a copy of the result because we're mutating our version
        result = await self.async_finish_flow(flow, result.copy())

        # _async_finish_flow may change result type, check it again
        if result["type"] == RESULT_TYPE_FORM:
            flow.cur_step = result
            return result

        # Abort and Success results both finish the flow
        self._async_remove_flow_progress(flow.flow_id)

        return result
Пример #2
0
    async def _async_handle_step(
        self,
        flow: Any,
        step_id: str,
        user_input: dict | BaseServiceInfo | None,
        step_done: asyncio.Future | None = None,
    ) -> FlowResult:
        """Handle a step of a flow."""
        method = f"async_step_{step_id}"

        if not hasattr(flow, method):
            self._async_remove_flow_progress(flow.flow_id)
            if step_done:
                step_done.set_result(None)
            raise UnknownStep(
                f"Handler {flow.__class__.__name__} doesn't support step {step_id}"
            )

        try:
            result: FlowResult = await getattr(flow, method)(user_input)
        except AbortFlow as err:
            result = _create_abort_data(flow.flow_id, flow.handler, err.reason,
                                        err.description_placeholders)

        # Mark the step as done.
        # We do this before calling async_finish_flow because config entries will hit a
        # circular dependency where async_finish_flow sets up new entry, which needs the
        # integration to be set up, which is waiting for init to be done.
        if step_done:
            step_done.set_result(None)

        if not isinstance(result["type"], FlowResultType):
            result["type"] = FlowResultType(
                result["type"])  # type: ignore[unreachable]
            report(
                "does not use FlowResultType enum for data entry flow result type. "
                "This is deprecated and will stop working in Home Assistant 2022.9",
                error_if_core=False,
            )

        if result["type"] in (
                FlowResultType.FORM,
                FlowResultType.EXTERNAL_STEP,
                FlowResultType.EXTERNAL_STEP_DONE,
                FlowResultType.SHOW_PROGRESS,
                FlowResultType.SHOW_PROGRESS_DONE,
                FlowResultType.MENU,
        ):
            flow.cur_step = result
            return result

        # We pass a copy of the result because we're mutating our version
        result = await self.async_finish_flow(flow, result.copy())

        # _async_finish_flow may change result type, check it again
        if result["type"] == FlowResultType.FORM:
            flow.cur_step = result
            return result

        # Abort and Success results both finish the flow
        self._async_remove_flow_progress(flow.flow_id)

        return result