Reduce boilerplate to abort for matching config entries (#50186)
Co-authored-by: Franck Nijhof <git@frenck.dev>
This commit is contained in:
parent
d6a202bd74
commit
34c84a6bbb
49 changed files with 183 additions and 350 deletions
|
@ -65,13 +65,9 @@ class AdGuardHomeFlowHandler(ConfigFlow, domain=DOMAIN):
|
|||
if user_input is None:
|
||||
return await self._show_setup_form(user_input)
|
||||
|
||||
entries = self._async_current_entries()
|
||||
for entry in entries:
|
||||
if (
|
||||
entry.data[CONF_HOST] == user_input[CONF_HOST]
|
||||
and entry.data[CONF_PORT] == user_input[CONF_PORT]
|
||||
):
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match(
|
||||
{CONF_HOST: user_input[CONF_HOST], CONF_PORT: user_input[CONF_PORT]}
|
||||
)
|
||||
|
||||
errors = {}
|
||||
|
||||
|
|
|
@ -50,8 +50,7 @@ class AmbiclimateFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
|
||||
async def async_step_user(self, user_input=None):
|
||||
"""Handle external yaml configuration."""
|
||||
if self.hass.config_entries.async_entries(DOMAIN):
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match()
|
||||
|
||||
config = self.hass.data.get(DATA_AMBICLIMATE_IMPL, {})
|
||||
|
||||
|
@ -63,8 +62,7 @@ class AmbiclimateFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
|
||||
async def async_step_auth(self, user_input=None):
|
||||
"""Handle a flow start."""
|
||||
if self.hass.config_entries.async_entries(DOMAIN):
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match()
|
||||
|
||||
errors = {}
|
||||
|
||||
|
@ -85,8 +83,7 @@ class AmbiclimateFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
|
||||
async def async_step_code(self, code=None):
|
||||
"""Received code for authentication."""
|
||||
if self.hass.config_entries.async_entries(DOMAIN):
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match()
|
||||
|
||||
token_info = await self._get_token_info(code)
|
||||
|
||||
|
|
|
@ -298,11 +298,7 @@ class BroadlinkFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
|
||||
async def async_step_import(self, import_info):
|
||||
"""Import a device."""
|
||||
if any(
|
||||
import_info[CONF_HOST] == entry.data[CONF_HOST]
|
||||
for entry in self._async_current_entries()
|
||||
):
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match({CONF_HOST: import_info[CONF_HOST]})
|
||||
return await self.async_step_user(import_info)
|
||||
|
||||
async def async_step_reauth(self, data):
|
||||
|
|
|
@ -199,9 +199,7 @@ class DenonAvrFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
"unique_id's will not be available",
|
||||
self.host,
|
||||
)
|
||||
for entry in self._async_current_entries():
|
||||
if entry.data[CONF_HOST] == self.host:
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match({CONF_HOST: self.host})
|
||||
|
||||
return self.async_create_entry(
|
||||
title=receiver.name,
|
||||
|
|
|
@ -73,8 +73,7 @@ class DuneHDConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
"""Handle configuration by yaml file."""
|
||||
self.host = user_input[CONF_HOST]
|
||||
|
||||
if self.host_already_configured(self.host):
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match({CONF_HOST: self.host})
|
||||
|
||||
try:
|
||||
await self.init_device(self.host)
|
||||
|
|
|
@ -26,12 +26,8 @@ class EmulatedRokuFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
errors = {}
|
||||
|
||||
if user_input is not None:
|
||||
name = user_input[CONF_NAME]
|
||||
|
||||
if name in configured_servers(self.hass):
|
||||
return self.async_abort(reason="already_configured")
|
||||
|
||||
return self.async_create_entry(title=name, data=user_input)
|
||||
self._async_abort_entries_match({CONF_NAME: user_input[CONF_NAME]})
|
||||
return self.async_create_entry(title=user_input[CONF_NAME], data=user_input)
|
||||
|
||||
servers_num = len(configured_servers(self.hass))
|
||||
|
||||
|
|
|
@ -133,9 +133,7 @@ class ForkedDaapdFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
"""
|
||||
if user_input is not None:
|
||||
# check for any entries with same host, abort if found
|
||||
for entry in self._async_current_entries():
|
||||
if entry.data.get(CONF_HOST) == user_input[CONF_HOST]:
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match({CONF_HOST: user_input[CONF_HOST]})
|
||||
validate_result = await self.validate_input(user_input)
|
||||
if validate_result[0] == "ok": # success
|
||||
_LOGGER.debug("Connected successfully. Creating entry")
|
||||
|
|
|
@ -47,13 +47,9 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
|
||||
Data has the keys from DATA_SCHEMA with values provided by the user.
|
||||
"""
|
||||
|
||||
for entry in self.hass.config_entries.async_entries(DOMAIN):
|
||||
if (
|
||||
entry.data[CONF_HOST] == data[CONF_HOST]
|
||||
and entry.data[CONF_PORT] == data[CONF_PORT]
|
||||
):
|
||||
raise AbortFlow("already_configured")
|
||||
self._async_abort_entries_match(
|
||||
{CONF_HOST: data[CONF_HOST], CONF_PORT: data[CONF_PORT]}
|
||||
)
|
||||
|
||||
camera = FoscamCamera(
|
||||
data[CONF_HOST],
|
||||
|
|
|
@ -92,10 +92,7 @@ class FritzboxConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
errors = {}
|
||||
|
||||
if user_input is not None:
|
||||
|
||||
for entry in self.hass.config_entries.async_entries(DOMAIN):
|
||||
if entry.data[CONF_HOST] == user_input[CONF_HOST]:
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match({CONF_HOST: user_input[CONF_HOST]})
|
||||
|
||||
self._host = user_input[CONF_HOST]
|
||||
self._name = user_input[CONF_HOST]
|
||||
|
|
|
@ -28,8 +28,7 @@ class GoalZeroFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
host = user_input[CONF_HOST]
|
||||
name = user_input[CONF_NAME]
|
||||
|
||||
if await self._async_endpoint_existed(host):
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match({CONF_HOST: host})
|
||||
|
||||
try:
|
||||
await self._async_try_connect(host)
|
||||
|
@ -64,12 +63,6 @@ class GoalZeroFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
errors=errors,
|
||||
)
|
||||
|
||||
async def _async_endpoint_existed(self, endpoint):
|
||||
for entry in self._async_current_entries():
|
||||
if endpoint == entry.data.get(CONF_HOST):
|
||||
return True
|
||||
return False
|
||||
|
||||
async def _async_try_connect(self, host):
|
||||
session = async_get_clientsession(self.hass)
|
||||
api = Yeti(host, self.hass.loop, session)
|
||||
|
|
|
@ -35,9 +35,7 @@ class Gogogate2FlowHandler(ConfigFlow, domain=DOMAIN):
|
|||
|
||||
ip_address = discovery_info["host"]
|
||||
|
||||
for entry in self._async_current_entries():
|
||||
if entry.data.get(CONF_IP_ADDRESS) == ip_address:
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match({CONF_IP_ADDRESS: ip_address})
|
||||
|
||||
self._ip_address = ip_address
|
||||
self._device_type = DEVICE_TYPE_ISMARTGATE
|
||||
|
|
|
@ -6,7 +6,6 @@ import voluptuous as vol
|
|||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD
|
||||
from homeassistant.core import callback
|
||||
|
||||
from .const import (
|
||||
CONF_2FA,
|
||||
|
@ -22,15 +21,6 @@ from .hangups_utils import (
|
|||
)
|
||||
|
||||
|
||||
@callback
|
||||
def configured_hangouts(hass):
|
||||
"""Return the configures Google Hangouts Account."""
|
||||
entries = hass.config_entries.async_entries(HANGOUTS_DOMAIN)
|
||||
if entries:
|
||||
return entries[0]
|
||||
return None
|
||||
|
||||
|
||||
@config_entries.HANDLERS.register(HANGOUTS_DOMAIN)
|
||||
class HangoutsFlowHandler(config_entries.ConfigFlow):
|
||||
"""Config flow Google Hangouts."""
|
||||
|
@ -46,8 +36,7 @@ class HangoutsFlowHandler(config_entries.ConfigFlow):
|
|||
"""Handle a flow start."""
|
||||
errors = {}
|
||||
|
||||
if configured_hangouts(self.hass) is not None:
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match()
|
||||
|
||||
if user_input is not None:
|
||||
user_email = user_input[CONF_EMAIL]
|
||||
|
|
|
@ -85,8 +85,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
parsed_url = urlparse(discovery_info[ssdp.ATTR_SSDP_LOCATION])
|
||||
friendly_name = discovery_info[ssdp.ATTR_UPNP_FRIENDLY_NAME]
|
||||
|
||||
if self._host_already_configured(parsed_url.hostname):
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match({CONF_HOST: parsed_url.hostname})
|
||||
|
||||
self.context["title_placeholders"] = {"name": friendly_name}
|
||||
|
||||
|
@ -147,16 +146,6 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
|
||||
return self.async_create_entry(title=validated[CONF_NAME], data=data)
|
||||
|
||||
def _host_already_configured(self, host):
|
||||
"""See if we already have a harmony entry matching the host."""
|
||||
for entry in self._async_current_entries():
|
||||
if CONF_HOST not in entry.data:
|
||||
continue
|
||||
|
||||
if entry.data[CONF_HOST] == host:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _options_from_user_input(user_input):
|
||||
options = {}
|
||||
|
|
|
@ -125,12 +125,7 @@ class HueFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
data_schema=vol.Schema({vol.Required(CONF_HOST): str}),
|
||||
)
|
||||
|
||||
if any(
|
||||
user_input["host"] == entry.data.get("host")
|
||||
for entry in self._async_current_entries()
|
||||
):
|
||||
return self.async_abort(reason="already_configured")
|
||||
|
||||
self._async_abort_entries_match({"host": user_input["host"]})
|
||||
self.bridge = self._async_get_bridge(user_input[CONF_HOST])
|
||||
return await self.async_step_link()
|
||||
|
||||
|
@ -233,11 +228,7 @@ class HueFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
This flow is also triggered by `async_step_discovery`.
|
||||
"""
|
||||
# Check if host exists, abort if so.
|
||||
if any(
|
||||
import_info["host"] == entry.data.get("host")
|
||||
for entry in self._async_current_entries()
|
||||
):
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match({"host": import_info["host"]})
|
||||
|
||||
self.bridge = self._async_get_bridge(import_info["host"])
|
||||
return await self.async_step_link()
|
||||
|
|
|
@ -7,7 +7,7 @@ from aiopvapi.helpers.aiorequest import AioRequest
|
|||
import async_timeout
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries, core, data_entry_flow, exceptions
|
||||
from homeassistant import config_entries, core, exceptions
|
||||
from homeassistant.components.dhcp import HOSTNAME, IP_ADDRESS
|
||||
from homeassistant.const import CONF_HOST, CONF_NAME
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
|
@ -73,8 +73,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
)
|
||||
|
||||
async def _async_validate_or_error(self, host):
|
||||
if self._host_already_configured(host):
|
||||
raise data_entry_flow.AbortFlow("already_configured")
|
||||
self._async_abort_entries_match({CONF_HOST: host})
|
||||
|
||||
try:
|
||||
info = await validate_input(self.hass, host)
|
||||
|
@ -118,8 +117,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
if progress.get("context", {}).get(CONF_HOST) == self.discovered_ip:
|
||||
return self.async_abort(reason="already_in_progress")
|
||||
|
||||
if self._host_already_configured(self.discovered_ip):
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match({CONF_HOST: self.discovered_ip})
|
||||
|
||||
info, error = await self._async_validate_or_error(self.discovered_ip)
|
||||
if error:
|
||||
|
@ -148,15 +146,6 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
step_id="link", description_placeholders=self.powerview_config
|
||||
)
|
||||
|
||||
def _host_already_configured(self, host):
|
||||
"""See if we already have a hub with the host address configured."""
|
||||
existing_hosts = {
|
||||
entry.data.get(CONF_HOST)
|
||||
for entry in self._async_current_entries()
|
||||
if CONF_HOST in entry.data
|
||||
}
|
||||
return host in existing_hosts
|
||||
|
||||
|
||||
class CannotConnect(exceptions.HomeAssistantError):
|
||||
"""Error to indicate we cannot connect."""
|
||||
|
|
|
@ -47,9 +47,7 @@ class KeeneticFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
"""Handle a flow initialized by the user."""
|
||||
errors = {}
|
||||
if user_input is not None:
|
||||
for entry in self.hass.config_entries.async_entries(DOMAIN):
|
||||
if entry.data[CONF_HOST] == user_input[CONF_HOST]:
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match({CONF_HOST: user_input[CONF_HOST]})
|
||||
|
||||
_client = Client(
|
||||
TelnetConnection(
|
||||
|
|
|
@ -8,7 +8,7 @@ import voluptuous as vol
|
|||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.const import CONF_BASE, CONF_HOST, CONF_PASSWORD
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
|
||||
from .const import DOMAIN
|
||||
|
@ -23,14 +23,6 @@ DATA_SCHEMA = vol.Schema(
|
|||
)
|
||||
|
||||
|
||||
@callback
|
||||
def configured_instances(hass):
|
||||
"""Return a set of configured Kostal Plenticore HOSTS."""
|
||||
return {
|
||||
entry.data[CONF_HOST] for entry in hass.config_entries.async_entries(DOMAIN)
|
||||
}
|
||||
|
||||
|
||||
async def test_connection(hass: HomeAssistant, data) -> str:
|
||||
"""Test the connection to the inverter.
|
||||
|
||||
|
@ -56,8 +48,8 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
hostname = None
|
||||
|
||||
if user_input is not None:
|
||||
if user_input[CONF_HOST] in configured_instances(self.hass):
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match({CONF_HOST: user_input[CONF_HOST]})
|
||||
|
||||
try:
|
||||
hostname = await test_connection(self.hass, user_input)
|
||||
except PlenticoreAuthenticationException as ex:
|
||||
|
|
|
@ -27,9 +27,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
errors = {}
|
||||
|
||||
if user_input is not None:
|
||||
for entry in self._async_current_entries():
|
||||
if entry.data[CONF_USERNAME] == user_input[CONF_USERNAME]:
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match({CONF_USERNAME: user_input[CONF_USERNAME]})
|
||||
|
||||
hub = LitterRobotHub(self.hass, user_input)
|
||||
try:
|
||||
|
|
|
@ -65,8 +65,7 @@ class LogiCircleFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
|
||||
async def async_step_import(self, user_input=None):
|
||||
"""Handle external yaml configuration."""
|
||||
if self.hass.config_entries.async_entries(DOMAIN):
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match()
|
||||
|
||||
self.flow_impl = DOMAIN
|
||||
|
||||
|
@ -76,8 +75,7 @@ class LogiCircleFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
"""Handle a flow start."""
|
||||
flows = self.hass.data.get(DATA_FLOW_IMPL, {})
|
||||
|
||||
if self.hass.config_entries.async_entries(DOMAIN):
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match()
|
||||
|
||||
if not flows:
|
||||
return self.async_abort(reason="missing_configuration")
|
||||
|
@ -138,8 +136,7 @@ class LogiCircleFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
|
||||
async def async_step_code(self, code=None):
|
||||
"""Received code for authentication."""
|
||||
if self.hass.config_entries.async_entries(DOMAIN):
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match()
|
||||
|
||||
return await self._async_create_session(code)
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@ from homeassistant.const import CONF_HOST, CONF_NAME
|
|||
from homeassistant.core import callback
|
||||
|
||||
from .const import (
|
||||
ABORT_REASON_ALREADY_CONFIGURED,
|
||||
ABORT_REASON_CANNOT_CONNECT,
|
||||
BRIDGE_TIMEOUT,
|
||||
CONF_CA_CERTS,
|
||||
|
@ -89,8 +88,7 @@ class LutronCasetaFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
"""Handle pairing with the hub."""
|
||||
errors = {}
|
||||
# Abort if existing entry with matching host exists.
|
||||
if self._async_data_host_is_already_configured():
|
||||
return self.async_abort(reason=ABORT_REASON_ALREADY_CONFIGURED)
|
||||
self._async_abort_entries_match({CONF_HOST: self.data[CONF_HOST]})
|
||||
|
||||
self._configure_tls_assets()
|
||||
|
||||
|
@ -155,15 +153,6 @@ class LutronCasetaFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
for asset_key, conf_key in FILE_MAPPING.items():
|
||||
self.data[conf_key] = TLS_ASSET_TEMPLATE.format(self.bridge_id, asset_key)
|
||||
|
||||
@callback
|
||||
def _async_data_host_is_already_configured(self):
|
||||
"""Check to see if the host is already configured."""
|
||||
return any(
|
||||
self.data[CONF_HOST] == entry.data[CONF_HOST]
|
||||
for entry in self._async_current_entries()
|
||||
if CONF_HOST in entry.data
|
||||
)
|
||||
|
||||
async def async_step_import(self, import_info):
|
||||
"""Import a new Caseta bridge as a config entry.
|
||||
|
||||
|
@ -174,8 +163,7 @@ class LutronCasetaFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
self.data[CONF_HOST] = host
|
||||
|
||||
# Abort if existing entry with matching host exists.
|
||||
if self._async_data_host_is_already_configured():
|
||||
return self.async_abort(reason=ABORT_REASON_ALREADY_CONFIGURED)
|
||||
self._async_abort_entries_match({CONF_HOST: self.data[CONF_HOST]})
|
||||
|
||||
self.data[CONF_KEYFILE] = import_info[CONF_KEYFILE]
|
||||
self.data[CONF_CERTFILE] = import_info[CONF_CERTFILE]
|
||||
|
|
|
@ -9,7 +9,6 @@ CONF_CA_CERTS = "ca_certs"
|
|||
STEP_IMPORT_FAILED = "import_failed"
|
||||
ERROR_CANNOT_CONNECT = "cannot_connect"
|
||||
ABORT_REASON_CANNOT_CONNECT = "cannot_connect"
|
||||
ABORT_REASON_ALREADY_CONFIGURED = "already_configured"
|
||||
|
||||
BRIDGE_LEAP = "leap"
|
||||
BRIDGE_LIP = "lip"
|
||||
|
|
|
@ -121,9 +121,7 @@ class MotionEyeConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||
|
||||
# Search for duplicates: there isn't a useful unique_id, but
|
||||
# at least prevent entries with the same motionEye URL.
|
||||
for existing_entry in self._async_current_entries(include_ignore=False):
|
||||
if existing_entry.data.get(CONF_URL) == user_input[CONF_URL]:
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match({CONF_URL: user_input[CONF_URL]})
|
||||
|
||||
return self.async_create_entry(
|
||||
title=f"{user_input[CONF_URL]}",
|
||||
|
|
|
@ -17,8 +17,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
|
||||
async def async_step_user(self, user_input=None):
|
||||
"""Handle the initial step."""
|
||||
if self.hass.config_entries.async_entries(DOMAIN):
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match()
|
||||
|
||||
errors = {}
|
||||
if user_input is not None:
|
||||
|
|
|
@ -56,20 +56,6 @@ async def validate_input_owserver(
|
|||
return {"title": host}
|
||||
|
||||
|
||||
def is_duplicate_owserver_entry(
|
||||
hass: HomeAssistant, user_input: dict[str, Any]
|
||||
) -> bool:
|
||||
"""Check existing entries for matching host and port."""
|
||||
for config_entry in hass.config_entries.async_entries(DOMAIN):
|
||||
if (
|
||||
config_entry.data[CONF_TYPE] == CONF_TYPE_OWSERVER
|
||||
and config_entry.data[CONF_HOST] == user_input[CONF_HOST]
|
||||
and config_entry.data[CONF_PORT] == user_input[CONF_PORT]
|
||||
):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
async def validate_input_mount_dir(
|
||||
hass: HomeAssistant, data: dict[str, Any]
|
||||
) -> dict[str, str]:
|
||||
|
@ -125,8 +111,13 @@ class OneWireFlowHandler(ConfigFlow, domain=DOMAIN):
|
|||
errors = {}
|
||||
if user_input:
|
||||
# Prevent duplicate entries
|
||||
if is_duplicate_owserver_entry(self.hass, user_input):
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match(
|
||||
{
|
||||
CONF_TYPE: CONF_TYPE_OWSERVER,
|
||||
CONF_HOST: user_input[CONF_HOST],
|
||||
CONF_PORT: user_input[CONF_PORT],
|
||||
}
|
||||
)
|
||||
|
||||
self.onewire_config.update(user_input)
|
||||
|
||||
|
|
|
@ -49,9 +49,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
|
||||
async def async_step_import(self, conf: dict) -> dict:
|
||||
"""Import a configuration from config.yaml."""
|
||||
for entry in self._async_current_entries():
|
||||
if entry.data[CONF_HOST] == conf[CONF_HOST]:
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match({CONF_HOST: conf[CONF_HOST]})
|
||||
|
||||
return await self.async_step_user(
|
||||
{
|
||||
|
|
|
@ -113,9 +113,7 @@ class PlugwiseConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
user_input[CONF_HOST] = self.discovery_info[CONF_HOST]
|
||||
user_input[CONF_PORT] = self.discovery_info.get(CONF_PORT, DEFAULT_PORT)
|
||||
|
||||
for entry in self._async_current_entries():
|
||||
if entry.data.get(CONF_HOST) == user_input[CONF_HOST]:
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match({CONF_HOST: user_input[CONF_HOST]})
|
||||
|
||||
try:
|
||||
api = await validate_gw_input(self.hass, user_input)
|
||||
|
|
|
@ -12,7 +12,6 @@ import voluptuous as vol
|
|||
from homeassistant import config_entries, core, exceptions
|
||||
from homeassistant.components.dhcp import IP_ADDRESS
|
||||
from homeassistant.const import CONF_IP_ADDRESS, CONF_PASSWORD
|
||||
from homeassistant.core import callback
|
||||
|
||||
from .const import DOMAIN
|
||||
|
||||
|
@ -60,9 +59,8 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
|
||||
async def async_step_dhcp(self, discovery_info):
|
||||
"""Handle dhcp discovery."""
|
||||
if self._async_ip_address_already_configured(discovery_info[IP_ADDRESS]):
|
||||
return self.async_abort(reason="already_configured")
|
||||
|
||||
self.ip_address = discovery_info[IP_ADDRESS]
|
||||
self._async_abort_entries_match({CONF_IP_ADDRESS: self.ip_address})
|
||||
self.ip_address = discovery_info[IP_ADDRESS]
|
||||
self.context["title_placeholders"] = {CONF_IP_ADDRESS: self.ip_address}
|
||||
return await self.async_step_user()
|
||||
|
@ -111,14 +109,6 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
self.ip_address = data[CONF_IP_ADDRESS]
|
||||
return await self.async_step_user()
|
||||
|
||||
@callback
|
||||
def _async_ip_address_already_configured(self, ip_address):
|
||||
"""See if we already have an entry matching the ip_address."""
|
||||
for entry in self._async_current_entries():
|
||||
if entry.data.get(CONF_IP_ADDRESS) == ip_address:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class WrongVersion(exceptions.HomeAssistantError):
|
||||
"""Error to indicate the powerwall uses a software version we cannot interact with."""
|
||||
|
|
|
@ -15,17 +15,6 @@ DATA_SCHEMA = vol.Schema(
|
|||
async def validate_input(hass: core.HomeAssistant, data):
|
||||
"""Validate the user host input."""
|
||||
|
||||
confs = hass.config_entries.async_entries(DOMAIN)
|
||||
same_entries = [
|
||||
True
|
||||
for entry in confs
|
||||
if entry.data.get("host") == data["host"]
|
||||
and entry.data.get("port") == data["port"]
|
||||
]
|
||||
|
||||
if same_entries:
|
||||
raise ExistingEntry
|
||||
|
||||
api_instance = ProgettiHWSWAPI(f'{data["host"]}:{data["port"]}')
|
||||
is_valid = await api_instance.check_board()
|
||||
|
||||
|
@ -80,13 +69,14 @@ class ProgettiHWSWConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
"""Handle the initial step."""
|
||||
errors = {}
|
||||
if user_input is not None:
|
||||
self._async_abort_entries_match(
|
||||
{"host": user_input["host"], "port": user_input["port"]}
|
||||
)
|
||||
|
||||
try:
|
||||
info = await validate_input(self.hass, user_input)
|
||||
except CannotConnect:
|
||||
errors["base"] = "cannot_connect"
|
||||
except ExistingEntry:
|
||||
return self.async_abort(reason="already_configured")
|
||||
except Exception: # pylint: disable=broad-except
|
||||
errors["base"] = "unknown"
|
||||
else:
|
||||
|
|
|
@ -79,14 +79,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
|
||||
async def async_step_homekit(self, discovery_info):
|
||||
"""Handle HomeKit discovery."""
|
||||
if self._async_current_entries():
|
||||
# We can see rachio on the network to tell them to configure
|
||||
# it, but since the device will not give up the account it is
|
||||
# bound to and there can be multiple rachio systems on a single
|
||||
# account, we avoid showing the device as discovered once
|
||||
# they already have one configured as they can always
|
||||
# add a new one via "+"
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match()
|
||||
properties = {
|
||||
key.lower(): value for (key, value) in discovery_info["properties"].items()
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import voluptuous as vol
|
|||
from homeassistant import config_entries
|
||||
from homeassistant.const import CONF_IP_ADDRESS, CONF_PASSWORD, CONF_PORT, CONF_SSL
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.data_entry_flow import AbortFlow
|
||||
from homeassistant.helpers import aiohttp_client, config_validation as cv
|
||||
from homeassistant.helpers.typing import DiscoveryInfoType
|
||||
|
||||
|
@ -53,14 +52,6 @@ class RainMachineFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
"""Define the config flow to handle options."""
|
||||
return RainMachineOptionsFlowHandler(config_entry)
|
||||
|
||||
@callback
|
||||
def _async_abort_ip_address_configured(self, ip_address):
|
||||
"""Abort if we already have an entry for the ip."""
|
||||
# IP already configured
|
||||
for entry in self._async_current_entries(include_ignore=False):
|
||||
if ip_address == entry.data[CONF_IP_ADDRESS]:
|
||||
raise AbortFlow("already_configured")
|
||||
|
||||
async def async_step_homekit(self, discovery_info):
|
||||
"""Handle a flow initialized by homekit discovery."""
|
||||
return await self.async_step_zeroconf(discovery_info)
|
||||
|
@ -69,7 +60,7 @@ class RainMachineFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
"""Handle discovery via zeroconf."""
|
||||
ip_address = discovery_info["host"]
|
||||
|
||||
self._async_abort_ip_address_configured(ip_address)
|
||||
self._async_abort_entries_match({CONF_IP_ADDRESS: ip_address})
|
||||
# Handle IP change
|
||||
for entry in self._async_current_entries(include_ignore=False):
|
||||
# Try our existing credentials to check for ip change
|
||||
|
@ -109,7 +100,9 @@ class RainMachineFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
"""Handle the start of the config flow."""
|
||||
errors = {}
|
||||
if user_input:
|
||||
self._async_abort_ip_address_configured(user_input[CONF_IP_ADDRESS])
|
||||
self._async_abort_entries_match(
|
||||
{CONF_IP_ADDRESS: user_input[CONF_IP_ADDRESS]}
|
||||
)
|
||||
controller = await async_get_controller(
|
||||
self.hass,
|
||||
user_input[CONF_IP_ADDRESS],
|
||||
|
|
|
@ -88,8 +88,7 @@ class RokuConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||
|
||||
# If we already have the host configured do
|
||||
# not open connections to it if we can avoid it.
|
||||
if self._host_already_configured(discovery_info[CONF_HOST]):
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match({CONF_HOST: discovery_info[CONF_HOST]})
|
||||
|
||||
self.discovery_info.update({CONF_HOST: discovery_info[CONF_HOST]})
|
||||
|
||||
|
@ -151,12 +150,3 @@ class RokuConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||
title=self.discovery_info[CONF_NAME],
|
||||
data=self.discovery_info,
|
||||
)
|
||||
|
||||
def _host_already_configured(self, host):
|
||||
"""See if we already have a hub with the host address configured."""
|
||||
existing_hosts = {
|
||||
entry.data[CONF_HOST]
|
||||
for entry in self._async_current_entries()
|
||||
if CONF_HOST in entry.data
|
||||
}
|
||||
return host in existing_hosts
|
||||
|
|
|
@ -79,8 +79,7 @@ class RoombaConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
|
||||
async def async_step_dhcp(self, discovery_info):
|
||||
"""Handle dhcp discovery."""
|
||||
if self._async_host_already_configured(discovery_info[IP_ADDRESS]):
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match({CONF_HOST: discovery_info[IP_ADDRESS]})
|
||||
|
||||
if not discovery_info[HOSTNAME].startswith(("irobot-", "roomba-")):
|
||||
return self.async_abort(reason="not_irobot_device")
|
||||
|
@ -183,11 +182,7 @@ class RoombaConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
),
|
||||
)
|
||||
|
||||
if any(
|
||||
user_input["host"] == entry.data.get("host")
|
||||
for entry in self._async_current_entries()
|
||||
):
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match({CONF_HOST: user_input["host"]})
|
||||
|
||||
self.host = user_input[CONF_HOST]
|
||||
self.blid = user_input[CONF_BLID].upper()
|
||||
|
@ -260,14 +255,6 @@ class RoombaConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
errors=errors,
|
||||
)
|
||||
|
||||
@callback
|
||||
def _async_host_already_configured(self, host):
|
||||
"""See if we already have an entry matching the host."""
|
||||
for entry in self._async_current_entries():
|
||||
if entry.data.get(CONF_HOST) == host:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class OptionsFlowHandler(config_entries.OptionsFlow):
|
||||
"""Handle options."""
|
||||
|
|
|
@ -60,8 +60,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
|
||||
async def async_step_dhcp(self, discovery_info):
|
||||
"""Handle dhcp discovery."""
|
||||
if self._host_already_configured(discovery_info[IP_ADDRESS]):
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match({CONF_HOST: discovery_info[IP_ADDRESS]})
|
||||
|
||||
formatted_mac = format_mac(discovery_info[MAC_ADDRESS])
|
||||
await self.async_set_unique_id(format_mac(formatted_mac))
|
||||
|
@ -79,8 +78,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
errors = {}
|
||||
|
||||
if user_input is not None:
|
||||
if self._host_already_configured(user_input[CONF_HOST]):
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match({CONF_HOST: user_input[CONF_HOST]})
|
||||
|
||||
try:
|
||||
info = await validate_input(self.hass, user_input)
|
||||
|
@ -108,18 +106,9 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
|
||||
async def async_step_import(self, user_input):
|
||||
"""Handle import."""
|
||||
if self._host_already_configured(user_input[CONF_HOST]):
|
||||
return self.async_abort(reason="already_configured")
|
||||
|
||||
self._async_abort_entries_match({CONF_HOST: user_input[CONF_HOST]})
|
||||
return await self.async_step_user(user_input)
|
||||
|
||||
def _host_already_configured(self, host):
|
||||
"""See if we already have an entry matching the host."""
|
||||
for entry in self._async_current_entries():
|
||||
if entry.data.get(CONF_HOST) == host:
|
||||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
@callback
|
||||
def async_get_options_flow(config_entry):
|
||||
|
|
|
@ -10,7 +10,6 @@ import voluptuous as vol
|
|||
from homeassistant import config_entries
|
||||
from homeassistant.components import ssdp
|
||||
from homeassistant.const import CONF_HOST, CONF_NAME
|
||||
from homeassistant.core import callback
|
||||
|
||||
from .const import CONF_ENDPOINT, DOMAIN
|
||||
|
||||
|
@ -75,9 +74,7 @@ class SongpalConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
async def async_step_init(self, user_input=None):
|
||||
"""Handle a flow start."""
|
||||
# Check if already configured
|
||||
if self._async_endpoint_already_configured():
|
||||
return self.async_abort(reason="already_configured")
|
||||
|
||||
self._async_abort_entries_match({CONF_ENDPOINT: self.conf.endpoint})
|
||||
if user_input is None:
|
||||
return self.async_show_form(
|
||||
step_id="init",
|
||||
|
@ -144,11 +141,3 @@ class SongpalConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
self.conf = SongpalConfig(name, parsed_url.hostname, endpoint)
|
||||
|
||||
return await self.async_step_init(user_input)
|
||||
|
||||
@callback
|
||||
def _async_endpoint_already_configured(self):
|
||||
"""See if we already have an endpoint matching user input configured."""
|
||||
for entry in self._async_current_entries():
|
||||
if entry.data.get(CONF_ENDPOINT) == self.conf.endpoint:
|
||||
return True
|
||||
return False
|
||||
|
|
|
@ -37,10 +37,7 @@ class SubaruConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
error = None
|
||||
|
||||
if user_input:
|
||||
if user_input[CONF_USERNAME] in [
|
||||
entry.data[CONF_USERNAME] for entry in self._async_current_entries()
|
||||
]:
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match({CONF_USERNAME: user_input[CONF_USERNAME]})
|
||||
|
||||
try:
|
||||
await self.validate_login_creds(user_input)
|
||||
|
|
|
@ -82,14 +82,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
|
||||
async def async_step_homekit(self, discovery_info):
|
||||
"""Handle HomeKit discovery."""
|
||||
if self._async_current_entries():
|
||||
# We can see tado on the network to tell them to configure
|
||||
# it, but since the device will not give up the account it is
|
||||
# bound to and there can be multiple tado devices on a single
|
||||
# account, we avoid showing the device as discovered once
|
||||
# they already have one configured as they can always
|
||||
# add a new one via "+"
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match()
|
||||
properties = {
|
||||
key.lower(): value for (key, value) in discovery_info["properties"].items()
|
||||
}
|
||||
|
|
|
@ -26,8 +26,7 @@ class TibberConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
async def async_step_user(self, user_input=None):
|
||||
"""Handle the initial step."""
|
||||
|
||||
if self._async_current_entries():
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match()
|
||||
|
||||
if user_input is not None:
|
||||
access_token = user_input[CONF_ACCESS_TOKEN].replace(" ", "")
|
||||
|
|
|
@ -106,9 +106,7 @@ class FlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
|
||||
async def async_step_import(self, user_input):
|
||||
"""Import a config entry."""
|
||||
for entry in self._async_current_entries():
|
||||
if entry.data.get(CONF_HOST) == user_input["host"]:
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match({CONF_HOST: user_input["host"]})
|
||||
|
||||
# Happens if user has host directly in configuration.yaml
|
||||
if "key" not in user_input:
|
||||
|
|
|
@ -66,10 +66,7 @@ class TwenteMilieuFlowHandler(ConfigFlow, domain=DOMAIN):
|
|||
errors["base"] = "invalid_address"
|
||||
return await self._show_setup_form(errors)
|
||||
|
||||
entries = self._async_current_entries()
|
||||
for entry in entries:
|
||||
if entry.data[CONF_ID] == unique_id:
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match({CONF_ID: unique_id})
|
||||
|
||||
return self.async_create_entry(
|
||||
title=str(unique_id),
|
||||
|
|
|
@ -225,8 +225,7 @@ class UnifiFlowHandler(config_entries.ConfigFlow, domain=UNIFI_DOMAIN):
|
|||
CONF_HOST: parsed_url.hostname,
|
||||
}
|
||||
|
||||
if self._host_already_configured(self.config[CONF_HOST]):
|
||||
return self.async_abort(reason="already_configured")
|
||||
self._async_abort_entries_match({CONF_HOST: self.config[CONF_HOST]})
|
||||
|
||||
await self.async_set_unique_id(mac_address)
|
||||
self._abort_if_unique_id_configured(updates=self.config)
|
||||
|
@ -242,13 +241,6 @@ class UnifiFlowHandler(config_entries.ConfigFlow, domain=UNIFI_DOMAIN):
|
|||
|
||||
return await self.async_step_user()
|
||||
|
||||
def _host_already_configured(self, host):
|
||||
"""See if we already have a UniFi entry matching the host."""
|
||||
for entry in self._async_current_entries():
|
||||
if entry.data.get(CONF_HOST) == host:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class UnifiOptionsFlowHandler(config_entries.OptionsFlow):
|
||||
"""Handle Unifi options."""
|
||||
|
|
|
@ -52,8 +52,6 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
)
|
||||
except CannotConnect:
|
||||
errors["base"] = "cannot_connect"
|
||||
except AlreadyConfigured:
|
||||
return self.async_abort(reason="already_configured")
|
||||
else:
|
||||
return await self.async_step_pick_device()
|
||||
|
||||
|
@ -114,8 +112,6 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
except CannotConnect:
|
||||
_LOGGER.error("Failed to import %s: cannot connect", host)
|
||||
return self.async_abort(reason="cannot_connect")
|
||||
except AlreadyConfigured:
|
||||
return self.async_abort(reason="already_configured")
|
||||
if CONF_NIGHTLIGHT_SWITCH_TYPE in user_input:
|
||||
user_input[CONF_NIGHTLIGHT_SWITCH] = (
|
||||
user_input.pop(CONF_NIGHTLIGHT_SWITCH_TYPE)
|
||||
|
@ -125,9 +121,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
|
||||
async def _async_try_connect(self, host):
|
||||
"""Set up with options."""
|
||||
for entry in self._async_current_entries():
|
||||
if entry.data.get(CONF_HOST) == host:
|
||||
raise AlreadyConfigured
|
||||
self._async_abort_entries_match({CONF_HOST: host})
|
||||
|
||||
bulb = yeelight.Bulb(host)
|
||||
try:
|
||||
|
@ -195,7 +189,3 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
|
|||
|
||||
class CannotConnect(exceptions.HomeAssistantError):
|
||||
"""Error to indicate we cannot connect."""
|
||||
|
||||
|
||||
class AlreadyConfigured(exceptions.HomeAssistantError):
|
||||
"""Indicate the ip address is already configured."""
|
||||
|
|
|
@ -1085,6 +1085,17 @@ class ConfigFlow(data_entry_flow.FlowHandler):
|
|||
"""Get the options flow for this handler."""
|
||||
raise data_entry_flow.UnknownHandler
|
||||
|
||||
@callback
|
||||
def _async_abort_entries_match(
|
||||
self, match_dict: dict[str, Any] | None = None
|
||||
) -> None:
|
||||
"""Abort if current entries match all data."""
|
||||
if match_dict is None:
|
||||
match_dict = {} # Match any entry
|
||||
for entry in self._async_current_entries(include_ignore=False):
|
||||
if all(item in entry.data.items() for item in match_dict.items()):
|
||||
raise data_entry_flow.AbortFlow("already_configured")
|
||||
|
||||
@callback
|
||||
def _abort_if_unique_id_configured(
|
||||
self,
|
||||
|
|
|
@ -2,14 +2,17 @@
|
|||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
import ambiclimate
|
||||
import pytest
|
||||
|
||||
from homeassistant import data_entry_flow
|
||||
from homeassistant import config_entries, data_entry_flow
|
||||
from homeassistant.components.ambiclimate import config_flow
|
||||
from homeassistant.config import async_process_ha_core_config
|
||||
from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET
|
||||
from homeassistant.setup import async_setup_component
|
||||
from homeassistant.util import aiohttp
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
async def init_config_flow(hass):
|
||||
"""Init a configuration flow."""
|
||||
|
@ -40,12 +43,15 @@ async def test_abort_if_already_setup(hass):
|
|||
"""Test we abort if Ambiclimate is already setup."""
|
||||
flow = await init_config_flow(hass)
|
||||
|
||||
with patch.object(hass.config_entries, "async_entries", return_value=[{}]):
|
||||
result = await flow.async_step_user()
|
||||
MockConfigEntry(domain=config_flow.DOMAIN).add_to_hass(hass)
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN,
|
||||
context={"source": config_entries.SOURCE_USER},
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "already_configured"
|
||||
|
||||
with patch.object(hass.config_entries, "async_entries", return_value=[{}]):
|
||||
with pytest.raises(data_entry_flow.AbortFlow):
|
||||
result = await flow.async_step_code()
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "already_configured"
|
||||
|
@ -103,11 +109,11 @@ async def test_abort_invalid_code(hass):
|
|||
|
||||
async def test_already_setup(hass):
|
||||
"""Test when already setup."""
|
||||
config_flow.register_flow_implementation(hass, None, None)
|
||||
flow = await init_config_flow(hass)
|
||||
|
||||
with patch.object(hass.config_entries, "async_entries", return_value=True):
|
||||
result = await flow.async_step_user()
|
||||
MockConfigEntry(domain=config_flow.DOMAIN).add_to_hass(hass)
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN,
|
||||
context={"source": config_entries.SOURCE_USER},
|
||||
)
|
||||
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "already_configured"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
"""Tests for emulated_roku config flow."""
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components.emulated_roku import config_flow
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
@ -6,10 +7,10 @@ from tests.common import MockConfigEntry
|
|||
|
||||
async def test_flow_works(hass):
|
||||
"""Test that config flow works."""
|
||||
flow = config_flow.EmulatedRokuFlowHandler()
|
||||
flow.hass = hass
|
||||
result = await flow.async_step_user(
|
||||
user_input={"name": "Emulated Roku Test", "listen_port": 8060}
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN,
|
||||
context={"source": config_entries.SOURCE_USER},
|
||||
data={"name": "Emulated Roku Test", "listen_port": 8060},
|
||||
)
|
||||
|
||||
assert result["type"] == "create_entry"
|
||||
|
@ -22,10 +23,12 @@ async def test_flow_already_registered_entry(hass):
|
|||
MockConfigEntry(
|
||||
domain="emulated_roku", data={"name": "Emulated Roku Test", "listen_port": 8062}
|
||||
).add_to_hass(hass)
|
||||
flow = config_flow.EmulatedRokuFlowHandler()
|
||||
flow.hass = hass
|
||||
|
||||
result = await flow.async_step_user(
|
||||
user_input={"name": "Emulated Roku Test", "listen_port": 8062}
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN,
|
||||
context={"source": config_entries.SOURCE_USER},
|
||||
data={"name": "Emulated Roku Test", "listen_port": 8062},
|
||||
)
|
||||
|
||||
assert result["type"] == "abort"
|
||||
assert result["reason"] == "already_configured"
|
||||
|
|
|
@ -5,7 +5,6 @@ from unittest.mock import ANY, AsyncMock, MagicMock, patch
|
|||
from kostal.plenticore import PlenticoreAuthenticationException
|
||||
|
||||
from homeassistant import config_entries, setup
|
||||
from homeassistant.components.kostal_plenticore import config_flow
|
||||
from homeassistant.components.kostal_plenticore.const import DOMAIN
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
@ -188,16 +187,3 @@ async def test_already_configured(hass):
|
|||
|
||||
assert result2["type"] == "abort"
|
||||
assert result2["reason"] == "already_configured"
|
||||
|
||||
|
||||
def test_configured_instances(hass):
|
||||
"""Test configured_instances returns all configured hosts."""
|
||||
MockConfigEntry(
|
||||
domain="kostal_plenticore",
|
||||
data={"host": "2.2.2.2", "password": "foobar"},
|
||||
unique_id="112233445566",
|
||||
).add_to_hass(hass)
|
||||
|
||||
result = config_flow.configured_instances(hass)
|
||||
|
||||
assert result == {"2.2.2.2"}
|
||||
|
|
|
@ -4,7 +4,7 @@ from unittest.mock import AsyncMock, Mock, patch
|
|||
|
||||
import pytest
|
||||
|
||||
from homeassistant import data_entry_flow
|
||||
from homeassistant import config_entries, data_entry_flow
|
||||
from homeassistant.components.logi_circle import config_flow
|
||||
from homeassistant.components.logi_circle.config_flow import (
|
||||
DOMAIN,
|
||||
|
@ -13,7 +13,7 @@ from homeassistant.components.logi_circle.config_flow import (
|
|||
)
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from tests.common import mock_coro
|
||||
from tests.common import MockConfigEntry, mock_coro
|
||||
|
||||
|
||||
class MockRequest:
|
||||
|
@ -121,24 +121,26 @@ async def test_abort_if_no_implementation_registered(hass):
|
|||
async def test_abort_if_already_setup(hass):
|
||||
"""Test we abort if Logi Circle is already setup."""
|
||||
flow = init_config_flow(hass)
|
||||
MockConfigEntry(domain=config_flow.DOMAIN).add_to_hass(hass)
|
||||
|
||||
with patch.object(hass.config_entries, "async_entries", return_value=[{}]):
|
||||
result = await flow.async_step_user()
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN,
|
||||
context={"source": config_entries.SOURCE_USER},
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "already_configured"
|
||||
|
||||
with patch.object(hass.config_entries, "async_entries", return_value=[{}]):
|
||||
result = await flow.async_step_import()
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
config_flow.DOMAIN,
|
||||
context={"source": config_entries.SOURCE_IMPORT},
|
||||
)
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "already_configured"
|
||||
|
||||
with patch.object(hass.config_entries, "async_entries", return_value=[{}]):
|
||||
with pytest.raises(data_entry_flow.AbortFlow):
|
||||
result = await flow.async_step_code()
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "already_configured"
|
||||
|
||||
with patch.object(hass.config_entries, "async_entries", return_value=[{}]):
|
||||
result = await flow.async_step_auth()
|
||||
result = await flow.async_step_auth()
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||
assert result["reason"] == "external_setup"
|
||||
|
||||
|
|
|
@ -189,7 +189,7 @@ async def test_duplicate_bridge_import(hass):
|
|||
)
|
||||
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||
assert result["reason"] == CasetaConfigFlow.ABORT_REASON_ALREADY_CONFIGURED
|
||||
assert result["reason"] == "already_configured"
|
||||
assert len(mock_setup_entry.mock_calls) == 0
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
"""Tests for the Twente Milieu config flow."""
|
||||
import aiohttp
|
||||
|
||||
from homeassistant import data_entry_flow
|
||||
from homeassistant import config_entries, data_entry_flow
|
||||
from homeassistant.components.twentemilieu import config_flow
|
||||
from homeassistant.components.twentemilieu.const import (
|
||||
CONF_HOUSE_LETTER,
|
||||
CONF_HOUSE_NUMBER,
|
||||
|
@ -83,7 +84,9 @@ async def test_address_already_set_up(
|
|||
)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": SOURCE_USER}, data=FIXTURE_USER_INPUT
|
||||
config_flow.DOMAIN,
|
||||
context={"source": config_entries.SOURCE_USER},
|
||||
data=FIXTURE_USER_INPUT,
|
||||
)
|
||||
|
||||
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
|
||||
|
|
|
@ -2755,3 +2755,60 @@ async def test_setup_retrying_during_shutdown(hass):
|
|||
await hass.async_block_till_done()
|
||||
|
||||
assert len(mock_call.return_value.mock_calls) == 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"matchers, reason",
|
||||
[
|
||||
({}, "already_configured"),
|
||||
({"host": "3.3.3.3"}, "no_match"),
|
||||
({"host": "3.4.5.6"}, "already_configured"),
|
||||
({"host": "3.4.5.6", "ip": "3.4.5.6"}, "no_match"),
|
||||
({"host": "3.4.5.6", "ip": "1.2.3.4"}, "already_configured"),
|
||||
({"host": "3.4.5.6", "ip": "1.2.3.4", "port": 23}, "already_configured"),
|
||||
({"ip": "9.9.9.9"}, "already_configured"),
|
||||
({"ip": "7.7.7.7"}, "no_match"), # ignored
|
||||
],
|
||||
)
|
||||
async def test__async_abort_entries_match(hass, manager, matchers, reason):
|
||||
"""Test aborting if matching config entries exist."""
|
||||
MockConfigEntry(
|
||||
domain="comp", data={"ip": "1.2.3.4", "host": "4.5.6.7", "port": 23}
|
||||
).add_to_hass(hass)
|
||||
MockConfigEntry(
|
||||
domain="comp", data={"ip": "9.9.9.9", "host": "4.5.6.7", "port": 23}
|
||||
).add_to_hass(hass)
|
||||
MockConfigEntry(
|
||||
domain="comp", data={"ip": "1.2.3.4", "host": "3.4.5.6", "port": 23}
|
||||
).add_to_hass(hass)
|
||||
MockConfigEntry(
|
||||
domain="comp",
|
||||
source=config_entries.SOURCE_IGNORE,
|
||||
data={"ip": "7.7.7.7", "host": "4.5.6.7", "port": 23},
|
||||
).add_to_hass(hass)
|
||||
|
||||
await async_setup_component(hass, "persistent_notification", {})
|
||||
|
||||
mock_setup_entry = AsyncMock(return_value=True)
|
||||
|
||||
mock_integration(hass, MockModule("comp", async_setup_entry=mock_setup_entry))
|
||||
mock_entity_platform(hass, "config_flow.comp", None)
|
||||
|
||||
class TestFlow(config_entries.ConfigFlow):
|
||||
"""Test flow."""
|
||||
|
||||
VERSION = 1
|
||||
|
||||
async def async_step_user(self, user_input=None):
|
||||
"""Test user step."""
|
||||
self._async_abort_entries_match(matchers)
|
||||
return self.async_abort(reason="no_match")
|
||||
|
||||
with patch.dict(config_entries.HANDLERS, {"comp": TestFlow, "beer": 5}):
|
||||
result = await manager.flow.async_init(
|
||||
"comp", context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result["type"] == "abort"
|
||||
assert result["reason"] == reason
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue