Skip to content

Commit

Permalink
Improve exception handling in Nord Pool (home-assistant#130386)
Browse files Browse the repository at this point in the history
* Improve exception handling in Nord Pool

* Improve auth string

* Remove auth
  • Loading branch information
gjohansson-ST authored Nov 11, 2024
1 parent d1c3e1c commit 3eab72b
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 74 deletions.
14 changes: 9 additions & 5 deletions homeassistant/components/nordpool/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@

from typing import Any

from pynordpool import Currency, NordPoolClient, NordPoolError
from pynordpool import (
Currency,
NordPoolClient,
NordPoolEmptyResponseError,
NordPoolError,
)
from pynordpool.const import AREAS
import voluptuous as vol

Expand Down Expand Up @@ -53,17 +58,16 @@ async def test_api(hass: HomeAssistant, user_input: dict[str, Any]) -> dict[str,
"""Test fetch data from Nord Pool."""
client = NordPoolClient(async_get_clientsession(hass))
try:
data = await client.async_get_delivery_period(
await client.async_get_delivery_period(
dt_util.now(),
Currency(user_input[CONF_CURRENCY]),
user_input[CONF_AREAS],
)
except NordPoolEmptyResponseError:
return {"base": "no_data"}
except NordPoolError:
return {"base": "cannot_connect"}

if not data.raw:
return {"base": "no_data"}

return {}


Expand Down
12 changes: 4 additions & 8 deletions homeassistant/components/nordpool/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
from pynordpool import (
Currency,
DeliveryPeriodData,
NordPoolAuthenticationError,
NordPoolClient,
NordPoolEmptyResponseError,
NordPoolError,
NordPoolResponseError,
)
Expand All @@ -19,7 +19,7 @@
from homeassistant.core import HomeAssistant
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.event import async_track_point_in_utc_time
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from homeassistant.util import dt as dt_util

from .const import CONF_AREAS, DOMAIN, LOGGER
Expand Down Expand Up @@ -75,8 +75,8 @@ async def fetch_data(self, now: datetime) -> None:
Currency(self.config_entry.data[CONF_CURRENCY]),
self.config_entry.data[CONF_AREAS],
)
except NordPoolAuthenticationError as error:
LOGGER.error("Authentication error: %s", error)
except NordPoolEmptyResponseError as error:
LOGGER.debug("Empty response error: %s", error)
self.async_set_update_error(error)
return
except NordPoolResponseError as error:
Expand All @@ -88,8 +88,4 @@ async def fetch_data(self, now: datetime) -> None:
self.async_set_update_error(error)
return

if not data.raw:
self.async_set_update_error(UpdateFailed("No data"))
return

self.async_set_updated_data(data)
45 changes: 3 additions & 42 deletions tests/components/nordpool/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@

from __future__ import annotations

from dataclasses import replace
from unittest.mock import patch

from pynordpool import (
DeliveryPeriodData,
NordPoolAuthenticationError,
NordPoolConnectionError,
NordPoolEmptyResponseError,
NordPoolError,
NordPoolResponseError,
)
Expand Down Expand Up @@ -71,7 +70,7 @@ async def test_single_config_entry(
("error_message", "p_error"),
[
(NordPoolConnectionError, "cannot_connect"),
(NordPoolAuthenticationError, "cannot_connect"),
(NordPoolEmptyResponseError, "no_data"),
(NordPoolError, "cannot_connect"),
(NordPoolResponseError, "cannot_connect"),
],
Expand Down Expand Up @@ -116,44 +115,6 @@ async def test_cannot_connect(
assert result["data"] == {"areas": ["SE3", "SE4"], "currency": "SEK"}


@pytest.mark.freeze_time("2024-11-05T18:00:00+00:00")
async def test_empty_data(hass: HomeAssistant, get_data: DeliveryPeriodData) -> None:
"""Test empty data error."""

result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_USER}
)

assert result["type"] is FlowResultType.FORM
assert result["step_id"] == config_entries.SOURCE_USER

invalid_data = replace(get_data, raw={})

with patch(
"homeassistant.components.nordpool.coordinator.NordPoolClient.async_get_delivery_period",
return_value=invalid_data,
):
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input=ENTRY_CONFIG,
)

assert result["errors"] == {"base": "no_data"}

with patch(
"homeassistant.components.nordpool.coordinator.NordPoolClient.async_get_delivery_period",
return_value=get_data,
):
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
user_input=ENTRY_CONFIG,
)

assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == "Nord Pool"
assert result["data"] == {"areas": ["SE3", "SE4"], "currency": "SEK"}


@pytest.mark.freeze_time("2024-11-05T18:00:00+00:00")
async def test_reconfigure(
hass: HomeAssistant,
Expand Down Expand Up @@ -193,7 +154,7 @@ async def test_reconfigure(
("error_message", "p_error"),
[
(NordPoolConnectionError, "cannot_connect"),
(NordPoolAuthenticationError, "cannot_connect"),
(NordPoolEmptyResponseError, "no_data"),
(NordPoolError, "cannot_connect"),
(NordPoolResponseError, "cannot_connect"),
],
Expand Down
30 changes: 11 additions & 19 deletions tests/components/nordpool/test_coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from pynordpool import (
DeliveryPeriodData,
NordPoolAuthenticationError,
NordPoolEmptyResponseError,
NordPoolError,
NordPoolResponseError,
)
Expand All @@ -18,14 +19,13 @@
from homeassistant.config_entries import SOURCE_USER
from homeassistant.const import STATE_UNAVAILABLE
from homeassistant.core import HomeAssistant
from homeassistant.util import dt as dt_util

from . import ENTRY_CONFIG

from tests.common import MockConfigEntry, async_fire_time_changed


@pytest.mark.freeze_time("2024-11-05T12:00:00+00:00")
@pytest.mark.freeze_time("2024-11-05T10:00:00+00:00")
async def test_coordinator(
hass: HomeAssistant,
get_data: DeliveryPeriodData,
Expand All @@ -51,7 +51,7 @@ async def test_coordinator(
await hass.async_block_till_done()
mock_data.assert_called_once()
state = hass.states.get("sensor.nord_pool_se3_current_price")
assert state.state == "0.94949"
assert state.state == "0.92737"
mock_data.reset_mock()

mock_data.side_effect = NordPoolError("error")
Expand All @@ -74,34 +74,26 @@ async def test_coordinator(
assert "Authentication error" in caplog.text
mock_data.reset_mock()

assert "Response error" not in caplog.text
mock_data.side_effect = NordPoolResponseError("Response error")
assert "Empty response" not in caplog.text
mock_data.side_effect = NordPoolEmptyResponseError("Empty response")
freezer.tick(timedelta(hours=1))
async_fire_time_changed(hass)
await hass.async_block_till_done(wait_background_tasks=True)
mock_data.assert_called_once()
state = hass.states.get("sensor.nord_pool_se3_current_price")
assert state.state == STATE_UNAVAILABLE
assert "Response error" in caplog.text
assert "Empty response" in caplog.text
mock_data.reset_mock()

mock_data.return_value = DeliveryPeriodData(
raw={},
requested_date="2024-11-05",
updated_at=dt_util.utcnow(),
entries=[],
block_prices=[],
currency="SEK",
exchange_rate=1,
area_average={},
)
mock_data.side_effect = None
assert "Response error" not in caplog.text
mock_data.side_effect = NordPoolResponseError("Response error")
freezer.tick(timedelta(hours=1))
async_fire_time_changed(hass)
await hass.async_block_till_done()
await hass.async_block_till_done(wait_background_tasks=True)
mock_data.assert_called_once()
state = hass.states.get("sensor.nord_pool_se3_current_price")
assert state.state == STATE_UNAVAILABLE
assert "Response error" in caplog.text
mock_data.reset_mock()

mock_data.return_value = get_data
Expand All @@ -111,4 +103,4 @@ async def test_coordinator(
await hass.async_block_till_done()
mock_data.assert_called_once()
state = hass.states.get("sensor.nord_pool_se3_current_price")
assert state.state == "1.81983"
assert state.state == "1.81645"

0 comments on commit 3eab72b

Please sign in to comment.