Remove Xiaomi Miio YAML import (#78995)

* Deprecate YAML import

* Add logging for unexpected errors

* remove unused import

* fix tests

* unused import

* fix tests

* fix snake_case

* Do not add to standard key string
This commit is contained in:
starkillerOG 2022-10-21 18:07:49 +02:00 committed by GitHub
parent 3aa24afad8
commit a2080492de
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 70 additions and 58 deletions

View file

@ -383,10 +383,6 @@ async def async_setup_gateway_entry(hass: HomeAssistant, entry: ConfigEntry) ->
assert gateway_id
# For backwards compat
if gateway_id.endswith("-gateway"):
hass.config_entries.async_update_entry(entry, unique_id=entry.data["mac"])
# Connect to gateway
gateway = ConnectXiaomiGateway(hass, entry)
try:

View file

@ -13,7 +13,7 @@ import voluptuous as vol
from homeassistant import config_entries
from homeassistant.components import zeroconf
from homeassistant.config_entries import SOURCE_REAUTH, ConfigEntry
from homeassistant.const import CONF_HOST, CONF_MODEL, CONF_NAME, CONF_TOKEN
from homeassistant.const import CONF_HOST, CONF_MODEL, CONF_TOKEN
from homeassistant.core import callback
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers.device_registry import format_mac
@ -145,18 +145,6 @@ class XiaomiMiioFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
return await self.async_step_cloud()
return self.async_show_form(step_id="reauth_confirm")
async def async_step_import(self, conf: dict[str, Any]) -> FlowResult:
"""Import a configuration from config.yaml."""
self.host = conf[CONF_HOST]
self.token = conf[CONF_TOKEN]
self.name = conf.get(CONF_NAME)
self.model = conf.get(CONF_MODEL)
self.context.update(
{"title_placeholders": {"name": f"YAML import {self.host}"}}
)
return await self.async_step_connect()
async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> FlowResult:
@ -250,15 +238,22 @@ class XiaomiMiioFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
errors["base"] = "cloud_login_error"
except MiCloudAccessDenied:
errors["base"] = "cloud_login_error"
except Exception: # pylint: disable=broad-except
_LOGGER.exception("Unexpected exception in Miio cloud login")
return self.async_abort(reason="unknown")
if errors:
return self.async_show_form(
step_id="cloud", data_schema=DEVICE_CLOUD_CONFIG, errors=errors
)
devices_raw = await self.hass.async_add_executor_job(
miio_cloud.get_devices, cloud_country
)
try:
devices_raw = await self.hass.async_add_executor_job(
miio_cloud.get_devices, cloud_country
)
except Exception: # pylint: disable=broad-except
_LOGGER.exception("Unexpected exception in Miio cloud get devices")
return self.async_abort(reason="unknown")
if not devices_raw:
errors["base"] = "cloud_no_devices"
@ -353,6 +348,9 @@ class XiaomiMiioFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
except SetupException:
if self.model is None:
errors["base"] = "cannot_connect"
except Exception: # pylint: disable=broad-except
_LOGGER.exception("Unexpected exception in connect Xiaomi device")
return self.async_abort(reason="unknown")
device_info = connect_device_class.device_info
@ -386,8 +384,8 @@ class XiaomiMiioFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
data[CONF_CLOUD_USERNAME] = self.cloud_username
data[CONF_CLOUD_PASSWORD] = self.cloud_password
data[CONF_CLOUD_COUNTRY] = self.cloud_country
self.hass.config_entries.async_update_entry(existing_entry, data=data)
await self.hass.config_entries.async_reload(existing_entry.entry_id)
if self.hass.config_entries.async_update_entry(existing_entry, data=data):
await self.hass.config_entries.async_reload(existing_entry.entry_id)
return self.async_abort(reason="reauth_successful")
if self.name is None:

View file

@ -5,7 +5,8 @@
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
"already_in_progress": "[%key:common::config_flow::abort::already_in_progress%]",
"incomplete_info": "Incomplete information to setup device, no host or token supplied.",
"not_xiaomi_miio": "Device is not (yet) supported by Xiaomi Miio."
"not_xiaomi_miio": "Device is not (yet) supported by Xiaomi Miio.",
"unknown": "[%key:common::config_flow::error::unknown%]"
},
"error": {
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",

View file

@ -5,7 +5,8 @@
"already_in_progress": "Configuration flow is already in progress",
"incomplete_info": "Incomplete information to setup device, no host or token supplied.",
"not_xiaomi_miio": "Device is not (yet) supported by Xiaomi Miio.",
"reauth_successful": "Re-authentication was successful"
"reauth_successful": "Re-authentication was successful",
"unknown": "Unexpected error"
},
"error": {
"cannot_connect": "Failed to connect",

View file

@ -9,7 +9,7 @@ import pytest
from homeassistant import config_entries, data_entry_flow
from homeassistant.components import zeroconf
from homeassistant.components.xiaomi_miio import const
from homeassistant.const import CONF_HOST, CONF_MODEL, CONF_NAME, CONF_TOKEN
from homeassistant.const import CONF_HOST, CONF_MODEL, CONF_TOKEN
from . import TEST_MAC
@ -67,7 +67,7 @@ TEST_CLOUD_DEVICES_2 = [
@pytest.fixture(name="xiaomi_miio_connect", autouse=True)
def xiaomi_miio_connect_fixture():
"""Mock denonavr connection and entry setup."""
"""Mock miio connection and entry setup."""
mock_info = get_mock_info()
with patch(
@ -320,6 +320,22 @@ async def test_config_flow_gateway_cloud_login_error(hass):
assert result["step_id"] == "cloud"
assert result["errors"] == {"base": "cloud_login_error"}
with patch(
"homeassistant.components.xiaomi_miio.config_flow.MiCloud.login",
side_effect=Exception({}),
):
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
const.CONF_CLOUD_USERNAME: TEST_CLOUD_USER,
const.CONF_CLOUD_PASSWORD: TEST_CLOUD_PASS,
const.CONF_CLOUD_COUNTRY: TEST_CLOUD_COUNTRY,
},
)
assert result["type"] == "abort"
assert result["reason"] == "unknown"
async def test_config_flow_gateway_cloud_no_devices(hass):
"""Test a failed config flow using cloud with no devices."""
@ -348,6 +364,22 @@ async def test_config_flow_gateway_cloud_no_devices(hass):
assert result["step_id"] == "cloud"
assert result["errors"] == {"base": "cloud_no_devices"}
with patch(
"homeassistant.components.xiaomi_miio.config_flow.MiCloud.get_devices",
side_effect=Exception({}),
):
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{
const.CONF_CLOUD_USERNAME: TEST_CLOUD_USER,
const.CONF_CLOUD_PASSWORD: TEST_CLOUD_PASS,
const.CONF_CLOUD_COUNTRY: TEST_CLOUD_COUNTRY,
},
)
assert result["type"] == "abort"
assert result["reason"] == "unknown"
async def test_config_flow_gateway_cloud_missing_token(hass):
"""Test a failed config flow using cloud with a missing token."""
@ -558,34 +590,6 @@ async def test_config_flow_step_unknown_device(hass):
assert result["errors"] == {"base": "unknown_device"}
async def test_import_flow_success(hass):
"""Test a successful import form yaml for a device."""
mock_info = get_mock_info(model=const.MODELS_SWITCH[0])
with patch(
"homeassistant.components.xiaomi_miio.device.Device.info",
return_value=mock_info,
):
result = await hass.config_entries.flow.async_init(
const.DOMAIN,
context={"source": config_entries.SOURCE_IMPORT},
data={CONF_NAME: TEST_NAME, CONF_HOST: TEST_HOST, CONF_TOKEN: TEST_TOKEN},
)
assert result["type"] == "create_entry"
assert result["title"] == TEST_NAME
assert result["data"] == {
const.CONF_FLOW_TYPE: const.CONF_DEVICE,
const.CONF_CLOUD_USERNAME: None,
const.CONF_CLOUD_PASSWORD: None,
const.CONF_CLOUD_COUNTRY: None,
CONF_HOST: TEST_HOST,
CONF_TOKEN: TEST_TOKEN,
CONF_MODEL: const.MODELS_SWITCH[0],
const.CONF_MAC: TEST_MAC,
}
async def test_config_flow_step_device_manual_model_error(hass):
"""Test config flow, device connection error, model None."""
result = await hass.config_entries.flow.async_init(
@ -618,6 +622,18 @@ async def test_config_flow_step_device_manual_model_error(hass):
assert result["step_id"] == "connect"
assert result["errors"] == {"base": "cannot_connect"}
with patch(
"homeassistant.components.xiaomi_miio.device.Device.info",
side_effect=Exception({}),
):
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
{CONF_MODEL: TEST_MODEL},
)
assert result["type"] == "abort"
assert result["reason"] == "unknown"
async def test_config_flow_step_device_manual_model_succes(hass):
"""Test config flow, device connection error, manual model."""
@ -724,7 +740,7 @@ async def config_flow_device_success(hass, model_to_test):
async def config_flow_generic_roborock(hass):
"""Test a successful config flow for a generic roborock vacuum."""
DUMMY_MODEL = "roborock.vacuum.dummy"
dummy_model = "roborock.vacuum.dummy"
result = await hass.config_entries.flow.async_init(
const.DOMAIN, context={"source": config_entries.SOURCE_USER}
@ -743,7 +759,7 @@ async def config_flow_generic_roborock(hass):
assert result["step_id"] == "manual"
assert result["errors"] == {}
mock_info = get_mock_info(model=DUMMY_MODEL)
mock_info = get_mock_info(model=dummy_model)
with patch(
"homeassistant.components.xiaomi_miio.device.Device.info",
@ -755,7 +771,7 @@ async def config_flow_generic_roborock(hass):
)
assert result["type"] == "create_entry"
assert result["title"] == DUMMY_MODEL
assert result["title"] == dummy_model
assert result["data"] == {
const.CONF_FLOW_TYPE: const.CONF_DEVICE,
const.CONF_CLOUD_USERNAME: None,
@ -763,7 +779,7 @@ async def config_flow_generic_roborock(hass):
const.CONF_CLOUD_COUNTRY: None,
CONF_HOST: TEST_HOST,
CONF_TOKEN: TEST_TOKEN,
CONF_MODEL: DUMMY_MODEL,
CONF_MODEL: dummy_model,
const.CONF_MAC: TEST_MAC,
}