"""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, )