"""Usine de construction du fournisseur d'agenda théorique. Ce module expose l'API publique du package ``theoretical`` : les classes :class:`~pronote_sync.sources.theoretical.provider.TheoreticalAgendaProvider`, :class:`~pronote_sync.sources.theoretical.file.JsonTheoreticalAgendaProvider`, :class:`~pronote_sync.sources.theoretical.parity.WeekParityService` et :class:`~pronote_sync.sources.theoretical.holidays.SchoolHolidayCalendar`, ainsi que la fonction :func:`get_theoretical_provider` qui assemble la configuration (chemin du fichier JSON, parité des semaines et vacances scolaires) pour produire un fournisseur d'agenda théorique prêt à l'emploi. """ from __future__ import annotations from datetime import date from typing import Literal from pronote_sync.errors import PronoteSyncError from pronote_sync.sources.theoretical.file import JsonTheoreticalAgendaProvider from pronote_sync.sources.theoretical.holidays import SchoolHolidayCalendar from pronote_sync.sources.theoretical.parity import WeekParityService from pronote_sync.sources.theoretical.provider import TheoreticalAgendaProvider __all__ = [ "TheoreticalAgendaProvider", "JsonTheoreticalAgendaProvider", "WeekParityService", "SchoolHolidayCalendar", "get_theoretical_provider", ] def get_theoretical_provider( agenda_path: str | None, holidays_path: str | None, anchor_date: date | None, anchor_type: Literal["even", "odd"] | None, ) -> TheoreticalAgendaProvider | None: """Construit un fournisseur d'agenda théorique depuis la configuration. :param agenda_path: Chemin du fichier JSON d'agenda théorique. Si None, retourne None. :param holidays_path: Chemin du fichier JSON de vacances scolaires (optionnel). :param anchor_date: Date de référence pour la parité des semaines. :param anchor_type: Type de la semaine de référence ("even" ou "odd"). :return: Le fournisseur configuré, ou None si l'agenda théorique est désactivé. :rtype: TheoreticalAgendaProvider | None :raises PronoteSyncError: Si la configuration de parité est incomplète (date sans type ou inversement) alors que l'agenda nécessite la parité. """ if agenda_path is None: return None # Build parity service if both anchor fields are provided parity_service: WeekParityService | None = None if anchor_date is not None and anchor_type is not None: parity_service = WeekParityService(anchor_date, anchor_type) elif anchor_date is not None or anchor_type is not None: # Partial parity config — one field without the other raise PronoteSyncError( "Configuration de parité incomplète : THEORETICAL_WEEK_ANCHOR_DATE et " "THEORETICAL_WEEK_ANCHOR_TYPE doivent être fournis ensemble." ) # Build holiday calendar if path is provided holiday_calendar: SchoolHolidayCalendar | None = None if holidays_path is not None: holiday_calendar = SchoolHolidayCalendar(holidays_path) # Build provider — the provider's __init__ will validate that parity_service # is provided if the JSON contains even/odd lessons return JsonTheoreticalAgendaProvider( file_path=agenda_path, parity_service=parity_service, holiday_calendar=holiday_calendar, )