Skip to content

Notification config

The dataclasses that represent a Notification configuration. The first one is for the main process, the second one is for the actual creation & waiting for callback process.

NotificationConfig dataclass

The standard representation of a Notifications. This is used inside the main process.

Source code in mac_notifications/notification_config.py
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
@dataclass
class NotificationConfig:
    """
    The standard representation of a Notifications. This is used inside the main process.
    """

    title: str
    subtitle: str | None
    text: str | None
    icon: str | None
    delay: timedelta
    action_button_str: str | None
    action_callback: Callable[[], None] | None
    reply_button_str: str | None
    reply_callback: Callable[[str], None] | None
    snooze_button_str: str | None
    sound: str | None
    uid: str = field(default_factory=lambda: uuid.uuid4().hex)

    @property
    def contains_callback(self) -> bool:
        return bool(self.action_callback or self.reply_callback)

    @staticmethod
    def c_compliant(a_str: str | None) -> str | None:
        return "".join(filter(lambda x: bool(str.isalnum or str.isspace), a_str)) if a_str else None  # type: ignore

    def to_json_notification(self) -> "JSONNotificationConfig":
        return JSONNotificationConfig(
            title=NotificationConfig.c_compliant(self.title) or "Notification title",
            subtitle=NotificationConfig.c_compliant(self.subtitle),
            text=NotificationConfig.c_compliant(self.text),
            icon=self.icon,
            sound=self.sound,
            delay_in_seconds=(self.delay or timedelta()).total_seconds(),
            action_button_str=NotificationConfig.c_compliant(self.action_button_str),
            action_callback_present=bool(self.action_callback),
            reply_button_str=NotificationConfig.c_compliant(self.reply_button_str),
            reply_callback_present=bool(self.reply_callback),
            snooze_button_str=NotificationConfig.c_compliant(self.snooze_button_str),
            uid=self.uid,
        )

JSONNotificationConfig dataclass

This notification configuration class that only contains serializable parts.

This class is required because waiting for user interaction with a notification is a blocking operation. Because it is a blocking operation, if we want to be able to receive any user interaction from the notification, without completely halting/freezing our main process, we need to open it in a background process. However, to be able to transfer the data from the notification to the other process, all the arguments should be serializable. As callbacks/functions are not serializable, we replaced them by booleans on whether it contained a callback or not. Once a callback should be triggered, we send a message over a multiprocessing Queue and trigger the callback in the main process.

Source code in mac_notifications/notification_config.py
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
@dataclass
class JSONNotificationConfig:
    """
    This notification configuration class that only contains serializable parts.

    This class is required because waiting for user interaction with a notification is a blocking operation.
    Because it is a blocking operation, if we want to be able to receive any user interaction from the notification,
    without completely halting/freezing our main process, we need to open it in a background process. However, to be
    able to transfer the data from the notification to the other process, all the arguments should be serializable. As
    callbacks/functions are not serializable, we replaced them by booleans on whether it contained a callback or not.
    Once a callback should be triggered, we send a message over a multiprocessing Queue and trigger the callback in
    the main process.
    """

    title: str
    subtitle: str | None
    text: str | None
    icon: str | None
    sound: str | None
    delay_in_seconds: float
    action_button_str: str | None
    action_callback_present: bool
    reply_button_str: str | None
    reply_callback_present: bool
    snooze_button_str: str | None
    uid: str

    @property
    def contains_callback(self) -> bool:
        return bool(self.action_callback_present or self.reply_callback_present)