mirror of
https://github.com/home-assistant/core.git
synced 2026-09-13 04:01:03 +01:00
Handle single_instance_allowed centrally (#181143)
This commit is contained in:
@@ -1,8 +1,7 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_account%]",
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_account%]"
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
},
|
||||
"step": {
|
||||
"confirm": {
|
||||
"description": "Please confirm setting up the Deako integration"
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
"config": {
|
||||
"abort": {
|
||||
"reconfigure_successful": "**Reconfiguration was successful**\n\nGo to the [webhook service of Dialogflow]({dialogflow_url}) and update the webhook with following settings:\n\n- URL: `{webhook_url}`\n- Method: POST\n- Content Type: application/json\n\nSee [the documentation]({docs_url}) for further details.",
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]",
|
||||
"webhook_not_internet_accessible": "[%key:common::config_flow::abort::webhook_not_internet_accessible%]"
|
||||
},
|
||||
"create_entry": {
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
},
|
||||
"error": {
|
||||
"directory_does_not_exist": "The directory could not be reached. Please check your settings."
|
||||
},
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
},
|
||||
"step": {
|
||||
"confirm": {
|
||||
"description": "Make sure to configure the 'split topic' data sources in DSMR Reader."
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]",
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]"
|
||||
},
|
||||
"error": {
|
||||
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]",
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
},
|
||||
"step": {
|
||||
"confirm": {
|
||||
"description": "Do you want to set up an Escea fireplace?"
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
"abort": {
|
||||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
||||
"invalid_data": "Received invalid data from Essent",
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]",
|
||||
"unknown": "[%key:common::config_flow::error::unknown%]"
|
||||
},
|
||||
"step": {
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"description": "Do you want to start the setup? The initial setup will take about 30-40 seconds."
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
},
|
||||
"step": {
|
||||
"confirm": {
|
||||
"description": "Do you want to set up Fjäråskupan?"
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
},
|
||||
"error": {
|
||||
"already_exists": "A camera with these URL settings already exists.",
|
||||
"invalid_still_image": "URL did not return a valid still image",
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
"config": {
|
||||
"abort": {
|
||||
"reconfigure_successful": "**Reconfiguration was successful**\n\nGo to the webhook feature in Geofency and update the webhook with the following settings:\n\n- URL: `{webhook_url}`\n- Method: POST\n\nSee [the documentation]({docs_url}) for further details.",
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]",
|
||||
"webhook_not_internet_accessible": "[%key:common::config_flow::abort::webhook_not_internet_accessible%]"
|
||||
},
|
||||
"create_entry": {
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
},
|
||||
"step": {
|
||||
"confirm": {
|
||||
"description": "[%key:common::config_flow::description::confirm_setup%]"
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
"config": {
|
||||
"abort": {
|
||||
"reconfigure_successful": "**Reconfiguration was successful**\n\nGo to the webhook feature in GPSLogger and update the webhook with the following settings:\n\n- URL: `{webhook_url}`\n- Method: POST\n\nSee [the documentation]({docs_url}) for further details.",
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]",
|
||||
"webhook_not_internet_accessible": "[%key:common::config_flow::abort::webhook_not_internet_accessible%]"
|
||||
},
|
||||
"create_entry": {
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
},
|
||||
"step": {
|
||||
"confirm": {
|
||||
"description": "[%key:common::config_flow::description::confirm_setup%]"
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
},
|
||||
"step": {
|
||||
"confirm": {
|
||||
"description": "Do you want to set up Hisense AEH-W4A1?"
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
"config": {
|
||||
"abort": {
|
||||
"reconfigure_successful": "**Reconfiguration was successful**\n\nGo to the \"Make a web request\" action from the [IFTTT webhook applet]({applet_url}) and update the webhook with the following settings:\n\n- URL: `{webhook_url}`\n- Method: POST\n- Content Type: application/json\n\nSee [the documentation]({docs_url}) on how to configure automations to handle incoming data.",
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]",
|
||||
"webhook_not_internet_accessible": "[%key:common::config_flow::abort::webhook_not_internet_accessible%]"
|
||||
},
|
||||
"create_entry": {
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
},
|
||||
"step": {
|
||||
"confirm": {
|
||||
"description": "[%key:common::config_flow::description::confirm_setup%]"
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_account%]",
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_account%]"
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
"config": {
|
||||
"abort": {
|
||||
"reconfigure_successful": "**Reconfiguration was successful**\n\nGo to webhooks in the Locative app and update webhook with the following settings:\n\n- URL: `{webhook_url}`\n- Method: POST\n\nSee [the documentation]({docs_url}) for further details.",
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]",
|
||||
"webhook_not_internet_accessible": "[%key:common::config_flow::abort::webhook_not_internet_accessible%]"
|
||||
},
|
||||
"create_entry": {
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
||||
"timeout_connect": "[%key:common::config_flow::error::timeout_connect%]",
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
"config": {
|
||||
"abort": {
|
||||
"reconfigure_successful": "**Reconfiguration was successful**\n\nGo to [webhooks in Mailgun]({mailgun_url}) and update the webhook with the following settings:\n\n- URL: `{webhook_url}`\n- Method: POST\n- Content Type: application/json\n\nSee [the documentation]({docs_url}) on how to configure automations to handle incoming data.",
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]",
|
||||
"webhook_not_internet_accessible": "[%key:common::config_flow::abort::webhook_not_internet_accessible%]"
|
||||
},
|
||||
"create_entry": {
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
"missing_configuration": "[%key:common::config_flow::abort::oauth2_missing_configuration%]",
|
||||
"no_devices_found": "[%key:common::config_flow::abort::no_devices_found%]",
|
||||
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]",
|
||||
"reconfigure_successful": "[%key:common::config_flow::abort::reconfigure_successful%]",
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
"reconfigure_successful": "[%key:common::config_flow::abort::reconfigure_successful%]"
|
||||
},
|
||||
"create_entry": {
|
||||
"default": "[%key:common::config_flow::create_entry::authenticated%]"
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
"addon_start_failed": "Failed to start the {addon} app.",
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_service%]",
|
||||
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]",
|
||||
"reconfigure_successful": "[%key:common::config_flow::abort::reconfigure_successful%]",
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
"reconfigure_successful": "[%key:common::config_flow::abort::reconfigure_successful%]"
|
||||
},
|
||||
"error": {
|
||||
"bad_birth": "Invalid birth topic",
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
"config": {
|
||||
"abort": {
|
||||
"missing_configuration": "[%key:common::config_flow::abort::oauth2_missing_configuration%]",
|
||||
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]",
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]"
|
||||
},
|
||||
"create_entry": {
|
||||
"default": "[%key:common::config_flow::create_entry::authenticated%]"
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]"
|
||||
},
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "The Thread border router is already configured",
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]",
|
||||
"unknown": "[%key:common::config_flow::error::unknown%]"
|
||||
},
|
||||
"error": {
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
"config": {
|
||||
"abort": {
|
||||
"mqtt_not_configured": "Home Assistant MQTT integration not configured.",
|
||||
"mqtt_not_connected": "Home Assistant MQTT integration not connected to MQTT broker.",
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
"mqtt_not_connected": "Home Assistant MQTT integration not connected to MQTT broker."
|
||||
},
|
||||
"step": {
|
||||
"confirm_from_mqtt": {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_account%]",
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]",
|
||||
"webhook_not_internet_accessible": "[%key:common::config_flow::abort::webhook_not_internet_accessible%]"
|
||||
},
|
||||
"create_entry": {
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
},
|
||||
"step": {
|
||||
"confirm": {
|
||||
"description": "[%key:common::config_flow::description::confirm_setup%]"
|
||||
|
||||
@@ -12,7 +12,7 @@ from homeassistant.config_entries import (
|
||||
ConfigFlowResult,
|
||||
OptionsFlow,
|
||||
)
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, callback
|
||||
|
||||
from .const import (
|
||||
CONF_DSN,
|
||||
@@ -56,7 +56,10 @@ class SentryConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
) -> ConfigFlowResult:
|
||||
"""Handle a user config flow."""
|
||||
if self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
return self.async_abort(
|
||||
reason="single_instance_allowed",
|
||||
translation_domain=HOMEASSISTANT_DOMAIN,
|
||||
)
|
||||
|
||||
errors = {}
|
||||
if user_input is not None:
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
},
|
||||
"error": {
|
||||
"bad_dsn": "Invalid DSN",
|
||||
"unknown": "[%key:common::config_flow::error::unknown%]"
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
from typing import Any, override
|
||||
|
||||
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
|
||||
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN
|
||||
|
||||
from .const import DEFAULT_NAME, DOMAIN
|
||||
|
||||
@@ -18,7 +19,10 @@ class SlimProtoConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
) -> ConfigFlowResult:
|
||||
"""Handle the initial step."""
|
||||
if self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
return self.async_abort(
|
||||
reason="single_instance_allowed",
|
||||
translation_domain=HOMEASSISTANT_DOMAIN,
|
||||
)
|
||||
|
||||
# we have nothing to configure so simply create the entry
|
||||
return self.async_create_entry(title=DEFAULT_NAME, data={})
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
},
|
||||
"step": {
|
||||
"user": {}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
"config": {
|
||||
"abort": {
|
||||
"not_ipv4_address": "No IPv4 address in SSDP discovery information",
|
||||
"not_sonos_device": "Discovered device is not a Sonos device",
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
"not_sonos_device": "Discovered device is not a Sonos device"
|
||||
},
|
||||
"step": {
|
||||
"confirm": {
|
||||
|
||||
@@ -9,7 +9,7 @@ from homeassistant.config_entries import (
|
||||
ConfigFlowResult,
|
||||
OptionsFlowWithReload,
|
||||
)
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, callback
|
||||
|
||||
from .const import (
|
||||
CONF_SERVER_ID,
|
||||
@@ -41,7 +41,10 @@ class SpeedTestFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
) -> ConfigFlowResult:
|
||||
"""Handle a flow initialized by the user."""
|
||||
if self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
return self.async_abort(
|
||||
reason="single_instance_allowed",
|
||||
translation_domain=HOMEASSISTANT_DOMAIN,
|
||||
)
|
||||
|
||||
if user_input is None:
|
||||
return self.async_show_form(step_id="user")
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"description": "[%key:common::config_flow::description::confirm_setup%]"
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
"invalid_config": "The YAML configuration is invalid and cannot be imported. Please check your configuration.yaml file.",
|
||||
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]",
|
||||
"reconfigure_successful": "[%key:common::config_flow::abort::reconfigure_successful%]",
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]",
|
||||
"unknown": "[%key:common::config_flow::error::unknown%]"
|
||||
},
|
||||
"error": {
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
"config": {
|
||||
"abort": {
|
||||
"no_devices_found": "[%key:common::config_flow::abort::no_devices_found%]",
|
||||
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]",
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]"
|
||||
},
|
||||
"error": {
|
||||
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]"
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::already_configured_service%]"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"description": "Select **Submit** for initial setup. On the created config entry, select configure to add sensors for selected processes"
|
||||
|
||||
@@ -6,6 +6,7 @@ import voluptuous as vol
|
||||
|
||||
from homeassistant.components.mqtt import valid_subscribe_topic
|
||||
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
|
||||
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN
|
||||
from homeassistant.helpers.service_info.mqtt import MqttServiceInfo
|
||||
|
||||
from .const import CONF_DISCOVERY_PREFIX, DEFAULT_PREFIX, DOMAIN
|
||||
@@ -26,7 +27,10 @@ class FlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
) -> ConfigFlowResult:
|
||||
"""Handle a flow initialized by MQTT discovery."""
|
||||
if self._async_in_progress() or self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
return self.async_abort(
|
||||
reason="single_instance_allowed",
|
||||
translation_domain=HOMEASSISTANT_DOMAIN,
|
||||
)
|
||||
|
||||
await self.async_set_unique_id(DOMAIN)
|
||||
|
||||
@@ -50,7 +54,10 @@ class FlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
) -> ConfigFlowResult:
|
||||
"""Handle a flow initialized by the user."""
|
||||
if self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
return self.async_abort(
|
||||
reason="single_instance_allowed",
|
||||
translation_domain=HOMEASSISTANT_DOMAIN,
|
||||
)
|
||||
|
||||
return await self.async_step_config()
|
||||
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
},
|
||||
"error": {
|
||||
"invalid_discovery_topic": "Invalid discovery topic prefix."
|
||||
},
|
||||
|
||||
@@ -10,6 +10,7 @@ import voluptuous as vol
|
||||
|
||||
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
|
||||
from homeassistant.const import CONF_TOKEN
|
||||
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN
|
||||
|
||||
from .const import DOMAIN
|
||||
|
||||
@@ -35,7 +36,10 @@ class TodoistConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
) -> ConfigFlowResult:
|
||||
"""Handle the initial step."""
|
||||
if self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
return self.async_abort(
|
||||
reason="single_instance_allowed",
|
||||
translation_domain=HOMEASSISTANT_DOMAIN,
|
||||
)
|
||||
|
||||
errors: dict[str, str] = {}
|
||||
if user_input is not None:
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
},
|
||||
"create_entry": {
|
||||
"default": "[%key:common::config_flow::create_entry::authenticated%]"
|
||||
},
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
"config": {
|
||||
"abort": {
|
||||
"reconfigure_successful": "**Reconfiguration was successful**\n\nGo to webhooks in the Traccar Client and update the webhook with the following URL: `{webhook_url}`\n\nSee [the documentation]({docs_url}) for further details.",
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]",
|
||||
"webhook_not_internet_accessible": "[%key:common::config_flow::abort::webhook_not_internet_accessible%]"
|
||||
},
|
||||
"create_entry": {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
"config": {
|
||||
"abort": {
|
||||
"reconfigure_successful": "**Reconfiguration was successful**\n\nGo to [webhooks in Twilio]({twilio_url}) and update the webhook with the following settings:\n\n- URL: `{webhook_url}`\n- Method: POST\n- Content Type: application/x-www-form-urlencoded\n\nSee [the documentation]({docs_url}) on how to configure automations to handle incoming data.",
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]",
|
||||
"webhook_not_internet_accessible": "[%key:common::config_flow::abort::webhook_not_internet_accessible%]"
|
||||
},
|
||||
"create_entry": {
|
||||
|
||||
@@ -5,6 +5,7 @@ import logging
|
||||
from typing import Any, override
|
||||
|
||||
from homeassistant.config_entries import SOURCE_REAUTH, ConfigFlowResult
|
||||
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN
|
||||
from homeassistant.helpers import config_entry_oauth2_flow
|
||||
from homeassistant.helpers.device_registry import format_mac
|
||||
from homeassistant.helpers.service_info.dhcp import DhcpServiceInfo
|
||||
@@ -35,7 +36,10 @@ class ViCareFlowHandler(
|
||||
) -> ConfigFlowResult:
|
||||
"""Handle a flow initiated by the user."""
|
||||
if self.source != SOURCE_REAUTH and self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
return self.async_abort(
|
||||
reason="single_instance_allowed",
|
||||
translation_domain=HOMEASSISTANT_DOMAIN,
|
||||
)
|
||||
|
||||
return await super().async_step_user(user_input)
|
||||
|
||||
@@ -81,6 +85,9 @@ class ViCareFlowHandler(
|
||||
self._abort_if_unique_id_configured()
|
||||
|
||||
if self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
return self.async_abort(
|
||||
reason="single_instance_allowed",
|
||||
translation_domain=HOMEASSISTANT_DOMAIN,
|
||||
)
|
||||
|
||||
return await self.async_step_user()
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
|
||||
"missing_configuration": "[%key:common::config_flow::abort::oauth2_missing_configuration%]",
|
||||
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]",
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]",
|
||||
"unknown": "[%key:common::config_flow::error::unknown%]"
|
||||
},
|
||||
"create_entry": {
|
||||
|
||||
@@ -11,7 +11,7 @@ from homeassistant.config_entries import (
|
||||
ConfigFlowResult,
|
||||
OptionsFlow,
|
||||
)
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, callback
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
|
||||
from .const import CONF_SIP_PORT, CONF_SIP_USER, DOMAIN
|
||||
@@ -28,7 +28,10 @@ class VoIPConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
) -> ConfigFlowResult:
|
||||
"""Handle the initial step."""
|
||||
if self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
return self.async_abort(
|
||||
reason="single_instance_allowed",
|
||||
translation_domain=HOMEASSISTANT_DOMAIN,
|
||||
)
|
||||
|
||||
if user_input is None:
|
||||
return self.async_show_form(
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"description": "Receive Voice over IP calls to interact with Assist."
|
||||
|
||||
@@ -9,7 +9,7 @@ from pyweatherflowudp.client import EVENT_DEVICE_DISCOVERED, WeatherFlowListener
|
||||
from pyweatherflowudp.errors import AddressInUseError, EndpointError, ListenerError
|
||||
|
||||
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, callback
|
||||
|
||||
from .const import (
|
||||
DOMAIN,
|
||||
@@ -55,7 +55,10 @@ class WeatherFlowConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
# will pick up all devices on the network and we don't want to
|
||||
# create multiple entries.
|
||||
if self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
return self.async_abort(
|
||||
reason="single_instance_allowed",
|
||||
translation_domain=HOMEASSISTANT_DOMAIN,
|
||||
)
|
||||
found = False
|
||||
errors = {}
|
||||
try:
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
},
|
||||
"error": {
|
||||
"address_in_use": "Unable to open local UDP port 50222.",
|
||||
"cannot_connect": "UDP discovery error.",
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
},
|
||||
"step": {
|
||||
"confirm": {
|
||||
"description": "Do you want to set up Wemo?"
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
},
|
||||
"step": {
|
||||
"confirm": {
|
||||
"description": "[%key:common::config_flow::description::confirm_setup%]"
|
||||
|
||||
@@ -31,7 +31,7 @@ from homeassistant.config_entries import (
|
||||
OptionsFlow,
|
||||
)
|
||||
from homeassistant.const import CONF_NAME
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, HomeAssistant, callback
|
||||
from homeassistant.data_entry_flow import AbortFlow
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.selector import (
|
||||
@@ -828,7 +828,10 @@ class ZhaConfigFlowHandler(BaseZhaFlow, ConfigFlow, domain=DOMAIN):
|
||||
|
||||
# Abort discovery if the device path is already configured
|
||||
if path is not None and path in current_device_paths:
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
return self.async_abort(
|
||||
reason="single_instance_allowed",
|
||||
translation_domain=HOMEASSISTANT_DOMAIN,
|
||||
)
|
||||
|
||||
# Without confirmation, discovery can automatically progress into parts of the
|
||||
# config flow logic that interacts with hardware.
|
||||
@@ -1032,7 +1035,10 @@ class ZhaConfigFlowHandler(BaseZhaFlow, ConfigFlow, domain=DOMAIN):
|
||||
|
||||
return self.async_create_entry(title="", data=data)
|
||||
# This should never be reached
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
return self.async_abort(
|
||||
reason="single_instance_allowed",
|
||||
translation_domain=HOMEASSISTANT_DOMAIN,
|
||||
)
|
||||
|
||||
|
||||
class ZhaOptionsFlowHandler(BaseZhaFlow, OptionsFlow):
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
"invalid_zeroconf_data": "The coordinator has invalid Zeroconf service info and cannot be identified by ZHA",
|
||||
"not_zha_device": "This device is not a ZHA device",
|
||||
"reconfigure_successful": "ZHA has successfully migrated from your old adapter to the new one. Give your Zigbee network a few minutes to stabilize.\n\nIf you no longer need the old adapter, you can now unplug it.",
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]",
|
||||
"usb_probe_failed": "Failed to probe the USB device",
|
||||
"wrong_firmware_installed": "Your device is running the wrong firmware and cannot be used with ZHA until the correct firmware is installed. [A repair has been created]({repair_url}) with more information and instructions for how to fix this."
|
||||
},
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
from typing import Any, override
|
||||
|
||||
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
|
||||
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN
|
||||
|
||||
from .const import DEFAULT_NAME, DOMAIN
|
||||
|
||||
@@ -18,7 +19,10 @@ class ZodiacConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
) -> ConfigFlowResult:
|
||||
"""Handle a flow initialized by the user."""
|
||||
if self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
return self.async_abort(
|
||||
reason="single_instance_allowed",
|
||||
translation_domain=HOMEASSISTANT_DOMAIN,
|
||||
)
|
||||
|
||||
if user_input is not None:
|
||||
return self.async_create_entry(title=DEFAULT_NAME, data={})
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"description": "[%key:common::config_flow::description::confirm_setup%]"
|
||||
|
||||
@@ -47,7 +47,10 @@ class DiscoveryFlowHandler[_R: Awaitable[bool] | bool](config_entries.ConfigFlow
|
||||
) -> config_entries.ConfigFlowResult:
|
||||
"""Handle a flow initialized by the user."""
|
||||
if self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
return self.async_abort(
|
||||
reason="single_instance_allowed",
|
||||
translation_domain=HOMEASSISTANT_DOMAIN,
|
||||
)
|
||||
|
||||
await self.async_set_unique_id(self._domain, raise_on_progress=False)
|
||||
|
||||
@@ -83,7 +86,10 @@ class DiscoveryFlowHandler[_R: Awaitable[bool] | bool](config_entries.ConfigFlow
|
||||
self.hass.config_entries.flow.async_abort(flow["flow_id"])
|
||||
|
||||
if self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
return self.async_abort(
|
||||
reason="single_instance_allowed",
|
||||
translation_domain=HOMEASSISTANT_DOMAIN,
|
||||
)
|
||||
|
||||
return self.async_create_entry(title=self._title, data={})
|
||||
|
||||
@@ -93,7 +99,10 @@ class DiscoveryFlowHandler[_R: Awaitable[bool] | bool](config_entries.ConfigFlow
|
||||
) -> config_entries.ConfigFlowResult:
|
||||
"""Handle a flow initialized by discovery."""
|
||||
if self._async_in_progress() or self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
return self.async_abort(
|
||||
reason="single_instance_allowed",
|
||||
translation_domain=HOMEASSISTANT_DOMAIN,
|
||||
)
|
||||
|
||||
await self.async_set_unique_id(self._domain)
|
||||
|
||||
@@ -105,7 +114,10 @@ class DiscoveryFlowHandler[_R: Awaitable[bool] | bool](config_entries.ConfigFlow
|
||||
) -> config_entries.ConfigFlowResult:
|
||||
"""Handle a flow initialized by bluetooth discovery."""
|
||||
if self._async_in_progress() or self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
return self.async_abort(
|
||||
reason="single_instance_allowed",
|
||||
translation_domain=HOMEASSISTANT_DOMAIN,
|
||||
)
|
||||
|
||||
await self.async_set_unique_id(self._domain)
|
||||
|
||||
@@ -117,7 +129,10 @@ class DiscoveryFlowHandler[_R: Awaitable[bool] | bool](config_entries.ConfigFlow
|
||||
) -> config_entries.ConfigFlowResult:
|
||||
"""Handle a flow initialized by dhcp discovery."""
|
||||
if self._async_in_progress() or self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
return self.async_abort(
|
||||
reason="single_instance_allowed",
|
||||
translation_domain=HOMEASSISTANT_DOMAIN,
|
||||
)
|
||||
|
||||
await self.async_set_unique_id(self._domain)
|
||||
|
||||
@@ -129,7 +144,10 @@ class DiscoveryFlowHandler[_R: Awaitable[bool] | bool](config_entries.ConfigFlow
|
||||
) -> config_entries.ConfigFlowResult:
|
||||
"""Handle a flow initialized by Homekit discovery."""
|
||||
if self._async_in_progress() or self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
return self.async_abort(
|
||||
reason="single_instance_allowed",
|
||||
translation_domain=HOMEASSISTANT_DOMAIN,
|
||||
)
|
||||
|
||||
await self.async_set_unique_id(self._domain)
|
||||
|
||||
@@ -141,7 +159,10 @@ class DiscoveryFlowHandler[_R: Awaitable[bool] | bool](config_entries.ConfigFlow
|
||||
) -> config_entries.ConfigFlowResult:
|
||||
"""Handle a flow initialized by mqtt discovery."""
|
||||
if self._async_in_progress() or self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
return self.async_abort(
|
||||
reason="single_instance_allowed",
|
||||
translation_domain=HOMEASSISTANT_DOMAIN,
|
||||
)
|
||||
|
||||
await self.async_set_unique_id(self._domain)
|
||||
|
||||
@@ -153,7 +174,10 @@ class DiscoveryFlowHandler[_R: Awaitable[bool] | bool](config_entries.ConfigFlow
|
||||
) -> config_entries.ConfigFlowResult:
|
||||
"""Handle a flow initialized by Zeroconf discovery."""
|
||||
if self._async_in_progress() or self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
return self.async_abort(
|
||||
reason="single_instance_allowed",
|
||||
translation_domain=HOMEASSISTANT_DOMAIN,
|
||||
)
|
||||
|
||||
await self.async_set_unique_id(self._domain)
|
||||
|
||||
@@ -165,7 +189,10 @@ class DiscoveryFlowHandler[_R: Awaitable[bool] | bool](config_entries.ConfigFlow
|
||||
) -> config_entries.ConfigFlowResult:
|
||||
"""Handle a flow initialized by Ssdp discovery."""
|
||||
if self._async_in_progress() or self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
return self.async_abort(
|
||||
reason="single_instance_allowed",
|
||||
translation_domain=HOMEASSISTANT_DOMAIN,
|
||||
)
|
||||
|
||||
await self.async_set_unique_id(self._domain)
|
||||
|
||||
@@ -176,7 +203,10 @@ class DiscoveryFlowHandler[_R: Awaitable[bool] | bool](config_entries.ConfigFlow
|
||||
) -> config_entries.ConfigFlowResult:
|
||||
"""Handle a flow initialized by import."""
|
||||
if self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
return self.async_abort(
|
||||
reason="single_instance_allowed",
|
||||
translation_domain=HOMEASSISTANT_DOMAIN,
|
||||
)
|
||||
|
||||
# Cancel other flows.
|
||||
in_progress = self._async_in_progress()
|
||||
@@ -230,7 +260,10 @@ class WebhookFlowHandler(config_entries.ConfigFlow):
|
||||
and self._async_current_entries()
|
||||
and self.source != config_entries.SOURCE_RECONFIGURE
|
||||
):
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
return self.async_abort(
|
||||
reason="single_instance_allowed",
|
||||
translation_domain=HOMEASSISTANT_DOMAIN,
|
||||
)
|
||||
|
||||
if user_input is None:
|
||||
return self.async_show_form(
|
||||
|
||||
@@ -77,6 +77,7 @@ async def test_single_entry_allowed(
|
||||
|
||||
assert result["type"] is data_entry_flow.FlowResultType.ABORT
|
||||
assert result["reason"] == "single_instance_allowed"
|
||||
assert result["translation_domain"] == HOMEASSISTANT_DOMAIN
|
||||
|
||||
|
||||
async def test_user_no_devices_found(
|
||||
@@ -152,6 +153,7 @@ async def test_user_has_confirmation_async_discovery_flow(
|
||||
[
|
||||
config_entries.SOURCE_BLUETOOTH,
|
||||
config_entries.SOURCE_DISCOVERY,
|
||||
config_entries.SOURCE_HOMEKIT,
|
||||
config_entries.SOURCE_MQTT,
|
||||
config_entries.SOURCE_SSDP,
|
||||
config_entries.SOURCE_ZEROCONF,
|
||||
@@ -171,6 +173,23 @@ async def test_discovery_single_instance(
|
||||
|
||||
assert result["type"] == data_entry_flow.FlowResultType.ABORT
|
||||
assert result["reason"] == "single_instance_allowed"
|
||||
assert result["translation_domain"] == HOMEASSISTANT_DOMAIN
|
||||
|
||||
|
||||
async def test_discovery_confirm_single_instance(
|
||||
hass: HomeAssistant, discovery_flow_conf: dict[str, bool]
|
||||
) -> None:
|
||||
"""Test confirming a discovery aborts once an entry exists."""
|
||||
flow = config_entries.HANDLERS["test"]()
|
||||
flow.hass = hass
|
||||
flow.context = {"source": config_entries.SOURCE_DISCOVERY}
|
||||
|
||||
MockConfigEntry(domain="test").add_to_hass(hass)
|
||||
result = await flow.async_step_confirm({})
|
||||
|
||||
assert result["type"] is data_entry_flow.FlowResultType.ABORT
|
||||
assert result["reason"] == "single_instance_allowed"
|
||||
assert result["translation_domain"] == HOMEASSISTANT_DOMAIN
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -322,6 +341,8 @@ async def test_import_single_instance(
|
||||
|
||||
result = await flow.async_step_import(None)
|
||||
assert result["type"] == data_entry_flow.FlowResultType.ABORT
|
||||
assert result["reason"] == "single_instance_allowed"
|
||||
assert result["translation_domain"] == HOMEASSISTANT_DOMAIN
|
||||
|
||||
|
||||
async def test_ignored_discoveries(
|
||||
@@ -370,6 +391,7 @@ async def test_webhook_single_entry_allowed(
|
||||
|
||||
assert result["type"] is data_entry_flow.FlowResultType.ABORT
|
||||
assert result["reason"] == "single_instance_allowed"
|
||||
assert result["translation_domain"] == HOMEASSISTANT_DOMAIN
|
||||
|
||||
|
||||
async def test_webhook_multiple_entries_allowed(
|
||||
|
||||
Reference in New Issue
Block a user