Implémentation complète de la source d'agenda théorique : - model.py : modèles Pydantic de parsing JSON (TheoreticalLessonEntry, TheoreticalAgendaFile) avec validation des formats d'heure et de l'ordre début/fin. - parity.py : WeekParityService déterministe calculant la parité d'une semaine (paire/impaire) à partir d'une date de référence. - holidays.py : SchoolHolidayCalendar lisant un fichier JSON de vacances scolaires (zone A) avec bornes inclusives. - provider.py : protocole TheoreticalAgendaProvider (get_lessons, get_lessons_for_range). - file.py : JsonTheoreticalAgendaProvider implémentant le protocole : filtrage par parité et vacances, génération d'IDs déterministes incluant le type de semaine, validation de l'unicité des IDs, tri stable par identifiant. - __init__.py : factory get_theoretical_provider câblant la configuration (None si désactivé, erreur si config de parité partielle). - Fixtures : theoretical.json (9 leçons all/even/odd) et school_holidays.json (zone A, 4 périodes). - 57 tests unitaires couvrant parsing, parité, vacances, provider, factory, déduplication de range, collisions d'IDs. - Guide : §8 et §12 alignés avec le format JSON. Co-authored-by: opencode/coder <coder@agents.invalid> Co-authored-by: opencode/test-engineer <test-engineer@agents.invalid>
76 lines
3.2 KiB
Python
76 lines
3.2 KiB
Python
"""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,
|
|
)
|