Use class instead of dict for events

This commit is contained in:
Edward Betts 2023-10-07 09:01:54 +01:00
parent f18c725221
commit 27a9ed0cf6
2 changed files with 35 additions and 26 deletions

View file

@ -1,4 +1,5 @@
import configparser import configparser
import dataclasses
import json import json
import operator import operator
import os import os
@ -49,6 +50,15 @@ access_key = config.get("exchangerate", "access_key")
data_dir = config.get("data", "dir") data_dir = config.get("data", "dir")
@dataclasses.dataclass
class Event:
"""Event."""
name: str
date: date
title: str | None = None
def next_uk_mothers_day(input_date: date) -> date: def next_uk_mothers_day(input_date: date) -> date:
"""Calculate the date of the next UK Mother's Day from the current date.""" """Calculate the date of the next UK Mother's Day from the current date."""
current_year = input_date.year current_year = input_date.year
@ -102,7 +112,7 @@ def get_next_timezone_transition(from_dt: datetime, tz_name: str) -> date:
return typing.cast(date, dt.date()) return typing.cast(date, dt.date())
def get_next_bank_holiday(input_date: date) -> dict[str, date | str]: def get_next_bank_holiday(input_date: date) -> Event:
"""Date and name of the next UK bank holiday.""" """Date and name of the next UK bank holiday."""
url = "https://www.gov.uk/bank-holidays.json" url = "https://www.gov.uk/bank-holidays.json"
filename = os.path.join(data_dir, "bank-holidays.json") filename = os.path.join(data_dir, "bank-holidays.json")
@ -117,7 +127,7 @@ def get_next_bank_holiday(input_date: date) -> dict[str, date | str]:
event_date = datetime.strptime(event["date"], "%Y-%m-%d").date() event_date = datetime.strptime(event["date"], "%Y-%m-%d").date()
if event_date < input_date: if event_date < input_date:
continue continue
next_holiday = {"date": event_date, "title": event["title"]} next_holiday = Event(name="bank_holiay", date=event_date, title=event["title"])
break break
assert next_holiday assert next_holiday
@ -257,15 +267,15 @@ def stock_markets() -> list[str]:
return reply return reply
def get_us_holiday(input_date: date) -> dict[str, date | str]: def get_us_holiday(input_date: date) -> Event:
"""Date and name of next US holiday.""" """Date and name of next US holiday."""
hols = holidays.UnitedStates(years=[input_date.year, input_date.year + 1]) hols = holidays.UnitedStates(years=[input_date.year, input_date.year + 1])
next_hol = next(x for x in sorted(hols.items()) if x[0] >= input_date) next_hol = next(x for x in sorted(hols.items()) if x[0] >= input_date)
return {"date": next_hol[0], "title": next_hol[1]} return Event(name="us_holiday", date=next_hol[0], title=next_hol[1])
def next_birthday(from_date: date, birth_date: date) -> dict[str, int | date]: def next_birthday(from_date: date, birth_date: date) -> tuple[date, int]:
"""Calculate the date of the next birthday based on a given birth date.""" """Calculate the date of the next birthday based on a given birth date."""
next_birthday_date = birth_date.replace(year=from_date.year) next_birthday_date = birth_date.replace(year=from_date.year)
@ -274,23 +284,22 @@ def next_birthday(from_date: date, birth_date: date) -> dict[str, int | date]:
age_at_next_birthday = next_birthday_date.year - birth_date.year age_at_next_birthday = next_birthday_date.year - birth_date.year
return {"next_birthday": next_birthday_date, "age": age_at_next_birthday} return next_birthday_date, age_at_next_birthday
def get_birthdays( def get_birthdays(from_date: date, config: configparser.ConfigParser) -> list[Event]:
from_date: date, config: configparser.ConfigParser """Get birthdays from config."""
) -> list[dict[str, date | str]]:
if "birthdays" not in config: if "birthdays" not in config:
return [] return []
events = [] events = []
for name, date_str in config["birthdays"].items(): for name, date_str in config["birthdays"].items():
bday = next_birthday(from_date, datetime.strptime(date_str, "%Y-%m-%d").date()) bday = next_birthday(from_date, datetime.strptime(date_str, "%Y-%m-%d").date())
events.append( events.append(
{ Event(
"date": bday["next_birthday"], date=bday[0],
"name": "birthday", name="birthday",
"title": f"{name} (aged {bday['age']})", title=f"{name} (aged {bday[1]})",
} )
) )
return events return events
@ -321,31 +330,31 @@ def get_data(now: datetime) -> dict[str, str | object]:
} }
skip = {"now", "gbpusd", "rockets", "stock_markets", "xmas_last_posting_dates"} skip = {"now", "gbpusd", "rockets", "stock_markets", "xmas_last_posting_dates"}
events = [] events: list[Event] = []
for key, value in reply.items(): for key, value in reply.items():
if key in skip: if key in skip:
continue continue
if "holiday" in key: if "holiday" in key:
assert isinstance(value, dict) assert isinstance(value, Event)
event = value event = value
event["name"] = key
else: else:
event = {"name": key, "date": value} assert isinstance(value, date)
event = Event(name=key, date=value)
events.append(event) events.append(event)
for key, value in xmas_last_posting_dates.items(): for key, value in xmas_last_posting_dates.items():
events.append({"name": f"xmas_last_{key}", "date": value}) events.append(Event(name=f"xmas_last_{key}", date=value))
events += get_birthdays(today, config) events += get_birthdays(today, config)
next_up_series = { next_up_series = Event(
"date": date(2026, 6, 1), date=date(2026, 6, 1),
"title": "70 Up", title="70 Up",
"name": "next_up_series", name="next_up_series",
} )
events.append(next_up_series) events.append(next_up_series)
events.sort(key=operator.itemgetter("date")) events.sort(key=operator.attrgetter("date"))
reply["events"] = events reply["events"] = events

View file

@ -103,7 +103,7 @@
</td> </td>
<td> <td>
{{ event_labels.get(event.name) or event.name }} {{ event_labels.get(event.name) or event.name }}
{%- if "title" in event -%}: {{ event.title }}{% endif %} {%- if event.title -%}: {{ event.title }}{% endif %}
</td> </td>
<td class="text-end"> <td class="text-end">
{{ days(event.date) }} {{ days(event.date) }}