Coverage for src/lexigram/notification/exceptions.py: 88%
43 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-26 02:32 +0800
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-26 02:32 +0800
1"""lexigram-notification leaf exceptions."""
3from __future__ import annotations
5from typing import Any
7from lexigram.contracts.exceptions.domain import DomainError
8from lexigram.contracts.mailer.errors import MailerError
9from lexigram.contracts.notification.errors import NotificationError
12class TwilioNotificationError(NotificationError):
13 """Twilio SMS delivery failure."""
15 _code = "LEX_ERR_NOTIF_003"
17 def __init__(
18 self,
19 message: str = "Twilio SMS error",
20 *,
21 twilio_code: int | None = None,
22 **kwargs: Any,
23 ) -> None:
24 super().__init__(message, channel="sms", backend="twilio", **kwargs)
25 self.twilio_code = twilio_code
28class FCMNotificationError(NotificationError):
29 """FCM push notification delivery failure."""
31 _code = "LEX_ERR_NOTIF_004"
33 def __init__(
34 self,
35 message: str = "FCM push error",
36 *,
37 fcm_error: str | None = None,
38 **kwargs: Any,
39 ) -> None:
40 super().__init__(message, channel="push", backend="fcm", **kwargs)
41 self.fcm_error = fcm_error
44class APNsNotificationError(NotificationError):
45 """APNs push notification delivery failure."""
47 _code = "LEX_ERR_NOTIF_005"
49 def __init__(
50 self,
51 message: str = "APNs push error",
52 *,
53 apns_reason: str | None = None,
54 **kwargs: Any,
55 ) -> None:
56 super().__init__(message, channel="push", backend="apns", **kwargs)
57 self.apns_reason = apns_reason
60class WebPushNotificationError(NotificationError):
61 """Web Push notification delivery failure."""
63 _code = "LEX_ERR_NOTIF_011"
65 def __init__(
66 self,
67 message: str = "Web Push error",
68 *,
69 status_code: int = 0,
70 reason: str | None = None,
71 **kwargs: Any,
72 ) -> None:
73 super().__init__(message, channel="push", backend="web_push", **kwargs)
74 self.status_code = status_code
75 self.reason = reason
78# === Mail Exceptions (merged from mail/exceptions.py) ===
81class SMTPMailerError(MailerError):
82 """SMTP-specific delivery failure (rejection, auth error, etc.)."""
84 _code = "LEX_ERR_NOTIF_006"
86 def __init__(
87 self,
88 message: str = "SMTP delivery error",
89 *,
90 smtp_code: int | None = None,
91 **kwargs: Any,
92 ) -> None:
93 super().__init__(message, backend="smtp", **kwargs)
94 self.smtp_code = smtp_code
97class SendGridMailerError(MailerError):
98 """SendGrid API delivery failure."""
100 _code = "LEX_ERR_NOTIF_007"
102 def __init__(
103 self,
104 message: str = "SendGrid delivery error",
105 *,
106 status_code: int | None = None,
107 **kwargs: Any,
108 ) -> None:
109 super().__init__(message, backend="sendgrid", **kwargs)
110 self.status_code = status_code
113# === Inbox Exceptions (merged from inbox/exceptions.py) ===
116class InboxError(DomainError):
117 """Base exception for all inbox submodule errors."""
119 _code: str = "LEX_ERR_NOTIF_008"
122class InboxMessageNotFoundError(InboxError):
123 """Raised when a requested inbox message does not exist."""
125 _code: str = "LEX_ERR_NOTIF_009"
128class InboxPermissionError(InboxError):
129 """Raised when a user attempts to access another user's inbox messages."""
131 _code: str = "LEX_ERR_NOTIF_010"
134__all__ = [
135 "APNsNotificationError",
136 "FCMNotificationError",
137 "InboxError",
138 "InboxMessageNotFoundError",
139 "InboxPermissionError",
140 "SMTPMailerError",
141 "SendGridMailerError",
142 "TwilioNotificationError",
143 "WebPushNotificationError",
144]