Skip to content

Commit

Permalink
Bump pydaikin to 2.0.1, catch HTTPForbidden exception (#35466)
Browse files Browse the repository at this point in the history
  • Loading branch information
fredrike committed May 11, 2020
1 parent 3de4bc5 commit 93f8d21
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 35 deletions.
40 changes: 25 additions & 15 deletions homeassistant/components/daikin/config_flow.py
Expand Up @@ -3,7 +3,7 @@
import logging
from uuid import uuid4

from aiohttp import ClientError
from aiohttp import ClientError, web_exceptions
from async_timeout import timeout
from pydaikin.daikin_base import Appliance
import voluptuous as vol
Expand All @@ -15,6 +15,14 @@

_LOGGER = logging.getLogger(__name__)

DATA_SCHEMA = vol.Schema(
{
vol.Required(CONF_HOST): str,
vol.Optional(CONF_KEY): str,
vol.Optional(CONF_PASSWORD): str,
}
)


@config_entries.HANDLERS.register("daikin")
class FlowHandler(config_entries.ConfigFlow):
Expand Down Expand Up @@ -43,7 +51,6 @@ def _create_entry(self, host, mac, key=None, uuid=None, password=None):

async def _create_device(self, host, key=None, password=None):
"""Create device."""

# BRP07Cxx devices needs uuid together with key
if key:
uuid = str(uuid4())
Expand All @@ -64,30 +71,33 @@ async def _create_device(self, host, key=None, password=None):
password=password,
)
except asyncio.TimeoutError:
return self.async_abort(reason="device_timeout")
return self.async_show_form(
step_id="user",
data_schema=DATA_SCHEMA,
errors={"base": "device_timeout"},
)
except web_exceptions.HTTPForbidden:
return self.async_show_form(
step_id="user", data_schema=DATA_SCHEMA, errors={"base": "forbidden"},
)
except ClientError:
_LOGGER.exception("ClientError")
return self.async_abort(reason="device_fail")
return self.async_show_form(
step_id="user", data_schema=DATA_SCHEMA, errors={"base": "device_fail"},
)
except Exception: # pylint: disable=broad-except
_LOGGER.exception("Unexpected error creating device")
return self.async_abort(reason="device_fail")
return self.async_show_form(
step_id="user", data_schema=DATA_SCHEMA, errors={"base": "device_fail"},
)

mac = device.mac
return self._create_entry(host, mac, key, uuid, password)

async def async_step_user(self, user_input=None):
"""User initiated config flow."""
if user_input is None:
return self.async_show_form(
step_id="user",
data_schema=vol.Schema(
{
vol.Required(CONF_HOST): str,
vol.Optional(CONF_KEY): str,
vol.Optional(CONF_PASSWORD): str,
}
),
)
return self.async_show_form(step_id="user", data_schema=DATA_SCHEMA,)
return await self._create_device(
user_input[CONF_HOST],
user_input.get(CONF_KEY),
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/daikin/manifest.json
Expand Up @@ -3,7 +3,7 @@
"name": "Daikin AC",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/daikin",
"requirements": ["pydaikin==2.0.0"],
"requirements": ["pydaikin==2.0.1"],
"codeowners": ["@fredrike"],
"quality_scale": "platinum"
}
17 changes: 10 additions & 7 deletions homeassistant/components/daikin/strings.json
Expand Up @@ -5,16 +5,19 @@
"title": "Configure Daikin AC",
"description": "Enter IP address of your Daikin AC.",
"data": {
"host": "Host",
"key": "Authentication key (only used by BRP072C/Zena devices)",
"password": "Device password (only used by SKYFi devices)"
}
"host": "[%key:common::config_flow::data::host%]",
"key": "[%key:common::config_flow::data::api_key%]",
"password": "[%key:common::config_flow::data::password%]"
}
}
},
"abort": {
"device_timeout": "Timeout connecting to the device.",
"device_fail": "Unexpected error creating device.",
"already_configured": "Device is already configured"
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
},
"error": {
"device_fail": "[%key:common::config_flow::error::unknown%]",
"forbidden": "[%key:common::config_flow::error::invalid_auth%]",
"device_timeout": "[%key:common::config_flow::error::cannot_connect%]"
}
}
}
2 changes: 1 addition & 1 deletion requirements_all.txt
Expand Up @@ -1263,7 +1263,7 @@ pycsspeechtts==1.0.3
# pycups==1.9.73

# homeassistant.components.daikin
pydaikin==2.0.0
pydaikin==2.0.1

# homeassistant.components.danfoss_air
pydanfossair==0.1.0
Expand Down
2 changes: 1 addition & 1 deletion requirements_test_all.txt
Expand Up @@ -533,7 +533,7 @@ pychromecast==5.1.0
pycoolmasternet==0.0.4

# homeassistant.components.daikin
pydaikin==2.0.0
pydaikin==2.0.1

# homeassistant.components.deconz
pydeconz==70
Expand Down
32 changes: 22 additions & 10 deletions tests/components/daikin/test_config_flow.py
Expand Up @@ -2,12 +2,18 @@
"""Tests for the Daikin config flow."""
import asyncio

from aiohttp import ClientError
from aiohttp.web_exceptions import HTTPForbidden
import pytest

from homeassistant import data_entry_flow
from homeassistant.components.daikin import config_flow
from homeassistant.components.daikin.const import KEY_IP, KEY_MAC
from homeassistant.const import CONF_HOST
from homeassistant.data_entry_flow import (
RESULT_TYPE_ABORT,
RESULT_TYPE_CREATE_ENTRY,
RESULT_TYPE_FORM,
)

from tests.async_mock import PropertyMock, patch
from tests.common import MockConfigEntry
Expand Down Expand Up @@ -42,11 +48,11 @@ async def test_user(hass, mock_daikin):
flow = init_config_flow(hass)

result = await flow.async_step_user()
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["type"] == RESULT_TYPE_FORM
assert result["step_id"] == "user"

result = await flow.async_step_user({CONF_HOST: HOST})
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
assert result["type"] == RESULT_TYPE_CREATE_ENTRY
assert result["title"] == HOST
assert result["data"][CONF_HOST] == HOST
assert result["data"][KEY_MAC] == MAC
Expand All @@ -58,7 +64,7 @@ async def test_abort_if_already_setup(hass, mock_daikin):
MockConfigEntry(domain="daikin", data={KEY_MAC: MAC}).add_to_hass(hass)

result = await flow.async_step_user({CONF_HOST: HOST})
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
assert result["type"] == RESULT_TYPE_ABORT
assert result["reason"] == "already_configured"


Expand All @@ -67,11 +73,11 @@ async def test_import(hass, mock_daikin):
flow = init_config_flow(hass)

result = await flow.async_step_import({})
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
assert result["type"] == RESULT_TYPE_FORM
assert result["step_id"] == "user"

result = await flow.async_step_import({CONF_HOST: HOST})
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
assert result["type"] == RESULT_TYPE_CREATE_ENTRY
assert result["title"] == HOST
assert result["data"][CONF_HOST] == HOST
assert result["data"][KEY_MAC] == MAC
Expand All @@ -82,21 +88,27 @@ async def test_discovery(hass, mock_daikin):
flow = init_config_flow(hass)

result = await flow.async_step_discovery({KEY_IP: HOST, KEY_MAC: MAC})
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
assert result["type"] == RESULT_TYPE_CREATE_ENTRY
assert result["title"] == HOST
assert result["data"][CONF_HOST] == HOST
assert result["data"][KEY_MAC] == MAC


@pytest.mark.parametrize(
"s_effect,reason",
[(asyncio.TimeoutError, "device_timeout"), (Exception, "device_fail")],
[
(asyncio.TimeoutError, "device_timeout"),
(HTTPForbidden, "forbidden"),
(ClientError, "device_fail"),
(Exception, "device_fail"),
],
)
async def test_device_abort(hass, mock_daikin, s_effect, reason):
"""Test device abort."""
flow = init_config_flow(hass)
mock_daikin.factory.side_effect = s_effect

result = await flow.async_step_user({CONF_HOST: HOST})
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
assert result["reason"] == reason
assert result["type"] == RESULT_TYPE_FORM
assert result["errors"] == {"base": reason}
assert result["step_id"] == "user"

0 comments on commit 93f8d21

Please sign in to comment.