Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update AEMET-OpenData to v0.3.0 #98810

Merged
merged 2 commits into from
Aug 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion homeassistant/components/aemet/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_API_KEY, CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME
from homeassistant.core import HomeAssistant
from homeassistant.helpers import aiohttp_client

from .const import (
CONF_STATION_UPDATES,
Expand All @@ -27,7 +28,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
longitude = entry.data[CONF_LONGITUDE]
station_updates = entry.options.get(CONF_STATION_UPDATES, True)

aemet = AEMET(api_key)
aemet = AEMET(aiohttp_client.async_get_clientsession(hass), api_key)
weather_coordinator = WeatherUpdateCoordinator(
hass, aemet, latitude, longitude, station_updates
)
Expand Down
19 changes: 9 additions & 10 deletions homeassistant/components/aemet/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
from __future__ import annotations

from aemet_opendata import AEMET
from aemet_opendata.exceptions import AuthError
import voluptuous as vol

from homeassistant import config_entries
from homeassistant.const import CONF_API_KEY, CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME
from homeassistant.core import callback
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers import aiohttp_client, config_validation as cv
from homeassistant.helpers.schema_config_entry_flow import (
SchemaFlowFormStep,
SchemaOptionsFlowHandler,
Expand Down Expand Up @@ -39,8 +40,13 @@ async def async_step_user(self, user_input=None):
await self.async_set_unique_id(f"{latitude}-{longitude}")
self._abort_if_unique_id_configured()

api_online = await _is_aemet_api_online(self.hass, user_input[CONF_API_KEY])
if not api_online:
aemet = AEMET(
aiohttp_client.async_get_clientsession(self.hass),
user_input[CONF_API_KEY],
)
try:
await aemet.get_conventional_observation_stations(False)
except AuthError:
errors["base"] = "invalid_api_key"

if not errors:
Expand Down Expand Up @@ -70,10 +76,3 @@ def async_get_options_flow(
) -> SchemaOptionsFlowHandler:
"""Get the options flow for this handler."""
return SchemaOptionsFlowHandler(config_entry, OPTIONS_FLOW)


async def _is_aemet_api_online(hass, api_key):
aemet = AEMET(api_key)
return await hass.async_add_executor_job(
aemet.get_conventional_observation_stations, False
)
2 changes: 1 addition & 1 deletion homeassistant/components/aemet/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/aemet",
"iot_class": "cloud_polling",
"loggers": ["aemet_opendata"],
"requirements": ["AEMET-OpenData==0.2.2"]
"requirements": ["AEMET-OpenData==0.3.0"]
}
24 changes: 13 additions & 11 deletions homeassistant/components/aemet/weather_update_coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,13 @@ async def _async_update_data(self):

async def _get_aemet_weather(self):
"""Poll weather data from AEMET OpenData."""
weather = await self.hass.async_add_executor_job(self._get_weather_and_forecast)
weather = await self._get_weather_and_forecast()
return weather

def _get_weather_station(self):
async def _get_weather_station(self):
if not self._station:
self._station = (
self._aemet.get_conventional_observation_station_by_coordinates(
await self._aemet.get_conventional_observation_station_by_coordinates(
self._latitude, self._longitude
)
)
Expand All @@ -171,9 +171,9 @@ def _get_weather_station(self):
)
return self._station

def _get_weather_town(self):
async def _get_weather_town(self):
if not self._town:
self._town = self._aemet.get_town_by_coordinates(
self._town = await self._aemet.get_town_by_coordinates(
self._latitude, self._longitude
)
if self._town:
Expand All @@ -192,18 +192,20 @@ def _get_weather_town(self):
raise TownNotFound
return self._town

def _get_weather_and_forecast(self):
async def _get_weather_and_forecast(self):
"""Get weather and forecast data from AEMET OpenData."""

self._get_weather_town()
await self._get_weather_town()

daily = self._aemet.get_specific_forecast_town_daily(self._town[AEMET_ATTR_ID])
daily = await self._aemet.get_specific_forecast_town_daily(
self._town[AEMET_ATTR_ID]
)
if not daily:
_LOGGER.error(
'Error fetching daily data for town "%s"', self._town[AEMET_ATTR_ID]
)

hourly = self._aemet.get_specific_forecast_town_hourly(
hourly = await self._aemet.get_specific_forecast_town_hourly(
self._town[AEMET_ATTR_ID]
)
if not hourly:
Expand All @@ -212,8 +214,8 @@ def _get_weather_and_forecast(self):
)

station = None
if self._station_updates and self._get_weather_station():
station = self._aemet.get_conventional_observation_station_data(
if self._station_updates and await self._get_weather_station():
station = await self._aemet.get_conventional_observation_station_data(
self._station[AEMET_ATTR_IDEMA]
)
if not station:
Expand Down
2 changes: 1 addition & 1 deletion requirements_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
-r requirements.txt

# homeassistant.components.aemet
AEMET-OpenData==0.2.2
AEMET-OpenData==0.3.0

# homeassistant.components.aladdin_connect
AIOAladdinConnect==0.1.57
Expand Down
2 changes: 1 addition & 1 deletion requirements_test_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
-r requirements_test.txt

# homeassistant.components.aemet
AEMET-OpenData==0.2.2
AEMET-OpenData==0.3.0

# homeassistant.components.aladdin_connect
AIOAladdinConnect==0.1.57
Expand Down
6 changes: 0 additions & 6 deletions tests/components/aemet/fixtures/station-3195.json

This file was deleted.

6 changes: 0 additions & 6 deletions tests/components/aemet/fixtures/station-list.json

This file was deleted.

This file was deleted.

This file was deleted.

32 changes: 17 additions & 15 deletions tests/components/aemet/test_config_flow.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""Define tests for the AEMET OpenData config flow."""
from unittest.mock import AsyncMock, MagicMock, patch

from aemet_opendata.exceptions import AuthError
import pytest
import requests_mock

from homeassistant import data_entry_flow
from homeassistant.components.aemet.const import CONF_STATION_UPDATES, DOMAIN
Expand All @@ -11,7 +11,7 @@
from homeassistant.core import HomeAssistant
import homeassistant.util.dt as dt_util

from .util import aemet_requests_mock
from .util import mock_api_call

from tests.common import MockConfigEntry

Expand All @@ -28,9 +28,10 @@
async def test_form(hass: HomeAssistant, mock_setup_entry: AsyncMock) -> None:
"""Test that the form is served with valid input."""

with requests_mock.mock() as _m:
aemet_requests_mock(_m)

with patch(
"homeassistant.components.aemet.AEMET.api_call",
side_effect=mock_api_call,
):
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
Expand Down Expand Up @@ -64,9 +65,10 @@ async def test_form_options(hass: HomeAssistant) -> None:
now = dt_util.parse_datetime("2021-01-09 12:00:00+00:00")
with patch("homeassistant.util.dt.now", return_value=now), patch(
"homeassistant.util.dt.utcnow", return_value=now
), requests_mock.mock() as _m:
aemet_requests_mock(_m)

), patch(
"homeassistant.components.aemet.AEMET.api_call",
side_effect=mock_api_call,
):
entry = MockConfigEntry(
domain=DOMAIN, unique_id="40.30403754--3.72935236", data=CONFIG
)
Expand Down Expand Up @@ -120,9 +122,10 @@ async def test_form_duplicated_id(hass: HomeAssistant) -> None:
now = dt_util.parse_datetime("2021-01-09 12:00:00+00:00")
with patch("homeassistant.util.dt.now", return_value=now), patch(
"homeassistant.util.dt.utcnow", return_value=now
), requests_mock.mock() as _m:
aemet_requests_mock(_m)

), patch(
"homeassistant.components.aemet.AEMET.api_call",
side_effect=mock_api_call,
):
entry = MockConfigEntry(
domain=DOMAIN, unique_id="40.30403754--3.72935236", data=CONFIG
)
Expand All @@ -136,11 +139,10 @@ async def test_form_duplicated_id(hass: HomeAssistant) -> None:
assert result["reason"] == "already_configured"


async def test_form_api_offline(hass: HomeAssistant) -> None:
"""Test setting up with api call error."""
async def test_form_auth_error(hass: HomeAssistant) -> None:
"""Test setting up with api auth error."""
mocked_aemet = MagicMock()

mocked_aemet.get_conventional_observation_stations.return_value = None
mocked_aemet.get_conventional_observation_stations.side_effect = AuthError

with patch(
"homeassistant.components.aemet.config_flow.AEMET",
Expand Down
11 changes: 5 additions & 6 deletions tests/components/aemet/test_init.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
"""Define tests for the AEMET OpenData init."""
from unittest.mock import patch

import requests_mock

from homeassistant.components.aemet.const import DOMAIN
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import CONF_API_KEY, CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME
from homeassistant.core import HomeAssistant
import homeassistant.util.dt as dt_util

from .util import aemet_requests_mock
from .util import mock_api_call

from tests.common import MockConfigEntry

Expand All @@ -27,9 +25,10 @@ async def test_unload_entry(hass: HomeAssistant) -> None:
now = dt_util.parse_datetime("2021-01-09 12:00:00+00:00")
with patch("homeassistant.util.dt.now", return_value=now), patch(
"homeassistant.util.dt.utcnow", return_value=now
), requests_mock.mock() as _m:
aemet_requests_mock(_m)

), patch(
"homeassistant.components.aemet.AEMET.api_call",
side_effect=mock_api_call,
):
config_entry = MockConfigEntry(
domain=DOMAIN, unique_id="aemet_unique_id", data=CONFIG
)
Expand Down
9 changes: 5 additions & 4 deletions tests/components/aemet/test_weather.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

from freezegun.api import FrozenDateTimeFactory
import pytest
import requests_mock
from syrupy.assertion import SnapshotAssertion

from homeassistant.components.aemet.const import ATTRIBUTION, DOMAIN
Expand Down Expand Up @@ -36,7 +35,7 @@
from homeassistant.helpers import entity_registry as er
import homeassistant.util.dt as dt_util

from .util import aemet_requests_mock, async_init_integration
from .util import async_init_integration, mock_api_call

from tests.typing import WebSocketGenerator

Expand Down Expand Up @@ -191,8 +190,10 @@ async def test_forecast_subscription(

assert forecast1 == snapshot

with requests_mock.mock() as _m:
aemet_requests_mock(_m)
with patch(
"homeassistant.components.aemet.AEMET.api_call",
side_effect=mock_api_call,
):
freezer.tick(WEATHER_UPDATE_INTERVAL + datetime.timedelta(seconds=1))
await hass.async_block_till_done()
msg = await client.receive_json()
Expand Down