Fix all 8 findings from the independent review (FIXME_M10.md): #1 Transport compatible with slixmpp 1.17.0 (D5): - Use real ClientXMPP type (remove Any), JID with resource - connect(host, port) explicit, no use_tls kwarg - enable_direct_tls/enable_starttls configured before connect - Single timeout via asyncio.Future for session_start/failed_auth/disconnected - Remove premature 'starttls' in features check, remove auto_reconnect - try/finally guarantees disconnect on all paths (#4) #2 Factory dry_run no longer bypassed (D6): - Single send() entry point in SyncXmppChannel - dry_run check before any ClientXMPP creation - Remove XmppChannel.send() dual implementation #3 Thread daemon removed — single asyncio.run(), documented limitation #5 Richer message format: - Target date header, change type [Ajouté/Supprimé/Modifié] - Lesson times, homework due date, message author - No pronote_messages duplication (external_info = blog + other_info only) #6 Error contract unified (D6): - Channel.send() -> bool never raises PipelineWarning - Errors logged with redaction, returns False - PipelineWarning(step='xmpp') will be created by pipeline M11 #7 Tests faithful to slixmpp 1.17.0 API: - FakeClientXMPP with real connect(host,port)/disconnect() signatures - Assertions on host, port, resource, mtype='chat' - No RuntimeWarning from unawaited coroutines #8 .secrets.baseline restored from main Coverage: 96.44% on channels/, 600 tests pass, pre-commit all-files green. Co-authored-by: opencode/coder <coder@agents.invalid> Co-authored-by: opencode/test-engineer <test-engineer@agents.invalid>
34 lines
1.1 KiB
Python
34 lines
1.1 KiB
Python
"""Protocole abstrait définissant le contrat des canaux de sortie."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Protocol, runtime_checkable
|
|
|
|
from pronote_sync.models.xmpp import XmppMessage
|
|
|
|
|
|
@runtime_checkable
|
|
class Channel(Protocol):
|
|
"""Contrat structurel d'un canal de sortie du pipeline.
|
|
|
|
Un canal de sortie reçoit un message final :class:`XmppMessage` et tente de
|
|
l'envoyer vers la destination qu'il représente (CalDAV, XMPP, etc.).
|
|
|
|
:ivar send: Envoie un message sur le canal.
|
|
"""
|
|
|
|
def send(self, message: XmppMessage) -> bool:
|
|
"""Envoie un message sur le canal.
|
|
|
|
Un canal ne lève jamais :pyexc:`PipelineWarning` ; en cas d'échec, il
|
|
retourne ``False``. Le :pyexc:`PipelineWarning` est créé par l'étape
|
|
pipeline, pas par le canal. Une :pyexc:`PipelineCriticalError` peut
|
|
en revanche être levée en cas de panne critique (ex. : chemin
|
|
CalDAV, non utilisé par le canal XMPP).
|
|
|
|
:param message: Message final à transmettre.
|
|
:return: ``True`` si l'envoi a réussi, ``False`` sinon.
|
|
:rtype: bool
|
|
"""
|
|
...
|