notifications.pyΒΆ

 1#!/usr/bin/env python
 2
 3"""Example: messages of each severity in the footer of a window, each shown for five seconds.
 4
 5i, w and e post an info, a warning and an error message, s posts one that stays until it is dismissed,
 6d dismisses the newest message, c clears them all, and q exits. The keys work in either case.
 7"""
 8
 9from __future__ import annotations
10
11import itertools
12
13import urwid
14
15
16def main() -> None:
17    """Build the window with the notifications footer and the key handling, and run the main loop."""
18    notifications = urwid.Notifications(
19        max_count=5,
20        severity_attr={
21            urwid.Severity.INFO: "info",
22            urwid.Severity.WARNING: "warning",
23            urwid.Severity.ERROR: "error",
24        },
25        default="i: info  w: warning  e: error  s: sticky  d: dismiss  c: clear  q: quit",
26        default_attr="help",
27    )
28    numbers = itertools.count(1)
29    severities = {"i": urwid.Severity.INFO, "w": urwid.Severity.WARNING, "e": urwid.Severity.ERROR}
30
31    def unhandled(key: str | tuple[str, int, int, int]) -> None:
32        if not isinstance(key, str):
33            return
34        # Shift or Caps Lock sends the upper-case key
35        key = key.lower()
36        if key == "q":
37            raise urwid.ExitMainLoop
38        if key in severities:
39            severity = severities[key]
40            notifications.notify(f"{severity.name.lower()} message {next(numbers)}", severity=severity)
41        elif key == "s":
42            notifications.notify(f"sticky message {next(numbers)}, d dismisses it", timeout=None)
43        elif key == "d" and notifications.notifications:
44            notifications.dismiss(notifications.notifications[-1])
45        elif key == "c":
46            notifications.clear()
47
48    body = urwid.Filler(urwid.Text("Messages appear in the footer, oldest at the top.", align="center"))
49    frame: urwid.Frame[urwid.Filler[urwid.Text], None, urwid.Notifications] = urwid.Frame(body, footer=notifications)
50    palette: list[tuple[str, str, str]] = [
51        ("help", "black", "light gray"),
52        ("info", "white", "dark blue"),
53        ("warning", "black", "brown"),
54        ("error", "white", "dark red"),
55    ]
56    urwid.MainLoop(frame, palette, unhandled_input=unhandled).run()
57
58
59if __name__ == "__main__":
60    main()