IPMA Code quality improvement (#77771)

* merge upstream/dev

* remove comment

* coverage increase

* merge upstream/dev

* refactor

* wait for another PR

* remove left overs

* wait for next PR

* only remove on successful unload

Co-authored-by: Shay Levy <levyshay1@gmail.com>

Co-authored-by: Shay Levy <levyshay1@gmail.com>
pull/79669/head^2
Diogo Gomes 2022-10-13 22:18:57 +01:00 committed by GitHub
parent e721d8ed02
commit 180b296426
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 184 additions and 151 deletions

View File

@ -57,4 +57,11 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS):
hass.data[DOMAIN].pop(entry.entry_id)
if not hass.data[DOMAIN]:
hass.data.pop(DOMAIN)
return unload_ok

View File

@ -5,7 +5,7 @@ DOMAIN = "ipma"
HOME_LOCATION_NAME = "Home"
ENTITY_ID_SENSOR_FORMAT_HOME = f"{WEATHER_DOMAIN}.ipma_{HOME_LOCATION_NAME}"
DATA_LOCATION = "location"
DATA_API = "api"
DATA_LOCATION = "location"
ENTITY_ID_SENSOR_FORMAT_HOME = f"{WEATHER_DOMAIN}.ipma_{HOME_LOCATION_NAME}"

View File

@ -8,7 +8,6 @@ import async_timeout
from pyipma.api import IPMA_API
from pyipma.forecast import Forecast
from pyipma.location import Location
import voluptuous as vol
from homeassistant.components.weather import (
ATTR_CONDITION_CLEAR_NIGHT,
@ -33,13 +32,10 @@ from homeassistant.components.weather import (
ATTR_FORECAST_PRECIPITATION_PROBABILITY,
ATTR_FORECAST_TIME,
ATTR_FORECAST_WIND_BEARING,
PLATFORM_SCHEMA,
WeatherEntity,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
CONF_LATITUDE,
CONF_LONGITUDE,
CONF_MODE,
CONF_NAME,
PRESSURE_HPA,
@ -47,7 +43,7 @@ from homeassistant.const import (
TEMP_CELSIUS,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import config_validation as cv, entity_registry
from homeassistant.helpers import entity_registry
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.sun import is_up
from homeassistant.util import Throttle
@ -80,15 +76,6 @@ CONDITION_CLASSES = {
FORECAST_MODE = ["hourly", "daily"]
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
{
vol.Optional(CONF_NAME): cv.string,
vol.Optional(CONF_LATITUDE): cv.latitude,
vol.Optional(CONF_LONGITUDE): cv.longitude,
vol.Optional(CONF_MODE, default="daily"): vol.In(FORECAST_MODE),
}
)
async def async_setup_entry(
hass: HomeAssistant,

View File

@ -1 +1,111 @@
"""Tests for the IPMA component."""
from collections import namedtuple
from datetime import datetime, timezone
from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE, CONF_MODE, CONF_NAME
ENTRY_CONFIG = {
CONF_NAME: "Home Town",
CONF_LATITUDE: "1",
CONF_LONGITUDE: "2",
CONF_MODE: "hourly",
}
class MockLocation:
"""Mock Location from pyipma."""
async def observation(self, api):
"""Mock Observation."""
Observation = namedtuple(
"Observation",
[
"accumulated_precipitation",
"humidity",
"pressure",
"radiation",
"temperature",
"wind_direction",
"wind_intensity_km",
],
)
return Observation(0.0, 71.0, 1000.0, 0.0, 18.0, "NW", 3.94)
async def forecast(self, api, period):
"""Mock Forecast."""
Forecast = namedtuple(
"Forecast",
[
"feels_like_temperature",
"forecast_date",
"forecasted_hours",
"humidity",
"max_temperature",
"min_temperature",
"precipitation_probability",
"temperature",
"update_date",
"weather_type",
"wind_direction",
"wind_strength",
],
)
WeatherType = namedtuple("WeatherType", ["id", "en", "pt"])
if period == 24:
return [
Forecast(
None,
datetime(2020, 1, 16, 0, 0, 0),
24,
None,
16.2,
10.6,
"100.0",
13.4,
"2020-01-15T07:51:00",
WeatherType(9, "Rain/showers", "Chuva/aguaceiros"),
"S",
"10",
),
]
if period == 1:
return [
Forecast(
"7.7",
datetime(2020, 1, 15, 1, 0, 0, tzinfo=timezone.utc),
1,
"86.9",
12.0,
None,
80.0,
10.6,
"2020-01-15T02:51:00",
WeatherType(10, "Light rain", "Chuva fraca ou chuvisco"),
"S",
"32.7",
),
Forecast(
"5.7",
datetime(2020, 1, 15, 2, 0, 0, tzinfo=timezone.utc),
1,
"86.9",
12.0,
None,
80.0,
10.6,
"2020-01-15T02:51:00",
WeatherType(1, "Clear sky", "C\u00e9u limpo"),
"S",
"32.7",
),
]
name = "HomeTown"
station = "HomeTown Station"
station_latitude = 0
station_longitude = 0
global_id_local = 1130600
id_station = 1200545

View File

@ -3,21 +3,14 @@
from unittest.mock import Mock, patch
from homeassistant.components.ipma import DOMAIN, config_flow
from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE, CONF_MODE, CONF_NAME
from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE, CONF_MODE
from homeassistant.helpers import entity_registry as er
from homeassistant.setup import async_setup_component
from .test_weather import MockLocation
from . import MockLocation
from tests.common import MockConfigEntry, mock_registry
ENTRY_CONFIG = {
CONF_NAME: "Home Town",
CONF_LATITUDE: "1",
CONF_LONGITUDE: "2",
CONF_MODE: "hourly",
}
async def test_show_config_form():
"""Test show configuration form."""

View File

@ -0,0 +1,57 @@
"""Test the IPMA integration."""
from unittest.mock import patch
from pyipma import IPMAException
from homeassistant.components.ipma import DOMAIN
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE, CONF_MODE
from .test_weather import MockLocation
from tests.common import MockConfigEntry
async def test_async_setup_raises_entry_not_ready(hass):
"""Test that it throws ConfigEntryNotReady when exception occurs during setup."""
with patch(
"pyipma.location.Location.get", side_effect=IPMAException("API unavailable")
):
config_entry = MockConfigEntry(
domain=DOMAIN,
title="Home",
data={CONF_LATITUDE: 0, CONF_LONGITUDE: 0, CONF_MODE: "daily"},
)
config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(config_entry.entry_id)
assert config_entry.state is ConfigEntryState.SETUP_RETRY
async def test_unload_config_entry(hass):
"""Test entry unloading."""
with patch(
"pyipma.location.Location.get",
return_value=MockLocation(),
):
config_entry = MockConfigEntry(
domain="ipma",
data={CONF_LATITUDE: 0, CONF_LONGITUDE: 0, CONF_MODE: "daily"},
)
config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
assert config_entry.state is ConfigEntryState.LOADED
await hass.config_entries.async_unload(config_entry.entry_id)
await hass.async_block_till_done()
assert config_entry.state is ConfigEntryState.NOT_LOADED

View File

@ -1,6 +1,5 @@
"""The tests for the IPMA weather component."""
from collections import namedtuple
from datetime import datetime, timezone
from datetime import datetime
from unittest.mock import patch
from freezegun import freeze_time
@ -22,6 +21,8 @@ from homeassistant.components.weather import (
)
from homeassistant.const import STATE_UNKNOWN
from . import MockLocation
from tests.common import MockConfigEntry
TEST_CONFIG = {
@ -39,128 +40,6 @@ TEST_CONFIG_HOURLY = {
}
class MockLocation:
"""Mock Location from pyipma."""
async def observation(self, api):
"""Mock Observation."""
Observation = namedtuple(
"Observation",
[
"accumulated_precipitation",
"humidity",
"pressure",
"radiation",
"temperature",
"wind_direction",
"wind_intensity_km",
],
)
return Observation(0.0, 71.0, 1000.0, 0.0, 18.0, "NW", 3.94)
async def forecast(self, api, period):
"""Mock Forecast."""
Forecast = namedtuple(
"Forecast",
[
"feels_like_temperature",
"forecast_date",
"forecasted_hours",
"humidity",
"max_temperature",
"min_temperature",
"precipitation_probability",
"temperature",
"update_date",
"weather_type",
"wind_direction",
"wind_strength",
],
)
WeatherType = namedtuple("WeatherType", ["id", "en", "pt"])
if period == 24:
return [
Forecast(
None,
datetime(2020, 1, 16, 0, 0, 0),
24,
None,
16.2,
10.6,
"100.0",
13.4,
"2020-01-15T07:51:00",
WeatherType(9, "Rain/showers", "Chuva/aguaceiros"),
"S",
"10",
),
]
if period == 1:
return [
Forecast(
"7.7",
datetime(2020, 1, 15, 1, 0, 0, tzinfo=timezone.utc),
1,
"86.9",
12.0,
None,
80.0,
10.6,
"2020-01-15T02:51:00",
WeatherType(10, "Light rain", "Chuva fraca ou chuvisco"),
"S",
"32.7",
),
Forecast(
"5.7",
datetime(2020, 1, 15, 2, 0, 0, tzinfo=timezone.utc),
1,
"86.9",
12.0,
None,
80.0,
10.6,
"2020-01-15T02:51:00",
WeatherType(1, "Clear sky", "C\u00e9u limpo"),
"S",
"32.7",
),
]
@property
def name(self):
"""Mock location."""
return "HomeTown"
@property
def station(self):
"""Mock station."""
return "HomeTown Station"
@property
def station_latitude(self):
"""Mock latitude."""
return 0
@property
def global_id_local(self):
"""Mock global identifier of the location."""
return 1130600
@property
def id_station(self):
"""Mock identifier of the station."""
return 1200545
@property
def station_longitude(self):
"""Mock longitude."""
return 0
class MockBadLocation(MockLocation):
"""Mock Location with unresponsive api."""