From 93083513b4715e6093b3949ef13c0dbe09b6d62f Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 6 Sep 2021 16:05:33 -0700 Subject: [PATCH] Bump hass-nabucasa 49 (#55823) --- homeassistant/components/cloud/http_api.py | 89 ++++++-------------- homeassistant/components/cloud/manifest.json | 2 +- homeassistant/package_constraints.txt | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/cloud/conftest.py | 2 +- tests/components/cloud/test_http_api.py | 49 +---------- 7 files changed, 36 insertions(+), 112 deletions(-) diff --git a/homeassistant/components/cloud/http_api.py b/homeassistant/components/cloud/http_api.py index e9771012379..cab41ebb0b8 100644 --- a/homeassistant/components/cloud/http_api.py +++ b/homeassistant/components/cloud/http_api.py @@ -6,7 +6,7 @@ import logging import aiohttp import async_timeout import attr -from hass_nabucasa import Cloud, auth, thingtalk +from hass_nabucasa import Cloud, auth, cloud_api, thingtalk from hass_nabucasa.const import STATE_DISCONNECTED from hass_nabucasa.voice import MAP_VOICE import voluptuous as vol @@ -24,7 +24,6 @@ from homeassistant.const import ( HTTP_BAD_GATEWAY, HTTP_BAD_REQUEST, HTTP_INTERNAL_SERVER_ERROR, - HTTP_OK, HTTP_UNAUTHORIZED, ) @@ -47,30 +46,6 @@ from .const import ( _LOGGER = logging.getLogger(__name__) -WS_TYPE_STATUS = "cloud/status" -SCHEMA_WS_STATUS = websocket_api.BASE_COMMAND_MESSAGE_SCHEMA.extend( - {vol.Required("type"): WS_TYPE_STATUS} -) - - -WS_TYPE_SUBSCRIPTION = "cloud/subscription" -SCHEMA_WS_SUBSCRIPTION = websocket_api.BASE_COMMAND_MESSAGE_SCHEMA.extend( - {vol.Required("type"): WS_TYPE_SUBSCRIPTION} -) - - -WS_TYPE_HOOK_CREATE = "cloud/cloudhook/create" -SCHEMA_WS_HOOK_CREATE = websocket_api.BASE_COMMAND_MESSAGE_SCHEMA.extend( - {vol.Required("type"): WS_TYPE_HOOK_CREATE, vol.Required("webhook_id"): str} -) - - -WS_TYPE_HOOK_DELETE = "cloud/cloudhook/delete" -SCHEMA_WS_HOOK_DELETE = websocket_api.BASE_COMMAND_MESSAGE_SCHEMA.extend( - {vol.Required("type"): WS_TYPE_HOOK_DELETE, vol.Required("webhook_id"): str} -) - - _CLOUD_ERRORS = { InvalidTrustedNetworks: ( HTTP_INTERNAL_SERVER_ERROR, @@ -94,17 +69,11 @@ _CLOUD_ERRORS = { async def async_setup(hass): """Initialize the HTTP API.""" async_register_command = hass.components.websocket_api.async_register_command - async_register_command(WS_TYPE_STATUS, websocket_cloud_status, SCHEMA_WS_STATUS) - async_register_command( - WS_TYPE_SUBSCRIPTION, websocket_subscription, SCHEMA_WS_SUBSCRIPTION - ) + async_register_command(websocket_cloud_status) + async_register_command(websocket_subscription) async_register_command(websocket_update_prefs) - async_register_command( - WS_TYPE_HOOK_CREATE, websocket_hook_create, SCHEMA_WS_HOOK_CREATE - ) - async_register_command( - WS_TYPE_HOOK_DELETE, websocket_hook_delete, SCHEMA_WS_HOOK_DELETE - ) + async_register_command(websocket_hook_create) + async_register_command(websocket_hook_delete) async_register_command(websocket_remote_connect) async_register_command(websocket_remote_disconnect) @@ -311,6 +280,7 @@ class CloudForgotPasswordView(HomeAssistantView): @websocket_api.async_response +@websocket_api.websocket_command({vol.Required("type"): "cloud/status"}) async def websocket_cloud_status(hass, connection, msg): """Handle request for account info. @@ -344,36 +314,19 @@ def _require_cloud_login(handler): @_require_cloud_login @websocket_api.async_response +@websocket_api.websocket_command({vol.Required("type"): "cloud/subscription"}) async def websocket_subscription(hass, connection, msg): """Handle request for account info.""" - cloud = hass.data[DOMAIN] - - with async_timeout.timeout(REQUEST_TIMEOUT): - response = await cloud.fetch_subscription_info() - - if response.status != HTTP_OK: - connection.send_message( - websocket_api.error_message( - msg["id"], "request_failed", "Failed to request subscription" - ) + try: + with async_timeout.timeout(REQUEST_TIMEOUT): + data = await cloud_api.async_subscription_info(cloud) + except aiohttp.ClientError: + connection.send_error( + msg["id"], "request_failed", "Failed to request subscription" ) - - data = await response.json() - - # Check if a user is subscribed but local info is outdated - # In that case, let's refresh and reconnect - if data.get("provider") and not cloud.is_connected: - _LOGGER.debug("Found disconnected account with valid subscriotion, connecting") - await cloud.auth.async_renew_access_token() - - # Cancel reconnect in progress - if cloud.iot.state != STATE_DISCONNECTED: - await cloud.iot.disconnect() - - hass.async_create_task(cloud.iot.connect()) - - connection.send_message(websocket_api.result_message(msg["id"], data)) + else: + connection.send_result(msg["id"], data) @_require_cloud_login @@ -429,6 +382,12 @@ async def websocket_update_prefs(hass, connection, msg): @_require_cloud_login @websocket_api.async_response @_ws_handle_cloud_errors +@websocket_api.websocket_command( + { + vol.Required("type"): "cloud/cloudhook/create", + vol.Required("webhook_id"): str, + } +) async def websocket_hook_create(hass, connection, msg): """Handle request for account info.""" cloud = hass.data[DOMAIN] @@ -439,6 +398,12 @@ async def websocket_hook_create(hass, connection, msg): @_require_cloud_login @websocket_api.async_response @_ws_handle_cloud_errors +@websocket_api.websocket_command( + { + vol.Required("type"): "cloud/cloudhook/delete", + vol.Required("webhook_id"): str, + } +) async def websocket_hook_delete(hass, connection, msg): """Handle request for account info.""" cloud = hass.data[DOMAIN] diff --git a/homeassistant/components/cloud/manifest.json b/homeassistant/components/cloud/manifest.json index d5e93a2a370..8eaad3b4129 100644 --- a/homeassistant/components/cloud/manifest.json +++ b/homeassistant/components/cloud/manifest.json @@ -2,7 +2,7 @@ "domain": "cloud", "name": "Home Assistant Cloud", "documentation": "https://www.home-assistant.io/integrations/cloud", - "requirements": ["hass-nabucasa==0.47.1"], + "requirements": ["hass-nabucasa==0.49.0"], "dependencies": ["http", "webhook"], "after_dependencies": ["google_assistant", "alexa"], "codeowners": ["@home-assistant/cloud"], diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index d32947244c5..e1d95a5cd23 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -15,7 +15,7 @@ ciso8601==2.1.3 cryptography==3.3.2 defusedxml==0.7.1 emoji==1.2.0 -hass-nabucasa==0.47.1 +hass-nabucasa==0.49.0 home-assistant-frontend==20210830.0 httpx==0.19.0 ifaddr==0.1.7 diff --git a/requirements_all.txt b/requirements_all.txt index 7fa52e65976..d6b076cd778 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -760,7 +760,7 @@ habitipy==0.2.0 hangups==0.4.14 # homeassistant.components.cloud -hass-nabucasa==0.47.1 +hass-nabucasa==0.49.0 # homeassistant.components.splunk hass_splunk==0.1.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 2266c9a0a6e..180c67cd3aa 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -441,7 +441,7 @@ habitipy==0.2.0 hangups==0.4.14 # homeassistant.components.cloud -hass-nabucasa==0.47.1 +hass-nabucasa==0.49.0 # homeassistant.components.tasmota hatasmota==0.2.20 diff --git a/tests/components/cloud/conftest.py b/tests/components/cloud/conftest.py index baa1dd6bae8..4bd5868db5f 100644 --- a/tests/components/cloud/conftest.py +++ b/tests/components/cloud/conftest.py @@ -12,7 +12,7 @@ from . import mock_cloud, mock_cloud_prefs @pytest.fixture(autouse=True) def mock_user_data(): """Mock os module.""" - with patch("hass_nabucasa.Cloud.write_user_info") as writer: + with patch("hass_nabucasa.Cloud._write_user_info") as writer: yield writer diff --git a/tests/components/cloud/test_http_api.py b/tests/components/cloud/test_http_api.py index 35d261d5603..b678796a5c4 100644 --- a/tests/components/cloud/test_http_api.py +++ b/tests/components/cloud/test_http_api.py @@ -71,7 +71,7 @@ def setup_api_fixture(hass, aioclient_mock): @pytest.fixture(name="cloud_client") def cloud_client_fixture(hass, hass_client): """Fixture that can fetch from the cloud client.""" - with patch("hass_nabucasa.Cloud.write_user_info"): + with patch("hass_nabucasa.Cloud._write_user_info"): yield hass.loop.run_until_complete(hass_client()) @@ -394,59 +394,18 @@ async def test_websocket_status_not_logged_in(hass, hass_ws_client): assert response["result"] == {"logged_in": False, "cloud": "disconnected"} -async def test_websocket_subscription_reconnect( +async def test_websocket_subscription_info( hass, hass_ws_client, aioclient_mock, mock_auth, mock_cloud_login ): """Test querying the status and connecting because valid account.""" aioclient_mock.get(SUBSCRIPTION_INFO_URL, json={"provider": "stripe"}) client = await hass_ws_client(hass) - with patch( - "hass_nabucasa.auth.CognitoAuth.async_renew_access_token" - ) as mock_renew, patch("hass_nabucasa.iot.CloudIoT.connect") as mock_connect: + with patch("hass_nabucasa.auth.CognitoAuth.async_renew_access_token") as mock_renew: await client.send_json({"id": 5, "type": "cloud/subscription"}) response = await client.receive_json() - assert response["result"] == {"provider": "stripe"} assert len(mock_renew.mock_calls) == 1 - assert len(mock_connect.mock_calls) == 1 - - -async def test_websocket_subscription_no_reconnect_if_connected( - hass, hass_ws_client, aioclient_mock, mock_auth, mock_cloud_login -): - """Test querying the status and not reconnecting because still expired.""" - aioclient_mock.get(SUBSCRIPTION_INFO_URL, json={"provider": "stripe"}) - hass.data[DOMAIN].iot.state = STATE_CONNECTED - client = await hass_ws_client(hass) - - with patch( - "hass_nabucasa.auth.CognitoAuth.async_renew_access_token" - ) as mock_renew, patch("hass_nabucasa.iot.CloudIoT.connect") as mock_connect: - await client.send_json({"id": 5, "type": "cloud/subscription"}) - response = await client.receive_json() - - assert response["result"] == {"provider": "stripe"} - assert len(mock_renew.mock_calls) == 0 - assert len(mock_connect.mock_calls) == 0 - - -async def test_websocket_subscription_no_reconnect_if_expired( - hass, hass_ws_client, aioclient_mock, mock_auth, mock_cloud_login -): - """Test querying the status and not reconnecting because still expired.""" - aioclient_mock.get(SUBSCRIPTION_INFO_URL, json={"provider": "stripe"}) - client = await hass_ws_client(hass) - - with patch( - "hass_nabucasa.auth.CognitoAuth.async_renew_access_token" - ) as mock_renew, patch("hass_nabucasa.iot.CloudIoT.connect") as mock_connect: - await client.send_json({"id": 5, "type": "cloud/subscription"}) - response = await client.receive_json() - - assert response["result"] == {"provider": "stripe"} - assert len(mock_renew.mock_calls) == 1 - assert len(mock_connect.mock_calls) == 1 async def test_websocket_subscription_fail( @@ -466,7 +425,7 @@ async def test_websocket_subscription_not_logged_in(hass, hass_ws_client): """Test querying the status.""" client = await hass_ws_client(hass) with patch( - "hass_nabucasa.Cloud.fetch_subscription_info", + "hass_nabucasa.cloud_api.async_subscription_info", return_value={"return": "value"}, ): await client.send_json({"id": 5, "type": "cloud/subscription"})