From 6c5fd40c92217588e051a4a5e62675ce40f6a906 Mon Sep 17 00:00:00 2001 From: Robert Hillis Date: Fri, 2 Jun 2023 16:18:58 -0400 Subject: [PATCH] Catch Google Sheets api error (#93979) --- .../components/google_sheets/__init__.py | 10 +++++- tests/components/google_sheets/test_init.py | 35 ++++++++++++++++++- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/google_sheets/__init__.py b/homeassistant/components/google_sheets/__init__.py index 803b737283b..590c7bd0c90 100644 --- a/homeassistant/components/google_sheets/__init__.py +++ b/homeassistant/components/google_sheets/__init__.py @@ -7,13 +7,18 @@ import aiohttp from google.auth.exceptions import RefreshError from google.oauth2.credentials import Credentials from gspread import Client +from gspread.exceptions import APIError from gspread.utils import ValueInputOption import voluptuous as vol from homeassistant.config_entries import ConfigEntry, ConfigEntryState from homeassistant.const import CONF_ACCESS_TOKEN, CONF_TOKEN from homeassistant.core import HomeAssistant, ServiceCall -from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady +from homeassistant.exceptions import ( + ConfigEntryAuthFailed, + ConfigEntryNotReady, + HomeAssistantError, +) from homeassistant.helpers.config_entry_oauth2_flow import ( OAuth2Session, async_get_config_entry_implementation, @@ -93,6 +98,9 @@ async def async_setup_service(hass: HomeAssistant) -> None: except RefreshError as ex: entry.async_start_reauth(hass) raise ex + except APIError as ex: + raise HomeAssistantError("Failed to write data") from ex + worksheet = sheet.worksheet(call.data.get(WORKSHEET, sheet.sheet1.title)) row_data = {"created": str(datetime.now())} | call.data[DATA] columns: list[str] = next(iter(worksheet.get_values("A1:ZZ1")), []) diff --git a/tests/components/google_sheets/test_init.py b/tests/components/google_sheets/test_init.py index 50c82ac5109..8f7ce7603e8 100644 --- a/tests/components/google_sheets/test_init.py +++ b/tests/components/google_sheets/test_init.py @@ -6,7 +6,9 @@ import time from typing import Any from unittest.mock import patch +from gspread.exceptions import APIError import pytest +from requests.models import Response from homeassistant.components.application_credentials import ( ClientCredential, @@ -15,7 +17,7 @@ from homeassistant.components.application_credentials import ( from homeassistant.components.google_sheets import DOMAIN from homeassistant.config_entries import ConfigEntryState from homeassistant.core import HomeAssistant -from homeassistant.exceptions import ServiceNotFound +from homeassistant.exceptions import HomeAssistantError, ServiceNotFound from homeassistant.setup import async_setup_component from tests.common import MockConfigEntry @@ -212,6 +214,37 @@ async def test_append_sheet( assert len(mock_client.mock_calls) == 8 +async def test_append_sheet_api_error( + hass: HomeAssistant, + setup_integration: ComponentSetup, + config_entry: MockConfigEntry, +) -> None: + """Test append to sheet service call API error.""" + await setup_integration() + + entries = hass.config_entries.async_entries(DOMAIN) + assert len(entries) == 1 + assert entries[0].state is ConfigEntryState.LOADED + + response = Response() + response.status_code = 503 + + with pytest.raises(HomeAssistantError), patch( + "homeassistant.components.google_sheets.Client.request", + side_effect=APIError(response), + ): + await hass.services.async_call( + DOMAIN, + "append_sheet", + { + "config_entry": config_entry.entry_id, + "worksheet": "Sheet1", + "data": {"foo": "bar"}, + }, + blocking=True, + ) + + async def test_append_sheet_invalid_config_entry( hass: HomeAssistant, setup_integration: ComponentSetup,