Jewish calendar: move value calculation to entity description (1/3) (#144272)

* Move make_zmanim() method to entity

* Move enum values to setup

* Create a Jewish Calendar Sensor Description

* Hold a single variable for the runtime data in the entity

* Move value calculation to sensor description

* Use a base class to keep timestamp sensor inheritance

* Move attr to entity description as well

* Move options to entity description as well

* Fix tests after merge

* Put multiline in parentheses

* Fix diagnostics tests
This commit is contained in:
Tsvi Mostovicz 2025-05-20 20:01:24 +03:00 committed by GitHub
parent 734d6cd247
commit b71870aba3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 322 additions and 149 deletions

View File

@ -82,18 +82,9 @@ class JewishCalendarBinarySensor(JewishCalendarEntity, BinarySensorEntity):
@property @property
def is_on(self) -> bool: def is_on(self) -> bool:
"""Return true if sensor is on.""" """Return true if sensor is on."""
zmanim = self._get_zmanim() zmanim = self.make_zmanim(dt.date.today())
return self.entity_description.is_on(zmanim, dt_util.now()) return self.entity_description.is_on(zmanim, dt_util.now())
def _get_zmanim(self) -> Zmanim:
"""Return the Zmanim object for now()."""
return Zmanim(
date=dt.date.today(),
location=self._location,
candle_lighting_offset=self._candle_lighting_offset,
havdalah_offset=self._havdalah_offset,
)
async def async_added_to_hass(self) -> None: async def async_added_to_hass(self) -> None:
"""Run when entity about to be added to hass.""" """Run when entity about to be added to hass."""
await super().async_added_to_hass() await super().async_added_to_hass()
@ -116,7 +107,7 @@ class JewishCalendarBinarySensor(JewishCalendarEntity, BinarySensorEntity):
def _schedule_update(self) -> None: def _schedule_update(self) -> None:
"""Schedule the next update of the sensor.""" """Schedule the next update of the sensor."""
now = dt_util.now() now = dt_util.now()
zmanim = self._get_zmanim() zmanim = self.make_zmanim(dt.date.today())
update = zmanim.netz_hachama.local + dt.timedelta(days=1) update = zmanim.netz_hachama.local + dt.timedelta(days=1)
candle_lighting = zmanim.candle_lighting candle_lighting = zmanim.candle_lighting
if candle_lighting is not None and now < candle_lighting < update: if candle_lighting is not None and now < candle_lighting < update:

View File

@ -1,8 +1,9 @@
"""Entity representing a Jewish Calendar sensor.""" """Entity representing a Jewish Calendar sensor."""
from dataclasses import dataclass from dataclasses import dataclass
import datetime as dt
from hdate import Location from hdate import HDateInfo, Location, Zmanim
from hdate.translator import Language, set_language from hdate.translator import Language, set_language
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
@ -14,6 +15,16 @@ from .const import DOMAIN
type JewishCalendarConfigEntry = ConfigEntry[JewishCalendarData] type JewishCalendarConfigEntry = ConfigEntry[JewishCalendarData]
@dataclass
class JewishCalendarDataResults:
"""Jewish Calendar results dataclass."""
daytime_date: HDateInfo
after_shkia_date: HDateInfo
after_tzais_date: HDateInfo
zmanim: Zmanim
@dataclass @dataclass
class JewishCalendarData: class JewishCalendarData:
"""Jewish Calendar runtime dataclass.""" """Jewish Calendar runtime dataclass."""
@ -23,6 +34,7 @@ class JewishCalendarData:
location: Location location: Location
candle_lighting_offset: int candle_lighting_offset: int
havdalah_offset: int havdalah_offset: int
results: JewishCalendarDataResults | None = None
class JewishCalendarEntity(Entity): class JewishCalendarEntity(Entity):
@ -42,9 +54,14 @@ class JewishCalendarEntity(Entity):
entry_type=DeviceEntryType.SERVICE, entry_type=DeviceEntryType.SERVICE,
identifiers={(DOMAIN, config_entry.entry_id)}, identifiers={(DOMAIN, config_entry.entry_id)},
) )
data = config_entry.runtime_data self.data = config_entry.runtime_data
self._location = data.location set_language(self.data.language)
self._candle_lighting_offset = data.candle_lighting_offset
self._havdalah_offset = data.havdalah_offset def make_zmanim(self, date: dt.date) -> Zmanim:
self._diaspora = data.diaspora """Create a Zmanim object."""
set_language(data.language) return Zmanim(
date=date,
location=self.data.location,
candle_lighting_offset=self.data.candle_lighting_offset,
havdalah_offset=self.data.havdalah_offset,
)

View File

@ -2,9 +2,10 @@
from __future__ import annotations from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
import datetime as dt import datetime as dt
import logging import logging
from typing import Any
from hdate import HDateInfo, Zmanim from hdate import HDateInfo, Zmanim
from hdate.holidays import HolidayDatabase from hdate.holidays import HolidayDatabase
@ -21,124 +22,192 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.sun import get_astral_event_date from homeassistant.helpers.sun import get_astral_event_date
from homeassistant.util import dt as dt_util from homeassistant.util import dt as dt_util
from .entity import JewishCalendarConfigEntry, JewishCalendarEntity from .entity import (
JewishCalendarConfigEntry,
JewishCalendarDataResults,
JewishCalendarEntity,
)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
PARALLEL_UPDATES = 0 PARALLEL_UPDATES = 0
INFO_SENSORS: tuple[SensorEntityDescription, ...] = (
SensorEntityDescription( @dataclass(frozen=True, kw_only=True)
class JewishCalendarBaseSensorDescription(SensorEntityDescription):
"""Base class describing Jewish Calendar sensor entities."""
value_fn: Callable | None
@dataclass(frozen=True, kw_only=True)
class JewishCalendarSensorDescription(JewishCalendarBaseSensorDescription):
"""Class describing Jewish Calendar sensor entities."""
value_fn: Callable[[JewishCalendarDataResults], str | int]
attr_fn: Callable[[JewishCalendarDataResults], dict[str, str]] | None = None
options_fn: Callable[[bool], list[str]] | None = None
@dataclass(frozen=True, kw_only=True)
class JewishCalendarTimestampSensorDescription(JewishCalendarBaseSensorDescription):
"""Class describing Jewish Calendar sensor timestamp entities."""
value_fn: (
Callable[[HDateInfo, Callable[[dt.date], Zmanim]], dt.datetime | None] | None
) = None
INFO_SENSORS: tuple[JewishCalendarSensorDescription, ...] = (
JewishCalendarSensorDescription(
key="date", key="date",
translation_key="hebrew_date", translation_key="hebrew_date",
value_fn=lambda results: str(results.after_shkia_date.hdate),
attr_fn=lambda results: {
"hebrew_year": str(results.after_shkia_date.hdate.year),
"hebrew_month_name": str(results.after_shkia_date.hdate.month),
"hebrew_day": str(results.after_shkia_date.hdate.day),
},
), ),
SensorEntityDescription( JewishCalendarSensorDescription(
key="weekly_portion", key="weekly_portion",
translation_key="weekly_portion", translation_key="weekly_portion",
device_class=SensorDeviceClass.ENUM, device_class=SensorDeviceClass.ENUM,
options_fn=lambda _: [str(p) for p in Parasha],
value_fn=lambda results: str(results.after_tzais_date.upcoming_shabbat.parasha),
), ),
SensorEntityDescription( JewishCalendarSensorDescription(
key="holiday", key="holiday",
translation_key="holiday", translation_key="holiday",
device_class=SensorDeviceClass.ENUM, device_class=SensorDeviceClass.ENUM,
options_fn=lambda diaspora: HolidayDatabase(diaspora).get_all_names(),
value_fn=lambda results: ", ".join(
str(holiday) for holiday in results.after_shkia_date.holidays
),
attr_fn=lambda results: {
"id": ", ".join(
holiday.name for holiday in results.after_shkia_date.holidays
),
"type": ", ".join(
dict.fromkeys(
_holiday.type.name for _holiday in results.after_shkia_date.holidays
)
),
},
), ),
SensorEntityDescription( JewishCalendarSensorDescription(
key="omer_count", key="omer_count",
translation_key="omer_count", translation_key="omer_count",
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
value_fn=lambda results: (
results.after_shkia_date.omer.total_days
if results.after_shkia_date.omer
else 0
),
), ),
SensorEntityDescription( JewishCalendarSensorDescription(
key="daf_yomi", key="daf_yomi",
translation_key="daf_yomi", translation_key="daf_yomi",
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
value_fn=lambda results: str(results.daytime_date.daf_yomi),
), ),
) )
TIME_SENSORS: tuple[SensorEntityDescription, ...] = ( TIME_SENSORS: tuple[JewishCalendarTimestampSensorDescription, ...] = (
SensorEntityDescription( JewishCalendarTimestampSensorDescription(
key="alot_hashachar", key="alot_hashachar",
translation_key="alot_hashachar", translation_key="alot_hashachar",
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
), ),
SensorEntityDescription( JewishCalendarTimestampSensorDescription(
key="talit_and_tefillin", key="talit_and_tefillin",
translation_key="talit_and_tefillin", translation_key="talit_and_tefillin",
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
), ),
SensorEntityDescription( JewishCalendarTimestampSensorDescription(
key="netz_hachama", key="netz_hachama",
translation_key="netz_hachama", translation_key="netz_hachama",
), ),
SensorEntityDescription( JewishCalendarTimestampSensorDescription(
key="sof_zman_shema_gra", key="sof_zman_shema_gra",
translation_key="sof_zman_shema_gra", translation_key="sof_zman_shema_gra",
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
), ),
SensorEntityDescription( JewishCalendarTimestampSensorDescription(
key="sof_zman_shema_mga", key="sof_zman_shema_mga",
translation_key="sof_zman_shema_mga", translation_key="sof_zman_shema_mga",
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
), ),
SensorEntityDescription( JewishCalendarTimestampSensorDescription(
key="sof_zman_tfilla_gra", key="sof_zman_tfilla_gra",
translation_key="sof_zman_tfilla_gra", translation_key="sof_zman_tfilla_gra",
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
), ),
SensorEntityDescription( JewishCalendarTimestampSensorDescription(
key="sof_zman_tfilla_mga", key="sof_zman_tfilla_mga",
translation_key="sof_zman_tfilla_mga", translation_key="sof_zman_tfilla_mga",
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
), ),
SensorEntityDescription( JewishCalendarTimestampSensorDescription(
key="chatzot_hayom", key="chatzot_hayom",
translation_key="chatzot_hayom", translation_key="chatzot_hayom",
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
), ),
SensorEntityDescription( JewishCalendarTimestampSensorDescription(
key="mincha_gedola", key="mincha_gedola",
translation_key="mincha_gedola", translation_key="mincha_gedola",
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
), ),
SensorEntityDescription( JewishCalendarTimestampSensorDescription(
key="mincha_ketana", key="mincha_ketana",
translation_key="mincha_ketana", translation_key="mincha_ketana",
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
), ),
SensorEntityDescription( JewishCalendarTimestampSensorDescription(
key="plag_hamincha", key="plag_hamincha",
translation_key="plag_hamincha", translation_key="plag_hamincha",
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
), ),
SensorEntityDescription( JewishCalendarTimestampSensorDescription(
key="shkia", key="shkia",
translation_key="shkia", translation_key="shkia",
), ),
SensorEntityDescription( JewishCalendarTimestampSensorDescription(
key="tset_hakohavim_tsom", key="tset_hakohavim_tsom",
translation_key="tset_hakohavim_tsom", translation_key="tset_hakohavim_tsom",
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
), ),
SensorEntityDescription( JewishCalendarTimestampSensorDescription(
key="tset_hakohavim_shabbat", key="tset_hakohavim_shabbat",
translation_key="tset_hakohavim_shabbat", translation_key="tset_hakohavim_shabbat",
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
), ),
SensorEntityDescription( JewishCalendarTimestampSensorDescription(
key="upcoming_shabbat_candle_lighting", key="upcoming_shabbat_candle_lighting",
translation_key="upcoming_shabbat_candle_lighting", translation_key="upcoming_shabbat_candle_lighting",
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
value_fn=lambda at_date, mz: mz(
at_date.upcoming_shabbat.previous_day.gdate
).candle_lighting,
), ),
SensorEntityDescription( JewishCalendarTimestampSensorDescription(
key="upcoming_shabbat_havdalah", key="upcoming_shabbat_havdalah",
translation_key="upcoming_shabbat_havdalah", translation_key="upcoming_shabbat_havdalah",
entity_registry_enabled_default=False, entity_registry_enabled_default=False,
value_fn=lambda at_date, mz: mz(at_date.upcoming_shabbat.gdate).havdalah,
), ),
SensorEntityDescription( JewishCalendarTimestampSensorDescription(
key="upcoming_candle_lighting", key="upcoming_candle_lighting",
translation_key="upcoming_candle_lighting", translation_key="upcoming_candle_lighting",
value_fn=lambda at_date, mz: mz(
at_date.upcoming_shabbat_or_yom_tov.first_day.previous_day.gdate
).candle_lighting,
), ),
SensorEntityDescription( JewishCalendarTimestampSensorDescription(
key="upcoming_havdalah", key="upcoming_havdalah",
translation_key="upcoming_havdalah", translation_key="upcoming_havdalah",
value_fn=lambda at_date, mz: mz(
at_date.upcoming_shabbat_or_yom_tov.last_day.gdate
).havdalah,
), ),
) )
@ -149,40 +218,30 @@ async def async_setup_entry(
async_add_entities: AddConfigEntryEntitiesCallback, async_add_entities: AddConfigEntryEntitiesCallback,
) -> None: ) -> None:
"""Set up the Jewish calendar sensors .""" """Set up the Jewish calendar sensors ."""
sensors = [ sensors: list[JewishCalendarBaseSensor] = [
JewishCalendarSensor(config_entry, description) for description in INFO_SENSORS JewishCalendarSensor(config_entry, description) for description in INFO_SENSORS
] ]
sensors.extend( sensors.extend(
JewishCalendarTimeSensor(config_entry, description) JewishCalendarTimeSensor(config_entry, description)
for description in TIME_SENSORS for description in TIME_SENSORS
) )
async_add_entities(sensors) async_add_entities(sensors)
class JewishCalendarSensor(JewishCalendarEntity, SensorEntity): class JewishCalendarBaseSensor(JewishCalendarEntity, SensorEntity):
"""Representation of an Jewish calendar sensor.""" """Base class for Jewish calendar sensors."""
_attr_entity_category = EntityCategory.DIAGNOSTIC _attr_entity_category = EntityCategory.DIAGNOSTIC
def __init__(
self,
config_entry: JewishCalendarConfigEntry,
description: SensorEntityDescription,
) -> None:
"""Initialize the Jewish calendar sensor."""
super().__init__(config_entry, description)
self._attrs: dict[str, str] = {}
async def async_added_to_hass(self) -> None: async def async_added_to_hass(self) -> None:
"""Call when entity is added to hass.""" """Call when entity is added to hass."""
await super().async_added_to_hass() await super().async_added_to_hass()
await self.async_update() await self.async_update_data()
async def async_update(self) -> None: async def async_update_data(self) -> None:
"""Update the state of the sensor.""" """Update the state of the sensor."""
now = dt_util.now() now = dt_util.now()
_LOGGER.debug("Now: %s Location: %r", now, self._location) _LOGGER.debug("Now: %s Location: %r", now, self.data.location)
today = now.date() today = now.date()
event_date = get_astral_event_date(self.hass, SUN_EVENT_SUNSET, today) event_date = get_astral_event_date(self.hass, SUN_EVENT_SUNSET, today)
@ -195,7 +254,7 @@ class JewishCalendarSensor(JewishCalendarEntity, SensorEntity):
_LOGGER.debug("Now: %s Sunset: %s", now, sunset) _LOGGER.debug("Now: %s Sunset: %s", now, sunset)
daytime_date = HDateInfo(today, diaspora=self._diaspora) daytime_date = HDateInfo(today, diaspora=self.data.diaspora)
# The Jewish day starts after darkness (called "tzais") and finishes at # The Jewish day starts after darkness (called "tzais") and finishes at
# sunset ("shkia"). The time in between is a gray area # sunset ("shkia"). The time in between is a gray area
@ -214,95 +273,57 @@ class JewishCalendarSensor(JewishCalendarEntity, SensorEntity):
if today_times.havdalah and now > today_times.havdalah: if today_times.havdalah and now > today_times.havdalah:
after_tzais_date = daytime_date.next_day after_tzais_date = daytime_date.next_day
self._attr_native_value = self.get_state( self.data.results = JewishCalendarDataResults(
daytime_date, after_shkia_date, after_tzais_date daytime_date, after_shkia_date, after_tzais_date, today_times
)
_LOGGER.debug(
"New value for %s: %s", self.entity_description.key, self._attr_native_value
) )
def make_zmanim(self, date: dt.date) -> Zmanim:
"""Create a Zmanim object.""" class JewishCalendarSensor(JewishCalendarBaseSensor):
return Zmanim( """Representation of an Jewish calendar sensor."""
date=date,
location=self._location, entity_description: JewishCalendarSensorDescription
candle_lighting_offset=self._candle_lighting_offset,
havdalah_offset=self._havdalah_offset, def __init__(
) self,
config_entry: JewishCalendarConfigEntry,
description: SensorEntityDescription,
) -> None:
"""Initialize the Jewish calendar sensor."""
super().__init__(config_entry, description)
# Set the options for enumeration sensors
if self.entity_description.options_fn is not None:
self._attr_options = self.entity_description.options_fn(self.data.diaspora)
@property
def native_value(self) -> str | int | dt.datetime | None:
"""Return the state of the sensor."""
if self.data.results is None:
return None
return self.entity_description.value_fn(self.data.results)
@property @property
def extra_state_attributes(self) -> dict[str, str]: def extra_state_attributes(self) -> dict[str, str]:
"""Return the state attributes.""" """Return the state attributes."""
return self._attrs if self.data.results is None:
return {}
def get_state( if self.entity_description.attr_fn is not None:
self, return self.entity_description.attr_fn(self.data.results)
daytime_date: HDateInfo, return {}
after_shkia_date: HDateInfo,
after_tzais_date: HDateInfo,
) -> Any | None:
"""For a given type of sensor, return the state."""
# Terminology note: by convention in py-libhdate library, "upcoming"
# refers to "current" or "upcoming" dates.
if self.entity_description.key == "date":
hdate = after_shkia_date.hdate
self._attrs = {
"hebrew_year": str(hdate.year),
"hebrew_month_name": str(hdate.month),
"hebrew_day": str(hdate.day),
}
return after_shkia_date.hdate
if self.entity_description.key == "weekly_portion":
self._attr_options = [str(p) for p in Parasha]
# Compute the weekly portion based on the upcoming shabbat.
return str(after_tzais_date.upcoming_shabbat.parasha)
if self.entity_description.key == "holiday":
_holidays = after_shkia_date.holidays
_id = ", ".join(holiday.name for holiday in _holidays)
_type = ", ".join(
dict.fromkeys(_holiday.type.name for _holiday in _holidays)
)
self._attrs = {"id": _id, "type": _type}
self._attr_options = HolidayDatabase(self._diaspora).get_all_names()
return ", ".join(str(holiday) for holiday in _holidays) if _holidays else ""
if self.entity_description.key == "omer_count":
return after_shkia_date.omer.total_days if after_shkia_date.omer else 0
if self.entity_description.key == "daf_yomi":
return daytime_date.daf_yomi
return None
class JewishCalendarTimeSensor(JewishCalendarSensor): class JewishCalendarTimeSensor(JewishCalendarBaseSensor):
"""Implement attributes for sensors returning times.""" """Implement attributes for sensors returning times."""
_attr_device_class = SensorDeviceClass.TIMESTAMP _attr_device_class = SensorDeviceClass.TIMESTAMP
entity_description: JewishCalendarTimestampSensorDescription
def get_state( @property
self, def native_value(self) -> dt.datetime | None:
daytime_date: HDateInfo, """Return the state of the sensor."""
after_shkia_date: HDateInfo, if self.data.results is None:
after_tzais_date: HDateInfo, return None
) -> Any | None: if self.entity_description.value_fn is None:
"""For a given type of sensor, return the state.""" return self.data.results.zmanim.zmanim[self.entity_description.key].local
if self.entity_description.key == "upcoming_shabbat_candle_lighting": return self.entity_description.value_fn(
times = self.make_zmanim( self.data.results.after_tzais_date, self.make_zmanim
after_tzais_date.upcoming_shabbat.previous_day.gdate )
)
return times.candle_lighting
if self.entity_description.key == "upcoming_candle_lighting":
times = self.make_zmanim(
after_tzais_date.upcoming_shabbat_or_yom_tov.first_day.previous_day.gdate
)
return times.candle_lighting
if self.entity_description.key == "upcoming_shabbat_havdalah":
times = self.make_zmanim(after_tzais_date.upcoming_shabbat.gdate)
return times.havdalah
if self.entity_description.key == "upcoming_havdalah":
times = self.make_zmanim(
after_tzais_date.upcoming_shabbat_or_yom_tov.last_day.gdate
)
return times.havdalah
times = self.make_zmanim(dt_util.now().date())
return times.zmanim[self.entity_description.key].local

View File

@ -1,5 +1,5 @@
# serializer version: 1 # serializer version: 1
# name: test_diagnostics[Jerusalem] # name: test_diagnostics[test_time0-Jerusalem]
dict({ dict({
'data': dict({ 'data': dict({
'candle_lighting_offset': 40, 'candle_lighting_offset': 40,
@ -17,6 +17,54 @@
'repr': "zoneinfo.ZoneInfo(key='Asia/Jerusalem')", 'repr': "zoneinfo.ZoneInfo(key='Asia/Jerusalem')",
}), }),
}), }),
'results': dict({
'after_shkia_date': dict({
'date': dict({
'day': 21,
'month': 10,
'year': 5785,
}),
'diaspora': False,
'nusach': 'sephardi',
}),
'after_tzais_date': dict({
'date': dict({
'day': 21,
'month': 10,
'year': 5785,
}),
'diaspora': False,
'nusach': 'sephardi',
}),
'daytime_date': dict({
'date': dict({
'day': 21,
'month': 10,
'year': 5785,
}),
'diaspora': False,
'nusach': 'sephardi',
}),
'zmanim': dict({
'candle_lighting_offset': 40,
'date': dict({
'__type': "<class 'freezegun.api.FakeDate'>",
'isoformat': '2025-05-19',
}),
'havdalah_offset': 0,
'location': dict({
'altitude': '**REDACTED**',
'diaspora': False,
'latitude': '**REDACTED**',
'longitude': '**REDACTED**',
'name': 'test home',
'timezone': dict({
'__type': "<class 'zoneinfo.ZoneInfo'>",
'repr': "zoneinfo.ZoneInfo(key='Asia/Jerusalem')",
}),
}),
}),
}),
}), }),
'entry_data': dict({ 'entry_data': dict({
'diaspora': False, 'diaspora': False,
@ -25,7 +73,7 @@
}), }),
}) })
# --- # ---
# name: test_diagnostics[New York] # name: test_diagnostics[test_time0-New York]
dict({ dict({
'data': dict({ 'data': dict({
'candle_lighting_offset': 18, 'candle_lighting_offset': 18,
@ -43,6 +91,54 @@
'repr': "zoneinfo.ZoneInfo(key='America/New_York')", 'repr': "zoneinfo.ZoneInfo(key='America/New_York')",
}), }),
}), }),
'results': dict({
'after_shkia_date': dict({
'date': dict({
'day': 21,
'month': 10,
'year': 5785,
}),
'diaspora': True,
'nusach': 'sephardi',
}),
'after_tzais_date': dict({
'date': dict({
'day': 21,
'month': 10,
'year': 5785,
}),
'diaspora': True,
'nusach': 'sephardi',
}),
'daytime_date': dict({
'date': dict({
'day': 21,
'month': 10,
'year': 5785,
}),
'diaspora': True,
'nusach': 'sephardi',
}),
'zmanim': dict({
'candle_lighting_offset': 18,
'date': dict({
'__type': "<class 'freezegun.api.FakeDate'>",
'isoformat': '2025-05-19',
}),
'havdalah_offset': 0,
'location': dict({
'altitude': '**REDACTED**',
'diaspora': True,
'latitude': '**REDACTED**',
'longitude': '**REDACTED**',
'name': 'test home',
'timezone': dict({
'__type': "<class 'zoneinfo.ZoneInfo'>",
'repr': "zoneinfo.ZoneInfo(key='America/New_York')",
}),
}),
}),
}),
}), }),
'entry_data': dict({ 'entry_data': dict({
'diaspora': True, 'diaspora': True,
@ -51,7 +147,7 @@
}), }),
}) })
# --- # ---
# name: test_diagnostics[None] # name: test_diagnostics[test_time0-None]
dict({ dict({
'data': dict({ 'data': dict({
'candle_lighting_offset': 18, 'candle_lighting_offset': 18,
@ -69,6 +165,54 @@
'repr': "zoneinfo.ZoneInfo(key='US/Pacific')", 'repr': "zoneinfo.ZoneInfo(key='US/Pacific')",
}), }),
}), }),
'results': dict({
'after_shkia_date': dict({
'date': dict({
'day': 21,
'month': 10,
'year': 5785,
}),
'diaspora': False,
'nusach': 'sephardi',
}),
'after_tzais_date': dict({
'date': dict({
'day': 21,
'month': 10,
'year': 5785,
}),
'diaspora': False,
'nusach': 'sephardi',
}),
'daytime_date': dict({
'date': dict({
'day': 21,
'month': 10,
'year': 5785,
}),
'diaspora': False,
'nusach': 'sephardi',
}),
'zmanim': dict({
'candle_lighting_offset': 18,
'date': dict({
'__type': "<class 'freezegun.api.FakeDate'>",
'isoformat': '2025-05-19',
}),
'havdalah_offset': 0,
'location': dict({
'altitude': '**REDACTED**',
'diaspora': False,
'latitude': '**REDACTED**',
'longitude': '**REDACTED**',
'name': 'test home',
'timezone': dict({
'__type': "<class 'zoneinfo.ZoneInfo'>",
'repr': "zoneinfo.ZoneInfo(key='US/Pacific')",
}),
}),
}),
}),
}), }),
'entry_data': dict({ 'entry_data': dict({
'language': 'en', 'language': 'en',

View File

@ -1,5 +1,7 @@
"""Tests for the diagnostics data provided by the Jewish Calendar integration.""" """Tests for the diagnostics data provided by the Jewish Calendar integration."""
import datetime as dt
import pytest import pytest
from syrupy.assertion import SnapshotAssertion from syrupy.assertion import SnapshotAssertion
@ -13,6 +15,8 @@ from tests.typing import ClientSessionGenerator
@pytest.mark.parametrize( @pytest.mark.parametrize(
("location_data"), ["Jerusalem", "New York", None], indirect=True ("location_data"), ["Jerusalem", "New York", None], indirect=True
) )
@pytest.mark.parametrize("test_time", [dt.datetime(2025, 5, 19)], indirect=True)
@pytest.mark.usefixtures("setup_at_time")
async def test_diagnostics( async def test_diagnostics(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: MockConfigEntry, config_entry: MockConfigEntry,
@ -20,10 +24,6 @@ async def test_diagnostics(
snapshot: SnapshotAssertion, snapshot: SnapshotAssertion,
) -> None: ) -> None:
"""Test diagnostics with different locations.""" """Test diagnostics with different locations."""
config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
diagnostics_data = await get_diagnostics_for_config_entry( diagnostics_data = await get_diagnostics_for_config_entry(
hass, hass_client, config_entry hass, hass_client, config_entry
) )