diff --git a/stw_potsdam/swp_webspeiseplan_parser.py b/stw_potsdam/swp_webspeiseplan_parser.py index a622ec6..95c1739 100644 --- a/stw_potsdam/swp_webspeiseplan_parser.py +++ b/stw_potsdam/swp_webspeiseplan_parser.py @@ -1,7 +1,7 @@ import logging from datetime import datetime, date from stw_potsdam.xml_types.canteen_xml import CanteenMeta, CanteenXML -from stw_potsdam.xml_types.times_xml import TimesXML +from stw_potsdam.xml_types.times_xml import CanteenOpenTimespec, TimesXML from stw_potsdam.xml_types.meal_xml import MealXML @@ -38,23 +38,21 @@ class SWPWebspeiseplanParser: ) canteen_meta = CanteenMeta(**meta) weekday_dict = { - "monday": f"{outlet['moZeit1']}, {outlet['moZeit2']}", - "tuesday": f"{outlet['diZeit1']}, {outlet['diZeit2']}", - "wednesday": f"{outlet['miZeit1']}, {outlet['miZeit2']}", - "thursday": f"{outlet['doZeit1']}, {outlet['doZeit2']}", - "friday": f"{outlet['frZeit1']}, {outlet['frZeit2']}", - "saturday": f"{outlet['saZeit1']}, {outlet['saZeit2']}", - "sunday": f"{outlet['soZeit1']}, {outlet['soZeit2']}", + # this approach only lists the first (valid) opening time, + # since OpenMensa does not support multiple time specs + # (yet). + "monday": outlet['moZeit1'] or outlet['moZeit2'], + "tuesday": outlet['diZeit1'] or outlet['diZeit2'], + "wednesday": outlet['miZeit1'] or outlet['miZeit2'], + "thursday": outlet['doZeit1'] or outlet['doZeit2'], + "friday": outlet['frZeit1'] or outlet['frZeit2'], + "saturday": outlet['saZeit1'] or outlet['saZeit2'], + "sunday": outlet['soZeit1'] or outlet['soZeit2'], } - weekday_dict = { - k: v.replace("None, None", "") - .replace("None,", "") - .replace(", None", "") - for k, v in weekday_dict.items() - } - - canteen_times = TimesXML(weekday_dict) + canteen_times = TimesXML({ + k: CanteenOpenTimespec(v) for k, v in weekday_dict.items() + }) canteen = CanteenXML(canteen_meta, canteen_times) return canteen diff --git a/stw_potsdam/xml_types/times_xml.py b/stw_potsdam/xml_types/times_xml.py index 210034c..a458d13 100644 --- a/stw_potsdam/xml_types/times_xml.py +++ b/stw_potsdam/xml_types/times_xml.py @@ -1,11 +1,60 @@ +import re + from dataclasses import dataclass from xml.dom import minidom +class CanteenOpenTimespec(str): + """Represents valid daily opening times in openMensaFeedv2.""" + + CLOSED = "geschlossen" + CLOSED_VALID_VALUES = { + CLOSED, + None, + False, + "", + } + + PATTERN = (r'.*(?P\d{1,2}):(?P\d{1,2})\s*' + r'-\s*(?P\d{1,2}):(?P\d{1,2}).*') + MATCHER = re.compile(PATTERN) + + def __new__(cls, spec): + """Create CanteenOpenTimespec object. + + Args: + spec (str | bool | None): time specification + """ + if spec in cls.CLOSED_VALID_VALUES: + return super().__new__(cls, cls.CLOSED) + + match = cls.MATCHER.match(str(spec)) + if not match: + raise ValueError(f'Invalid time specification: {spec!r} does' + f' not conform to regex {cls.PATTERN!r}') + # parse to int for format zerofill + int_spec = {k: int(v) for k, v in match.groupdict().items()} + clean_spec = ( + f'{int_spec["hour1"]:02}:{int_spec["min1"]:02}-' + f'{int_spec["hour2"]:02}:{int_spec["min2"]:02}' + ) + return super().__new__(cls, clean_spec) + + @dataclass class TimesXML: """Represents the times tag in openMensaFeedv2.""" + VALID_DAYS = ( + "monday", + "tuesday", + "wednesday", + "thursday", + "friday", + "saturday", + "sunday", + ) + monday: str tuesday: str wednesday: str @@ -14,29 +63,24 @@ class TimesXML: saturday: str sunday: str - def __init__(self, weekday_dict: dict[str, str] = None): + def __init__(self, weekday_dict: dict[str, CanteenOpenTimespec] = None): """Init TimesXML object. Args: weekday_dict (dict[str, str]): _description_ """ for key in weekday_dict: - if key in ( - "monday", - "tuesday", - "wednesday", - "thursday", - "friday", - "saturday", - "sunday", - ): + if key in self.VALID_DAYS: setattr(self, key, weekday_dict[key]) else: raise KeyError() - def __create_node(self, doc: minidom.Document, tag: str, value: str): + def __create_node(self, + doc: minidom.Document, + tag: str, + value: CanteenOpenTimespec): elem = doc.createElement(tag) - if value == "geschlossen": + if value in CanteenOpenTimespec.CLOSED_VALID_VALUES: elem.setAttribute("closed", "true") else: elem.setAttribute("open", value) @@ -53,18 +97,9 @@ class TimesXML: """ times = doc.createElement("times") times.setAttribute("type", "opening") - monday = self.__create_node(doc, "monday", self.monday) - times.appendChild(monday) - tuesday = self.__create_node(doc, "tuesday", self.tuesday) - times.appendChild(tuesday) - wednesday = self.__create_node(doc, "wednesday", self.wednesday) - times.appendChild(wednesday) - thursday = self.__create_node(doc, "thursday", self.thursday) - times.appendChild(thursday) - friday = self.__create_node(doc, "friday", self.friday) - times.appendChild(friday) - saturday = self.__create_node(doc, "saturday", self.saturday) - times.appendChild(saturday) - sunday = self.__create_node(doc, "sunday", self.sunday) - times.appendChild(sunday) + + for day in self.VALID_DAYS: + day_node = self.__create_node(doc, day, getattr(self, day)) + times.appendChild(day_node) + return times