Source code for pretalx_client.adapters.schedule

"""Schedule slot parsing and datetime normalization for Pretalx API data.

Handles the differences between the legacy Pretalx schedule format (string
room/code/title) and the paginated ``/slots/`` endpoint format (integer
room IDs, ``submission`` key instead of ``code``, no ``title``).
"""

from datetime import datetime
from typing import Any

from pretalx_client.adapters.normalization import localized, resolve_id_or_localized


[docs] def parse_datetime(value: str) -> datetime | None: """Parse an ISO 8601 datetime string, returning ``None`` on failure. Args: value: An ISO 8601 formatted datetime string. Returns: A ``datetime`` instance, or ``None`` if the string is empty or cannot be parsed. """ if not value: return None try: return datetime.fromisoformat(value) except (ValueError, TypeError): # fmt: skip return None
[docs] def normalize_slot( data: dict[str, Any], *, rooms: dict[int, str] | None = None, ) -> dict[str, Any]: """Normalize a raw Pretalx slot dict into a consistent field set. Handles both the legacy format (string ``room``, ``code``, ``title`` keys) and the real paginated ``/slots/`` format (integer ``room`` ID, ``submission`` key instead of ``code``, no ``title``). Args: data: A single slot object from the Pretalx schedule endpoint. rooms: Optional ``{id: name}`` mapping for resolving integer room IDs. Returns: A dict with normalized keys: ``room``, ``start``, ``end``, ``code``, ``title``, ``start_dt``, ``end_dt``. """ start_str = data.get("start") or "" end_str = data.get("end") or "" room_raw = data.get("room") room = resolve_id_or_localized(room_raw, rooms) code = data.get("submission") or data.get("code") or "" title = localized(data.get("title")) if "title" in data else "" return { "room": room, "start": start_str, "end": end_str, "code": code, "title": title, "start_dt": parse_datetime(start_str), "end_dt": parse_datetime(end_str), }