Add updates argument to update_reload_and_abort helper (#127781)

* Add updates argument to update_reload_and_abort helper

* Also apply to airvisual_pro

* Rename argument

* docstring

* Use modern syntax

Co-authored-by: Erik Montnemery <erik@montnemery.com>

* Apply suggestion

Co-authored-by: Erik Montnemery <erik@montnemery.com>

* Apply suggestion

* Docstring

---------

Co-authored-by: Erik Montnemery <erik@montnemery.com>
pull/127989/head
epenet 2024-10-09 07:47:18 +02:00 committed by GitHub
parent 2dec36f210
commit 99eb466223
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 74 additions and 15 deletions

View File

@ -14,7 +14,7 @@ from pyairvisual.node import (
)
import voluptuous as vol
from homeassistant.config_entries import ConfigEntry, ConfigFlow, ConfigFlowResult
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
from homeassistant.const import CONF_IP_ADDRESS, CONF_PASSWORD
from .const import DOMAIN, LOGGER
@ -76,7 +76,7 @@ class AirVisualProFlowHandler(ConfigFlow, domain=DOMAIN):
VERSION = 1
_reauth_entry: ConfigEntry
_reauth_entry_data: Mapping[str, Any]
async def async_step_import(self, import_data: dict[str, Any]) -> ConfigFlowResult:
"""Import a config entry from `airvisual` integration (see #83882)."""
@ -86,7 +86,7 @@ class AirVisualProFlowHandler(ConfigFlow, domain=DOMAIN):
self, entry_data: Mapping[str, Any]
) -> ConfigFlowResult:
"""Handle configuration by re-auth."""
self._reauth_entry = self._get_reauth_entry()
self._reauth_entry_data = entry_data
return await self.async_step_reauth_confirm()
async def async_step_reauth_confirm(
@ -99,7 +99,7 @@ class AirVisualProFlowHandler(ConfigFlow, domain=DOMAIN):
)
validation_result = await async_validate_credentials(
self._reauth_entry.data[CONF_IP_ADDRESS], user_input[CONF_PASSWORD]
self._reauth_entry_data[CONF_IP_ADDRESS], user_input[CONF_PASSWORD]
)
if validation_result.errors:
@ -110,7 +110,7 @@ class AirVisualProFlowHandler(ConfigFlow, domain=DOMAIN):
)
return self.async_update_reload_and_abort(
self._reauth_entry, data=self._reauth_entry.data | user_input
self._get_reauth_entry(), data_updates=user_input
)
async def async_step_user(

View File

@ -88,12 +88,11 @@ class AOSmithConfigFlow(ConfigFlow, domain=DOMAIN):
if user_input:
password = user_input[CONF_PASSWORD]
entry = self._get_reauth_entry()
error = await self._async_validate_credentials(self._reauth_email, password)
if error is None:
return self.async_update_reload_and_abort(
entry,
data=entry.data | user_input,
self._get_reauth_entry(),
data_updates=user_input,
)
errors["base"] = error

View File

@ -2761,11 +2761,30 @@ class ConfigFlow(ConfigEntryBaseFlow):
unique_id: str | None | UndefinedType = UNDEFINED,
title: str | UndefinedType = UNDEFINED,
data: Mapping[str, Any] | UndefinedType = UNDEFINED,
data_updates: Mapping[str, Any] | UndefinedType = UNDEFINED,
options: Mapping[str, Any] | UndefinedType = UNDEFINED,
reason: str | UndefinedType = UNDEFINED,
reload_even_if_entry_is_unchanged: bool = True,
) -> ConfigFlowResult:
"""Update config entry, reload config entry and finish config flow."""
"""Update config entry, reload config entry and finish config flow.
:param data: replace the entry data with new data
:param data_updates: add items from data_updates to entry data - existing keys
are overridden
:param options: replace the entry options with new options
:param title: replace the title of the entry
:param unique_id: replace the unique_id of the entry
:param reason: set the reason for the abort, defaults to
`reauth_successful` or `reconfigure_successful` based on flow source
:param reload_even_if_entry_is_unchanged: set this to `False` if the entry
should not be reloaded if it is unchanged
"""
if data_updates is not UNDEFINED:
if data is not UNDEFINED:
raise ValueError("Cannot set both data and data_updates")
data = entry.data | data_updates
result = self.hass.config_entries.async_update_entry(
entry=entry,
unique_id=unique_id,

View File

@ -5122,6 +5122,7 @@ def test_raise_trying_to_add_same_config_entry_twice(
"expected_data",
"expected_options",
"calls_entry_load_unload",
"raises",
),
[
(
@ -5136,6 +5137,7 @@ def test_raise_trying_to_add_same_config_entry_twice(
{"vendor": "data2"},
{"vendor": "options2"},
(2, 1),
None,
),
(
{
@ -5149,6 +5151,7 @@ def test_raise_trying_to_add_same_config_entry_twice(
{"vendor": "data"},
{"vendor": "options"},
(2, 1),
None,
),
(
{
@ -5163,6 +5166,7 @@ def test_raise_trying_to_add_same_config_entry_twice(
{"vendor": "data2"},
{"vendor": "options2"},
(2, 1),
None,
),
(
{
@ -5177,6 +5181,7 @@ def test_raise_trying_to_add_same_config_entry_twice(
{"vendor": "data"},
{"vendor": "options"},
(1, 0),
None,
),
(
{},
@ -5185,6 +5190,7 @@ def test_raise_trying_to_add_same_config_entry_twice(
{"vendor": "data"},
{"vendor": "options"},
(2, 1),
None,
),
(
{"data": {"buyer": "me"}, "options": {}},
@ -5193,6 +5199,31 @@ def test_raise_trying_to_add_same_config_entry_twice(
{"buyer": "me"},
{},
(2, 1),
None,
),
(
{"data_updates": {"buyer": "me"}},
"Test",
"1234",
{"vendor": "data", "buyer": "me"},
{"vendor": "options"},
(2, 1),
None,
),
(
{
"unique_id": "5678",
"title": "Updated title",
"data": {"vendor": "data2"},
"options": {"vendor": "options2"},
"data_updates": {"buyer": "me"},
},
"Test",
"1234",
{"vendor": "data"},
{"vendor": "options"},
(1, 0),
ValueError,
),
],
ids=[
@ -5202,6 +5233,8 @@ def test_raise_trying_to_add_same_config_entry_twice(
"unchanged_entry_no_reload",
"no_kwargs",
"replace_data",
"update_data",
"update_and_data_raises",
],
)
@pytest.mark.parametrize(
@ -5221,6 +5254,7 @@ async def test_update_entry_and_reload(
expected_options: dict[str, Any],
kwargs: dict[str, Any],
calls_entry_load_unload: tuple[int, int],
raises: type[Exception] | None,
) -> None:
"""Test updating an entry and reloading."""
entry = MockConfigEntry(
@ -5255,11 +5289,15 @@ async def test_update_entry_and_reload(
"""Mock Reconfigure."""
return self.async_update_reload_and_abort(entry, **kwargs)
err: Exception
with mock_config_flow("comp", MockFlowHandler):
if source == config_entries.SOURCE_REAUTH:
result = await entry.start_reauth_flow(hass)
elif source == config_entries.SOURCE_RECONFIGURE:
result = await entry.start_reconfigure_flow(hass)
try:
if source == config_entries.SOURCE_REAUTH:
result = await entry.start_reauth_flow(hass)
elif source == config_entries.SOURCE_RECONFIGURE:
result = await entry.start_reconfigure_flow(hass)
except Exception as ex: # noqa: BLE001
err = ex
await hass.async_block_till_done()
@ -5268,8 +5306,11 @@ async def test_update_entry_and_reload(
assert entry.data == expected_data
assert entry.options == expected_options
assert entry.state == config_entries.ConfigEntryState.LOADED
assert result["type"] == FlowResultType.ABORT
assert result["reason"] == reason
if raises:
assert isinstance(err, raises)
else:
assert result["type"] == FlowResultType.ABORT
assert result["reason"] == reason
# Assert entry was reloaded
assert len(comp.async_setup_entry.mock_calls) == calls_entry_load_unload[0]
assert len(comp.async_unload_entry.mock_calls) == calls_entry_load_unload[1]