Improve exception handling in Nord Pool (#130386)
* Improve exception handling in Nord Pool * Improve auth string * Remove authpull/130327/head^2
parent
d1c3e1caa9
commit
3eab72b2aa
|
@ -4,7 +4,12 @@ from __future__ import annotations
|
|||
|
||||
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
|
||||
|
||||
|
@ -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 {}
|
||||
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@ from typing import TYPE_CHECKING
|
|||
from pynordpool import (
|
||||
Currency,
|
||||
DeliveryPeriodData,
|
||||
NordPoolAuthenticationError,
|
||||
NordPoolClient,
|
||||
NordPoolEmptyResponseError,
|
||||
NordPoolError,
|
||||
NordPoolResponseError,
|
||||
)
|
||||
|
@ -19,7 +19,7 @@ from homeassistant.const import CONF_CURRENCY
|
|||
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
|
||||
|
@ -75,8 +75,8 @@ class NordPoolDataUpdateCoordinator(DataUpdateCoordinator[DeliveryPeriodData]):
|
|||
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:
|
||||
|
@ -88,8 +88,4 @@ class NordPoolDataUpdateCoordinator(DataUpdateCoordinator[DeliveryPeriodData]):
|
|||
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)
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
|
@ -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"),
|
||||
],
|
||||
|
@ -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,
|
||||
|
@ -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"),
|
||||
],
|
||||
|
|
|
@ -9,6 +9,7 @@ from freezegun.api import FrozenDateTimeFactory
|
|||
from pynordpool import (
|
||||
DeliveryPeriodData,
|
||||
NordPoolAuthenticationError,
|
||||
NordPoolEmptyResponseError,
|
||||
NordPoolError,
|
||||
NordPoolResponseError,
|
||||
)
|
||||
|
@ -18,14 +19,13 @@ from homeassistant.components.nordpool.const import DOMAIN
|
|||
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,
|
||||
|
@ -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")
|
||||
|
@ -74,6 +74,17 @@ async def test_coordinator(
|
|||
assert "Authentication error" in caplog.text
|
||||
mock_data.reset_mock()
|
||||
|
||||
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 "Empty response" in caplog.text
|
||||
mock_data.reset_mock()
|
||||
|
||||
assert "Response error" not in caplog.text
|
||||
mock_data.side_effect = NordPoolResponseError("Response error")
|
||||
freezer.tick(timedelta(hours=1))
|
||||
|
@ -85,25 +96,6 @@ async def test_coordinator(
|
|||
assert "Response error" 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
|
||||
freezer.tick(timedelta(hours=1))
|
||||
async_fire_time_changed(hass)
|
||||
await hass.async_block_till_done()
|
||||
mock_data.assert_called_once()
|
||||
state = hass.states.get("sensor.nord_pool_se3_current_price")
|
||||
assert state.state == STATE_UNAVAILABLE
|
||||
mock_data.reset_mock()
|
||||
|
||||
mock_data.return_value = get_data
|
||||
mock_data.side_effect = None
|
||||
freezer.tick(timedelta(hours=1))
|
||||
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue