mirror of
https://github.com/home-assistant/core.git
synced 2025-06-25 01:21:51 +02:00
Remove cloud dependency from islamic-prayer-times
(#115146)
Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
@ -683,8 +683,8 @@ build.json @home-assistant/supervisor
|
||||
/homeassistant/components/iqvia/ @bachya
|
||||
/tests/components/iqvia/ @bachya
|
||||
/homeassistant/components/irish_rail_transport/ @ttroy50
|
||||
/homeassistant/components/islamic_prayer_times/ @engrbm87
|
||||
/tests/components/islamic_prayer_times/ @engrbm87
|
||||
/homeassistant/components/islamic_prayer_times/ @engrbm87 @cpfair
|
||||
/tests/components/islamic_prayer_times/ @engrbm87 @cpfair
|
||||
/homeassistant/components/iss/ @DurgNomis-drol
|
||||
/tests/components/iss/ @DurgNomis-drol
|
||||
/homeassistant/components/isy994/ @bdraco @shbatm
|
||||
|
@ -4,8 +4,6 @@ from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from prayer_times_calculator import InvalidResponseError, PrayerTimesCalculator
|
||||
from requests.exceptions import ConnectionError as ConnError
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.config_entries import (
|
||||
@ -15,7 +13,7 @@ from homeassistant.config_entries import (
|
||||
OptionsFlow,
|
||||
)
|
||||
from homeassistant.const import CONF_LATITUDE, CONF_LOCATION, CONF_LONGITUDE, CONF_NAME
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.selector import (
|
||||
LocationSelector,
|
||||
SelectSelector,
|
||||
@ -23,7 +21,6 @@ from homeassistant.helpers.selector import (
|
||||
SelectSelectorMode,
|
||||
TextSelector,
|
||||
)
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
||||
from .const import (
|
||||
CALC_METHODS,
|
||||
@ -43,26 +40,6 @@ from .const import (
|
||||
)
|
||||
|
||||
|
||||
async def async_validate_location(
|
||||
hass: HomeAssistant, lat: float, lon: float
|
||||
) -> dict[str, str]:
|
||||
"""Check if the selected location is valid."""
|
||||
errors = {}
|
||||
calc = PrayerTimesCalculator(
|
||||
latitude=lat,
|
||||
longitude=lon,
|
||||
calculation_method=DEFAULT_CALC_METHOD,
|
||||
date=str(dt_util.now().date()),
|
||||
)
|
||||
try:
|
||||
await hass.async_add_executor_job(calc.fetch_prayer_times)
|
||||
except InvalidResponseError:
|
||||
errors["base"] = "invalid_location"
|
||||
except ConnError:
|
||||
errors["base"] = "conn_error"
|
||||
return errors
|
||||
|
||||
|
||||
class IslamicPrayerFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
"""Handle the Islamic Prayer config flow."""
|
||||
|
||||
@ -81,7 +58,6 @@ class IslamicPrayerFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> ConfigFlowResult:
|
||||
"""Handle a flow initialized by the user."""
|
||||
errors = {}
|
||||
|
||||
if user_input is not None:
|
||||
lat: float = user_input[CONF_LOCATION][CONF_LATITUDE]
|
||||
@ -89,14 +65,13 @@ class IslamicPrayerFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
await self.async_set_unique_id(f"{lat}-{lon}")
|
||||
self._abort_if_unique_id_configured()
|
||||
|
||||
if not (errors := await async_validate_location(self.hass, lat, lon)):
|
||||
return self.async_create_entry(
|
||||
title=user_input[CONF_NAME],
|
||||
data={
|
||||
CONF_LATITUDE: lat,
|
||||
CONF_LONGITUDE: lon,
|
||||
},
|
||||
)
|
||||
return self.async_create_entry(
|
||||
title=user_input[CONF_NAME],
|
||||
data={
|
||||
CONF_LATITUDE: lat,
|
||||
CONF_LONGITUDE: lon,
|
||||
},
|
||||
)
|
||||
|
||||
home_location = {
|
||||
CONF_LATITUDE: self.hass.config.latitude,
|
||||
@ -112,7 +87,6 @@ class IslamicPrayerFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
): LocationSelector(),
|
||||
}
|
||||
),
|
||||
errors=errors,
|
||||
)
|
||||
|
||||
|
||||
|
@ -6,14 +6,13 @@ from datetime import datetime, timedelta
|
||||
import logging
|
||||
from typing import Any, cast
|
||||
|
||||
from prayer_times_calculator import PrayerTimesCalculator, exceptions
|
||||
from requests.exceptions import ConnectionError as ConnError
|
||||
from prayer_times_calculator_offline import PrayerTimesCalculator
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE
|
||||
from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback
|
||||
from homeassistant.helpers.event import async_call_later, async_track_point_in_time
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
from homeassistant.helpers.event import async_track_point_in_time
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
||||
from .const import (
|
||||
@ -142,13 +141,7 @@ class IslamicPrayerDataUpdateCoordinator(DataUpdateCoordinator[dict[str, datetim
|
||||
|
||||
async def _async_update_data(self) -> dict[str, datetime]:
|
||||
"""Update sensors with new prayer times."""
|
||||
try:
|
||||
prayer_times = await self.hass.async_add_executor_job(
|
||||
self.get_new_prayer_times
|
||||
)
|
||||
except (exceptions.InvalidResponseError, ConnError) as err:
|
||||
async_call_later(self.hass, 60, self.async_request_update)
|
||||
raise UpdateFailed from err
|
||||
prayer_times = self.get_new_prayer_times()
|
||||
|
||||
# introduced in prayer-times-calculator 0.0.8
|
||||
prayer_times.pop("date", None)
|
||||
|
@ -1,10 +1,10 @@
|
||||
{
|
||||
"domain": "islamic_prayer_times",
|
||||
"name": "Islamic Prayer Times",
|
||||
"codeowners": ["@engrbm87"],
|
||||
"codeowners": ["@engrbm87", "@cpfair"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/islamic_prayer_times",
|
||||
"iot_class": "cloud_polling",
|
||||
"iot_class": "calculated",
|
||||
"loggers": ["prayer_times_calculator"],
|
||||
"requirements": ["prayer-times-calculator==0.0.12"]
|
||||
"requirements": ["prayer-times-calculator-offline==1.0.3"]
|
||||
}
|
||||
|
@ -2879,7 +2879,7 @@
|
||||
"islamic_prayer_times": {
|
||||
"integration_type": "hub",
|
||||
"config_flow": true,
|
||||
"iot_class": "cloud_polling"
|
||||
"iot_class": "calculated"
|
||||
},
|
||||
"ismartwindow": {
|
||||
"name": "iSmartWindow",
|
||||
|
@ -1556,7 +1556,7 @@ poolsense==0.0.8
|
||||
praw==7.5.0
|
||||
|
||||
# homeassistant.components.islamic_prayer_times
|
||||
prayer-times-calculator==0.0.12
|
||||
prayer-times-calculator-offline==1.0.3
|
||||
|
||||
# homeassistant.components.proliphix
|
||||
proliphix==0.4.1
|
||||
|
@ -1227,7 +1227,7 @@ poolsense==0.0.8
|
||||
praw==7.5.0
|
||||
|
||||
# homeassistant.components.islamic_prayer_times
|
||||
prayer-times-calculator==0.0.12
|
||||
prayer-times-calculator-offline==1.0.3
|
||||
|
||||
# homeassistant.components.prometheus
|
||||
prometheus-client==0.17.1
|
||||
|
@ -22,14 +22,4 @@ PRAYER_TIMES = {
|
||||
"Midnight": "2020-01-01T00:45:00+00:00",
|
||||
}
|
||||
|
||||
NEW_PRAYER_TIMES = {
|
||||
"Fajr": "2020-01-02T06:00:00+00:00",
|
||||
"Sunrise": "2020-01-02T07:25:00+00:00",
|
||||
"Dhuhr": "2020-01-02T12:30:00+00:00",
|
||||
"Asr": "2020-01-02T15:32:00+00:00",
|
||||
"Maghrib": "2020-01-02T17:45:00+00:00",
|
||||
"Isha": "2020-01-02T18:53:00+00:00",
|
||||
"Midnight": "2020-01-02T00:43:00+00:00",
|
||||
}
|
||||
|
||||
NOW = datetime(2020, 1, 1, 00, 00, 0, tzinfo=dt_util.UTC)
|
||||
|
@ -1,10 +1,6 @@
|
||||
"""Tests for Islamic Prayer Times config flow."""
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
from prayer_times_calculator import InvalidResponseError
|
||||
import pytest
|
||||
from requests.exceptions import ConnectionError as ConnError
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components import islamic_prayer_times
|
||||
@ -33,49 +29,15 @@ async def test_flow_works(hass: HomeAssistant) -> None:
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "user"
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.islamic_prayer_times.config_flow.async_validate_location",
|
||||
return_value={},
|
||||
):
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input=MOCK_USER_INPUT
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input=MOCK_USER_INPUT
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == "Home"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("exception", "error"),
|
||||
[
|
||||
(InvalidResponseError, "invalid_location"),
|
||||
(ConnError, "conn_error"),
|
||||
],
|
||||
)
|
||||
async def test_flow_error(
|
||||
hass: HomeAssistant, exception: Exception, error: str
|
||||
) -> None:
|
||||
"""Test flow errors."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
islamic_prayer_times.DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["step_id"] == "user"
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.islamic_prayer_times.config_flow.PrayerTimesCalculator.fetch_prayer_times",
|
||||
side_effect=exception,
|
||||
):
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input=MOCK_USER_INPUT
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result["type"] is FlowResultType.FORM
|
||||
assert result["errors"]["base"] == error
|
||||
|
||||
|
||||
async def test_options(hass: HomeAssistant) -> None:
|
||||
"""Test updating options."""
|
||||
entry = MockConfigEntry(
|
||||
|
@ -1,24 +1,21 @@
|
||||
"""Tests for Islamic Prayer Times init."""
|
||||
|
||||
from datetime import timedelta
|
||||
from unittest.mock import patch
|
||||
|
||||
from freezegun import freeze_time
|
||||
from prayer_times_calculator.exceptions import InvalidResponseError
|
||||
import pytest
|
||||
|
||||
from homeassistant.components import islamic_prayer_times
|
||||
from homeassistant.components.islamic_prayer_times.const import CONF_CALC_METHOD
|
||||
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE, STATE_UNAVAILABLE
|
||||
from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
||||
from . import NEW_PRAYER_TIMES, NOW, PRAYER_TIMES
|
||||
from . import NOW, PRAYER_TIMES
|
||||
|
||||
from tests.common import MockConfigEntry, async_fire_time_changed
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
@ -37,7 +34,7 @@ async def test_successful_config_entry(hass: HomeAssistant) -> None:
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
with patch(
|
||||
"prayer_times_calculator.PrayerTimesCalculator.fetch_prayer_times",
|
||||
"prayer_times_calculator_offline.PrayerTimesCalculator.fetch_prayer_times",
|
||||
return_value=PRAYER_TIMES,
|
||||
):
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
@ -46,25 +43,6 @@ async def test_successful_config_entry(hass: HomeAssistant) -> None:
|
||||
assert entry.state is ConfigEntryState.LOADED
|
||||
|
||||
|
||||
async def test_setup_failed(hass: HomeAssistant) -> None:
|
||||
"""Test Islamic Prayer Times failed due to an error."""
|
||||
|
||||
entry = MockConfigEntry(
|
||||
domain=islamic_prayer_times.DOMAIN,
|
||||
data={},
|
||||
)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
# test request error raising ConfigEntryNotReady
|
||||
with patch(
|
||||
"prayer_times_calculator.PrayerTimesCalculator.fetch_prayer_times",
|
||||
side_effect=InvalidResponseError(),
|
||||
):
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert entry.state is ConfigEntryState.SETUP_RETRY
|
||||
|
||||
|
||||
async def test_unload_entry(hass: HomeAssistant) -> None:
|
||||
"""Test removing Islamic Prayer Times."""
|
||||
entry = MockConfigEntry(
|
||||
@ -74,7 +52,7 @@ async def test_unload_entry(hass: HomeAssistant) -> None:
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
with patch(
|
||||
"prayer_times_calculator.PrayerTimesCalculator.fetch_prayer_times",
|
||||
"prayer_times_calculator_offline.PrayerTimesCalculator.fetch_prayer_times",
|
||||
return_value=PRAYER_TIMES,
|
||||
):
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
@ -91,7 +69,7 @@ async def test_options_listener(hass: HomeAssistant) -> None:
|
||||
|
||||
with (
|
||||
patch(
|
||||
"prayer_times_calculator.PrayerTimesCalculator.fetch_prayer_times",
|
||||
"prayer_times_calculator_offline.PrayerTimesCalculator.fetch_prayer_times",
|
||||
return_value=PRAYER_TIMES,
|
||||
) as mock_fetch_prayer_times,
|
||||
freeze_time(NOW),
|
||||
@ -107,49 +85,6 @@ async def test_options_listener(hass: HomeAssistant) -> None:
|
||||
assert mock_fetch_prayer_times.call_count == 2
|
||||
|
||||
|
||||
async def test_update_failed(hass: HomeAssistant) -> None:
|
||||
"""Test integrations tries to update after 1 min if update fails."""
|
||||
entry = MockConfigEntry(domain=islamic_prayer_times.DOMAIN, data={})
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
with (
|
||||
patch(
|
||||
"prayer_times_calculator.PrayerTimesCalculator.fetch_prayer_times",
|
||||
return_value=PRAYER_TIMES,
|
||||
),
|
||||
freeze_time(NOW),
|
||||
):
|
||||
await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert entry.state is ConfigEntryState.LOADED
|
||||
|
||||
with patch(
|
||||
"prayer_times_calculator.PrayerTimesCalculator.fetch_prayer_times"
|
||||
) as FetchPrayerTimes:
|
||||
FetchPrayerTimes.side_effect = [
|
||||
InvalidResponseError,
|
||||
NEW_PRAYER_TIMES,
|
||||
]
|
||||
midnight_time = dt_util.parse_datetime(PRAYER_TIMES["Midnight"])
|
||||
assert midnight_time
|
||||
future = midnight_time + timedelta(days=1, minutes=1)
|
||||
with freeze_time(future):
|
||||
async_fire_time_changed(hass, future)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("sensor.islamic_prayer_times_fajr_prayer")
|
||||
assert state.state == STATE_UNAVAILABLE
|
||||
|
||||
# coordinator tries to update after 1 minute
|
||||
future = future + timedelta(minutes=1)
|
||||
with freeze_time(future):
|
||||
async_fire_time_changed(hass, future)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("sensor.islamic_prayer_times_fajr_prayer")
|
||||
assert state.state == "2020-01-02T06:00:00+00:00"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("object_id", "old_unique_id"),
|
||||
[
|
||||
@ -184,7 +119,7 @@ async def test_migrate_unique_id(
|
||||
|
||||
with (
|
||||
patch(
|
||||
"prayer_times_calculator.PrayerTimesCalculator.fetch_prayer_times",
|
||||
"prayer_times_calculator_offline.PrayerTimesCalculator.fetch_prayer_times",
|
||||
return_value=PRAYER_TIMES,
|
||||
),
|
||||
freeze_time(NOW),
|
||||
@ -207,7 +142,7 @@ async def test_migration_from_1_1_to_1_2(hass: HomeAssistant) -> None:
|
||||
|
||||
with (
|
||||
patch(
|
||||
"prayer_times_calculator.PrayerTimesCalculator.fetch_prayer_times",
|
||||
"prayer_times_calculator_offline.PrayerTimesCalculator.fetch_prayer_times",
|
||||
return_value=PRAYER_TIMES,
|
||||
),
|
||||
freeze_time(NOW),
|
||||
|
@ -40,7 +40,7 @@ async def test_islamic_prayer_times_sensors(
|
||||
|
||||
with (
|
||||
patch(
|
||||
"prayer_times_calculator.PrayerTimesCalculator.fetch_prayer_times",
|
||||
"prayer_times_calculator_offline.PrayerTimesCalculator.fetch_prayer_times",
|
||||
return_value=PRAYER_TIMES,
|
||||
),
|
||||
freeze_time(NOW),
|
||||
|
Reference in New Issue
Block a user