Skip to content

Commit 76816f5

Browse files
committed
Add examples
Both to documentation and `examples` folder. 1. Simple notification blocking 2. Simple notification async 3. Listening to action invoked and notification closed signals.
1 parent da3cf67 commit 76816f5

File tree

5 files changed

+310
-0
lines changed

5 files changed

+310
-0
lines changed

docs/examples.rst

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
.. SPDX-License-Identifier: LGPL-2.1-or-later
2+
.. SPDX-FileCopyrightText: 2025 igo95862
3+
4+
Examples
5+
========
6+
7+
Examples source code can be found in ``examples`` directory.
8+
9+
Sending notification using blocking API
10+
---------------------------------------
11+
12+
Send a simple notification without waiting for user interaction.
13+
Blocking API version.
14+
15+
.. code-block:: python
16+
17+
from __future__ import annotations
18+
19+
from sdbus_block.notifications import FreedesktopNotifications
20+
21+
22+
def main() -> None:
23+
# Default bus will be used if no bus is explicitly passed.
24+
# When running as user the default bus will be session bus where
25+
# Notifications daemon usually runs.
26+
notifications = FreedesktopNotifications()
27+
28+
notifications.notify(
29+
# summary is the only required argument.
30+
# For other arguments default values will be used.
31+
summary="FooBar",
32+
)
33+
34+
35+
if __name__ == "__main__":
36+
main()
37+
38+
Sending notification using async API
39+
------------------------------------
40+
41+
Send a simple notification without waiting for user interaction.
42+
Async API version.
43+
44+
.. code-block:: python
45+
46+
from __future__ import annotations
47+
48+
from asyncio import run as asyncio_run
49+
50+
from sdbus_async.notifications import FreedesktopNotifications
51+
52+
# FreedesktopNotifications is a class that automatically proxies to
53+
# the notifications daemon's service name and path.
54+
# NotificationsInterface is the raw interface that can be used to
55+
# implement your own daemon or proxied to non-standard path.
56+
57+
58+
async def main() -> None:
59+
# Default bus will be used if no bus is explicitly passed.
60+
# When running as user the default bus will be session bus where
61+
# Notifications daemon usually runs.
62+
notifications = FreedesktopNotifications()
63+
64+
await notifications.notify(
65+
# summary is the only required argument.
66+
# For other arguments default values will be used.
67+
summary="FooBar",
68+
)
69+
70+
71+
if __name__ == "__main__":
72+
asyncio_run(main())
73+
74+
Sending notification and waiting for user interaction
75+
-----------------------------------------------------
76+
77+
Because ``python-sdbus`` only supports signals in async API there is only
78+
async version of this.
79+
80+
Send notifications with 2 buttons displaying ``Foo`` and ``Bar`` and wait for
81+
user to press one of them or dismiss the notification.
82+
83+
Remmember to bind signal reading task to a variable or otherwise it might get garbage
84+
collected.
85+
86+
Monitor ``action_invoked`` and ``notification_closed`` signals to track user interaction.
87+
88+
89+
.. code-block:: python
90+
91+
from __future__ import annotations
92+
93+
from asyncio import FIRST_COMPLETED, get_running_loop
94+
from asyncio import run as asyncio_run
95+
from asyncio import wait
96+
97+
from sdbus_async.notifications import FreedesktopNotifications
98+
99+
# FreedesktopNotifications is a class that automatically proxies to
100+
# the notifications daemon's service name and path.
101+
# NotificationsInterface is the raw interface that can be used to
102+
# implement your own daemon or proxied to non-standard path.
103+
104+
105+
async def wait_action_invoked(
106+
notifications: FreedesktopNotifications,
107+
notifications_waiting: set[int],
108+
) -> None:
109+
async for (
110+
notification_id,
111+
action_key,
112+
) in notifications.action_invoked.catch():
113+
if notification_id in notifications_waiting:
114+
print("Action invoked:", action_key)
115+
return
116+
117+
118+
async def wait_notification_closed(
119+
notifications: FreedesktopNotifications,
120+
notifications_waiting: set[int],
121+
) -> None:
122+
async for (
123+
notification_id,
124+
reason,
125+
) in notifications.notification_closed.catch():
126+
if notification_id in notifications_waiting:
127+
print("Notification closed!")
128+
return
129+
130+
131+
async def main() -> None:
132+
# Default bus will be used if no bus is explicitly passed.
133+
# When running as user the default bus will be session bus where
134+
# Notifications daemon usually runs.
135+
notifications = FreedesktopNotifications()
136+
notifications_waiting: set[int] = set()
137+
138+
loop = get_running_loop()
139+
140+
# Always bind tasks to variables or they will be garbage collected
141+
action_invoked_task = loop.create_task(
142+
wait_action_invoked(
143+
notifications,
144+
notifications_waiting,
145+
)
146+
)
147+
notification_closed_task = loop.create_task(
148+
wait_notification_closed(
149+
notifications,
150+
notifications_waiting,
151+
)
152+
)
153+
154+
notification_id = await notifications.notify(
155+
# summary is the only required argument.
156+
# For other arguments default values will be used.
157+
summary="Foo or Bar?",
158+
body="Select either Foo or Bar.",
159+
# Actions are defined in pairs of action_key to displayed string.
160+
actions=["foo", "Foo", "bar", "Bar"],
161+
)
162+
notifications_waiting.add(notification_id)
163+
164+
await wait(
165+
(action_invoked_task, notification_closed_task),
166+
return_when=FIRST_COMPLETED,
167+
)
168+
169+
170+
if __name__ == "__main__":
171+
asyncio_run(main())
172+

docs/index.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ Freedesktop Notifications binds for python-sdbus
44
This package contains python-sdbus binds for
55
`Freedesktop notifications standard <https://specifications.freedesktop.org/notification-spec/notification-spec-latest.html>`_.
66

7+
.. toctree::
8+
9+
examples
10+
711
.. py:currentmodule:: sdbus_async.notifications
812
913
:py:class:`FreedesktopNotifications` is the proxy automatically connects.

examples/async/await_action.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# SPDX-License-Identifier: MIT
2+
# SPDX-FileCopyrightText: 2025 igo95862
3+
from __future__ import annotations
4+
5+
from asyncio import FIRST_COMPLETED, get_running_loop
6+
from asyncio import run as asyncio_run
7+
from asyncio import wait
8+
9+
from sdbus_async.notifications import FreedesktopNotifications
10+
11+
# FreedesktopNotifications is a class that automatically proxies to
12+
# the notifications daemon's service name and path.
13+
# NotificationsInterface is the raw interface that can be used to
14+
# implement your own daemon or proxied to non-standard path.
15+
16+
17+
async def wait_action_invoked(
18+
notifications: FreedesktopNotifications,
19+
notifications_waiting: set[int],
20+
) -> None:
21+
async for (
22+
notification_id,
23+
action_key,
24+
) in notifications.action_invoked.catch():
25+
if notification_id in notifications_waiting:
26+
print("Action invoked:", action_key)
27+
return
28+
29+
30+
async def wait_notification_closed(
31+
notifications: FreedesktopNotifications,
32+
notifications_waiting: set[int],
33+
) -> None:
34+
async for (
35+
notification_id,
36+
reason,
37+
) in notifications.notification_closed.catch():
38+
if notification_id in notifications_waiting:
39+
print("Notification closed!")
40+
return
41+
42+
43+
async def main() -> None:
44+
# Default bus will be used if no bus is explicitly passed.
45+
# When running as user the default bus will be session bus where
46+
# Notifications daemon usually runs.
47+
notifications = FreedesktopNotifications()
48+
notifications_waiting: set[int] = set()
49+
50+
loop = get_running_loop()
51+
52+
# Always bind tasks to variables or they will be garbage collected
53+
action_invoked_task = loop.create_task(
54+
wait_action_invoked(
55+
notifications,
56+
notifications_waiting,
57+
)
58+
)
59+
notification_closed_task = loop.create_task(
60+
wait_notification_closed(
61+
notifications,
62+
notifications_waiting,
63+
)
64+
)
65+
66+
notification_id = await notifications.notify(
67+
# summary is the only required argument.
68+
# For other arguments default values will be used.
69+
summary="Foo or Bar?",
70+
body="Select either Foo or Bar.",
71+
# Actions are defined in pairs of action_key to displayed string.
72+
actions=["foo", "Foo", "bar", "Bar"],
73+
)
74+
notifications_waiting.add(notification_id)
75+
76+
await wait(
77+
(action_invoked_task, notification_closed_task),
78+
return_when=FIRST_COMPLETED,
79+
)
80+
81+
82+
if __name__ == "__main__":
83+
asyncio_run(main())

examples/async/simple.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# SPDX-License-Identifier: MIT
2+
# SPDX-FileCopyrightText: 2025 igo95862
3+
from __future__ import annotations
4+
5+
from asyncio import run as asyncio_run
6+
7+
from sdbus_async.notifications import FreedesktopNotifications
8+
9+
# FreedesktopNotifications is a class that automatically proxies to
10+
# the notifications daemon's service name and path.
11+
# NotificationsInterface is the raw interface that can be used to
12+
# implement your own daemon or proxied to non-standard path.
13+
14+
15+
async def main() -> None:
16+
# Default bus will be used if no bus is explicitly passed.
17+
# When running as user the default bus will be session bus where
18+
# Notifications daemon usually runs.
19+
notifications = FreedesktopNotifications()
20+
21+
await notifications.notify(
22+
# summary is the only required argument.
23+
# For other arguments default values will be used.
24+
summary="FooBar",
25+
)
26+
27+
28+
if __name__ == "__main__":
29+
asyncio_run(main())

examples/block/simple.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# SPDX-License-Identifier: MIT
2+
# SPDX-FileCopyrightText: 2025 igo95862
3+
from __future__ import annotations
4+
5+
from sdbus_block.notifications import FreedesktopNotifications
6+
7+
8+
def main() -> None:
9+
# Default bus will be used if no bus is explicitly passed.
10+
# When running as user the default bus will be session bus where
11+
# Notifications daemon usually runs.
12+
notifications = FreedesktopNotifications()
13+
14+
notifications.notify(
15+
# summary is the only required argument.
16+
# For other arguments default values will be used.
17+
summary="FooBar",
18+
)
19+
20+
21+
if __name__ == "__main__":
22+
main()

0 commit comments

Comments
 (0)