Add reconfigure flow to filesize (#131106)

This commit is contained in:
G Johansson 2024-11-26 10:29:46 +01:00 committed by GitHub
parent 7e58aa8af1
commit 066af3a5da
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 156 additions and 21 deletions

View File

@ -11,7 +11,6 @@ import voluptuous as vol
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
from homeassistant.const import CONF_FILE_PATH
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from .const import DOMAIN
@ -20,20 +19,20 @@ DATA_SCHEMA = vol.Schema({vol.Required(CONF_FILE_PATH): str})
_LOGGER = logging.getLogger(__name__)
def validate_path(hass: HomeAssistant, path: str) -> str:
def validate_path(hass: HomeAssistant, path: str) -> tuple[str | None, dict[str, str]]:
"""Validate path."""
get_path = pathlib.Path(path)
if not get_path.exists() or not get_path.is_file():
_LOGGER.error("Can not access file %s", path)
raise NotValidError
return (None, {"base": "not_valid"})
if not hass.config.is_allowed_path(path):
_LOGGER.error("Filepath %s is not allowed", path)
raise NotAllowedError
return (None, {"base": "not_allowed"})
full_path = get_path.absolute()
return str(full_path)
return (str(full_path), {})
class FilesizeConfigFlow(ConfigFlow, domain=DOMAIN):
@ -45,18 +44,13 @@ class FilesizeConfigFlow(ConfigFlow, domain=DOMAIN):
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle a flow initialized by the user."""
errors: dict[str, Any] = {}
errors: dict[str, str] = {}
if user_input is not None:
try:
full_path = await self.hass.async_add_executor_job(
validate_path, self.hass, user_input[CONF_FILE_PATH]
)
except NotValidError:
errors["base"] = "not_valid"
except NotAllowedError:
errors["base"] = "not_allowed"
else:
full_path, errors = await self.hass.async_add_executor_job(
validate_path, self.hass, user_input[CONF_FILE_PATH]
)
if not errors:
await self.async_set_unique_id(full_path)
self._abort_if_unique_id_configured()
@ -70,10 +64,29 @@ class FilesizeConfigFlow(ConfigFlow, domain=DOMAIN):
step_id="user", data_schema=DATA_SCHEMA, errors=errors
)
async def async_step_reconfigure(
self, user_input: dict[str, Any] | None = None
) -> ConfigFlowResult:
"""Handle a reconfigure flow initialized by the user."""
errors: dict[str, str] = {}
class NotValidError(HomeAssistantError):
"""Path is not valid error."""
if user_input is not None:
reconfigure_entry = self._get_reconfigure_entry()
full_path, errors = await self.hass.async_add_executor_job(
validate_path, self.hass, user_input[CONF_FILE_PATH]
)
if not errors:
await self.async_set_unique_id(full_path)
self._abort_if_unique_id_configured()
name = str(user_input[CONF_FILE_PATH]).rsplit("/", maxsplit=1)[-1]
return self.async_update_reload_and_abort(
reconfigure_entry,
title=name,
unique_id=self.unique_id,
data_updates={CONF_FILE_PATH: user_input[CONF_FILE_PATH]},
)
class NotAllowedError(HomeAssistantError):
"""Path is not allowed error."""
return self.async_show_form(
step_id="reconfigure", data_schema=DATA_SCHEMA, errors=errors
)

View File

@ -5,6 +5,11 @@
"data": {
"file_path": "Path to file"
}
},
"reconfigure": {
"data": {
"file_path": "[%key:component::filesize::config::step::user::data::file_path%]"
}
}
},
"error": {
@ -12,7 +17,8 @@
"not_allowed": "Path is not allowed"
},
"abort": {
"already_configured": "[%key:common::config_flow::abort::already_configured_service%]"
"already_configured": "[%key:common::config_flow::abort::already_configured_service%]",
"reconfigure_successful": "[%key:common::config_flow::abort::reconfigure_successful%]"
}
},
"title": "Filesize",

View File

@ -11,7 +11,7 @@ from homeassistant.const import CONF_FILE_PATH
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType
from . import TEST_FILE_NAME, async_create_file
from . import TEST_FILE_NAME, TEST_FILE_NAME2, async_create_file
from tests.common import MockConfigEntry
@ -108,3 +108,119 @@ async def test_flow_fails_on_validation(hass: HomeAssistant, tmp_path: Path) ->
assert result2["data"] == {
CONF_FILE_PATH: test_file,
}
async def test_reconfigure_flow(
hass: HomeAssistant, mock_config_entry: MockConfigEntry, tmp_path: Path
) -> None:
"""Test a reconfigure flow."""
test_file = str(tmp_path.joinpath(TEST_FILE_NAME2))
await async_create_file(hass, test_file)
hass.config.allowlist_external_dirs = {tmp_path}
mock_config_entry.add_to_hass(hass)
result = await mock_config_entry.start_reconfigure_flow(hass)
assert result["step_id"] == "reconfigure"
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {}
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_FILE_PATH: test_file},
)
await hass.async_block_till_done()
assert result2["type"] is FlowResultType.ABORT
assert result2["reason"] == "reconfigure_successful"
assert mock_config_entry.data == {CONF_FILE_PATH: str(test_file)}
async def test_unique_id_already_exist_in_reconfigure_flow(
hass: HomeAssistant, tmp_path: Path
) -> None:
"""Test a reconfigure flow fails when unique id already exist."""
test_file = str(tmp_path.joinpath(TEST_FILE_NAME))
test_file2 = str(tmp_path.joinpath(TEST_FILE_NAME2))
await async_create_file(hass, test_file)
await async_create_file(hass, test_file2)
hass.config.allowlist_external_dirs = {tmp_path}
test_file = str(tmp_path.joinpath(TEST_FILE_NAME))
mock_config_entry = MockConfigEntry(
title=TEST_FILE_NAME,
domain=DOMAIN,
data={CONF_FILE_PATH: test_file},
unique_id=test_file,
)
mock_config_entry2 = MockConfigEntry(
title=TEST_FILE_NAME2,
domain=DOMAIN,
data={CONF_FILE_PATH: test_file2},
unique_id=test_file2,
)
mock_config_entry.add_to_hass(hass)
mock_config_entry2.add_to_hass(hass)
result = await mock_config_entry.start_reconfigure_flow(hass)
assert result["step_id"] == "reconfigure"
assert result["type"] is FlowResultType.FORM
assert result["errors"] == {}
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_FILE_PATH: test_file2},
)
await hass.async_block_till_done()
assert result2["type"] is FlowResultType.ABORT
assert result2["reason"] == "already_configured"
async def test_reconfigure_flow_fails_on_validation(
hass: HomeAssistant, mock_config_entry: MockConfigEntry, tmp_path: Path
) -> None:
"""Test config flow errors in reconfigure."""
test_file2 = str(tmp_path.joinpath(TEST_FILE_NAME2))
hass.config.allowlist_external_dirs = {}
mock_config_entry.add_to_hass(hass)
result = await mock_config_entry.start_reconfigure_flow(hass)
assert result["type"] is FlowResultType.FORM
assert result["step_id"] == "reconfigure"
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_FILE_PATH: test_file2,
},
)
assert result["errors"] == {"base": "not_valid"}
await async_create_file(hass, test_file2)
with patch(
"homeassistant.components.filesize.config_flow.pathlib.Path",
):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_FILE_PATH: test_file2,
},
)
assert result2["errors"] == {"base": "not_allowed"}
hass.config.allowlist_external_dirs = {tmp_path}
with patch(
"homeassistant.components.filesize.config_flow.pathlib.Path",
):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input={
CONF_FILE_PATH: test_file2,
},
)
assert result2["type"] is FlowResultType.ABORT
assert result2["reason"] == "reconfigure_successful"