62 lines
1.8 KiB
Python
62 lines
1.8 KiB
Python
"""Shared parser contract for city-specific OpenMensa parsers."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass, field
|
|
from typing import Any, Protocol
|
|
|
|
from openmensa_parsers.config import Canteen
|
|
from openmensa_parsers.xml_types.canteen_xml import CanteenXML
|
|
from openmensa_parsers.xml_types.feed_xml import FeedXML, ScheduleXML
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class FeedDefinition:
|
|
"""Default feed metadata used when publishing a parser result."""
|
|
|
|
source: str
|
|
name: str = "full"
|
|
priority: int = 0
|
|
schedule: dict[str, Any] = field(
|
|
default_factory=lambda: {"hour": "8-14", "retry": "30 1"}
|
|
)
|
|
|
|
|
|
class OpenMensaParser(Protocol):
|
|
"""Contract implemented by each city/source parser."""
|
|
|
|
id: str
|
|
feed: FeedDefinition
|
|
|
|
def fetch(self) -> Any:
|
|
"""Download or load source-specific raw data."""
|
|
|
|
def parse(
|
|
self,
|
|
config: dict[str, Canteen],
|
|
raw_data: Any,
|
|
) -> dict[str, CanteenXML]:
|
|
"""Convert raw source data into OpenMensa canteen structures."""
|
|
|
|
def create_feed(self, canteen: Canteen, url: str) -> FeedXML:
|
|
"""Build the OpenMensa feed metadata for one configured canteen."""
|
|
|
|
|
|
class BaseOpenMensaParser: # pylint: disable=too-few-public-methods
|
|
"""Base helper for parsers that use the standard OpenMensa feed block."""
|
|
|
|
id = "base"
|
|
feed: FeedDefinition
|
|
|
|
def create_feed(self, _canteen: Canteen, url: str) -> FeedXML:
|
|
"""Create a standard feed tag for a configured canteen."""
|
|
schedule_data = dict(self.feed.schedule)
|
|
schedule = ScheduleXML(**schedule_data)
|
|
return FeedXML(
|
|
name=self.feed.name,
|
|
priority=self.feed.priority,
|
|
source=self.feed.source,
|
|
url=url,
|
|
schedule=schedule,
|
|
)
|