From ebe48e78b7991f20b91d478853456fa4f4bd82eb Mon Sep 17 00:00:00 2001 From: Yuval Aboulafia Date: Wed, 25 Aug 2021 13:05:58 +0300 Subject: [PATCH] Refactor Jewish Calendar to use EntityDescription (#54852) --- .../components/jewish_calendar/__init__.py | 33 ---- .../jewish_calendar/binary_sensor.py | 49 +++-- .../components/jewish_calendar/sensor.py | 172 +++++++++++++++--- 3 files changed, 173 insertions(+), 81 deletions(-) diff --git a/homeassistant/components/jewish_calendar/__init__.py b/homeassistant/components/jewish_calendar/__init__.py index 35c1505561d..bb7cc9d2841 100644 --- a/homeassistant/components/jewish_calendar/__init__.py +++ b/homeassistant/components/jewish_calendar/__init__.py @@ -10,39 +10,6 @@ from homeassistant.helpers.discovery import async_load_platform DOMAIN = "jewish_calendar" -SENSOR_TYPES = { - "binary": { - "issur_melacha_in_effect": ["Issur Melacha in Effect", "mdi:power-plug-off"] - }, - "data": { - "date": ["Date", "mdi:judaism"], - "weekly_portion": ["Parshat Hashavua", "mdi:book-open-variant"], - "holiday": ["Holiday", "mdi:calendar-star"], - "omer_count": ["Day of the Omer", "mdi:counter"], - "daf_yomi": ["Daf Yomi", "mdi:book-open-variant"], - }, - "time": { - "first_light": ["Alot Hashachar", "mdi:weather-sunset-up"], - "talit": ["Talit and Tefillin", "mdi:calendar-clock"], - "gra_end_shma": ['Latest time for Shma Gr"a', "mdi:calendar-clock"], - "mga_end_shma": ['Latest time for Shma MG"A', "mdi:calendar-clock"], - "gra_end_tfila": ['Latest time for Tefilla Gr"a', "mdi:calendar-clock"], - "mga_end_tfila": ['Latest time for Tefilla MG"A', "mdi:calendar-clock"], - "big_mincha": ["Mincha Gedola", "mdi:calendar-clock"], - "small_mincha": ["Mincha Ketana", "mdi:calendar-clock"], - "plag_mincha": ["Plag Hamincha", "mdi:weather-sunset-down"], - "sunset": ["Shkia", "mdi:weather-sunset"], - "first_stars": ["T'set Hakochavim", "mdi:weather-night"], - "upcoming_shabbat_candle_lighting": [ - "Upcoming Shabbat Candle Lighting", - "mdi:candle", - ], - "upcoming_shabbat_havdalah": ["Upcoming Shabbat Havdalah", "mdi:weather-night"], - "upcoming_candle_lighting": ["Upcoming Candle Lighting", "mdi:candle"], - "upcoming_havdalah": ["Upcoming Havdalah", "mdi:weather-night"], - }, -} - CONF_DIASPORA = "diaspora" CONF_LANGUAGE = "language" CONF_CANDLE_LIGHT_MINUTES = "candle_lighting_minutes_before_sunset" diff --git a/homeassistant/components/jewish_calendar/binary_sensor.py b/homeassistant/components/jewish_calendar/binary_sensor.py index 954b22debd0..c4e9b1e347f 100644 --- a/homeassistant/components/jewish_calendar/binary_sensor.py +++ b/homeassistant/components/jewish_calendar/binary_sensor.py @@ -1,40 +1,51 @@ """Support for Jewish Calendar binary sensors.""" +from __future__ import annotations + import datetime as dt import hdate -from homeassistant.components.binary_sensor import BinarySensorEntity -from homeassistant.core import callback +from homeassistant.components.binary_sensor import ( + BinarySensorEntity, + BinarySensorEntityDescription, +) +from homeassistant.core import HomeAssistant, callback from homeassistant.helpers import event +from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType import homeassistant.util.dt as dt_util -from . import DOMAIN, SENSOR_TYPES +from . import DOMAIN + +BINARY_SENSORS = BinarySensorEntityDescription( + key="issur_melacha_in_effect", + name="Issur Melacha in Effect", + icon="mdi:power-plug-off", +) -async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): +async def async_setup_platform( + hass: HomeAssistant, + config: ConfigType, + async_add_entities: AddEntitiesCallback, + discovery_info: DiscoveryInfoType | None = None, +): """Set up the Jewish Calendar binary sensor devices.""" if discovery_info is None: return - async_add_entities( - [ - JewishCalendarBinarySensor(hass.data[DOMAIN], sensor, sensor_info) - for sensor, sensor_info in SENSOR_TYPES["binary"].items() - ] - ) + async_add_entities([JewishCalendarBinarySensor(hass.data[DOMAIN], BINARY_SENSORS)]) class JewishCalendarBinarySensor(BinarySensorEntity): """Representation of an Jewish Calendar binary sensor.""" - def __init__(self, data, sensor, sensor_info): + _attr_should_poll = False + + def __init__(self, data, description: BinarySensorEntityDescription) -> None: """Initialize the binary sensor.""" - self._type = sensor - self._prefix = data["prefix"] - self._attr_name = f"{data['name']} {sensor_info[0]}" - self._attr_unique_id = f"{self._prefix}_{self._type}" - self._attr_icon = sensor_info[1] - self._attr_should_poll = False + self._attr_name = f"{data['name']} {description.name}" + self._attr_unique_id = f"{data['prefix']}_{description.key}" self._location = data["location"] self._hebrew = data["language"] == "hebrew" self._candle_lighting_offset = data["candle_lighting_offset"] @@ -42,7 +53,7 @@ class JewishCalendarBinarySensor(BinarySensorEntity): self._update_unsub = None @property - def is_on(self): + def is_on(self) -> bool: """Return true if sensor is on.""" return self._get_zmanim().issur_melacha_in_effect @@ -56,7 +67,7 @@ class JewishCalendarBinarySensor(BinarySensorEntity): hebrew=self._hebrew, ) - async def async_added_to_hass(self): + async def async_added_to_hass(self) -> None: """Run when entity about to be added to hass.""" await super().async_added_to_hass() self._schedule_update() diff --git a/homeassistant/components/jewish_calendar/sensor.py b/homeassistant/components/jewish_calendar/sensor.py index e3f51ea5e2c..4e90dd00058 100644 --- a/homeassistant/components/jewish_calendar/sensor.py +++ b/homeassistant/components/jewish_calendar/sensor.py @@ -1,31 +1,147 @@ """Platform to retrieve Jewish calendar information for Home Assistant.""" +from __future__ import annotations + from datetime import datetime import logging import hdate -from homeassistant.components.sensor import SensorEntity +from homeassistant.components.sensor import SensorEntity, SensorEntityDescription from homeassistant.const import DEVICE_CLASS_TIMESTAMP, SUN_EVENT_SUNSET +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.sun import get_astral_event_date +from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType import homeassistant.util.dt as dt_util -from . import DOMAIN, SENSOR_TYPES +from . import DOMAIN _LOGGER = logging.getLogger(__name__) +DATA_SENSORS = ( + SensorEntityDescription( + key="date", + name="Date", + icon="mdi:judaism", + ), + SensorEntityDescription( + key="weekly_portion", + name="Parshat Hashavua", + icon="mdi:book-open-variant", + ), + SensorEntityDescription( + key="holiday", + name="Holiday", + icon="mdi:calendar-star", + ), + SensorEntityDescription( + key="omer_count", + name="Day of the Omer", + icon="mdi:counter", + ), + SensorEntityDescription( + key="daf_yomi", + name="Daf Yomi", + icon="mdi:book-open-variant", + ), +) -async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): +TIME_SENSORS = ( + SensorEntityDescription( + key="first_light", + name="Alot Hashachar", + icon="mdi:weather-sunset-up", + ), + SensorEntityDescription( + key="talit", + name="Talit and Tefillin", + icon="mdi:calendar-clock", + ), + SensorEntityDescription( + key="gra_end_shma", + name='Latest time for Shma Gr"a', + icon="mdi:calendar-clock", + ), + SensorEntityDescription( + key="mga_end_shma", + name='Latest time for Shma MG"A', + icon="mdi:calendar-clock", + ), + SensorEntityDescription( + key="gra_end_tfila", + name='Latest time for Tefilla Gr"a', + icon="mdi:calendar-clock", + ), + SensorEntityDescription( + key="mga_end_tfila", + name='Latest time for Tefilla MG"A', + icon="mdi:calendar-clock", + ), + SensorEntityDescription( + key="big_mincha", + name="Mincha Gedola", + icon="mdi:calendar-clock", + ), + SensorEntityDescription( + key="small_mincha", + name="Mincha Ketana", + icon="mdi:calendar-clock", + ), + SensorEntityDescription( + key="plag_mincha", + name="Plag Hamincha", + icon="mdi:weather-sunset-down", + ), + SensorEntityDescription( + key="sunset", + name="Shkia", + icon="mdi:weather-sunset", + ), + SensorEntityDescription( + key="first_stars", + name="T'set Hakochavim", + icon="mdi:weather-night", + ), + SensorEntityDescription( + key="upcoming_shabbat_candle_lighting", + name="Upcoming Shabbat Candle Lighting", + icon="mdi:candle", + ), + SensorEntityDescription( + key="upcoming_shabbat_havdalah", + name="Upcoming Shabbat Havdalah", + icon="mdi:weather-night", + ), + SensorEntityDescription( + key="upcoming_candle_lighting", + name="Upcoming Candle Lighting", + icon="mdi:candle", + ), + SensorEntityDescription( + key="upcoming_havdalah", + name="Upcoming Havdalah", + icon="mdi:weather-night", + ), +) + + +async def async_setup_platform( + hass: HomeAssistant, + config: ConfigType, + async_add_entities: AddEntitiesCallback, + discovery_info: DiscoveryInfoType | None = None, +): """Set up the Jewish calendar sensor platform.""" if discovery_info is None: return sensors = [ - JewishCalendarSensor(hass.data[DOMAIN], sensor, sensor_info) - for sensor, sensor_info in SENSOR_TYPES["data"].items() + JewishCalendarSensor(hass.data[DOMAIN], description) + for description in DATA_SENSORS ] sensors.extend( - JewishCalendarTimeSensor(hass.data[DOMAIN], sensor, sensor_info) - for sensor, sensor_info in SENSOR_TYPES["time"].items() + JewishCalendarTimeSensor(hass.data[DOMAIN], description) + for description in TIME_SENSORS ) async_add_entities(sensors) @@ -34,20 +150,18 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= class JewishCalendarSensor(SensorEntity): """Representation of an Jewish calendar sensor.""" - def __init__(self, data, sensor, sensor_info): + def __init__(self, data, description: SensorEntityDescription) -> None: """Initialize the Jewish calendar sensor.""" - self._type = sensor - self._prefix = data["prefix"] - self._attr_name = f"{data['name']} {sensor_info[0]}" - self._attr_unique_id = f"{self._prefix}_{self._type}" - self._attr_icon = sensor_info[1] + self.entity_description = description + self._attr_name = f"{data['name']} {description.name}" + self._attr_unique_id = f"{data['prefix']}_{description.key}" self._location = data["location"] self._hebrew = data["language"] == "hebrew" self._candle_lighting_offset = data["candle_lighting_offset"] self._havdalah_offset = data["havdalah_offset"] self._diaspora = data["diaspora"] self._state = None - self._holiday_attrs = {} + self._holiday_attrs: dict[str, str] = {} @property def native_value(self): @@ -87,7 +201,7 @@ class JewishCalendarSensor(SensorEntity): after_tzais_date = daytime_date.next_day self._state = self.get_state(daytime_date, after_shkia_date, after_tzais_date) - _LOGGER.debug("New value for %s: %s", self._type, self._state) + _LOGGER.debug("New value for %s: %s", self.entity_description.key, self._state) def make_zmanim(self, date): """Create a Zmanim object.""" @@ -100,9 +214,9 @@ class JewishCalendarSensor(SensorEntity): ) @property - def extra_state_attributes(self): + def extra_state_attributes(self) -> dict[str, str]: """Return the state attributes.""" - if self._type != "holiday": + if self.entity_description.key != "holiday": return {} return self._holiday_attrs @@ -110,19 +224,19 @@ class JewishCalendarSensor(SensorEntity): """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._type == "date": + if self.entity_description.key == "date": return after_shkia_date.hebrew_date - if self._type == "weekly_portion": + if self.entity_description.key == "weekly_portion": # Compute the weekly portion based on the upcoming shabbat. return after_tzais_date.upcoming_shabbat.parasha - if self._type == "holiday": + if self.entity_description.key == "holiday": self._holiday_attrs["id"] = after_shkia_date.holiday_name self._holiday_attrs["type"] = after_shkia_date.holiday_type.name self._holiday_attrs["type_id"] = after_shkia_date.holiday_type.value return after_shkia_date.holiday_description - if self._type == "omer_count": + if self.entity_description.key == "omer_count": return after_shkia_date.omer_day - if self._type == "daf_yomi": + if self.entity_description.key == "daf_yomi": return daytime_date.daf_yomi return None @@ -141,9 +255,9 @@ class JewishCalendarTimeSensor(JewishCalendarSensor): return dt_util.as_utc(self._state).isoformat() @property - def extra_state_attributes(self): + def extra_state_attributes(self) -> dict[str, str]: """Return the state attributes.""" - attrs = {} + attrs: dict[str, str] = {} if self._state is None: return attrs @@ -152,24 +266,24 @@ class JewishCalendarTimeSensor(JewishCalendarSensor): def get_state(self, daytime_date, after_shkia_date, after_tzais_date): """For a given type of sensor, return the state.""" - if self._type == "upcoming_shabbat_candle_lighting": + if self.entity_description.key == "upcoming_shabbat_candle_lighting": times = self.make_zmanim( after_tzais_date.upcoming_shabbat.previous_day.gdate ) return times.candle_lighting - if self._type == "upcoming_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._type == "upcoming_shabbat_havdalah": + if self.entity_description.key == "upcoming_shabbat_havdalah": times = self.make_zmanim(after_tzais_date.upcoming_shabbat.gdate) return times.havdalah - if self._type == "upcoming_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()).zmanim - return times[self._type] + return times[self.entity_description.key]