mirror of
https://github.com/home-assistant/core.git
synced 2025-07-20 19:57:07 +00:00
Bump pytrafikverket to 0.3.1 (#92425)
* Bump pytrafikverket 0.3.0 * 0.3.1 * mypy * Fix exceptions
This commit is contained in:
parent
85dcd4007c
commit
82b4368d1d
@ -5,6 +5,7 @@ from collections.abc import Mapping
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from pytrafikverket import TrafikverketFerry
|
from pytrafikverket import TrafikverketFerry
|
||||||
|
from pytrafikverket.exceptions import InvalidAuthentication, NoFerryFound
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
@ -16,9 +17,6 @@ from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
|||||||
from .const import CONF_FROM, CONF_TIME, CONF_TO, DOMAIN
|
from .const import CONF_FROM, CONF_TIME, CONF_TO, DOMAIN
|
||||||
from .util import create_unique_id
|
from .util import create_unique_id
|
||||||
|
|
||||||
ERROR_INVALID_AUTH = "Source: Security, message: Invalid authentication"
|
|
||||||
ERROR_INVALID_ROUTE = "No FerryAnnouncement found"
|
|
||||||
|
|
||||||
DATA_SCHEMA = vol.Schema(
|
DATA_SCHEMA = vol.Schema(
|
||||||
{
|
{
|
||||||
vol.Required(CONF_API_KEY): selector.TextSelector(
|
vol.Required(CONF_API_KEY): selector.TextSelector(
|
||||||
@ -81,13 +79,12 @@ class TVFerryConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
await self.validate_input(
|
await self.validate_input(
|
||||||
api_key, self.entry.data[CONF_FROM], self.entry.data[CONF_TO]
|
api_key, self.entry.data[CONF_FROM], self.entry.data[CONF_TO]
|
||||||
)
|
)
|
||||||
except ValueError as err:
|
except InvalidAuthentication:
|
||||||
if str(err) == ERROR_INVALID_AUTH:
|
errors["base"] = "invalid_auth"
|
||||||
errors["base"] = "invalid_auth"
|
except NoFerryFound:
|
||||||
elif str(err) == ERROR_INVALID_ROUTE:
|
errors["base"] = "invalid_route"
|
||||||
errors["base"] = "invalid_route"
|
except Exception: # pylint: disable=broad-exception-caught
|
||||||
else:
|
errors["base"] = "cannot_connect"
|
||||||
errors["base"] = "cannot_connect"
|
|
||||||
else:
|
else:
|
||||||
self.hass.config_entries.async_update_entry(
|
self.hass.config_entries.async_update_entry(
|
||||||
self.entry,
|
self.entry,
|
||||||
@ -126,13 +123,12 @@ class TVFerryConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
await self.validate_input(api_key, ferry_from, ferry_to)
|
await self.validate_input(api_key, ferry_from, ferry_to)
|
||||||
except ValueError as err:
|
except InvalidAuthentication:
|
||||||
if str(err) == ERROR_INVALID_AUTH:
|
errors["base"] = "invalid_auth"
|
||||||
errors["base"] = "invalid_auth"
|
except NoFerryFound:
|
||||||
elif str(err) == ERROR_INVALID_ROUTE:
|
errors["base"] = "invalid_route"
|
||||||
errors["base"] = "invalid_route"
|
except Exception: # pylint: disable=broad-exception-caught
|
||||||
else:
|
errors["base"] = "cannot_connect"
|
||||||
errors["base"] = "cannot_connect"
|
|
||||||
else:
|
else:
|
||||||
if not errors:
|
if not errors:
|
||||||
unique_id = create_unique_id(
|
unique_id = create_unique_id(
|
||||||
|
@ -6,11 +6,13 @@ import logging
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from pytrafikverket import TrafikverketFerry
|
from pytrafikverket import TrafikverketFerry
|
||||||
|
from pytrafikverket.exceptions import InvalidAuthentication, NoFerryFound
|
||||||
from pytrafikverket.trafikverket_ferry import FerryStop
|
from pytrafikverket.trafikverket_ferry import FerryStop
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_API_KEY, CONF_WEEKDAY, WEEKDAYS
|
from homeassistant.const import CONF_API_KEY, CONF_WEEKDAY, WEEKDAYS
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.exceptions import ConfigEntryAuthFailed
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||||
from homeassistant.util import dt
|
from homeassistant.util import dt
|
||||||
@ -82,10 +84,12 @@ class TVDataUpdateCoordinator(DataUpdateCoordinator):
|
|||||||
] = await self._ferry_api.async_get_next_ferry_stops(
|
] = await self._ferry_api.async_get_next_ferry_stops(
|
||||||
self._from, self._to, when, 3
|
self._from, self._to, when, 3
|
||||||
)
|
)
|
||||||
except ValueError as error:
|
except NoFerryFound as error:
|
||||||
raise UpdateFailed(
|
raise UpdateFailed(
|
||||||
f"Departure {when} encountered a problem: {error}"
|
f"Departure {when} encountered a problem: {error}"
|
||||||
) from error
|
) from error
|
||||||
|
except InvalidAuthentication as error:
|
||||||
|
raise ConfigEntryAuthFailed(error) from error
|
||||||
|
|
||||||
states = {
|
states = {
|
||||||
"departure_time": routedata[0].departure_time,
|
"departure_time": routedata[0].departure_time,
|
||||||
|
@ -6,5 +6,5 @@
|
|||||||
"documentation": "https://www.home-assistant.io/integrations/trafikverket_ferry",
|
"documentation": "https://www.home-assistant.io/integrations/trafikverket_ferry",
|
||||||
"iot_class": "cloud_polling",
|
"iot_class": "cloud_polling",
|
||||||
"loggers": ["pytrafikverket"],
|
"loggers": ["pytrafikverket"],
|
||||||
"requirements": ["pytrafikverket==0.2.3"]
|
"requirements": ["pytrafikverket==0.3.1"]
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,11 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from pytrafikverket import TrafikverketTrain
|
from pytrafikverket import TrafikverketTrain
|
||||||
|
from pytrafikverket.exceptions import (
|
||||||
|
InvalidAuthentication,
|
||||||
|
MultipleTrainStationsFound,
|
||||||
|
NoTrainStationFound,
|
||||||
|
)
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_API_KEY
|
from homeassistant.const import CONF_API_KEY
|
||||||
@ -21,9 +26,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
try:
|
try:
|
||||||
to_station = await train_api.async_get_train_station(entry.data[CONF_TO])
|
to_station = await train_api.async_get_train_station(entry.data[CONF_TO])
|
||||||
from_station = await train_api.async_get_train_station(entry.data[CONF_FROM])
|
from_station = await train_api.async_get_train_station(entry.data[CONF_FROM])
|
||||||
except ValueError as error:
|
except InvalidAuthentication as error:
|
||||||
if "Invalid authentication" in error.args[0]:
|
raise ConfigEntryAuthFailed from error
|
||||||
raise ConfigEntryAuthFailed from error
|
except (NoTrainStationFound, MultipleTrainStationsFound) as error:
|
||||||
raise ConfigEntryNotReady(
|
raise ConfigEntryNotReady(
|
||||||
f"Problem when trying station {entry.data[CONF_FROM]} to"
|
f"Problem when trying station {entry.data[CONF_FROM]} to"
|
||||||
f" {entry.data[CONF_TO]}. Error: {error} "
|
f" {entry.data[CONF_TO]}. Error: {error} "
|
||||||
|
@ -5,6 +5,11 @@ from collections.abc import Mapping
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from pytrafikverket import TrafikverketTrain
|
from pytrafikverket import TrafikverketTrain
|
||||||
|
from pytrafikverket.exceptions import (
|
||||||
|
InvalidAuthentication,
|
||||||
|
MultipleTrainStationsFound,
|
||||||
|
NoTrainStationFound,
|
||||||
|
)
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
@ -23,10 +28,6 @@ import homeassistant.util.dt as dt_util
|
|||||||
from .const import CONF_FROM, CONF_TIME, CONF_TO, DOMAIN
|
from .const import CONF_FROM, CONF_TIME, CONF_TO, DOMAIN
|
||||||
from .util import create_unique_id
|
from .util import create_unique_id
|
||||||
|
|
||||||
ERROR_INVALID_AUTH = "Source: Security, message: Invalid authentication"
|
|
||||||
ERROR_INVALID_STATION = "Could not find a station with the specified name"
|
|
||||||
ERROR_MULTIPLE_STATION = "Found multiple stations with the specified name"
|
|
||||||
|
|
||||||
DATA_SCHEMA = vol.Schema(
|
DATA_SCHEMA = vol.Schema(
|
||||||
{
|
{
|
||||||
vol.Required(CONF_API_KEY): TextSelector(),
|
vol.Required(CONF_API_KEY): TextSelector(),
|
||||||
@ -86,15 +87,14 @@ class TVTrainConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
await self.validate_input(
|
await self.validate_input(
|
||||||
api_key, self.entry.data[CONF_FROM], self.entry.data[CONF_TO]
|
api_key, self.entry.data[CONF_FROM], self.entry.data[CONF_TO]
|
||||||
)
|
)
|
||||||
except ValueError as err:
|
except InvalidAuthentication:
|
||||||
if str(err) == ERROR_INVALID_AUTH:
|
errors["base"] = "invalid_auth"
|
||||||
errors["base"] = "invalid_auth"
|
except NoTrainStationFound:
|
||||||
elif str(err) == ERROR_INVALID_STATION:
|
errors["base"] = "invalid_station"
|
||||||
errors["base"] = "invalid_station"
|
except MultipleTrainStationsFound:
|
||||||
elif str(err) == ERROR_MULTIPLE_STATION:
|
errors["base"] = "more_stations"
|
||||||
errors["base"] = "more_stations"
|
except Exception: # pylint: disable=broad-exception-caught
|
||||||
else:
|
errors["base"] = "cannot_connect"
|
||||||
errors["base"] = "cannot_connect"
|
|
||||||
else:
|
else:
|
||||||
self.hass.config_entries.async_update_entry(
|
self.hass.config_entries.async_update_entry(
|
||||||
self.entry,
|
self.entry,
|
||||||
@ -131,15 +131,14 @@ class TVTrainConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
await self.validate_input(api_key, train_from, train_to)
|
await self.validate_input(api_key, train_from, train_to)
|
||||||
except ValueError as err:
|
except InvalidAuthentication:
|
||||||
if str(err) == ERROR_INVALID_AUTH:
|
errors["base"] = "invalid_auth"
|
||||||
errors["base"] = "invalid_auth"
|
except NoTrainStationFound:
|
||||||
elif str(err) == ERROR_INVALID_STATION:
|
errors["base"] = "invalid_station"
|
||||||
errors["base"] = "invalid_station"
|
except MultipleTrainStationsFound:
|
||||||
elif str(err) == ERROR_MULTIPLE_STATION:
|
errors["base"] = "more_stations"
|
||||||
errors["base"] = "more_stations"
|
except Exception: # pylint: disable=broad-exception-caught
|
||||||
else:
|
errors["base"] = "cannot_connect"
|
||||||
errors["base"] = "cannot_connect"
|
|
||||||
else:
|
else:
|
||||||
if train_time:
|
if train_time:
|
||||||
if bool(dt_util.parse_time(train_time) is None):
|
if bool(dt_util.parse_time(train_time) is None):
|
||||||
|
@ -6,5 +6,5 @@
|
|||||||
"documentation": "https://www.home-assistant.io/integrations/trafikverket_train",
|
"documentation": "https://www.home-assistant.io/integrations/trafikverket_train",
|
||||||
"iot_class": "cloud_polling",
|
"iot_class": "cloud_polling",
|
||||||
"loggers": ["pytrafikverket"],
|
"loggers": ["pytrafikverket"],
|
||||||
"requirements": ["pytrafikverket==0.2.3"]
|
"requirements": ["pytrafikverket==0.3.1"]
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,13 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from datetime import date, datetime, time, timedelta
|
from datetime import date, datetime, time, timedelta
|
||||||
import logging
|
import logging
|
||||||
from typing import Any
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
from pytrafikverket import TrafikverketTrain
|
from pytrafikverket import TrafikverketTrain
|
||||||
|
from pytrafikverket.exceptions import (
|
||||||
|
MultipleTrainAnnouncementFound,
|
||||||
|
NoTrainAnnouncementFound,
|
||||||
|
)
|
||||||
from pytrafikverket.trafikverket_train import StationInfo, TrainStop
|
from pytrafikverket.trafikverket_train import StationInfo, TrainStop
|
||||||
|
|
||||||
from homeassistant.components.sensor import SensorDeviceClass, SensorEntity
|
from homeassistant.components.sensor import SensorDeviceClass, SensorEntity
|
||||||
@ -119,6 +123,8 @@ class TrainSensor(SensorEntity):
|
|||||||
name=name,
|
name=name,
|
||||||
configuration_url="https://api.trafikinfo.trafikverket.se/",
|
configuration_url="https://api.trafikinfo.trafikverket.se/",
|
||||||
)
|
)
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
assert from_station.name and to_station.name
|
||||||
self._attr_unique_id = create_unique_id(
|
self._attr_unique_id = create_unique_id(
|
||||||
from_station.name, to_station.name, departuretime, weekday
|
from_station.name, to_station.name, departuretime, weekday
|
||||||
)
|
)
|
||||||
@ -134,6 +140,7 @@ class TrainSensor(SensorEntity):
|
|||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
if self._time:
|
if self._time:
|
||||||
|
_LOGGER.debug("%s, %s, %s", self._from_station, self._to_station, when)
|
||||||
_state = await self._train_api.async_get_train_stop(
|
_state = await self._train_api.async_get_train_stop(
|
||||||
self._from_station, self._to_station, when
|
self._from_station, self._to_station, when
|
||||||
)
|
)
|
||||||
@ -141,7 +148,7 @@ class TrainSensor(SensorEntity):
|
|||||||
_state = await self._train_api.async_get_next_train_stop(
|
_state = await self._train_api.async_get_next_train_stop(
|
||||||
self._from_station, self._to_station, when
|
self._from_station, self._to_station, when
|
||||||
)
|
)
|
||||||
except ValueError as error:
|
except (NoTrainAnnouncementFound, MultipleTrainAnnouncementFound) as error:
|
||||||
_LOGGER.error("Departure %s encountered a problem: %s", when, error)
|
_LOGGER.error("Departure %s encountered a problem: %s", when, error)
|
||||||
|
|
||||||
if not _state:
|
if not _state:
|
||||||
@ -153,6 +160,8 @@ class TrainSensor(SensorEntity):
|
|||||||
self._attr_available = True
|
self._attr_available = True
|
||||||
|
|
||||||
# The original datetime doesn't provide a timezone so therefore attaching it here.
|
# The original datetime doesn't provide a timezone so therefore attaching it here.
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
assert _state.advertised_time_at_location
|
||||||
self._attr_native_value = dt.as_utc(_state.advertised_time_at_location)
|
self._attr_native_value = dt.as_utc(_state.advertised_time_at_location)
|
||||||
if _state.time_at_location:
|
if _state.time_at_location:
|
||||||
self._attr_native_value = dt.as_utc(_state.time_at_location)
|
self._attr_native_value = dt.as_utc(_state.time_at_location)
|
||||||
@ -165,7 +174,7 @@ class TrainSensor(SensorEntity):
|
|||||||
"""Return extra state attributes."""
|
"""Return extra state attributes."""
|
||||||
|
|
||||||
attributes: dict[str, Any] = {
|
attributes: dict[str, Any] = {
|
||||||
ATTR_DEPARTURE_STATE: state.get_state().name,
|
ATTR_DEPARTURE_STATE: state.get_state().value,
|
||||||
ATTR_CANCELED: state.canceled,
|
ATTR_CANCELED: state.canceled,
|
||||||
ATTR_DELAY_TIME: None,
|
ATTR_DELAY_TIME: None,
|
||||||
ATTR_PLANNED_TIME: None,
|
ATTR_PLANNED_TIME: None,
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
"""Adds config flow for Trafikverket Weather integration."""
|
"""Adds config flow for Trafikverket Weather integration."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from pytrafikverket.exceptions import (
|
||||||
|
InvalidAuthentication,
|
||||||
|
MultipleWeatherStationsFound,
|
||||||
|
NoWeatherStationFound,
|
||||||
|
)
|
||||||
from pytrafikverket.trafikverket_weather import TrafikverketWeather
|
from pytrafikverket.trafikverket_weather import TrafikverketWeather
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
@ -20,15 +25,11 @@ class TVWeatherConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
|
|
||||||
entry: config_entries.ConfigEntry
|
entry: config_entries.ConfigEntry
|
||||||
|
|
||||||
async def validate_input(self, sensor_api: str, station: str) -> str:
|
async def validate_input(self, sensor_api: str, station: str) -> None:
|
||||||
"""Validate input from user input."""
|
"""Validate input from user input."""
|
||||||
web_session = async_get_clientsession(self.hass)
|
web_session = async_get_clientsession(self.hass)
|
||||||
weather_api = TrafikverketWeather(web_session, sensor_api)
|
weather_api = TrafikverketWeather(web_session, sensor_api)
|
||||||
try:
|
await weather_api.async_get_weather(station)
|
||||||
await weather_api.async_get_weather(station)
|
|
||||||
except ValueError as err:
|
|
||||||
return str(err)
|
|
||||||
return "connected"
|
|
||||||
|
|
||||||
async def async_step_user(
|
async def async_step_user(
|
||||||
self, user_input: dict[str, str] | None = None
|
self, user_input: dict[str, str] | None = None
|
||||||
@ -41,8 +42,17 @@ class TVWeatherConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
api_key = user_input[CONF_API_KEY]
|
api_key = user_input[CONF_API_KEY]
|
||||||
station = user_input[CONF_STATION]
|
station = user_input[CONF_STATION]
|
||||||
|
|
||||||
validate = await self.validate_input(api_key, station)
|
try:
|
||||||
if validate == "connected":
|
await self.validate_input(api_key, station)
|
||||||
|
except InvalidAuthentication:
|
||||||
|
errors["base"] = "invalid_auth"
|
||||||
|
except NoWeatherStationFound:
|
||||||
|
errors["base"] = "invalid_station"
|
||||||
|
except MultipleWeatherStationsFound:
|
||||||
|
errors["base"] = "more_stations"
|
||||||
|
except Exception: # pylint: disable=broad-exception-caught
|
||||||
|
errors["base"] = "cannot_connect"
|
||||||
|
else:
|
||||||
return self.async_create_entry(
|
return self.async_create_entry(
|
||||||
title=name,
|
title=name,
|
||||||
data={
|
data={
|
||||||
@ -50,14 +60,6 @@ class TVWeatherConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
CONF_STATION: station,
|
CONF_STATION: station,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if validate == "Source: Security, message: Invalid authentication":
|
|
||||||
errors["base"] = "invalid_auth"
|
|
||||||
elif validate == "Could not find a weather station with the specified name":
|
|
||||||
errors["base"] = "invalid_station"
|
|
||||||
elif validate == "Found multiple weather stations with the specified name":
|
|
||||||
errors["base"] = "more_stations"
|
|
||||||
else:
|
|
||||||
errors["base"] = "cannot_connect"
|
|
||||||
|
|
||||||
return self.async_show_form(
|
return self.async_show_form(
|
||||||
step_id="user",
|
step_id="user",
|
||||||
|
@ -4,11 +4,17 @@ from __future__ import annotations
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from pytrafikverket.exceptions import (
|
||||||
|
InvalidAuthentication,
|
||||||
|
MultipleWeatherStationsFound,
|
||||||
|
NoWeatherStationFound,
|
||||||
|
)
|
||||||
from pytrafikverket.trafikverket_weather import TrafikverketWeather, WeatherStationInfo
|
from pytrafikverket.trafikverket_weather import TrafikverketWeather, WeatherStationInfo
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_API_KEY
|
from homeassistant.const import CONF_API_KEY
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.exceptions import ConfigEntryAuthFailed
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||||
|
|
||||||
@ -38,6 +44,8 @@ class TVDataUpdateCoordinator(DataUpdateCoordinator[WeatherStationInfo]):
|
|||||||
"""Fetch data from Trafikverket."""
|
"""Fetch data from Trafikverket."""
|
||||||
try:
|
try:
|
||||||
weatherdata = await self._weather_api.async_get_weather(self._station)
|
weatherdata = await self._weather_api.async_get_weather(self._station)
|
||||||
except ValueError as error:
|
except InvalidAuthentication as error:
|
||||||
|
raise ConfigEntryAuthFailed from error
|
||||||
|
except (NoWeatherStationFound, MultipleWeatherStationsFound) as error:
|
||||||
raise UpdateFailed from error
|
raise UpdateFailed from error
|
||||||
return weatherdata
|
return weatherdata
|
||||||
|
@ -6,5 +6,5 @@
|
|||||||
"documentation": "https://www.home-assistant.io/integrations/trafikverket_weatherstation",
|
"documentation": "https://www.home-assistant.io/integrations/trafikverket_weatherstation",
|
||||||
"iot_class": "cloud_polling",
|
"iot_class": "cloud_polling",
|
||||||
"loggers": ["pytrafikverket"],
|
"loggers": ["pytrafikverket"],
|
||||||
"requirements": ["pytrafikverket==0.2.3"]
|
"requirements": ["pytrafikverket==0.3.1"]
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from homeassistant.components.sensor import (
|
from homeassistant.components.sensor import (
|
||||||
SensorDeviceClass,
|
SensorDeviceClass,
|
||||||
@ -190,7 +191,9 @@ class TrafikverketWeatherStation(
|
|||||||
def native_value(self) -> StateType | datetime:
|
def native_value(self) -> StateType | datetime:
|
||||||
"""Return state of sensor."""
|
"""Return state of sensor."""
|
||||||
if self.entity_description.api_key == "measure_time":
|
if self.entity_description.api_key == "measure_time":
|
||||||
return _to_datetime(self.coordinator.data.measure_time)
|
if TYPE_CHECKING:
|
||||||
|
assert self.coordinator.data.measure_time
|
||||||
|
return self.coordinator.data.measure_time
|
||||||
|
|
||||||
state: StateType = getattr(
|
state: StateType = getattr(
|
||||||
self.coordinator.data, self.entity_description.api_key
|
self.coordinator.data, self.entity_description.api_key
|
||||||
@ -204,4 +207,6 @@ class TrafikverketWeatherStation(
|
|||||||
@property
|
@property
|
||||||
def available(self) -> bool:
|
def available(self) -> bool:
|
||||||
"""Return if entity is available."""
|
"""Return if entity is available."""
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
assert self.coordinator.data.active
|
||||||
return self.coordinator.data.active and super().available
|
return self.coordinator.data.active and super().available
|
||||||
|
@ -2146,7 +2146,7 @@ pytradfri[async]==9.0.1
|
|||||||
# homeassistant.components.trafikverket_ferry
|
# homeassistant.components.trafikverket_ferry
|
||||||
# homeassistant.components.trafikverket_train
|
# homeassistant.components.trafikverket_train
|
||||||
# homeassistant.components.trafikverket_weatherstation
|
# homeassistant.components.trafikverket_weatherstation
|
||||||
pytrafikverket==0.2.3
|
pytrafikverket==0.3.1
|
||||||
|
|
||||||
# homeassistant.components.usb
|
# homeassistant.components.usb
|
||||||
pyudev==0.23.2
|
pyudev==0.23.2
|
||||||
|
@ -1551,7 +1551,7 @@ pytradfri[async]==9.0.1
|
|||||||
# homeassistant.components.trafikverket_ferry
|
# homeassistant.components.trafikverket_ferry
|
||||||
# homeassistant.components.trafikverket_train
|
# homeassistant.components.trafikverket_train
|
||||||
# homeassistant.components.trafikverket_weatherstation
|
# homeassistant.components.trafikverket_weatherstation
|
||||||
pytrafikverket==0.2.3
|
pytrafikverket==0.3.1
|
||||||
|
|
||||||
# homeassistant.components.usb
|
# homeassistant.components.usb
|
||||||
pyudev==0.23.2
|
pyudev==0.23.2
|
||||||
|
@ -4,6 +4,7 @@ from __future__ import annotations
|
|||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from pytrafikverket.exceptions import InvalidAuthentication, NoFerryFound
|
||||||
|
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
from homeassistant.components.trafikverket_ferry.const import (
|
from homeassistant.components.trafikverket_ferry.const import (
|
||||||
@ -63,24 +64,24 @@ async def test_form(hass: HomeAssistant) -> None:
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("error_message", "base_error"),
|
("side_effect", "base_error"),
|
||||||
[
|
[
|
||||||
(
|
(
|
||||||
"Source: Security, message: Invalid authentication",
|
InvalidAuthentication,
|
||||||
"invalid_auth",
|
"invalid_auth",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"No FerryAnnouncement found",
|
NoFerryFound,
|
||||||
"invalid_route",
|
"invalid_route",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"Unknown",
|
Exception,
|
||||||
"cannot_connect",
|
"cannot_connect",
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
async def test_flow_fails(
|
async def test_flow_fails(
|
||||||
hass: HomeAssistant, error_message: str, base_error: str
|
hass: HomeAssistant, side_effect: str, base_error: str
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test config flow errors."""
|
"""Test config flow errors."""
|
||||||
result4 = await hass.config_entries.flow.async_init(
|
result4 = await hass.config_entries.flow.async_init(
|
||||||
@ -92,7 +93,7 @@ async def test_flow_fails(
|
|||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.trafikverket_ferry.config_flow.TrafikverketFerry.async_get_next_ferry_stop",
|
"homeassistant.components.trafikverket_ferry.config_flow.TrafikverketFerry.async_get_next_ferry_stop",
|
||||||
side_effect=ValueError(error_message),
|
side_effect=side_effect(),
|
||||||
):
|
):
|
||||||
result4 = await hass.config_entries.flow.async_configure(
|
result4 = await hass.config_entries.flow.async_configure(
|
||||||
result4["flow_id"],
|
result4["flow_id"],
|
||||||
@ -161,24 +162,24 @@ async def test_reauth_flow(hass: HomeAssistant) -> None:
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("sideeffect", "p_error"),
|
("side_effect", "p_error"),
|
||||||
[
|
[
|
||||||
(
|
(
|
||||||
ValueError("Source: Security, message: Invalid authentication"),
|
InvalidAuthentication,
|
||||||
"invalid_auth",
|
"invalid_auth",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
ValueError("No FerryAnnouncement found"),
|
NoFerryFound,
|
||||||
"invalid_route",
|
"invalid_route",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
ValueError("Unknown"),
|
Exception,
|
||||||
"cannot_connect",
|
"cannot_connect",
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
async def test_reauth_flow_error(
|
async def test_reauth_flow_error(
|
||||||
hass: HomeAssistant, sideeffect: Exception, p_error: str
|
hass: HomeAssistant, side_effect: Exception, p_error: str
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test a reauthentication flow with error."""
|
"""Test a reauthentication flow with error."""
|
||||||
entry = MockConfigEntry(
|
entry = MockConfigEntry(
|
||||||
@ -207,7 +208,7 @@ async def test_reauth_flow_error(
|
|||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.trafikverket_ferry.config_flow.TrafikverketFerry.async_get_next_ferry_stop",
|
"homeassistant.components.trafikverket_ferry.config_flow.TrafikverketFerry.async_get_next_ferry_stop",
|
||||||
side_effect=sideeffect,
|
side_effect=side_effect(),
|
||||||
):
|
):
|
||||||
result2 = await hass.config_entries.flow.async_configure(
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
|
@ -2,10 +2,11 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from datetime import date, datetime, timedelta
|
from datetime import date, datetime, timedelta
|
||||||
from unittest.mock import AsyncMock, patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
from freezegun.api import FrozenDateTimeFactory
|
from freezegun.api import FrozenDateTimeFactory
|
||||||
import pytest
|
import pytest
|
||||||
|
from pytrafikverket.exceptions import InvalidAuthentication, NoFerryFound
|
||||||
from pytrafikverket.trafikverket_ferry import FerryStop
|
from pytrafikverket.trafikverket_ferry import FerryStop
|
||||||
|
|
||||||
from homeassistant.components.trafikverket_ferry.const import DOMAIN
|
from homeassistant.components.trafikverket_ferry.const import DOMAIN
|
||||||
@ -22,7 +23,7 @@ from tests.common import MockConfigEntry, async_fire_time_changed
|
|||||||
|
|
||||||
async def test_coordinator(
|
async def test_coordinator(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
entity_registry_enabled_by_default: AsyncMock,
|
entity_registry_enabled_by_default: None,
|
||||||
monkeypatch: pytest.MonkeyPatch,
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
get_ferries: list[FerryStop],
|
get_ferries: list[FerryStop],
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -69,7 +70,7 @@ async def test_coordinator(
|
|||||||
assert state3.state == str(dt.now().year + 2) + "-05-01T12:00:00+00:00"
|
assert state3.state == str(dt.now().year + 2) + "-05-01T12:00:00+00:00"
|
||||||
mock_data.reset_mock()
|
mock_data.reset_mock()
|
||||||
|
|
||||||
mock_data.side_effect = ValueError("info")
|
mock_data.side_effect = NoFerryFound()
|
||||||
async_fire_time_changed(hass, dt.utcnow() + timedelta(minutes=6))
|
async_fire_time_changed(hass, dt.utcnow() + timedelta(minutes=6))
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
mock_data.assert_called_once()
|
mock_data.assert_called_once()
|
||||||
@ -81,11 +82,19 @@ async def test_coordinator(
|
|||||||
mock_data.side_effect = None
|
mock_data.side_effect = None
|
||||||
async_fire_time_changed(hass, dt.utcnow() + timedelta(minutes=6))
|
async_fire_time_changed(hass, dt.utcnow() + timedelta(minutes=6))
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
mock_data.assert_called_once()
|
# mock_data.assert_called_once()
|
||||||
state1 = hass.states.get("sensor.harbor1_departure_from")
|
state1 = hass.states.get("sensor.harbor1_departure_from")
|
||||||
assert state1.state == "Harbor 1"
|
assert state1.state == "Harbor 1"
|
||||||
mock_data.reset_mock()
|
mock_data.reset_mock()
|
||||||
|
|
||||||
|
mock_data.side_effect = InvalidAuthentication()
|
||||||
|
async_fire_time_changed(hass, dt.utcnow() + timedelta(minutes=6))
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
mock_data.assert_called_once()
|
||||||
|
state1 = hass.states.get("sensor.harbor1_departure_from")
|
||||||
|
assert state1.state == STATE_UNAVAILABLE
|
||||||
|
mock_data.reset_mock()
|
||||||
|
|
||||||
|
|
||||||
async def test_coordinator_next_departuredate(freezer: FrozenDateTimeFactory) -> None:
|
async def test_coordinator_next_departuredate(freezer: FrozenDateTimeFactory) -> None:
|
||||||
"""Test the Trafikverket Ferry next_departuredate calculation."""
|
"""Test the Trafikverket Ferry next_departuredate calculation."""
|
||||||
|
@ -4,6 +4,11 @@ from __future__ import annotations
|
|||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from pytrafikverket.exceptions import (
|
||||||
|
InvalidAuthentication,
|
||||||
|
MultipleTrainStationsFound,
|
||||||
|
NoTrainStationFound,
|
||||||
|
)
|
||||||
|
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
from homeassistant.components.trafikverket_train.const import (
|
from homeassistant.components.trafikverket_train.const import (
|
||||||
@ -108,28 +113,28 @@ async def test_form_entry_already_exist(hass: HomeAssistant) -> None:
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("error_message", "base_error"),
|
("side_effect", "base_error"),
|
||||||
[
|
[
|
||||||
(
|
(
|
||||||
"Source: Security, message: Invalid authentication",
|
InvalidAuthentication,
|
||||||
"invalid_auth",
|
"invalid_auth",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"Could not find a station with the specified name",
|
NoTrainStationFound,
|
||||||
"invalid_station",
|
"invalid_station",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"Found multiple stations with the specified name",
|
MultipleTrainStationsFound,
|
||||||
"more_stations",
|
"more_stations",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"Unknown",
|
Exception,
|
||||||
"cannot_connect",
|
"cannot_connect",
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
async def test_flow_fails(
|
async def test_flow_fails(
|
||||||
hass: HomeAssistant, error_message: str, base_error: str
|
hass: HomeAssistant, side_effect: Exception, base_error: str
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test config flow errors."""
|
"""Test config flow errors."""
|
||||||
result4 = await hass.config_entries.flow.async_init(
|
result4 = await hass.config_entries.flow.async_init(
|
||||||
@ -141,7 +146,7 @@ async def test_flow_fails(
|
|||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.trafikverket_train.config_flow.TrafikverketTrain.async_get_train_station",
|
"homeassistant.components.trafikverket_train.config_flow.TrafikverketTrain.async_get_train_station",
|
||||||
side_effect=ValueError(error_message),
|
side_effect=side_effect(),
|
||||||
):
|
):
|
||||||
result4 = await hass.config_entries.flow.async_configure(
|
result4 = await hass.config_entries.flow.async_configure(
|
||||||
result4["flow_id"],
|
result4["flow_id"],
|
||||||
@ -234,28 +239,28 @@ async def test_reauth_flow(hass: HomeAssistant) -> None:
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("sideeffect", "p_error"),
|
("side_effect", "p_error"),
|
||||||
[
|
[
|
||||||
(
|
(
|
||||||
ValueError("Source: Security, message: Invalid authentication"),
|
InvalidAuthentication,
|
||||||
"invalid_auth",
|
"invalid_auth",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
ValueError("Could not find a station with the specified name"),
|
NoTrainStationFound,
|
||||||
"invalid_station",
|
"invalid_station",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
ValueError("Found multiple stations with the specified name"),
|
MultipleTrainStationsFound,
|
||||||
"more_stations",
|
"more_stations",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
ValueError("Unknown"),
|
Exception,
|
||||||
"cannot_connect",
|
"cannot_connect",
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
async def test_reauth_flow_error(
|
async def test_reauth_flow_error(
|
||||||
hass: HomeAssistant, sideeffect: Exception, p_error: str
|
hass: HomeAssistant, side_effect: Exception, p_error: str
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test a reauthentication flow with error."""
|
"""Test a reauthentication flow with error."""
|
||||||
entry = MockConfigEntry(
|
entry = MockConfigEntry(
|
||||||
@ -284,7 +289,7 @@ async def test_reauth_flow_error(
|
|||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.trafikverket_train.config_flow.TrafikverketTrain.async_get_train_station",
|
"homeassistant.components.trafikverket_train.config_flow.TrafikverketTrain.async_get_train_station",
|
||||||
side_effect=sideeffect,
|
side_effect=side_effect(),
|
||||||
):
|
):
|
||||||
result2 = await hass.config_entries.flow.async_configure(
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
|
@ -4,6 +4,11 @@ from __future__ import annotations
|
|||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from pytrafikverket.exceptions import (
|
||||||
|
InvalidAuthentication,
|
||||||
|
MultipleWeatherStationsFound,
|
||||||
|
NoWeatherStationFound,
|
||||||
|
)
|
||||||
|
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
from homeassistant.const import CONF_API_KEY
|
from homeassistant.const import CONF_API_KEY
|
||||||
@ -48,28 +53,28 @@ async def test_form(hass: HomeAssistant) -> None:
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("error_message", "base_error"),
|
("side_effect", "base_error"),
|
||||||
[
|
[
|
||||||
(
|
(
|
||||||
"Source: Security, message: Invalid authentication",
|
InvalidAuthentication,
|
||||||
"invalid_auth",
|
"invalid_auth",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"Could not find a weather station with the specified name",
|
NoWeatherStationFound,
|
||||||
"invalid_station",
|
"invalid_station",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"Found multiple weather stations with the specified name",
|
MultipleWeatherStationsFound,
|
||||||
"more_stations",
|
"more_stations",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"Unknown",
|
Exception,
|
||||||
"cannot_connect",
|
"cannot_connect",
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
async def test_flow_fails(
|
async def test_flow_fails(
|
||||||
hass: HomeAssistant, error_message: str, base_error: str
|
hass: HomeAssistant, side_effect: Exception, base_error: str
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test config flow errors."""
|
"""Test config flow errors."""
|
||||||
result4 = await hass.config_entries.flow.async_init(
|
result4 = await hass.config_entries.flow.async_init(
|
||||||
@ -81,7 +86,7 @@ async def test_flow_fails(
|
|||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.trafikverket_weatherstation.config_flow.TrafikverketWeather.async_get_weather",
|
"homeassistant.components.trafikverket_weatherstation.config_flow.TrafikverketWeather.async_get_weather",
|
||||||
side_effect=ValueError(error_message),
|
side_effect=side_effect(),
|
||||||
):
|
):
|
||||||
result4 = await hass.config_entries.flow.async_configure(
|
result4 = await hass.config_entries.flow.async_configure(
|
||||||
result4["flow_id"],
|
result4["flow_id"],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user