Add tray desktop notification helper
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
a57cf4a16f
commit
2fce7d412a
2 changed files with 61 additions and 0 deletions
27
enodia_sentinel/tray/notify.py
Normal file
27
enodia_sentinel/tray/notify.py
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
"""Desktop notification helper. Prefers notify-send; no GUI imports."""
|
||||
from __future__ import annotations
|
||||
|
||||
import shutil
|
||||
import subprocess
|
||||
from typing import Callable, Optional, Sequence
|
||||
|
||||
Runner = Callable[[Sequence[str]], "subprocess.CompletedProcess"]
|
||||
|
||||
|
||||
def _default_runner(cmd: Sequence[str]) -> "subprocess.CompletedProcess":
|
||||
try:
|
||||
return subprocess.run(list(cmd), capture_output=True, text=True,
|
||||
timeout=10, check=False)
|
||||
except (OSError, subprocess.TimeoutExpired) as exc:
|
||||
return subprocess.CompletedProcess(list(cmd), 127, "", str(exc))
|
||||
|
||||
|
||||
def notify(title: str, body: str, *, runner: Optional[Runner] = None,
|
||||
which: Callable[[str], object] = shutil.which) -> bool:
|
||||
"""Show a desktop notification. Returns True if notify-send was invoked."""
|
||||
if which("notify-send") is None:
|
||||
return False
|
||||
run = runner or _default_runner
|
||||
run(["notify-send", "-a", "Enodia Sentinel", title, body])
|
||||
return True
|
||||
34
tests/test_tray_notify.py
Normal file
34
tests/test_tray_notify.py
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
"""Desktop notification helper: notify-send when available, else no-op."""
|
||||
import subprocess
|
||||
import unittest
|
||||
|
||||
from enodia_sentinel.tray import notify
|
||||
|
||||
|
||||
class TestNotify(unittest.TestCase):
|
||||
def test_no_notify_send_is_noop(self):
|
||||
calls = []
|
||||
|
||||
def runner(cmd):
|
||||
calls.append(cmd)
|
||||
return subprocess.CompletedProcess(cmd, 0)
|
||||
|
||||
used = notify.notify("t", "b", runner=runner, which=lambda _n: None)
|
||||
self.assertFalse(used)
|
||||
self.assertEqual(calls, [])
|
||||
|
||||
def test_uses_notify_send_with_app_name(self):
|
||||
calls = []
|
||||
|
||||
def runner(cmd):
|
||||
calls.append(cmd)
|
||||
return subprocess.CompletedProcess(cmd, 0)
|
||||
|
||||
used = notify.notify("Title", "Body", runner=runner,
|
||||
which=lambda _n: "/usr/bin/notify-send")
|
||||
self.assertTrue(used)
|
||||
self.assertEqual(len(calls), 1)
|
||||
self.assertIn("notify-send", calls[0][0])
|
||||
self.assertIn("Title", calls[0])
|
||||
self.assertIn("Body", calls[0])
|
||||
Loading…
Add table
Add a link
Reference in a new issue